/** * Copyright 2005-2010 hdiv.org * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.hdiv.filter; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; import java.util.StringTokenizer; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponseWrapper; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.hdiv.util.Constants; import org.hdiv.util.HDIVUtil; /** * A wrapper for HTTP servlet response. * * @author Gorka Vicente * @see javax.servlet.http.HttpServletResponseWrapper * @since HDIV 1.1 */ public class ResponseWrapper extends HttpServletResponseWrapper { /** * Commons Logging instance. */ private static Log log = LogFactory.getLog(ResponseWrapper.class); /** * HTTP header to sent cookies */ private static final String SET_COOKIE = "Set-Cookie"; /** * The set of Cookies associated with this Response. */ private Hashtable cookies; /** * Confidentiality indicator to know if information is accessible only for those * who are authorized. */ private boolean confidentiality; /** * Indicates if cookie confidentiality is applied or not. If the value is * <code>true</code> cookie values must not be replaced by relative values. If * it is <code>false</code> they must be replaced by relative values to provide * confidentiality. */ private boolean avoidCookiesConfidentiality; /** * Constructs a response object wrapping the given response. * * @param originalResponse response */ public ResponseWrapper(HttpServletResponse originalResponse) { super(originalResponse); this.cookies = new Hashtable(); this.confidentiality = ((Boolean) HDIVUtil.getApplication().getBean("confidentiality")).booleanValue(); this.avoidCookiesConfidentiality = ((Boolean) HDIVUtil.getApplication().getBean("avoidCookiesConfidentiality")).booleanValue(); } /** * The default behavior of this method is to return setHeader(String name, String * value) on the wrapped response object. * * @param name the name of the header * @param value the header value * @see javax.servlet.http.HttpServletResponseWrapper#setHeader(java.lang.String, * java.lang.String) */ public void setHeader(String name, String value) { String confidentialValue = value; if (name.equalsIgnoreCase(SET_COOKIE)) { this.cookies.clear(); this.removeCookiesFromSession(); List parseValues = this.parseCookieString(value); if (this.confidentiality && !this.avoidCookiesConfidentiality) { confidentialValue = this.replaceOriginalValues(parseValues, value); } } super.setHeader(name, confidentialValue); } /** * The default behavior of this method is to return addHeader(String name, String * value) on the wrapped response object. * * @param name the name of the header * @param value the header value * @see javax.servlet.http.HttpServletResponseWrapper#addHeader(java.lang.String, * java.lang.String) */ public void addHeader(String name, String value) { String confidentialValue = value; if (name.equalsIgnoreCase(SET_COOKIE)) { List parseValues = this.parseCookieString(value); if (this.confidentiality && !this.avoidCookiesConfidentiality) { confidentialValue = this.replaceOriginalValues(parseValues, value); } } super.addHeader(name, confidentialValue); } /** * Replaces cookies' original values by relative values in order to provide * confidentiality. * * @param values List of the original values to be replaced * @param value Original value of the cookie to be added * @return Confidential values for the cookies */ public String replaceOriginalValues(List values, String value) { String currentValue = null; for (int i = 0; i < values.size(); i++) { currentValue = (String) values.get(i); value = value.replaceFirst("=" + currentValue, "=0"); } return value; } /** * Resets the response. */ public void reset() { super.reset(); this.cookies.clear(); this.removeCookiesFromSession(); } /** * Parses an http cookie request header and append a keyword/value pair to * <code>cookies</code> map. * * @param cookieString value assigned to Set-Cookie attribute */ private List parseCookieString(String cookieString) { List values = new ArrayList(); cookieString = cookieString.trim(); // Cookie fields are separated by ';' StringTokenizer tokens = new StringTokenizer(cookieString, ";"); while (tokens.hasMoreTokens()) { // field name is separated from value by '=' StringTokenizer t = new StringTokenizer(tokens.nextToken(), "="); String name = t.nextToken().trim(); if (t.hasMoreTokens()) { String value = t.nextToken().trim(); this.cookies.put(name, new SavedCookie(name, value)); values.add(value); } } this.updateSessionCookies(); return values; } /** * Adds the specified cookie to the response. It can be called multiple times to * set more than one cookie. * * @param The <code>Cookie</code> to return to the client * @see javax.servlet.http.HttpServletResponse#addCookie */ public void addCookie(Cookie cookie) { SavedCookie savedCookie = new SavedCookie(cookie); this.cookies.put(savedCookie.getName(), savedCookie); this.updateSessionCookies(); if (this.confidentiality && !this.avoidCookiesConfidentiality) { cookie.setValue("0"); } super.addCookie(cookie); } /** * It updates cookies stored in the user's session with the wrapper's cookies. */ private void updateSessionCookies() { if (HDIVUtil.getHttpSession() != null) { Hashtable sessionOriginalCookies = (Hashtable) HDIVUtil.getHttpSession() .getAttribute(Constants.HDIV_COOKIES_KEY); if ((sessionOriginalCookies != null) && (sessionOriginalCookies.size() > 0)) { sessionOriginalCookies.putAll(this.cookies); HDIVUtil.getHttpSession().setAttribute(Constants.HDIV_COOKIES_KEY, sessionOriginalCookies); } else { HDIVUtil.getHttpSession().setAttribute(Constants.HDIV_COOKIES_KEY, this.cookies); } } } /** * Removes from user's session the cookies added by the application. */ public void removeCookiesFromSession() { if (HDIVUtil.getHttpSession() != null) { HDIVUtil.getHttpSession().removeAttribute(Constants.HDIV_COOKIES_KEY); } } /** * Obtains all the cookies added by the application. * * @return cookies added by the application */ public Hashtable getCookies() { return this.cookies; } }