001: /**
002: * Copyright 2006 Webmedia Group Ltd.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: **/package org.araneaframework.http.filter;
016:
017: import java.lang.reflect.Method;
018: import java.util.HashMap;
019: import java.util.Iterator;
020: import java.util.Map;
021: import javax.servlet.ServletResponse;
022: import javax.servlet.ServletResponseWrapper;
023: import javax.servlet.http.Cookie;
024: import javax.servlet.http.HttpServletResponse;
025: import org.apache.commons.logging.Log;
026: import org.apache.commons.logging.LogFactory;
027: import org.araneaframework.InputData;
028: import org.araneaframework.OutputData;
029: import org.araneaframework.Path;
030: import org.araneaframework.core.AraneaRuntimeException;
031: import org.araneaframework.framework.core.BaseFilterService;
032: import org.araneaframework.http.util.ServletUtil;
033:
034: /**
035: * A filter which sets all the necessary headers of the response.
036: *
037: * @author Jevgeni Kabanov (ekabanov <i>at</i> araneaframework <i>dot</i> org)
038: */
039: public class StandardHttpResponseFilterService extends
040: BaseFilterService {
041: private static final Log log = LogFactory
042: .getLog(StandardHttpResponseFilterService.class);
043:
044: private String contentType = "text/html; charset=UTF-8";
045: private boolean cacheable = false;
046: private long cacheHoldingTime = 3600000;
047:
048: private Map cookies = new HashMap();
049: private Map headers = new HashMap();
050:
051: /**
052: * Sets if the response is cacheable or not. By default it is not cacheable.
053: */
054: public void setCacheable(boolean cacheable) {
055: this .cacheable = cacheable;
056: }
057:
058: /**
059: * Sets the content type of the response. This is a required field of the response.
060: */
061: public void setContentType(String contentType) {
062: this .contentType = contentType;
063: }
064:
065: /**
066: * Constructs cookies from the key, value pair in the map of the cookies and sets them.
067: * @param cookies
068: */
069: public void setCookies(Map cookies) {
070: this .cookies = cookies;
071: }
072:
073: /**
074: * Sets the headers of the response from the map headers. The key of the map is the name of
075: * the header and the value is the corresponding value.
076: */
077: public void setHeaders(Map headers) {
078: this .headers = headers;
079: }
080:
081: /**
082: * Sets the cache-control's max-age parameter, value is in milliseconds.
083: */
084: public void setCacheHoldingTime(long cacheHoldingTime) {
085: this .cacheHoldingTime = cacheHoldingTime;
086: }
087:
088: protected void action(Path path, InputData input, OutputData output)
089: throws Exception {
090: HttpServletResponse response = ServletUtil.getResponse(output);
091:
092: if (contentType == null) {
093: throw new AraneaRuntimeException("Content type not set!");
094: }
095:
096: response.setContentType(contentType);
097: log.trace("response.characterEncoding: "
098: + response.getCharacterEncoding());
099:
100: int idx = contentType.indexOf(';');
101: if (idx > 0) {
102: // the encoding is set, looking for the charset...
103: idx = contentType.indexOf("charset=", idx + 1);
104: if (idx > 0) {
105: String encoding = contentType.substring(idx + 8);
106: if (!encoding.equals(response.getCharacterEncoding())) {
107: // the encoding didn't change, applying hack...
108: ServletResponse r = ((ServletResponseWrapper) response)
109: .getResponse();
110: // detecting Weblogic...
111: Method method = null;
112: try {
113: method = r.getClass().getMethod("getDelegate",
114: null);
115: } catch (NoSuchMethodException e) {
116: }
117: if (method != null) {
118: log
119: .debug("Applying Weblogic hack to set the response character encoding...");
120: HttpServletResponse delegate = (HttpServletResponse) method
121: .invoke(r, null);
122: if (delegate != null) {
123: delegate.setContentType(contentType);
124: }
125: }
126: if (!encoding.equals(response
127: .getCharacterEncoding())) {
128: log
129: .warn("Unable to change the character encoding.");
130: }
131: }
132: }
133: }
134:
135: if (!cacheable) {
136: response.setHeader("Pragma", "no-cache");
137: response
138: .addHeader("Cache-Control",
139: "no-store, no-cache, must-revalidate, post-check=0, pre-check=0");
140: response.setDateHeader("Expires", 1);
141: } else {
142: response.setHeader("Cache-Control", "max-age="
143: + (cacheHoldingTime / 1000));
144: response.setDateHeader("Expires", System
145: .currentTimeMillis()
146: + cacheHoldingTime);
147: }
148:
149: for (Iterator i = headers.entrySet().iterator(); i.hasNext();) {
150: Map.Entry entry = (Map.Entry) i.next();
151: response.setHeader((String) entry.getKey(), (String) entry
152: .getValue());
153: }
154:
155: for (Iterator i = cookies.entrySet().iterator(); i.hasNext();) {
156: Map.Entry entry = (Map.Entry) i.next();
157: response.addCookie(new Cookie((String) entry.getKey(),
158: (String) entry.getValue()));
159: }
160:
161: childService._getService().action(path, input, output);
162: }
163: }
|