org.sakaiproject.util.ResponseHeaderFilter.java Source code

Java tutorial

Introduction

Here is the source code for org.sakaiproject.util.ResponseHeaderFilter.java

Source

/**********************************************************************************
 * $URL: https://source.sakaiproject.org/svn/kernel/trunk/api/src/main/java/org/sakaiproject/util/ResponseHeaderFilter.java $
 * $Id:  $
 ***********************************************************************************
 *
 * Copyright (c) 2010 Sakai Foundation
 *
 * Licensed under the Educational Community 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.opensource.org/licenses/ECL-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.sakaiproject.util;

import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.component.api.ServerConfigurationService;

/**
 * ResponseHeaderFilter is responsible for adding response headers to the HttpServletResponses.
 * e.g. It can be used to cache resources like *.css and *.js
 * 
 * To use the filter: 
 * Add the filter definition to the web.xml and specify the response header information 
 * in the init parameters and add the appropriate filter mapping.
 * <code>
 *    <filter>
 *      <description>Response Header Filter to enable JS caching</description>
 *      <display-name>Cache Filter For One Week</display-name>
 *      <filter-name>CacheFilterForWeek</filter-name>
 *      <filter-class>org.sakaiproject.util.ResponseHeaderFilter</filter-class>
 *      <init-param>
 *         <param-name>Cache-Control</param-name>
 *         <param-value>max-age=604800, public</param-value>
 *      </init-param>
 *   </filter>
 *   <filter-mapping>
 *      <filter-name>CacheFilterForWeek</filter-name>
 *      <url-pattern>/js/*</url-pattern>
 *   </filter-mapping>   
 * </code> 
 */
public class ResponseHeaderFilter implements Filter {

    private static Log log = LogFactory.getLog(ResponseHeaderFilter.class);

    private Map<String, String> headerMap = new ConcurrentHashMap<String, String>();

    public Map<String, String> getHeaderMap() {
        return new HashMap<String, String>(this.headerMap);
    }

    /**
     * Adds a header or replaces an existing one or clears a header if the value is null
     * 
     * @param name the header name
     * @param value the header value
     * @return the previous value associated with the name OR null if none
     * @throws IllegalArgumentException if the name is null or empty
     */
    public String addHeader(String name, String value) {
        if (name == null || "".equals(name)) {
            throw new IllegalArgumentException("header name cannot be null or blank");
        }
        if (this.headerMap != null) {
            if (value == null) {
                // remove the header value
                return this.headerMap.remove(name);
            } else {
                // add / update the header value
                return this.headerMap.put(name, value);
            }
        }
        return null;
    }

    @SuppressWarnings("unchecked")
    public void init(FilterConfig filterConfig) throws ServletException {
        String webappName = filterConfig.getServletContext().getServletContextName();
        // storing the header information in a local map
        for (Enumeration<String> paramNames = filterConfig.getInitParameterNames(); paramNames.hasMoreElements();) {
            String paramName = paramNames.nextElement();
            String paramValue = filterConfig.getInitParameter(paramName);
            if (paramName != null && paramValue != null) {
                this.headerMap.put(paramName, paramValue);
            }
        }
        // adding the configured ones from sakai config
        ServerConfigurationService serverConfigurationService = org.sakaiproject.component.cover.ServerConfigurationService
                .getInstance();
        if (serverConfigurationService != null) {
            String[] headerStrings = serverConfigurationService.getStrings("response.headers");
            if (headerStrings != null) {
                for (String headerString : headerStrings) {
                    if (headerString != null && !"".equals(headerString)) {
                        int loc = headerString.indexOf("::");
                        if (loc <= 0) {
                            log.warn("Invalid header string in sakai config (must contain '::', e.g. key::value): "
                                    + headerString);
                            continue;
                        }
                        String name = headerString.substring(0, loc);
                        if (name == null || "".equals(name)) {
                            log.warn("Invalid header string in sakai config (name must not be empty): "
                                    + headerString);
                            continue;
                        }
                        String value = null;
                        if (headerString.length() > loc + 2) {
                            value = headerString.substring(loc + 2);
                        }
                        addHeader(name, value);
                        if (value == null) {
                            log.info("Removing header (" + name + ") from all responses for current webapp: "
                                    + webappName);
                        } else {
                            log.info("Adding header (" + name + " -> " + value
                                    + ") to all responses for current webapp: " + webappName);
                        }
                    }
                }
            }
        }
        log.info("INIT: for webapp " + webappName);
    }

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        // If the response is a http servlet response add the header information 
        if (response instanceof HttpServletResponse) {
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            for (Entry<String, String> headerEntry : this.headerMap.entrySet()) {
                httpResponse.addHeader(headerEntry.getKey(), headerEntry.getValue());
            }
        }
        chain.doFilter(request, response);
    }

    public void destroy() {
        if (this.headerMap != null) {
            this.headerMap.clear();
        }
        log.info("DESTROY");
    }

}