View Javadoc

1   /*
2    * Copyright 2010 FatWire Corporation. All Rights Reserved.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *    http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package com.fatwire.gst.foundation.httpstatus;
18  
19  import static com.fatwire.gst.foundation.httpstatus.HttpStatusStrings.X_FATWIRE_HEADER;
20  import static com.fatwire.gst.foundation.httpstatus.HttpStatusStrings.X_FATWIRE_STATUS;
21  
22  import java.io.IOException;
23  
24  import javax.servlet.http.HttpServletResponse;
25  import javax.servlet.http.HttpServletResponseWrapper;
26  
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  
30  /**
31   * <p>
32   * A filter that transforms 2 special headers into a response status or response
33   * header. In a ContentServer XML element you can call
34   * ics.StreamHeader("X-Fatwire-Status","404") to set the response status for
35   * Satellite Server to 404.
36   * </p>
37   * 
38   * 
39   * @version 15 June 2009
40   * @author Dolf Dijkstra
41   * 
42   */
43  public class StatusFilterHttpResponseWrapper extends HttpServletResponseWrapper {
44  
45      private static Log log = LogFactory.getLog(StatusFilterHttpResponseWrapper.class.getPackage().getName());
46  
47      private int status = -1;
48  
49      private final boolean sendError;
50  
51      /**
52       * Class constructor instantiating the response object
53       */
54      public StatusFilterHttpResponseWrapper(HttpServletResponse origResponse, boolean sendError) {
55          super(origResponse);
56          this.sendError = sendError;
57  
58      }
59  
60      /**
61       * This method sets the response header value and names. It just proxies the
62       * custom response header information if the environment is CS
63       * (ContentServer). If the environment is SS (Satellite Server) then the
64       * custom header information supplied as "X-FatWire-Header" and
65       * "X-FatWire-Status" is parsed and set in the response header accordingly
66       * 
67       * @param hdrName Response header name
68       * @param hdrValue Response header value
69       */
70      public void setHeader(String hdrName, String hdrValue) {
71          if (log.isDebugEnabled()) {
72              log.debug("original setHeader " + hdrName + ": " + hdrValue);
73          }
74  
75          if (X_FATWIRE_STATUS.equalsIgnoreCase(hdrName)) {
76              try {
77                  status = Integer.parseInt(hdrValue);
78              } catch (Throwable t) {
79                  log.warn("Exception parsing  the " + hdrName + " header. " + t.getMessage());
80              }
81              if (status > 300) {
82                  // TODO low priority: is sendRedirectNeeded for 302 or 301?
83                  if (log.isDebugEnabled()) {
84                      log.debug("setStatus to  " + status + " from " + hdrName);
85                  }
86                  if (this.isCommitted()) {
87                      log.debug("wanted to setStatus to  " + status + " from " + hdrName
88                              + " but the response is already committed");
89                  }
90                  if (sendError && status >= 400) {
91                      try {
92                          super.sendError(status);
93                      } catch (IOException e) {
94                          log.warn("Could not send error " + status + ".", e);
95                      }
96                  } else {
97                      super.setStatus(status);
98                  }
99                  // ignore the header all together after the setStatus, so
100                 // we are not leaking to the public
101 
102             } else if (status != -1) {
103                 log.debug("ignoring status header with value " + status + " from " + hdrName);
104             }
105         } else if (X_FATWIRE_HEADER.equalsIgnoreCase(hdrName)) {
106             // splitting header name/value based on passed in header value,
107             // pipe seperated;
108             String[] headers = hdrValue.split("\\|");
109             if (headers.length == 2 && headers[0] != null && headers[1] != null) {
110 
111                 super.setHeader(headers[0], headers[1]);
112             } else {
113                 log.debug(hdrName + " could not be split into something useful. " + hdrValue);
114             }
115 
116         } else {
117             super.setHeader(hdrName, hdrValue);
118         }
119 
120     }
121 
122     @Override
123     public void setStatus(int sc) {
124         if (status == -1) {
125             // only set it if we have not overridden it
126             super.setStatus(sc);
127         } else {
128             if (log.isTraceEnabled()) {
129                 log.trace("setStatus " + sc + " is being ignored because " + X_FATWIRE_STATUS + " header set it to "
130                         + status);
131             }
132 
133         }
134     }
135 
136 }// end of BufferedHttpResponseWrapper
137