/*
* Weblounge: Web Content Management System
* Copyright (c) 2003 - 2011 The Weblounge Team
* http://entwinemedia.com/weblounge
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package ch.entwine.weblounge.cache.impl;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletResponse;
/**
* In the <code>CachedResponseMetaInfo</code>, the cache stores
* <code>HTTP</code> headers that have been set in the associated
* <code>HttpServletResponse</code>.
*/
final class CacheableHttpServletResponseHeaders implements Serializable {
/** The serial version uid */
private static final long serialVersionUID = 8273352269230366714L;
/** List of custom headers */
private Map<String, String> headers = new HashMap<String, String>(5);
/** List with headers to ignore */
private static final List<String> ignoredHeaders = new ArrayList<String>();
static {
ignoredHeaders.add("content-length");
ignoredHeaders.add("etag");
ignoredHeaders.add("expires");
ignoredHeaders.add("content-type");
}
/**
* Writes the cached response headers to a new response.
*
* @param response
* the response
*/
void apply(HttpServletResponse response) {
if (response == null)
return;
for (Map.Entry<String, String> e : headers.entrySet()) {
String key = e.getKey();
int hashIndex = key.indexOf('#');
if (hashIndex > 0)
key = key.substring(hashIndex);
if (!ignoredHeaders.contains(key.toLowerCase()))
response.addHeader(key, e.getValue());
}
}
/**
* Returns <code>true</code> if the response headers contain the header with
* name <code>header</code>.
*
* @param header
* the header name
* @return <code>true</code> if the header was set
*/
boolean containsHeader(String header) {
return headers.containsKey(header);
}
/**
* Adds an <code>HTTP</code> header to the response, possibly replacing any
* existing headers with that name.
*
* @param key
* the header name
* @param value
* the header value
*/
void setHeader(String key, String value) {
headers.put(key, value);
}
/**
* Adds an <code>HTTP</code> header to the response. If a header with that
* name has already been set, then the value is added to the existing values
* for that header.
* <p>
* Note that this method will flatten those headers that have multiple values.
* Use {@link #getHeaders()} to receive them in their original form.
*
* @param key
* the header name
* @param value
* the header value
*/
void addHeader(String key, String value) {
String o = headers.get(key);
if (o == null) {
headers.put(key, value);
} else {
int i = 1;
while (true) {
String overflowKey = new StringBuffer(key).append("#").append(i).toString();
if (headers.containsKey(overflowKey)) {
i++;
continue;
}
headers.put(overflowKey, value);
break;
}
}
}
/**
* Returns the headers as they were originally added to the response.
*
* @return the headers
*/
@SuppressWarnings("unchecked")
Map<String, Object> getHeaders() {
Map<String, Object> original = new HashMap<String, Object>();
for (Map.Entry<String, String> entry : headers.entrySet()) {
String key = entry.getKey();
int hashIndex = key.indexOf('#');
if (hashIndex > 0)
key = key.substring(0, hashIndex);
if (original.containsKey(key)) {
Object value = original.get(key);
if (value instanceof List) {
((List<String>) value).add(entry.getValue());
} else {
List<String> values = new ArrayList<String>();
values.add((String)value);
values.add(entry.getValue());
value = values;
}
original.put(key, value);
} else {
original.put(key, entry.getValue());
}
}
return original;
}
/**
* Returns the number of headers.
*
* @return the number of headers
*/
public int size() {
return headers.size();
}
}