mirror of
https://github.com/haraldk/TwelveMonkeys.git
synced 2025-10-05 13:17:12 -04:00
Merge branch 'master' of https://github.com/haraldk/TwelveMonkeys
This commit is contained in:
@@ -11,7 +11,6 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>com.twelvemonkeys.servlet</groupId>
|
||||
<artifactId>servlet</artifactId>
|
||||
<version>3.0-SNAPSHOT</version>
|
||||
<name>TwelveMonkeys :: Servlet</name>
|
||||
|
||||
<dependencies>
|
||||
@@ -77,15 +76,14 @@
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.3.1</version>
|
||||
<version>4.7</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>jmock</groupId>
|
||||
<artifactId>jmock-cglib</artifactId>
|
||||
<version>1.0.1</version>
|
||||
<scope>test</scope>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<version>1.8.5</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
|
@@ -9,41 +9,43 @@ import java.util.*;
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/AbstractServletMapAdapter.java#1 $
|
||||
* @version $Id: AbstractServletMapAdapter.java#1 $
|
||||
*/
|
||||
abstract class AbstractServletMapAdapter extends AbstractMap<String, List<String>> {
|
||||
// TODO: This map is now a little too lazy.. Should cache entries too (instead?) !
|
||||
|
||||
private final static List<String> NULL_LIST = new ArrayList<String>();
|
||||
|
||||
private transient Map<String, List<String>> mCache = new HashMap<String, List<String>>();
|
||||
private transient int mSize = -1;
|
||||
private transient AbstractSet<Entry<String, List<String>>> mEntries;
|
||||
private transient Map<String, List<String>> cache = new HashMap<String, List<String>>();
|
||||
private transient int size = -1;
|
||||
private transient AbstractSet<Entry<String, List<String>>> entries;
|
||||
|
||||
protected abstract Iterator<String> keysImpl();
|
||||
|
||||
protected abstract Iterator<String> valuesImpl(String pName);
|
||||
|
||||
@Override
|
||||
public List<String> get(Object pKey) {
|
||||
public List<String> get(final Object pKey) {
|
||||
if (pKey instanceof String) {
|
||||
return getValues((String) pKey);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private List<String> getValues(String pName) {
|
||||
List<String> values = mCache.get(pName);
|
||||
private List<String> getValues(final String pName) {
|
||||
List<String> values = cache.get(pName);
|
||||
|
||||
if (values == null) {
|
||||
//noinspection unchecked
|
||||
Iterator<String> headers = valuesImpl(pName);
|
||||
|
||||
if (headers == null) {
|
||||
mCache.put(pName, NULL_LIST);
|
||||
cache.put(pName, NULL_LIST);
|
||||
}
|
||||
else {
|
||||
values = toList(headers);
|
||||
mCache.put(pName, values);
|
||||
cache.put(pName, values);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,34 +60,35 @@ abstract class AbstractServletMapAdapter extends AbstractMap<String, List<String
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
if (mSize == -1) {
|
||||
if (size == -1) {
|
||||
computeSize();
|
||||
}
|
||||
return mSize;
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
private void computeSize() {
|
||||
Iterator<String> names = keysImpl();
|
||||
mSize = 0;
|
||||
for (;names.hasNext(); names.next()) {
|
||||
mSize++;
|
||||
size = 0;
|
||||
|
||||
for (Iterator<String> names = keysImpl(); names.hasNext(); names.next()) {
|
||||
size++;
|
||||
}
|
||||
}
|
||||
|
||||
public Set<Entry<String, List<String>>> entrySet() {
|
||||
if (mEntries == null) {
|
||||
mEntries = new AbstractSet<Entry<String, List<String>>>() {
|
||||
if (entries == null) {
|
||||
entries = new AbstractSet<Entry<String, List<String>>>() {
|
||||
public Iterator<Entry<String, List<String>>> iterator() {
|
||||
return new Iterator<Entry<String, List<String>>>() {
|
||||
Iterator<String> mHeaderNames = keysImpl();
|
||||
Iterator<String> headerNames = keysImpl();
|
||||
|
||||
public boolean hasNext() {
|
||||
return mHeaderNames.hasNext();
|
||||
return headerNames.hasNext();
|
||||
}
|
||||
|
||||
public Entry<String, List<String>> next() {
|
||||
// TODO: Replace with cached lookup
|
||||
return new HeaderEntry(mHeaderNames.next());
|
||||
return new HeaderEntry(headerNames.next());
|
||||
}
|
||||
|
||||
public void remove() {
|
||||
@@ -100,22 +103,22 @@ abstract class AbstractServletMapAdapter extends AbstractMap<String, List<String
|
||||
};
|
||||
}
|
||||
|
||||
return mEntries;
|
||||
return entries;
|
||||
}
|
||||
|
||||
private class HeaderEntry implements Entry<String, List<String>> {
|
||||
String mHeaderName;
|
||||
String headerName;
|
||||
|
||||
public HeaderEntry(String pHeaderName) {
|
||||
mHeaderName = pHeaderName;
|
||||
headerName = pHeaderName;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return mHeaderName;
|
||||
return headerName;
|
||||
}
|
||||
|
||||
public List<String> getValue() {
|
||||
return get(mHeaderName);
|
||||
return get(headerName);
|
||||
}
|
||||
|
||||
public List<String> setValue(List<String> pValue) {
|
||||
@@ -125,7 +128,7 @@ abstract class AbstractServletMapAdapter extends AbstractMap<String, List<String
|
||||
@Override
|
||||
public int hashCode() {
|
||||
List<String> value;
|
||||
return (mHeaderName == null ? 0 : mHeaderName.hashCode()) ^
|
||||
return (headerName == null ? 0 : headerName.hashCode()) ^
|
||||
((value = getValue()) == null ? 0 : value.hashCode());
|
||||
}
|
||||
|
||||
|
@@ -30,16 +30,16 @@ package com.twelvemonkeys.servlet;
|
||||
|
||||
import com.twelvemonkeys.lang.StringUtil;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.FilterChain;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.ServletResponse;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletRequestWrapper;
|
||||
import java.io.IOException;
|
||||
import java.util.Properties;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
|
||||
@@ -47,14 +47,15 @@ import java.util.regex.PatternSyntaxException;
|
||||
* BrowserHelperFilter
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/BrowserHelperFilter.java#1 $
|
||||
* @version $Id: BrowserHelperFilter.java#1 $
|
||||
*/
|
||||
public class BrowserHelperFilter extends GenericFilter {
|
||||
private static final String HTTP_HEADER_ACCEPT = "Accept";
|
||||
protected static final String HTTP_HEADER_USER_AGENT = "User-Agent";
|
||||
|
||||
private Pattern[] mKnownAgentPatterns;
|
||||
private String[] mKnownAgentAccpets;
|
||||
// TODO: Consider using unmodifiable LinkedHashMap<Pattern, String> instead
|
||||
private Pattern[] knownAgentPatterns;
|
||||
private String[] knownAgentAccepts;
|
||||
|
||||
/**
|
||||
* Sets the accept-mappings for this filter
|
||||
@@ -62,55 +63,63 @@ public class BrowserHelperFilter extends GenericFilter {
|
||||
* @throws ServletConfigException if the accept-mappings properties
|
||||
* file cannot be read.
|
||||
*/
|
||||
@InitParam(name = "accept-mappings-file")
|
||||
public void setAcceptMappingsFile(String pPropertiesFile) throws ServletConfigException {
|
||||
// NOTE: Format is:
|
||||
// <agent-name>=<reg-exp>
|
||||
// <agent-name>.accept=<http-accept-header>
|
||||
|
||||
Properties mappings = new Properties();
|
||||
|
||||
try {
|
||||
log("Reading Accept-mappings properties file: " + pPropertiesFile);
|
||||
mappings.load(getServletContext().getResourceAsStream(pPropertiesFile));
|
||||
|
||||
List<Pattern> patterns = new ArrayList<Pattern>();
|
||||
List<String> accepts = new ArrayList<String>();
|
||||
|
||||
//System.out.println("--> Loaded file: " + pPropertiesFile);
|
||||
|
||||
for (Object key : mappings.keySet()) {
|
||||
String agent = (String) key;
|
||||
if (agent.endsWith(".accept")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//System.out.println("--> Adding accept-mapping for User-Agent: " + agent);
|
||||
|
||||
try {
|
||||
String accept = (String) mappings.get(agent + ".accept");
|
||||
if (!StringUtil.isEmpty(accept)) {
|
||||
patterns.add(Pattern.compile((String) mappings.get(agent)));
|
||||
accepts.add(accept);
|
||||
//System.out.println("--> " + agent + " accepts: " + accept);
|
||||
}
|
||||
else {
|
||||
log("Missing Accept mapping for User-Agent: " + agent);
|
||||
}
|
||||
}
|
||||
catch (PatternSyntaxException e) {
|
||||
log("Could not parse User-Agent identification for " + agent, e);
|
||||
}
|
||||
|
||||
mKnownAgentPatterns = patterns.toArray(new Pattern[patterns.size()]);
|
||||
mKnownAgentAccpets = accepts.toArray(new String[accepts.size()]);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new ServletConfigException("Could not read Accept-mappings properties file: " + pPropertiesFile, e);
|
||||
}
|
||||
|
||||
parseMappings(mappings);
|
||||
}
|
||||
|
||||
private void parseMappings(Properties mappings) {
|
||||
List<Pattern> patterns = new ArrayList<Pattern>();
|
||||
List<String> accepts = new ArrayList<String>();
|
||||
|
||||
for (Object key : mappings.keySet()) {
|
||||
String agent = (String) key;
|
||||
|
||||
if (agent.endsWith(".accept")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//System.out.println("--> Adding accept-mapping for User-Agent: " + agent);
|
||||
|
||||
try {
|
||||
String accept = (String) mappings.get(agent + ".accept");
|
||||
|
||||
if (!StringUtil.isEmpty(accept)) {
|
||||
patterns.add(Pattern.compile((String) mappings.get(agent)));
|
||||
accepts.add(accept);
|
||||
//System.out.println("--> " + agent + " accepts: " + accept);
|
||||
}
|
||||
else {
|
||||
log("Missing Accept mapping for User-Agent: " + agent);
|
||||
}
|
||||
}
|
||||
catch (PatternSyntaxException e) {
|
||||
log("Could not parse User-Agent identification for " + agent, e);
|
||||
}
|
||||
|
||||
knownAgentPatterns = patterns.toArray(new Pattern[patterns.size()]);
|
||||
knownAgentAccepts = accepts.toArray(new String[accepts.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
public void init() throws ServletException {
|
||||
if (mKnownAgentAccpets == null || mKnownAgentAccpets.length == 0) {
|
||||
if (knownAgentAccepts == null || knownAgentAccepts.length == 0) {
|
||||
throw new ServletConfigException("No User-Agent/Accept mappings for filter: " + getFilterName());
|
||||
}
|
||||
}
|
||||
@@ -119,18 +128,19 @@ public class BrowserHelperFilter extends GenericFilter {
|
||||
if (pRequest instanceof HttpServletRequest) {
|
||||
//System.out.println("--> Trying to find User-Agent/Accept headers...");
|
||||
HttpServletRequest request = (HttpServletRequest) pRequest;
|
||||
|
||||
// Check if User-Agent is in list of known agents
|
||||
if (mKnownAgentPatterns != null && mKnownAgentPatterns.length > 0) {
|
||||
if (knownAgentPatterns != null && knownAgentPatterns.length > 0) {
|
||||
String agent = request.getHeader(HTTP_HEADER_USER_AGENT);
|
||||
//System.out.println("--> User-Agent: " + agent);
|
||||
|
||||
for (int i = 0; i < mKnownAgentPatterns.length; i++) {
|
||||
Pattern pattern = mKnownAgentPatterns[i];
|
||||
for (int i = 0; i < knownAgentPatterns.length; i++) {
|
||||
Pattern pattern = knownAgentPatterns[i];
|
||||
//System.out.println("--> Pattern: " + pattern);
|
||||
if (pattern.matcher(agent).matches()) {
|
||||
// TODO: Consider merge known with real accpet, in case plugins add extra capabilities?
|
||||
final String fakeAccept = mKnownAgentAccpets[i];
|
||||
|
||||
if (pattern.matcher(agent).matches()) {
|
||||
// TODO: Consider merge known with real accept, in case plugins add extra capabilities?
|
||||
final String fakeAccept = knownAgentAccepts[i];
|
||||
//System.out.println("--> User-Agent: " + agent + " accepts: " + fakeAccept);
|
||||
|
||||
pRequest = new HttpServletRequestWrapper(request) {
|
||||
@@ -138,14 +148,17 @@ public class BrowserHelperFilter extends GenericFilter {
|
||||
if (HTTP_HEADER_ACCEPT.equals(pName)) {
|
||||
return fakeAccept;
|
||||
}
|
||||
|
||||
return super.getHeader(pName);
|
||||
}
|
||||
};
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pChain.doFilter(pRequest, pResponse);
|
||||
}
|
||||
}
|
||||
|
@@ -42,10 +42,10 @@ import java.util.Enumeration;
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/DebugServlet.java#1 $
|
||||
* @version $Id: DebugServlet.java#1 $
|
||||
*/
|
||||
public class DebugServlet extends GenericServlet {
|
||||
private long mDateModified;
|
||||
private long dateModified;
|
||||
|
||||
public final void service(ServletRequest pRequest, ServletResponse pResponse) throws ServletException, IOException {
|
||||
service((HttpServletRequest) pRequest, (HttpServletResponse) pResponse);
|
||||
@@ -53,13 +53,13 @@ public class DebugServlet extends GenericServlet {
|
||||
|
||||
public void init() throws ServletException {
|
||||
super.init();
|
||||
mDateModified = System.currentTimeMillis();
|
||||
dateModified = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public void service(HttpServletRequest pRequest, HttpServletResponse pResponse) throws ServletException, IOException {
|
||||
pResponse.setContentType("text/plain");
|
||||
// Include these to allow browser caching
|
||||
pResponse.setDateHeader("Last-Modified", mDateModified);
|
||||
pResponse.setDateHeader("Last-Modified", dateModified);
|
||||
pResponse.setHeader("ETag", getServletName());
|
||||
|
||||
ServletOutputStream out = pResponse.getOutputStream();
|
||||
|
@@ -56,12 +56,12 @@ import java.util.Enumeration;
|
||||
* most basic types, if neccessary.
|
||||
* <p/>
|
||||
* To write a generic filter, you need only override the abstract
|
||||
* {@link #doFilterImpl doFilterImpl} method.
|
||||
* {@link #doFilterImpl(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)} doFilterImpl} method.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
*
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/GenericFilter.java#1 $
|
||||
* @version $Id: GenericFilter.java#1 $
|
||||
*
|
||||
* @see Filter
|
||||
* @see FilterConfig
|
||||
@@ -71,14 +71,14 @@ public abstract class GenericFilter implements Filter, FilterConfig, Serializabl
|
||||
/**
|
||||
* The filter config.
|
||||
*/
|
||||
private transient FilterConfig mFilterConfig = null;
|
||||
private transient FilterConfig filterConfig = null;
|
||||
|
||||
/**
|
||||
* Makes sure the filter runs once per request
|
||||
* <p/>
|
||||
* see #isRunOnce
|
||||
*
|
||||
* @see #mOncePerRequest
|
||||
* @see #oncePerRequest
|
||||
* see #ATTRIB_RUN_ONCE_VALUE
|
||||
*/
|
||||
private final static String ATTRIB_RUN_ONCE_EXT = ".REQUEST_HANDLED";
|
||||
@@ -90,17 +90,17 @@ public abstract class GenericFilter implements Filter, FilterConfig, Serializabl
|
||||
* <p/>
|
||||
* see #isRunOnce
|
||||
*
|
||||
* @see #mOncePerRequest
|
||||
* @see #oncePerRequest
|
||||
* see #ATTRIB_RUN_ONCE_VALUE
|
||||
*/
|
||||
private String mAttribRunOnce = null;
|
||||
private String attribRunOnce = null;
|
||||
|
||||
/**
|
||||
* Makes sure the filter runs once per request
|
||||
* <p/>
|
||||
* see #isRunOnce
|
||||
*
|
||||
* @see #mOncePerRequest
|
||||
* @see #oncePerRequest
|
||||
* see #ATTRIB_RUN_ONCE_EXT
|
||||
*/
|
||||
private static final Object ATTRIB_RUN_ONCE_VALUE = new Object();
|
||||
@@ -119,7 +119,7 @@ public abstract class GenericFilter implements Filter, FilterConfig, Serializabl
|
||||
* <pre><dispatcher>REQUEST</dispatcher></pre>
|
||||
* </em>
|
||||
*/
|
||||
protected boolean mOncePerRequest = false;
|
||||
protected boolean oncePerRequest = false;
|
||||
|
||||
/**
|
||||
* Does nothing.
|
||||
@@ -143,17 +143,17 @@ public abstract class GenericFilter implements Filter, FilterConfig, Serializabl
|
||||
* @param pConfig the filter config
|
||||
* @throws ServletException if an error occurs during init
|
||||
*
|
||||
* @see Filter#init
|
||||
* @see Filter#init(javax.servlet.FilterConfig)
|
||||
* @see #init() init
|
||||
* @see BeanUtil#configure(Object, java.util.Map, boolean)
|
||||
*/
|
||||
public void init(FilterConfig pConfig) throws ServletException {
|
||||
public void init(final FilterConfig pConfig) throws ServletException {
|
||||
if (pConfig == null) {
|
||||
throw new ServletConfigException("filterconfig == null");
|
||||
throw new ServletConfigException("filter config == null");
|
||||
}
|
||||
|
||||
// Store filterconfig
|
||||
mFilterConfig = pConfig;
|
||||
// Store filter config
|
||||
filterConfig = pConfig;
|
||||
|
||||
// Configure this
|
||||
try {
|
||||
@@ -164,8 +164,8 @@ public abstract class GenericFilter implements Filter, FilterConfig, Serializabl
|
||||
}
|
||||
|
||||
// Create run-once attribute name
|
||||
mAttribRunOnce = pConfig.getFilterName() + ATTRIB_RUN_ONCE_EXT;
|
||||
log("init (oncePerRequest=" + mOncePerRequest + ", attribRunOnce=" + mAttribRunOnce + ")");
|
||||
attribRunOnce = pConfig.getFilterName() + ATTRIB_RUN_ONCE_EXT;
|
||||
log("init (oncePerRequest=" + oncePerRequest + ", attribRunOnce=" + attribRunOnce + ")");
|
||||
init();
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ public abstract class GenericFilter implements Filter, FilterConfig, Serializabl
|
||||
* client request for a resource at the end of the chain.
|
||||
* <p/>
|
||||
* Subclasses <em>should not override this method</em>, but rather the
|
||||
* abstract {@link #doFilterImpl doFilterImpl} method.
|
||||
* abstract {@link #doFilterImpl(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)} doFilterImpl} method.
|
||||
*
|
||||
* @param pRequest the servlet request
|
||||
* @param pResponse the servlet response
|
||||
@@ -194,12 +194,12 @@ public abstract class GenericFilter implements Filter, FilterConfig, Serializabl
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*
|
||||
* @see Filter#doFilter Filter.doFilter
|
||||
* @see #doFilterImpl doFilterImpl
|
||||
* @see Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain) Filter.doFilter
|
||||
* @see #doFilterImpl(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain) doFilterImpl
|
||||
*/
|
||||
public final void doFilter(ServletRequest pRequest, ServletResponse pResponse, FilterChain pFilterChain) throws IOException, ServletException {
|
||||
// If request filter and allready run, continue chain and return fast
|
||||
if (mOncePerRequest && isRunOnce(pRequest)) {
|
||||
public final void doFilter(final ServletRequest pRequest, final ServletResponse pResponse, final FilterChain pFilterChain) throws IOException, ServletException {
|
||||
// If request filter and already run, continue chain and return fast
|
||||
if (oncePerRequest && isRunOnce(pRequest)) {
|
||||
pFilterChain.doFilter(pRequest, pResponse);
|
||||
return;
|
||||
}
|
||||
@@ -225,20 +225,20 @@ public abstract class GenericFilter implements Filter, FilterConfig, Serializabl
|
||||
* @return {@code true} if the request is allready filtered, otherwise
|
||||
* {@code false}.
|
||||
*/
|
||||
private boolean isRunOnce(ServletRequest pRequest) {
|
||||
// If request allready filtered, return true (skip)
|
||||
if (pRequest.getAttribute(mAttribRunOnce) == ATTRIB_RUN_ONCE_VALUE) {
|
||||
private boolean isRunOnce(final ServletRequest pRequest) {
|
||||
// If request already filtered, return true (skip)
|
||||
if (pRequest.getAttribute(attribRunOnce) == ATTRIB_RUN_ONCE_VALUE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Set attribute and return false (continue)
|
||||
pRequest.setAttribute(mAttribRunOnce, ATTRIB_RUN_ONCE_VALUE);
|
||||
pRequest.setAttribute(attribRunOnce, ATTRIB_RUN_ONCE_VALUE);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invoked once, or each time a request/response pair is passed through the
|
||||
* chain, depending on the {@link #mOncePerRequest} member variable.
|
||||
* chain, depending on the {@link #oncePerRequest} member variable.
|
||||
*
|
||||
* @param pRequest the servlet request
|
||||
* @param pResponse the servlet response
|
||||
@@ -247,9 +247,9 @@ public abstract class GenericFilter implements Filter, FilterConfig, Serializabl
|
||||
* @throws IOException if an I/O error occurs
|
||||
* @throws ServletException if an exception occurs during the filter process
|
||||
*
|
||||
* @see #mOncePerRequest
|
||||
* @see #doFilter doFilter
|
||||
* @see Filter#doFilter Filter.doFilter
|
||||
* @see #oncePerRequest
|
||||
* @see #doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain) doFilter
|
||||
* @see Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain) Filter.doFilter
|
||||
*/
|
||||
protected abstract void doFilterImpl(ServletRequest pRequest, ServletResponse pResponse, FilterChain pChain)
|
||||
throws IOException, ServletException;
|
||||
@@ -262,7 +262,7 @@ public abstract class GenericFilter implements Filter, FilterConfig, Serializabl
|
||||
*/
|
||||
public void destroy() {
|
||||
log("destroy");
|
||||
mFilterConfig = null;
|
||||
filterConfig = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -273,7 +273,7 @@ public abstract class GenericFilter implements Filter, FilterConfig, Serializabl
|
||||
* @see FilterConfig#getFilterName
|
||||
*/
|
||||
public String getFilterName() {
|
||||
return mFilterConfig.getFilterName();
|
||||
return filterConfig.getFilterName();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -287,7 +287,7 @@ public abstract class GenericFilter implements Filter, FilterConfig, Serializabl
|
||||
*/
|
||||
public ServletContext getServletContext() {
|
||||
// TODO: Create a servlet context wrapper that lets you log to a log4j appender?
|
||||
return mFilterConfig.getServletContext();
|
||||
return filterConfig.getServletContext();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -299,8 +299,8 @@ public abstract class GenericFilter implements Filter, FilterConfig, Serializabl
|
||||
* @return a {@code String} containing the value of the initialization
|
||||
* parameter
|
||||
*/
|
||||
public String getInitParameter(String pKey) {
|
||||
return mFilterConfig.getInitParameter(pKey);
|
||||
public String getInitParameter(final String pKey) {
|
||||
return filterConfig.getInitParameter(pKey);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -312,7 +312,7 @@ public abstract class GenericFilter implements Filter, FilterConfig, Serializabl
|
||||
* containing the mNames of the servlet's initialization parameters
|
||||
*/
|
||||
public Enumeration getInitParameterNames() {
|
||||
return mFilterConfig.getInitParameterNames();
|
||||
return filterConfig.getInitParameterNames();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -322,7 +322,7 @@ public abstract class GenericFilter implements Filter, FilterConfig, Serializabl
|
||||
* @param pMessage the log message
|
||||
* @see ServletContext#log(String)
|
||||
*/
|
||||
protected void log(String pMessage) {
|
||||
protected void log(final String pMessage) {
|
||||
getServletContext().log(getFilterName() + ": " + pMessage);
|
||||
}
|
||||
|
||||
@@ -335,7 +335,7 @@ public abstract class GenericFilter implements Filter, FilterConfig, Serializabl
|
||||
* @param pThrowable the exception
|
||||
* @see ServletContext#log(String,Throwable)
|
||||
*/
|
||||
protected void log(String pMessage, Throwable pThrowable) {
|
||||
protected void log(final String pMessage, final Throwable pThrowable) {
|
||||
getServletContext().log(getFilterName() + ": " + pMessage, pThrowable);
|
||||
}
|
||||
|
||||
@@ -347,12 +347,12 @@ public abstract class GenericFilter implements Filter, FilterConfig, Serializabl
|
||||
*
|
||||
* @deprecated For compatibility only, use {@link #init init} instead.
|
||||
*/
|
||||
public void setFilterConfig(FilterConfig pFilterConfig) {
|
||||
public void setFilterConfig(final FilterConfig pFilterConfig) {
|
||||
try {
|
||||
init(pFilterConfig);
|
||||
}
|
||||
catch (ServletException e) {
|
||||
log("Error in init(), see stacktrace for details.", e);
|
||||
log("Error in init(), see stack trace for details.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,7 +363,7 @@ public abstract class GenericFilter implements Filter, FilterConfig, Serializabl
|
||||
* @see FilterConfig
|
||||
*/
|
||||
public FilterConfig getFilterConfig() {
|
||||
return mFilterConfig;
|
||||
return filterConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -374,10 +374,10 @@ public abstract class GenericFilter implements Filter, FilterConfig, Serializabl
|
||||
*
|
||||
* @param pOncePerRequest {@code true} if the filter should run only
|
||||
* once per request
|
||||
* @see #mOncePerRequest
|
||||
* @see #oncePerRequest
|
||||
*/
|
||||
@InitParam
|
||||
public void setOncePerRequest(boolean pOncePerRequest) {
|
||||
mOncePerRequest = pOncePerRequest;
|
||||
@InitParam(name = "once-per-request")
|
||||
public void setOncePerRequest(final boolean pOncePerRequest) {
|
||||
oncePerRequest = pOncePerRequest;
|
||||
}
|
||||
}
|
||||
|
@@ -41,13 +41,13 @@ import java.lang.reflect.InvocationTargetException;
|
||||
* the method matching the signature {@code void setX(<Type>)},
|
||||
* for every init-parameter {@code x}. Both camelCase and lisp-style paramter
|
||||
* naming is supported, lisp-style names will be converted to camelCase.
|
||||
* Parameter values are automatically converted from string represenation to
|
||||
* most basic types, if neccessary.
|
||||
* Parameter values are automatically converted from string representation to
|
||||
* most basic types, if necessary.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
*
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/GenericServlet.java#1 $
|
||||
* @version $Id: GenericServlet.java#1 $
|
||||
*/
|
||||
public abstract class GenericServlet extends javax.servlet.GenericServlet {
|
||||
|
||||
@@ -70,9 +70,9 @@ public abstract class GenericServlet extends javax.servlet.GenericServlet {
|
||||
* @see BeanUtil#configure(Object, java.util.Map, boolean)
|
||||
*/
|
||||
@Override
|
||||
public void init(ServletConfig pConfig) throws ServletException {
|
||||
public void init(final ServletConfig pConfig) throws ServletException {
|
||||
if (pConfig == null) {
|
||||
throw new ServletConfigException("servletconfig == null");
|
||||
throw new ServletConfigException("servlet config == null");
|
||||
}
|
||||
|
||||
try {
|
||||
|
@@ -41,13 +41,13 @@ import java.lang.reflect.InvocationTargetException;
|
||||
* the method matching the signature {@code void setX(<Type>)},
|
||||
* for every init-parameter {@code x}. Both camelCase and lisp-style paramter
|
||||
* naming is supported, lisp-style names will be converted to camelCase.
|
||||
* Parameter values are automatically converted from string represenation to
|
||||
* most basic types, if neccessary.
|
||||
* Parameter values are automatically converted from string representation to
|
||||
* most basic types, if necessary.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
*
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/HttpServlet.java#1 $
|
||||
* @version $Id: HttpServlet.java#1 $
|
||||
*/
|
||||
public abstract class HttpServlet extends javax.servlet.http.HttpServlet {
|
||||
|
||||
@@ -63,7 +63,7 @@ public abstract class HttpServlet extends javax.servlet.http.HttpServlet {
|
||||
* have a matching setter method annotated with {@link InitParam}.
|
||||
*
|
||||
* @param pConfig the servlet config
|
||||
* @throws ServletException if an error ouccured during init
|
||||
* @throws ServletException if an error occurred during init
|
||||
*
|
||||
* @see javax.servlet.GenericServlet#init
|
||||
* @see #init() init
|
||||
@@ -72,7 +72,7 @@ public abstract class HttpServlet extends javax.servlet.http.HttpServlet {
|
||||
@Override
|
||||
public void init(ServletConfig pConfig) throws ServletException {
|
||||
if (pConfig == null) {
|
||||
throw new ServletConfigException("servletconfig == null");
|
||||
throw new ServletConfigException("servlet config == null");
|
||||
}
|
||||
|
||||
try {
|
||||
|
@@ -31,20 +31,25 @@ package com.twelvemonkeys.servlet;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Annotation to be used by serlvets/filters, to have their init-method
|
||||
* Annotation to be used by servlets/filters, to have their {@code init}-method
|
||||
* automatically convert and set values from their respective configuration.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/InitParam.java#1 $
|
||||
* @version $Id: InitParam.java#1 $
|
||||
* @see com.twelvemonkeys.servlet.ServletConfigurator
|
||||
* @see com.twelvemonkeys.servlet.GenericFilter#init(javax.servlet.FilterConfig)
|
||||
* @see com.twelvemonkeys.servlet.GenericServlet#init(javax.servlet.ServletConfig)
|
||||
* @see com.twelvemonkeys.servlet.HttpServlet#init(javax.servlet.ServletConfig)
|
||||
*/
|
||||
// TODO: Actually implement for version 3.0!
|
||||
@Documented
|
||||
@Inherited
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
@Target({ElementType.METHOD/*, TODO: ElementType.FIELD*/})
|
||||
public @interface InitParam {
|
||||
String name() default "";
|
||||
static final String UNDEFINED = "";
|
||||
String name() default UNDEFINED;
|
||||
String defaultValue() default UNDEFINED; // TODO: Consider separate annotation?
|
||||
boolean required() default false; // TODO: Consider separate annotation?
|
||||
}
|
||||
|
@@ -28,6 +28,8 @@
|
||||
|
||||
package com.twelvemonkeys.servlet;
|
||||
|
||||
import com.twelvemonkeys.lang.Validate;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
@@ -61,13 +63,13 @@ import java.io.OutputStream;
|
||||
* </pre>
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/OutputStreamAdapter.java#1 $
|
||||
* @version $Id: OutputStreamAdapter.java#1 $
|
||||
*
|
||||
*/
|
||||
public class OutputStreamAdapter extends ServletOutputStream {
|
||||
|
||||
/** The wrapped {@code OutputStream}. */
|
||||
protected final OutputStream mOut;
|
||||
protected final OutputStream out;
|
||||
|
||||
/**
|
||||
* Creates an {@code OutputStreamAdapter}.
|
||||
@@ -76,11 +78,9 @@ public class OutputStreamAdapter extends ServletOutputStream {
|
||||
*
|
||||
* @throws IllegalArgumentException if {@code pOut} is {@code null}.
|
||||
*/
|
||||
public OutputStreamAdapter(OutputStream pOut) {
|
||||
if (pOut == null) {
|
||||
throw new IllegalArgumentException("out == null");
|
||||
}
|
||||
mOut = pOut;
|
||||
public OutputStreamAdapter(final OutputStream pOut) {
|
||||
Validate.notNull(pOut, "out");
|
||||
out = pOut;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,11 +89,12 @@ public class OutputStreamAdapter extends ServletOutputStream {
|
||||
* @return the wrapped {@code OutputStream}.
|
||||
*/
|
||||
public OutputStream getOutputStream() {
|
||||
return mOut;
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "ServletOutputStream adapted from " + mOut.toString();
|
||||
return "ServletOutputStream adapted from " + out.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,20 +104,17 @@ public class OutputStreamAdapter extends ServletOutputStream {
|
||||
*
|
||||
* @throws IOException if an error occurs during writing
|
||||
*/
|
||||
public void write(int pByte)
|
||||
throws IOException {
|
||||
mOut.write(pByte);
|
||||
public void write(final int pByte) throws IOException {
|
||||
out.write(pByte);
|
||||
}
|
||||
|
||||
// Overide for efficiency
|
||||
public void write(byte pBytes[])
|
||||
throws IOException {
|
||||
mOut.write(pBytes);
|
||||
public void write(final byte pBytes[]) throws IOException {
|
||||
out.write(pBytes);
|
||||
}
|
||||
|
||||
// Overide for efficiency
|
||||
public void write(byte pBytes[], int pOff, int pLen)
|
||||
throws IOException {
|
||||
mOut.write(pBytes, pOff, pLen);
|
||||
public void write(final byte pBytes[], final int pOff, final int pLen) throws IOException {
|
||||
out.write(pBytes, pOff, pLen);
|
||||
}
|
||||
}
|
||||
|
@@ -66,16 +66,16 @@ import java.util.Enumeration;
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
*
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/ProxyServlet.java#1 $
|
||||
* @version $Id: ProxyServlet.java#1 $
|
||||
*/
|
||||
public class ProxyServlet extends GenericServlet {
|
||||
|
||||
/** Remote server host name or IP address */
|
||||
protected String mRemoteServer = null;
|
||||
protected String remoteServer = null;
|
||||
/** Remote server port */
|
||||
protected int mRemotePort = 80;
|
||||
protected int remotePort = 80;
|
||||
/** Remote server "mount" path */
|
||||
protected String mRemotePath = "";
|
||||
protected String remotePath = "";
|
||||
|
||||
private static final String HTTP_REQUEST_HEADER_HOST = "host";
|
||||
private static final String HTTP_RESPONSE_HEADER_SERVER = "server";
|
||||
@@ -88,7 +88,7 @@ public class ProxyServlet extends GenericServlet {
|
||||
* @param pRemoteServer
|
||||
*/
|
||||
public void setRemoteServer(String pRemoteServer) {
|
||||
mRemoteServer = pRemoteServer;
|
||||
remoteServer = pRemoteServer;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -99,7 +99,7 @@ public class ProxyServlet extends GenericServlet {
|
||||
*/
|
||||
public void setRemotePort(String pRemotePort) {
|
||||
try {
|
||||
mRemotePort = Integer.parseInt(pRemotePort);
|
||||
remotePort = Integer.parseInt(pRemotePort);
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
log("RemotePort must be a number!", e);
|
||||
@@ -121,7 +121,7 @@ public class ProxyServlet extends GenericServlet {
|
||||
pRemotePath = "/" + pRemotePath;
|
||||
}
|
||||
|
||||
mRemotePath = pRemotePath;
|
||||
remotePath = pRemotePath;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,7 +153,7 @@ public class ProxyServlet extends GenericServlet {
|
||||
*/
|
||||
protected void service(HttpServletRequest pRequest, HttpServletResponse pResponse) throws ServletException, IOException {
|
||||
// Sanity check configuration
|
||||
if (mRemoteServer == null) {
|
||||
if (remoteServer == null) {
|
||||
log(MESSAGE_REMOTE_SERVER_NOT_CONFIGURED);
|
||||
pResponse.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
|
||||
MESSAGE_REMOTE_SERVER_NOT_CONFIGURED);
|
||||
@@ -164,7 +164,7 @@ public class ProxyServlet extends GenericServlet {
|
||||
try {
|
||||
// Recreate request URI for remote request
|
||||
String requestURI = createRemoteRequestURI(pRequest);
|
||||
URL remoteURL = new URL(pRequest.getScheme(), mRemoteServer, mRemotePort, requestURI);
|
||||
URL remoteURL = new URL(pRequest.getScheme(), remoteServer, remotePort, requestURI);
|
||||
|
||||
// Get connection, with method from original request
|
||||
// NOTE: The actual connection is not done before we ask for streams...
|
||||
@@ -319,7 +319,7 @@ public class ProxyServlet extends GenericServlet {
|
||||
* @return a {@code String} representing the remote request URI
|
||||
*/
|
||||
private String createRemoteRequestURI(HttpServletRequest pRequest) {
|
||||
StringBuilder requestURI = new StringBuilder(mRemotePath);
|
||||
StringBuilder requestURI = new StringBuilder(remotePath);
|
||||
requestURI.append(pRequest.getPathInfo());
|
||||
|
||||
if (!StringUtil.isEmpty(pRequest.getQueryString())) {
|
||||
|
@@ -1,38 +0,0 @@
|
||||
package com.twelvemonkeys.servlet;
|
||||
|
||||
import com.twelvemonkeys.util.CollectionUtil;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Iterator;
|
||||
import java.util.Enumeration;
|
||||
|
||||
/**
|
||||
* HeaderMap
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/SerlvetParametersMapAdapter.java#1 $
|
||||
*/
|
||||
class SerlvetParametersMapAdapter extends AbstractServletMapAdapter {
|
||||
|
||||
protected final HttpServletRequest mRequest;
|
||||
|
||||
public SerlvetParametersMapAdapter(HttpServletRequest pRequest) {
|
||||
if (pRequest == null) {
|
||||
throw new IllegalArgumentException("request == null");
|
||||
}
|
||||
mRequest = pRequest;
|
||||
}
|
||||
|
||||
protected Iterator<String> valuesImpl(String pName) {
|
||||
String[] values = mRequest.getParameterValues(pName);
|
||||
return values == null ? null : CollectionUtil.iterator(values);
|
||||
}
|
||||
|
||||
protected Iterator<String> keysImpl() {
|
||||
//noinspection unchecked
|
||||
Enumeration<String> names = mRequest.getParameterNames();
|
||||
return names == null ? null : CollectionUtil.iterator(names);
|
||||
}
|
||||
|
||||
}
|
@@ -34,10 +34,12 @@ import javax.servlet.ServletException;
|
||||
* ServletConfigException.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/ServletConfigException.java#2 $
|
||||
* @version $Id: ServletConfigException.java#2 $
|
||||
*/
|
||||
public class ServletConfigException extends ServletException {
|
||||
|
||||
// TODO: Parameters for init-param at fault, and possibly servlet name?
|
||||
|
||||
/**
|
||||
* Creates a {@code ServletConfigException} with the given message.
|
||||
*
|
||||
@@ -53,11 +55,10 @@ public class ServletConfigException extends ServletException {
|
||||
* @param pMessage the exception message
|
||||
* @param pCause the exception cause
|
||||
*/
|
||||
public ServletConfigException(String pMessage, Throwable pCause) {
|
||||
public ServletConfigException(final String pMessage, final Throwable pCause) {
|
||||
super(pMessage, pCause);
|
||||
if (getCause() == null) {
|
||||
initCause(pCause);
|
||||
}
|
||||
|
||||
maybeInitCause(pCause);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,28 +66,16 @@ public class ServletConfigException extends ServletException {
|
||||
*
|
||||
* @param pCause the exception cause
|
||||
*/
|
||||
public ServletConfigException(Throwable pCause) {
|
||||
super("Erorr in Servlet configuration: " + pCause.getMessage(), pCause);
|
||||
public ServletConfigException(final Throwable pCause) {
|
||||
super(String.format("Error in Servlet configuration: %s", pCause.getMessage()), pCause);
|
||||
|
||||
maybeInitCause(pCause);
|
||||
}
|
||||
|
||||
private void maybeInitCause(Throwable pCause) {
|
||||
// Workaround for ServletExceptions that does not do proper exception chaining
|
||||
if (getCause() == null) {
|
||||
initCause(pCause);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the cause of this {@code ServletConfigException}.
|
||||
*
|
||||
* @return the cause, or {@code null} if unknown.
|
||||
* @see #getRootCause()
|
||||
*/
|
||||
// public final Throwable getCause() {
|
||||
// Throwable cause = super.getCause();
|
||||
// return cause != null ? cause : super.getRootCause();
|
||||
// }
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link #getCause()} instead.
|
||||
*/
|
||||
// public final Throwable getRootCause() {
|
||||
// return getCause();
|
||||
// }
|
||||
}
|
||||
|
@@ -29,6 +29,7 @@
|
||||
package com.twelvemonkeys.servlet;
|
||||
|
||||
import com.twelvemonkeys.lang.StringUtil;
|
||||
import com.twelvemonkeys.lang.Validate;
|
||||
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletConfig;
|
||||
@@ -44,7 +45,7 @@ import java.util.*;
|
||||
* <p/>
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/ServletConfigMapAdapter.java#2 $
|
||||
* @version $Id: ServletConfigMapAdapter.java#2 $
|
||||
*/
|
||||
class ServletConfigMapAdapter extends AbstractMap<String, String> implements Map<String, String>, Serializable, Cloneable {
|
||||
|
||||
@@ -52,51 +53,48 @@ class ServletConfigMapAdapter extends AbstractMap<String, String> implements Map
|
||||
ServletConfig, FilterConfig, ServletContext
|
||||
}
|
||||
|
||||
// private final boolean mIsServlet;
|
||||
private final ConfigType mType;
|
||||
private final ConfigType type;
|
||||
|
||||
private final ServletConfig mServletConfig;
|
||||
private final FilterConfig mFilterConfig;
|
||||
private final ServletContext mServletContext;
|
||||
private final ServletConfig servletConfig;
|
||||
private final FilterConfig filterConfig;
|
||||
private final ServletContext servletContext;
|
||||
|
||||
// Cache the entry set
|
||||
private transient Set<Entry<String, String>> mEntrySet;
|
||||
private transient Set<Entry<String, String>> entrySet;
|
||||
|
||||
public ServletConfigMapAdapter(ServletConfig pConfig) {
|
||||
public ServletConfigMapAdapter(final ServletConfig pConfig) {
|
||||
this(pConfig, ConfigType.ServletConfig);
|
||||
}
|
||||
|
||||
public ServletConfigMapAdapter(FilterConfig pConfig) {
|
||||
public ServletConfigMapAdapter(final FilterConfig pConfig) {
|
||||
this(pConfig, ConfigType.FilterConfig);
|
||||
}
|
||||
|
||||
public ServletConfigMapAdapter(ServletContext pContext) {
|
||||
public ServletConfigMapAdapter(final ServletContext pContext) {
|
||||
this(pContext, ConfigType.ServletContext);
|
||||
}
|
||||
|
||||
private ServletConfigMapAdapter(Object pConfig, ConfigType pType) {
|
||||
if (pConfig == null) {
|
||||
// Could happen of client code invokes with null reference
|
||||
throw new IllegalArgumentException("Config == null");
|
||||
}
|
||||
private ServletConfigMapAdapter(final Object pConfig, final ConfigType pType) {
|
||||
// Could happen if client code invokes with null reference
|
||||
Validate.notNull(pConfig, "config");
|
||||
|
||||
mType = pType;
|
||||
type = pType;
|
||||
|
||||
switch (mType) {
|
||||
switch (type) {
|
||||
case ServletConfig:
|
||||
mServletConfig = (ServletConfig) pConfig;
|
||||
mFilterConfig = null;
|
||||
mServletContext = null;
|
||||
servletConfig = (ServletConfig) pConfig;
|
||||
filterConfig = null;
|
||||
servletContext = null;
|
||||
break;
|
||||
case FilterConfig:
|
||||
mServletConfig = null;
|
||||
mFilterConfig = (FilterConfig) pConfig;
|
||||
mServletContext = null;
|
||||
servletConfig = null;
|
||||
filterConfig = (FilterConfig) pConfig;
|
||||
servletContext = null;
|
||||
break;
|
||||
case ServletContext:
|
||||
mServletConfig = null;
|
||||
mFilterConfig = null;
|
||||
mServletContext = (ServletContext) pConfig;
|
||||
servletConfig = null;
|
||||
filterConfig = null;
|
||||
servletContext = (ServletContext) pConfig;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Wrong type: " + pType);
|
||||
@@ -109,13 +107,13 @@ class ServletConfigMapAdapter extends AbstractMap<String, String> implements Map
|
||||
* @return the servlet or filter name
|
||||
*/
|
||||
public final String getName() {
|
||||
switch (mType) {
|
||||
switch (type) {
|
||||
case ServletConfig:
|
||||
return mServletConfig.getServletName();
|
||||
return servletConfig.getServletName();
|
||||
case FilterConfig:
|
||||
return mFilterConfig.getFilterName();
|
||||
return filterConfig.getFilterName();
|
||||
case ServletContext:
|
||||
return mServletContext.getServletContextName();
|
||||
return servletContext.getServletContextName();
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
@@ -127,67 +125,67 @@ class ServletConfigMapAdapter extends AbstractMap<String, String> implements Map
|
||||
* @return the servlet context
|
||||
*/
|
||||
public final ServletContext getServletContext() {
|
||||
switch (mType) {
|
||||
switch (type) {
|
||||
case ServletConfig:
|
||||
return mServletConfig.getServletContext();
|
||||
return servletConfig.getServletContext();
|
||||
case FilterConfig:
|
||||
return mFilterConfig.getServletContext();
|
||||
return filterConfig.getServletContext();
|
||||
case ServletContext:
|
||||
return mServletContext;
|
||||
return servletContext;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
public final Enumeration getInitParameterNames() {
|
||||
switch (mType) {
|
||||
switch (type) {
|
||||
case ServletConfig:
|
||||
return mServletConfig.getInitParameterNames();
|
||||
return servletConfig.getInitParameterNames();
|
||||
case FilterConfig:
|
||||
return mFilterConfig.getInitParameterNames();
|
||||
return filterConfig.getInitParameterNames();
|
||||
case ServletContext:
|
||||
return mServletContext.getInitParameterNames();
|
||||
return servletContext.getInitParameterNames();
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
public final String getInitParameter(final String pName) {
|
||||
switch (mType) {
|
||||
switch (type) {
|
||||
case ServletConfig:
|
||||
return mServletConfig.getInitParameter(pName);
|
||||
return servletConfig.getInitParameter(pName);
|
||||
case FilterConfig:
|
||||
return mFilterConfig.getInitParameter(pName);
|
||||
return filterConfig.getInitParameter(pName);
|
||||
case ServletContext:
|
||||
return mServletContext.getInitParameter(pName);
|
||||
return servletContext.getInitParameter(pName);
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
public Set<Entry<String, String>> entrySet() {
|
||||
if (mEntrySet == null) {
|
||||
mEntrySet = createEntrySet();
|
||||
if (entrySet == null) {
|
||||
entrySet = createEntrySet();
|
||||
}
|
||||
return mEntrySet;
|
||||
return entrySet;
|
||||
}
|
||||
|
||||
private Set<Entry<String, String>> createEntrySet() {
|
||||
return new AbstractSet<Entry<String, String>>() {
|
||||
// Cache size, if requested, -1 means not calculated
|
||||
private int mSize = -1;
|
||||
private int size = -1;
|
||||
|
||||
public Iterator<Entry<String, String>> iterator() {
|
||||
return new Iterator<Entry<String, String>>() {
|
||||
// Iterator is backed by initParameterNames enumeration
|
||||
final Enumeration mNames = getInitParameterNames();
|
||||
final Enumeration names = getInitParameterNames();
|
||||
|
||||
public boolean hasNext() {
|
||||
return mNames.hasMoreElements();
|
||||
return names.hasMoreElements();
|
||||
}
|
||||
|
||||
public Entry<String, String> next() {
|
||||
final String key = (String) mNames.nextElement();
|
||||
final String key = (String) names.nextElement();
|
||||
return new Entry<String, String>() {
|
||||
public String getKey() {
|
||||
return key;
|
||||
@@ -236,11 +234,11 @@ class ServletConfigMapAdapter extends AbstractMap<String, String> implements Map
|
||||
}
|
||||
|
||||
public int size() {
|
||||
if (mSize < 0) {
|
||||
mSize = calculateSize();
|
||||
if (size < 0) {
|
||||
size = calculateSize();
|
||||
}
|
||||
|
||||
return mSize;
|
||||
return size;
|
||||
}
|
||||
|
||||
private int calculateSize() {
|
||||
|
@@ -0,0 +1,241 @@
|
||||
package com.twelvemonkeys.servlet;
|
||||
|
||||
import com.twelvemonkeys.lang.StringUtil;
|
||||
import com.twelvemonkeys.util.FilterIterator;
|
||||
import com.twelvemonkeys.util.convert.ConversionException;
|
||||
import com.twelvemonkeys.util.convert.Converter;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletConfig;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* ServletConfigurator
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: ServletConfigurator.java,v 1.0 Apr 30, 2010 2:51:38 PM haraldk Exp$
|
||||
* @see com.twelvemonkeys.servlet.InitParam
|
||||
*/
|
||||
final class ServletConfigurator {
|
||||
// TODO: Rethink @InitParam? Allow annotation of method parameters instead? Allows setLocation(@InitParam int x, @InitParam int y)
|
||||
// TODO: At least allow field injection
|
||||
// TODO: defaultValue, required
|
||||
|
||||
private ServletConfigurator() {
|
||||
}
|
||||
|
||||
public static void configure(final Servlet pServlet, final ServletConfig pConfig) throws ServletConfigException {
|
||||
new Configurator(pServlet, pConfig.getServletName()).configure(ServletUtil.asMap(pConfig));
|
||||
}
|
||||
|
||||
public static void configure(final Filter pFilter, final FilterConfig pConfig) throws ServletConfigException {
|
||||
new Configurator(pFilter, pConfig.getFilterName()).configure(ServletUtil.asMap(pConfig));
|
||||
}
|
||||
|
||||
private static class Configurator {
|
||||
private final Object servletOrFilter;
|
||||
private final String name;
|
||||
|
||||
private Configurator(final Object servletOrFilter, final String name) {
|
||||
this.servletOrFilter = servletOrFilter;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
private void configure(final Map<String, String> pMapping) throws ServletConfigException {
|
||||
// Loop over methods with InitParam annotations
|
||||
for (Method method : annotatedMethods(servletOrFilter.getClass(), InitParam.class)) {
|
||||
assertAcceptableMethod(method);
|
||||
|
||||
// Get value or default, throw exception if missing required value
|
||||
Object value = getConfiguredValue(method, pMapping);
|
||||
|
||||
if (value != null) {
|
||||
// Inject value to this method
|
||||
try {
|
||||
method.invoke(servletOrFilter, value);
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
// We know the method is accessible, so this should never happen
|
||||
throw new Error(e);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
throw new ServletConfigException(String.format("Could not configure %s: %s", name, e.getCause().getMessage()), e.getCause());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Loop over fields with InitParam annotations
|
||||
|
||||
// TODO: Log warning for mappings not present among InitParam annotated methods?
|
||||
}
|
||||
|
||||
private Object getConfiguredValue(final Method method, final Map<String, String> mapping) throws ServletConfigException {
|
||||
InitParam initParam = method.getAnnotation(InitParam.class);
|
||||
String paramName = getParameterName(method, initParam);
|
||||
|
||||
// Get parameter value
|
||||
String stringValue = mapping.get(paramName);
|
||||
|
||||
if (stringValue == null && initParam.name().equals(InitParam.UNDEFINED)) {
|
||||
stringValue = mapping.get(StringUtil.camelToLisp(paramName));
|
||||
}
|
||||
|
||||
if (stringValue == null) {
|
||||
// InitParam support required = true and throw exception if not present in map
|
||||
if (initParam.required()) {
|
||||
throw new ServletConfigException(
|
||||
String.format(
|
||||
"Could not configure %s: Required init-parameter \"%s\" of type %s is missing",
|
||||
name, paramName, method.getParameterTypes()[0]
|
||||
)
|
||||
);
|
||||
}
|
||||
else if (!initParam.defaultValue().equals(InitParam.UNDEFINED)) {
|
||||
// Support default values
|
||||
stringValue = initParam.defaultValue();
|
||||
}
|
||||
}
|
||||
|
||||
// Convert value based on method arguments...
|
||||
return stringValue == null ? null : convertValue(method, stringValue);
|
||||
}
|
||||
|
||||
private Object convertValue(final Method method, final String stringValue) throws ServletConfigException {
|
||||
// We know it's a single parameter method
|
||||
Class<?> type = method.getParameterTypes()[0];
|
||||
|
||||
try {
|
||||
return String.class.equals(type) ? stringValue : Converter.getInstance().toObject(stringValue, type);
|
||||
}
|
||||
catch (ConversionException e) {
|
||||
throw new ServletConfigException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private String getParameterName(final Method method, final InitParam initParam) throws ServletConfigException {
|
||||
String paramName = initParam.name();
|
||||
|
||||
if (paramName.equals(InitParam.UNDEFINED)) {
|
||||
String methodName = method.getName();
|
||||
if (methodName.startsWith("set") && methodName.length() > 3) {
|
||||
paramName = Character.toLowerCase(methodName.charAt(3)) + methodName.substring(4);
|
||||
}
|
||||
else {
|
||||
throw new ServletConfigException(
|
||||
String.format(
|
||||
"Could not configure %s: InitParam annotated method must either specify name or follow Bean standard for properties (ie. setFoo => 'foo'): %s",
|
||||
name, method
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return paramName;
|
||||
}
|
||||
|
||||
private void assertAcceptableMethod(final Method method) throws ServletConfigException {
|
||||
// Try to use setAccessible, if not public
|
||||
boolean isAccessible = Modifier.isPublic(method.getModifiers());
|
||||
|
||||
if (!isAccessible) {
|
||||
try {
|
||||
method.setAccessible(true);
|
||||
isAccessible = true;
|
||||
}
|
||||
catch (SecurityException ignore) {
|
||||
// Won't be accessible, we'll fail below
|
||||
}
|
||||
}
|
||||
|
||||
if (!isAccessible || method.getReturnType() != Void.TYPE || method.getParameterTypes().length != 1) {
|
||||
throw new ServletConfigException(
|
||||
String.format(
|
||||
"Could not configure %s: InitParam annotated method must be public void and have a single parameter argument list: %s",
|
||||
name, method
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets all methods annotated with the given annotations.
|
||||
*
|
||||
* @param pClass the class to get annotated methods from
|
||||
* @param pAnnotations the annotations to test for
|
||||
* @return an iterable that allows iterating over all methods with the given annotations.
|
||||
*/
|
||||
private Iterable<Method> annotatedMethods(final Class<?> pClass, final Class<? extends Annotation>... pAnnotations) {
|
||||
return new Iterable<Method>() {
|
||||
public Iterator<Method> iterator() {
|
||||
Set<Method> methods = new LinkedHashSet<Method>();
|
||||
|
||||
Class<?> cl = pClass;
|
||||
while (cl.getSuperclass() != null) { // There's no annotations of interest on java.lang.Object
|
||||
methods.addAll(Arrays.asList(cl.getDeclaredMethods()));
|
||||
|
||||
// TODO: What about interface methods? Do we really want them?
|
||||
Class<?>[] interfaces = cl.getInterfaces();
|
||||
for (Class<?> i : interfaces) {
|
||||
methods.addAll(Arrays.asList(i.getDeclaredMethods()));
|
||||
}
|
||||
|
||||
cl = cl.getSuperclass();
|
||||
}
|
||||
|
||||
return new FilterIterator<Method>(methods.iterator(), new FilterIterator.Filter<Method>() {
|
||||
public boolean accept(final Method pMethod) {
|
||||
for (Class<? extends Annotation> annotation : pAnnotations) {
|
||||
if (!pMethod.isAnnotationPresent(annotation) || isOverriddenWithAnnotation(pMethod, annotation)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param pMethod the method to test for override
|
||||
* @param pAnnotation the annotation that must be present
|
||||
* @return {@code true} iff the method is overridden in a subclass, and has annotation
|
||||
* @see <a href="http://java.sun.com/docs/books/jls/third_edition/html/classes.html#8.4.8">The Java Language Specification: Classes: Inheritance, Overriding, and Hiding</a>
|
||||
*/
|
||||
private boolean isOverriddenWithAnnotation(final Method pMethod, final Class<? extends Annotation> pAnnotation) {
|
||||
if (Modifier.isPrivate(pMethod.getModifiers())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Class cl = pClass;
|
||||
|
||||
// Loop down up from subclass to superclass declaring the method
|
||||
while (cl != null && !pMethod.getDeclaringClass().equals(cl)) {
|
||||
try {
|
||||
Method override = cl.getDeclaredMethod(pMethod.getName(), pMethod.getParameterTypes());
|
||||
|
||||
// Overridden, test if it has the annotation present
|
||||
if (override.isAnnotationPresent(pAnnotation)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
catch (NoSuchMethodException ignore) {
|
||||
}
|
||||
|
||||
cl = cl.getSuperclass();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,5 +1,6 @@
|
||||
package com.twelvemonkeys.servlet;
|
||||
|
||||
import com.twelvemonkeys.lang.Validate;
|
||||
import com.twelvemonkeys.util.CollectionUtil;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@@ -7,33 +8,29 @@ import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* HeaderMap
|
||||
* ServletHeadersMapAdapter
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/SerlvetHeadersMapAdapter.java#1 $
|
||||
* @version $Id: ServletHeadersMapAdapter.java#1 $
|
||||
*/
|
||||
class SerlvetHeadersMapAdapter extends AbstractServletMapAdapter {
|
||||
class ServletHeadersMapAdapter extends AbstractServletMapAdapter {
|
||||
|
||||
protected final HttpServletRequest mRequest;
|
||||
protected final HttpServletRequest request;
|
||||
|
||||
public SerlvetHeadersMapAdapter(HttpServletRequest pRequest) {
|
||||
if (pRequest == null) {
|
||||
throw new IllegalArgumentException("request == null");
|
||||
}
|
||||
mRequest = pRequest;
|
||||
public ServletHeadersMapAdapter(HttpServletRequest pRequest) {
|
||||
request = Validate.notNull(pRequest, "request");
|
||||
}
|
||||
|
||||
|
||||
protected Iterator<String> valuesImpl(String pName) {
|
||||
//noinspection unchecked
|
||||
Enumeration<String> headers = mRequest.getHeaders(pName);
|
||||
Enumeration<String> headers = request.getHeaders(pName);
|
||||
return headers == null ? null : CollectionUtil.iterator(headers);
|
||||
}
|
||||
|
||||
protected Iterator<String> keysImpl() {
|
||||
//noinspection unchecked
|
||||
Enumeration<String> headerNames = mRequest.getHeaderNames();
|
||||
Enumeration<String> headerNames = request.getHeaderNames();
|
||||
return headerNames == null ? null : CollectionUtil.iterator(headerNames);
|
||||
}
|
||||
|
@@ -0,0 +1,36 @@
|
||||
package com.twelvemonkeys.servlet;
|
||||
|
||||
import com.twelvemonkeys.lang.Validate;
|
||||
import com.twelvemonkeys.util.CollectionUtil;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* ServletParametersMapAdapter
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: ServletParametersMapAdapter.java#1 $
|
||||
*/
|
||||
class ServletParametersMapAdapter extends AbstractServletMapAdapter {
|
||||
|
||||
protected final HttpServletRequest request;
|
||||
|
||||
public ServletParametersMapAdapter(HttpServletRequest pRequest) {
|
||||
request = Validate.notNull(pRequest, "request");
|
||||
}
|
||||
|
||||
protected Iterator<String> valuesImpl(String pName) {
|
||||
String[] values = request.getParameterValues(pName);
|
||||
return values == null ? null : CollectionUtil.iterator(values);
|
||||
}
|
||||
|
||||
protected Iterator<String> keysImpl() {
|
||||
//noinspection unchecked
|
||||
Enumeration<String> names = request.getParameterNames();
|
||||
return names == null ? null : CollectionUtil.iterator(names);
|
||||
}
|
||||
|
||||
}
|
@@ -28,6 +28,8 @@
|
||||
|
||||
package com.twelvemonkeys.servlet;
|
||||
|
||||
import com.twelvemonkeys.lang.Validate;
|
||||
|
||||
import javax.servlet.ServletOutputStream;
|
||||
import javax.servlet.ServletResponse;
|
||||
import java.io.IOException;
|
||||
@@ -40,47 +42,44 @@ import java.io.OutputStream;
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/ServletResponseStreamDelegate.java#2 $
|
||||
* @version $Id: ServletResponseStreamDelegate.java#2 $
|
||||
*/
|
||||
public class ServletResponseStreamDelegate {
|
||||
private Object mOut = null;
|
||||
protected final ServletResponse mResponse;
|
||||
private Object out = null;
|
||||
protected final ServletResponse response;
|
||||
|
||||
public ServletResponseStreamDelegate(ServletResponse pResponse) {
|
||||
if (pResponse == null) {
|
||||
throw new IllegalArgumentException("response == null");
|
||||
}
|
||||
mResponse = pResponse;
|
||||
response = Validate.notNull(pResponse, "response");
|
||||
}
|
||||
|
||||
// NOTE: Intentionally NOT threadsafe, as one request/response should be
|
||||
// handled by one thread ONLY.
|
||||
public final ServletOutputStream getOutputStream() throws IOException {
|
||||
if (mOut == null) {
|
||||
if (out == null) {
|
||||
OutputStream out = createOutputStream();
|
||||
mOut = out instanceof ServletOutputStream ? out : new OutputStreamAdapter(out);
|
||||
this.out = out instanceof ServletOutputStream ? out : new OutputStreamAdapter(out);
|
||||
}
|
||||
else if (mOut instanceof PrintWriter) {
|
||||
else if (out instanceof PrintWriter) {
|
||||
throw new IllegalStateException("getWriter() allready called.");
|
||||
}
|
||||
|
||||
return (ServletOutputStream) mOut;
|
||||
return (ServletOutputStream) out;
|
||||
}
|
||||
|
||||
// NOTE: Intentionally NOT threadsafe, as one request/response should be
|
||||
// handled by one thread ONLY.
|
||||
public final PrintWriter getWriter() throws IOException {
|
||||
if (mOut == null) {
|
||||
if (out == null) {
|
||||
// NOTE: getCharacterEncoding may should not return null
|
||||
OutputStream out = createOutputStream();
|
||||
String charEncoding = mResponse.getCharacterEncoding();
|
||||
mOut = new PrintWriter(charEncoding != null ? new OutputStreamWriter(out, charEncoding) : new OutputStreamWriter(out));
|
||||
String charEncoding = response.getCharacterEncoding();
|
||||
this.out = new PrintWriter(charEncoding != null ? new OutputStreamWriter(out, charEncoding) : new OutputStreamWriter(out));
|
||||
}
|
||||
else if (mOut instanceof ServletOutputStream) {
|
||||
else if (out instanceof ServletOutputStream) {
|
||||
throw new IllegalStateException("getOutputStream() allready called.");
|
||||
}
|
||||
|
||||
return (PrintWriter) mOut;
|
||||
return (PrintWriter) out;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,20 +94,20 @@ public class ServletResponseStreamDelegate {
|
||||
* @throws IOException if an I/O exception occurs
|
||||
*/
|
||||
protected OutputStream createOutputStream() throws IOException {
|
||||
return mResponse.getOutputStream();
|
||||
return response.getOutputStream();
|
||||
}
|
||||
|
||||
public void flushBuffer() throws IOException {
|
||||
if (mOut instanceof ServletOutputStream) {
|
||||
((ServletOutputStream) mOut).flush();
|
||||
if (out instanceof ServletOutputStream) {
|
||||
((ServletOutputStream) out).flush();
|
||||
}
|
||||
else if (mOut != null) {
|
||||
((PrintWriter) mOut).flush();
|
||||
else if (out != null) {
|
||||
((PrintWriter) out).flush();
|
||||
}
|
||||
}
|
||||
|
||||
public void resetBuffer() {
|
||||
// TODO: Is this okay? Probably not... :-)
|
||||
mOut = null;
|
||||
out = null;
|
||||
}
|
||||
}
|
||||
|
@@ -37,15 +37,12 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
import java.io.File;
|
||||
import java.io.PrintStream;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Date;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -56,57 +53,57 @@ import java.util.Map;
|
||||
* @author Harald Kuhr
|
||||
* @author Eirik Torske
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/ServletUtil.java#3 $
|
||||
* @version $Id: ServletUtil.java#3 $
|
||||
*/
|
||||
public final class ServletUtil {
|
||||
|
||||
/**
|
||||
* "javax.servlet.include.request_uri"
|
||||
* {@code "javax.servlet.include.request_uri"}
|
||||
*/
|
||||
private final static String ATTRIB_INC_REQUEST_URI = "javax.servlet.include.request_uri";
|
||||
|
||||
/**
|
||||
* "javax.servlet.include.context_path"
|
||||
* {@code "javax.servlet.include.context_path"}
|
||||
*/
|
||||
private final static String ATTRIB_INC_CONTEXT_PATH = "javax.servlet.include.context_path";
|
||||
|
||||
/**
|
||||
* "javax.servlet.include.servlet_path"
|
||||
* {@code "javax.servlet.include.servlet_path"}
|
||||
*/
|
||||
private final static String ATTRIB_INC_SERVLET_PATH = "javax.servlet.include.servlet_path";
|
||||
|
||||
/**
|
||||
* "javax.servlet.include.path_info"
|
||||
* {@code "javax.servlet.include.path_info"}
|
||||
*/
|
||||
private final static String ATTRIB_INC_PATH_INFO = "javax.servlet.include.path_info";
|
||||
|
||||
/**
|
||||
* "javax.servlet.include.query_string"
|
||||
* {@code "javax.servlet.include.query_string"}
|
||||
*/
|
||||
private final static String ATTRIB_INC_QUERY_STRING = "javax.servlet.include.query_string";
|
||||
|
||||
/**
|
||||
* "javax.servlet.forward.request_uri"
|
||||
* {@code "javax.servlet.forward.request_uri"}
|
||||
*/
|
||||
private final static String ATTRIB_FWD_REQUEST_URI = "javax.servlet.forward.request_uri";
|
||||
|
||||
/**
|
||||
* "javax.servlet.forward.context_path"
|
||||
* {@code "javax.servlet.forward.context_path"}
|
||||
*/
|
||||
private final static String ATTRIB_FWD_CONTEXT_PATH = "javax.servlet.forward.context_path";
|
||||
|
||||
/**
|
||||
* "javax.servlet.forward.servlet_path"
|
||||
* {@code "javax.servlet.forward.servlet_path"}
|
||||
*/
|
||||
private final static String ATTRIB_FWD_SERVLET_PATH = "javax.servlet.forward.servlet_path";
|
||||
|
||||
/**
|
||||
* "javax.servlet.forward.path_info"
|
||||
* {@code "javax.servlet.forward.path_info"}
|
||||
*/
|
||||
private final static String ATTRIB_FWD_PATH_INFO = "javax.servlet.forward.path_info";
|
||||
|
||||
/**
|
||||
* "javax.servlet.forward.query_string"
|
||||
* {@code "javax.servlet.forward.query_string"}
|
||||
*/
|
||||
private final static String ATTRIB_FWD_QUERY_STRING = "javax.servlet.forward.query_string";
|
||||
|
||||
@@ -126,10 +123,10 @@ public final class ServletUtil {
|
||||
* @return the value of the parameter, or the default value, if the
|
||||
* parameter is not set.
|
||||
*/
|
||||
public static String getParameter(ServletRequest pReq, String pName, String pDefault) {
|
||||
public static String getParameter(final ServletRequest pReq, final String pName, final String pDefault) {
|
||||
String str = pReq.getParameter(pName);
|
||||
|
||||
return ((str != null) ? str : pDefault);
|
||||
return str != null ? str : pDefault;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -148,13 +145,10 @@ public final class ServletUtil {
|
||||
* non-{@code null} and not an instance of {@code pType}
|
||||
* @throws NullPointerException if {@code pReq}, {@code pName} or
|
||||
* {@code pType} is {@code null}.
|
||||
* @todo Well, it's done. Need some thinking...
|
||||
* @todo Well, it's done. Need some thinking... We probably don't want default if conversion fails...
|
||||
* @see Converter#toObject
|
||||
*/
|
||||
|
||||
// public static T getParameter<T>(ServletRequest pReq, String pName,
|
||||
// String pFormat, T pDefault) {
|
||||
static <T> T getParameter(ServletRequest pReq, String pName, Class<T> pType, String pFormat, T pDefault) {
|
||||
static <T> T getParameter(final ServletRequest pReq, final String pName, final Class<T> pType, final String pFormat, final T pDefault) {
|
||||
// Test if pDefault is either null or instance of pType
|
||||
if (pDefault != null && !pType.isInstance(pDefault)) {
|
||||
throw new IllegalArgumentException("default value not instance of " + pType + ": " + pDefault.getClass());
|
||||
@@ -165,6 +159,7 @@ public final class ServletUtil {
|
||||
if (str == null) {
|
||||
return pDefault;
|
||||
}
|
||||
|
||||
try {
|
||||
return pType.cast(Converter.getInstance().toObject(str, pType, pFormat));
|
||||
}
|
||||
@@ -175,20 +170,20 @@ public final class ServletUtil {
|
||||
|
||||
/**
|
||||
* Gets the value of the given parameter from the request converted to
|
||||
* a boolean. If the parameter is not set or not parseable, the default
|
||||
* a {@code boolean}. If the parameter is not set or not parseable, the default
|
||||
* value is returned.
|
||||
*
|
||||
* @param pReq the servlet request
|
||||
* @param pName the parameter name
|
||||
* @param pDefault the default value
|
||||
* @return the value of the parameter converted to a boolean, or the
|
||||
* @return the value of the parameter converted to a {@code boolean}, or the
|
||||
* default value, if the parameter is not set.
|
||||
*/
|
||||
public static boolean getBooleanParameter(ServletRequest pReq, String pName, boolean pDefault) {
|
||||
public static boolean getBooleanParameter(final ServletRequest pReq, final String pName, final boolean pDefault) {
|
||||
String str = pReq.getParameter(pName);
|
||||
|
||||
try {
|
||||
return ((str != null) ? Boolean.valueOf(str) : pDefault);
|
||||
return str != null ? Boolean.valueOf(str) : pDefault;
|
||||
}
|
||||
catch (NumberFormatException nfe) {
|
||||
return pDefault;
|
||||
@@ -197,20 +192,20 @@ public final class ServletUtil {
|
||||
|
||||
/**
|
||||
* Gets the value of the given parameter from the request converted to
|
||||
* an int. If the parameter is not set or not parseable, the default
|
||||
* an {@code int}. If the parameter is not set or not parseable, the default
|
||||
* value is returned.
|
||||
*
|
||||
* @param pReq the servlet request
|
||||
* @param pName the parameter name
|
||||
* @param pDefault the default value
|
||||
* @return the value of the parameter converted to an int, or the default
|
||||
* @return the value of the parameter converted to an {@code int}, or the default
|
||||
* value, if the parameter is not set.
|
||||
*/
|
||||
public static int getIntParameter(ServletRequest pReq, String pName, int pDefault) {
|
||||
public static int getIntParameter(final ServletRequest pReq, final String pName, final int pDefault) {
|
||||
String str = pReq.getParameter(pName);
|
||||
|
||||
try {
|
||||
return ((str != null) ? Integer.parseInt(str) : pDefault);
|
||||
return str != null ? Integer.parseInt(str) : pDefault;
|
||||
}
|
||||
catch (NumberFormatException nfe) {
|
||||
return pDefault;
|
||||
@@ -219,20 +214,20 @@ public final class ServletUtil {
|
||||
|
||||
/**
|
||||
* Gets the value of the given parameter from the request converted to
|
||||
* an long. If the parameter is not set or not parseable, the default
|
||||
* an {@code long}. If the parameter is not set or not parseable, the default
|
||||
* value is returned.
|
||||
*
|
||||
* @param pReq the servlet request
|
||||
* @param pName the parameter name
|
||||
* @param pDefault the default value
|
||||
* @return the value of the parameter converted to an long, or the default
|
||||
* @return the value of the parameter converted to an {@code long}, or the default
|
||||
* value, if the parameter is not set.
|
||||
*/
|
||||
public static long getLongParameter(ServletRequest pReq, String pName, long pDefault) {
|
||||
public static long getLongParameter(final ServletRequest pReq, final String pName, final long pDefault) {
|
||||
String str = pReq.getParameter(pName);
|
||||
|
||||
try {
|
||||
return ((str != null) ? Long.parseLong(str) : pDefault);
|
||||
return str != null ? Long.parseLong(str) : pDefault;
|
||||
}
|
||||
catch (NumberFormatException nfe) {
|
||||
return pDefault;
|
||||
@@ -241,20 +236,20 @@ public final class ServletUtil {
|
||||
|
||||
/**
|
||||
* Gets the value of the given parameter from the request converted to
|
||||
* a float. If the parameter is not set or not parseable, the default
|
||||
* a {@code float}. If the parameter is not set or not parseable, the default
|
||||
* value is returned.
|
||||
*
|
||||
* @param pReq the servlet request
|
||||
* @param pName the parameter name
|
||||
* @param pDefault the default value
|
||||
* @return the value of the parameter converted to a float, or the default
|
||||
* @return the value of the parameter converted to a {@code float}, or the default
|
||||
* value, if the parameter is not set.
|
||||
*/
|
||||
public static float getFloatParameter(ServletRequest pReq, String pName, float pDefault) {
|
||||
public static float getFloatParameter(final ServletRequest pReq, final String pName, final float pDefault) {
|
||||
String str = pReq.getParameter(pName);
|
||||
|
||||
try {
|
||||
return ((str != null) ? Float.parseFloat(str) : pDefault);
|
||||
return str != null ? Float.parseFloat(str) : pDefault;
|
||||
}
|
||||
catch (NumberFormatException nfe) {
|
||||
return pDefault;
|
||||
@@ -263,20 +258,20 @@ public final class ServletUtil {
|
||||
|
||||
/**
|
||||
* Gets the value of the given parameter from the request converted to
|
||||
* a double. If the parameter is not set or not parseable, the default
|
||||
* a {@code double}. If the parameter is not set or not parseable, the default
|
||||
* value is returned.
|
||||
*
|
||||
* @param pReq the servlet request
|
||||
* @param pName the parameter name
|
||||
* @param pDefault the default value
|
||||
* @return the value of the parameter converted to n double, or the default
|
||||
* @return the value of the parameter converted to n {@code double}, or the default
|
||||
* value, if the parameter is not set.
|
||||
*/
|
||||
public static double getDoubleParameter(ServletRequest pReq, String pName, double pDefault) {
|
||||
public static double getDoubleParameter(final ServletRequest pReq, final String pName, final double pDefault) {
|
||||
String str = pReq.getParameter(pName);
|
||||
|
||||
try {
|
||||
return ((str != null) ? Double.parseDouble(str) : pDefault);
|
||||
return str != null ? Double.parseDouble(str) : pDefault;
|
||||
}
|
||||
catch (NumberFormatException nfe) {
|
||||
return pDefault;
|
||||
@@ -285,20 +280,20 @@ public final class ServletUtil {
|
||||
|
||||
/**
|
||||
* Gets the value of the given parameter from the request converted to
|
||||
* a Date. If the parameter is not set or not parseable, the
|
||||
* a {@code Date}. If the parameter is not set or not parseable, the
|
||||
* default value is returned.
|
||||
*
|
||||
* @param pReq the servlet request
|
||||
* @param pName the parameter name
|
||||
* @param pDefault the default value
|
||||
* @return the value of the parameter converted to a Date, or the
|
||||
* @return the value of the parameter converted to a {@code Date}, or the
|
||||
* default value, if the parameter is not set.
|
||||
* @see com.twelvemonkeys.lang.StringUtil#toDate(String)
|
||||
*/
|
||||
public static long getDateParameter(ServletRequest pReq, String pName, long pDefault) {
|
||||
public static long getDateParameter(final ServletRequest pReq, final String pName, final long pDefault) {
|
||||
String str = pReq.getParameter(pName);
|
||||
try {
|
||||
return ((str != null) ? StringUtil.toDate(str).getTime() : pDefault);
|
||||
return str != null ? StringUtil.toDate(str).getTime() : pDefault;
|
||||
}
|
||||
catch (IllegalArgumentException iae) {
|
||||
return pDefault;
|
||||
@@ -341,7 +336,7 @@ public final class ServletUtil {
|
||||
* @deprecated Use {@link javax.servlet.http.HttpServletRequest#getRequestURL()}
|
||||
* instead.
|
||||
*/
|
||||
static StringBuffer buildHTTPURL(HttpServletRequest pRequest) {
|
||||
static StringBuffer buildHTTPURL(final HttpServletRequest pRequest) {
|
||||
StringBuffer resultURL = new StringBuffer();
|
||||
|
||||
// Scheme, as in http, https, ftp etc
|
||||
@@ -381,7 +376,7 @@ public final class ServletUtil {
|
||||
* @see HttpServletRequest#getRequestURI
|
||||
* @since Servlet 2.2
|
||||
*/
|
||||
public static String getIncludeRequestURI(ServletRequest pRequest) {
|
||||
public static String getIncludeRequestURI(final ServletRequest pRequest) {
|
||||
return (String) pRequest.getAttribute(ATTRIB_INC_REQUEST_URI);
|
||||
}
|
||||
|
||||
@@ -395,7 +390,7 @@ public final class ServletUtil {
|
||||
* @see HttpServletRequest#getContextPath
|
||||
* @since Servlet 2.2
|
||||
*/
|
||||
public static String getIncludeContextPath(ServletRequest pRequest) {
|
||||
public static String getIncludeContextPath(final ServletRequest pRequest) {
|
||||
return (String) pRequest.getAttribute(ATTRIB_INC_CONTEXT_PATH);
|
||||
}
|
||||
|
||||
@@ -409,7 +404,7 @@ public final class ServletUtil {
|
||||
* @see HttpServletRequest#getServletPath
|
||||
* @since Servlet 2.2
|
||||
*/
|
||||
public static String getIncludeServletPath(ServletRequest pRequest) {
|
||||
public static String getIncludeServletPath(final ServletRequest pRequest) {
|
||||
return (String) pRequest.getAttribute(ATTRIB_INC_SERVLET_PATH);
|
||||
}
|
||||
|
||||
@@ -423,7 +418,7 @@ public final class ServletUtil {
|
||||
* @see HttpServletRequest#getPathInfo
|
||||
* @since Servlet 2.2
|
||||
*/
|
||||
public static String getIncludePathInfo(ServletRequest pRequest) {
|
||||
public static String getIncludePathInfo(final ServletRequest pRequest) {
|
||||
return (String) pRequest.getAttribute(ATTRIB_INC_PATH_INFO);
|
||||
}
|
||||
|
||||
@@ -437,7 +432,7 @@ public final class ServletUtil {
|
||||
* @see HttpServletRequest#getQueryString
|
||||
* @since Servlet 2.2
|
||||
*/
|
||||
public static String getIncludeQueryString(ServletRequest pRequest) {
|
||||
public static String getIncludeQueryString(final ServletRequest pRequest) {
|
||||
return (String) pRequest.getAttribute(ATTRIB_INC_QUERY_STRING);
|
||||
}
|
||||
|
||||
@@ -451,7 +446,7 @@ public final class ServletUtil {
|
||||
* @see HttpServletRequest#getRequestURI
|
||||
* @since Servlet 2.4
|
||||
*/
|
||||
public static String getForwardRequestURI(ServletRequest pRequest) {
|
||||
public static String getForwardRequestURI(final ServletRequest pRequest) {
|
||||
return (String) pRequest.getAttribute(ATTRIB_FWD_REQUEST_URI);
|
||||
}
|
||||
|
||||
@@ -465,7 +460,7 @@ public final class ServletUtil {
|
||||
* @see HttpServletRequest#getContextPath
|
||||
* @since Servlet 2.4
|
||||
*/
|
||||
public static String getForwardContextPath(ServletRequest pRequest) {
|
||||
public static String getForwardContextPath(final ServletRequest pRequest) {
|
||||
return (String) pRequest.getAttribute(ATTRIB_FWD_CONTEXT_PATH);
|
||||
}
|
||||
|
||||
@@ -479,7 +474,7 @@ public final class ServletUtil {
|
||||
* @see HttpServletRequest#getServletPath
|
||||
* @since Servlet 2.4
|
||||
*/
|
||||
public static String getForwardServletPath(ServletRequest pRequest) {
|
||||
public static String getForwardServletPath(final ServletRequest pRequest) {
|
||||
return (String) pRequest.getAttribute(ATTRIB_FWD_SERVLET_PATH);
|
||||
}
|
||||
|
||||
@@ -493,7 +488,7 @@ public final class ServletUtil {
|
||||
* @see HttpServletRequest#getPathInfo
|
||||
* @since Servlet 2.4
|
||||
*/
|
||||
public static String getForwardPathInfo(ServletRequest pRequest) {
|
||||
public static String getForwardPathInfo(final ServletRequest pRequest) {
|
||||
return (String) pRequest.getAttribute(ATTRIB_FWD_PATH_INFO);
|
||||
}
|
||||
|
||||
@@ -507,7 +502,7 @@ public final class ServletUtil {
|
||||
* @see HttpServletRequest#getQueryString
|
||||
* @since Servlet 2.4
|
||||
*/
|
||||
public static String getForwardQueryString(ServletRequest pRequest) {
|
||||
public static String getForwardQueryString(final ServletRequest pRequest) {
|
||||
return (String) pRequest.getAttribute(ATTRIB_FWD_QUERY_STRING);
|
||||
}
|
||||
|
||||
@@ -519,7 +514,7 @@ public final class ServletUtil {
|
||||
* @todo Read the spec, seems to be a mismatch with the Servlet API...
|
||||
* @see javax.servlet.http.HttpServletRequest#getServletPath()
|
||||
*/
|
||||
static String getScriptName(HttpServletRequest pRequest) {
|
||||
static String getScriptName(final HttpServletRequest pRequest) {
|
||||
String requestURI = pRequest.getRequestURI();
|
||||
return StringUtil.getLastElement(requestURI, "/");
|
||||
}
|
||||
@@ -536,11 +531,13 @@ public final class ServletUtil {
|
||||
* @param pRequest the current HTTP request
|
||||
* @return the request URI relative to the current context path.
|
||||
*/
|
||||
public static String getContextRelativeURI(HttpServletRequest pRequest) {
|
||||
public static String getContextRelativeURI(final HttpServletRequest pRequest) {
|
||||
String context = pRequest.getContextPath();
|
||||
|
||||
if (!StringUtil.isEmpty(context)) { // "" for root context
|
||||
return pRequest.getRequestURI().substring(context.length());
|
||||
}
|
||||
|
||||
return pRequest.getRequestURI();
|
||||
}
|
||||
|
||||
@@ -557,12 +554,14 @@ public final class ServletUtil {
|
||||
* @see ServletContext#getRealPath(java.lang.String)
|
||||
* @see ServletContext#getResource(java.lang.String)
|
||||
*/
|
||||
public static URL getRealURL(ServletContext pContext, String pPath) throws MalformedURLException {
|
||||
public static URL getRealURL(final ServletContext pContext, final String pPath) throws MalformedURLException {
|
||||
String realPath = pContext.getRealPath(pPath);
|
||||
|
||||
if (realPath != null) {
|
||||
// NOTE: First convert to URI, as of Java 6 File.toURL is deprecated
|
||||
return new File(realPath).toURI().toURL();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -572,20 +571,19 @@ public final class ServletUtil {
|
||||
* @param pContext the servlet context
|
||||
* @return the temp directory
|
||||
*/
|
||||
public static File getTempDir(ServletContext pContext) {
|
||||
public static File getTempDir(final ServletContext pContext) {
|
||||
return (File) pContext.getAttribute("javax.servlet.context.tempdir");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the identificator string containing the unique identifier assigned
|
||||
* to this session.
|
||||
* Gets the unique identifier assigned to this session.
|
||||
* The identifier is assigned by the servlet container and is implementation
|
||||
* dependent.
|
||||
*
|
||||
* @param pRequest The HTTP servlet request object.
|
||||
* @return the session Id
|
||||
*/
|
||||
public static String getSessionId(HttpServletRequest pRequest) {
|
||||
public static String getSessionId(final HttpServletRequest pRequest) {
|
||||
HttpSession session = pRequest.getSession();
|
||||
|
||||
return (session != null) ? session.getId() : null;
|
||||
@@ -598,11 +596,11 @@ public final class ServletUtil {
|
||||
* operations and iterating over it's {@code keySet}.
|
||||
* For other operations it may not perform well.</small>
|
||||
*
|
||||
* @param pConfig the serlvet configuration
|
||||
* @param pConfig the servlet configuration
|
||||
* @return a {@code Map} view of the config
|
||||
* @throws IllegalArgumentException if {@code pConfig} is {@code null}
|
||||
*/
|
||||
public static Map<String, String> asMap(ServletConfig pConfig) {
|
||||
public static Map<String, String> asMap(final ServletConfig pConfig) {
|
||||
return new ServletConfigMapAdapter(pConfig);
|
||||
}
|
||||
|
||||
@@ -617,7 +615,7 @@ public final class ServletUtil {
|
||||
* @return a {@code Map} view of the config
|
||||
* @throws IllegalArgumentException if {@code pConfig} is {@code null}
|
||||
*/
|
||||
public static Map<String, String> asMap(FilterConfig pConfig) {
|
||||
public static Map<String, String> asMap(final FilterConfig pConfig) {
|
||||
return new ServletConfigMapAdapter(pConfig);
|
||||
}
|
||||
|
||||
@@ -636,6 +634,13 @@ public final class ServletUtil {
|
||||
return new ServletConfigMapAdapter(pContext);
|
||||
}
|
||||
|
||||
// TODO?
|
||||
// public static Map<String, ?> attributesAsMap(final ServletContext pContext) {
|
||||
// }
|
||||
//
|
||||
// public static Map<String, ?> attributesAsMap(final ServletRequest pRequest) {
|
||||
// }
|
||||
//
|
||||
/**
|
||||
* Creates an unmodifiable {@code Map} view of the given
|
||||
* {@code HttpServletRequest}s request parameters.
|
||||
@@ -645,7 +650,7 @@ public final class ServletUtil {
|
||||
* @throws IllegalArgumentException if {@code pRequest} is {@code null}
|
||||
*/
|
||||
public static Map<String, List<String>> parametersAsMap(final HttpServletRequest pRequest) {
|
||||
return new SerlvetParametersMapAdapter(pRequest);
|
||||
return new ServletParametersMapAdapter(pRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -657,7 +662,7 @@ public final class ServletUtil {
|
||||
* @throws IllegalArgumentException if {@code pRequest} is {@code null}
|
||||
*/
|
||||
public static Map<String, List<String>> headersAsMap(final HttpServletRequest pRequest) {
|
||||
return new SerlvetHeadersMapAdapter(pRequest);
|
||||
return new ServletHeadersMapAdapter(pRequest);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -700,329 +705,22 @@ public final class ServletUtil {
|
||||
return pImplementation;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Prints the init parameters in a {@code javax.servlet.ServletConfig}
|
||||
* object to a {@code java.io.PrintStream}.
|
||||
* <p/>
|
||||
*
|
||||
* @param pServletConfig The Servlet Config object.
|
||||
* @param pPrintStream The {@code java.io.PrintStream} for flushing
|
||||
* the results.
|
||||
*/
|
||||
public static void printDebug(final ServletConfig pServletConfig, final PrintStream pPrintStream) {
|
||||
Enumeration parameterNames = pServletConfig.getInitParameterNames();
|
||||
|
||||
while (parameterNames.hasMoreElements()) {
|
||||
String initParameterName = (String) parameterNames.nextElement();
|
||||
|
||||
pPrintStream.println(initParameterName + ": " + pServletConfig.getInitParameter(initParameterName));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the init parameters in a {@code javax.servlet.ServletConfig}
|
||||
* object to {@code System.out}.
|
||||
*
|
||||
* @param pServletConfig the Servlet Config object.
|
||||
*/
|
||||
public static void printDebug(final ServletConfig pServletConfig) {
|
||||
printDebug(pServletConfig, System.out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the init parameters in a {@code javax.servlet.ServletContext}
|
||||
* object to a {@code java.io.PrintStream}.
|
||||
*
|
||||
* @param pServletContext the Servlet Context object.
|
||||
* @param pPrintStream the {@code java.io.PrintStream} for flushing the
|
||||
* results.
|
||||
*/
|
||||
public static void printDebug(final ServletContext pServletContext, final PrintStream pPrintStream) {
|
||||
Enumeration parameterNames = pServletContext.getInitParameterNames();
|
||||
|
||||
while (parameterNames.hasMoreElements()) {
|
||||
String initParameterName = (String) parameterNames.nextElement();
|
||||
|
||||
pPrintStream.println(initParameterName + ": " + pServletContext.getInitParameter(initParameterName));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints the init parameters in a {@code javax.servlet.ServletContext}
|
||||
* object to {@code System.out}.
|
||||
*
|
||||
* @param pServletContext The Servlet Context object.
|
||||
*/
|
||||
public static void printDebug(final ServletContext pServletContext) {
|
||||
printDebug(pServletContext, System.out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints an excerpt of the residing information in a
|
||||
* {@code javax.servlet.http.HttpServletRequest} object to a
|
||||
* {@code java.io.PrintStream}.
|
||||
*
|
||||
* @param pRequest The HTTP servlet request object.
|
||||
* @param pPrintStream The {@code java.io.PrintStream} for flushing
|
||||
* the results.
|
||||
*/
|
||||
public static void printDebug(final HttpServletRequest pRequest, final PrintStream pPrintStream) {
|
||||
String indentation = " ";
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
|
||||
// Returns the name of the authentication scheme used to protect the
|
||||
// servlet, for example, "BASIC" or "SSL," or null if the servlet was
|
||||
// not protected.
|
||||
buffer.append(indentation);
|
||||
buffer.append("Authentication scheme: ");
|
||||
buffer.append(pRequest.getAuthType());
|
||||
buffer.append("\n");
|
||||
|
||||
// Returns the portion of the request URI that indicates the context
|
||||
// of the request.
|
||||
buffer.append(indentation);
|
||||
buffer.append("Context path: ");
|
||||
buffer.append(pRequest.getContextPath());
|
||||
buffer.append("\n");
|
||||
|
||||
// Returns an enumeration of all the header mNames this request contains.
|
||||
buffer.append(indentation);
|
||||
buffer.append("Header:");
|
||||
buffer.append("\n");
|
||||
Enumeration headerNames = pRequest.getHeaderNames();
|
||||
|
||||
while (headerNames.hasMoreElements()) {
|
||||
String headerElement = (String) headerNames.nextElement();
|
||||
|
||||
buffer.append(indentation);
|
||||
buffer.append(indentation);
|
||||
buffer.append(headerElement);
|
||||
buffer.append(": ");
|
||||
buffer.append(pRequest.getHeader(headerElement));
|
||||
buffer.append("\n");
|
||||
}
|
||||
|
||||
// Returns the name of the HTTP method with which this request was made,
|
||||
// for example, GET, POST, or PUT.
|
||||
buffer.append(indentation);
|
||||
buffer.append("HTTP method: ");
|
||||
buffer.append(pRequest.getMethod());
|
||||
buffer.append("\n");
|
||||
|
||||
// Returns any extra path information associated with the URL the client
|
||||
// sent when it made this request.
|
||||
buffer.append(indentation);
|
||||
buffer.append("Extra path information from client: ");
|
||||
buffer.append(pRequest.getPathInfo());
|
||||
buffer.append("\n");
|
||||
|
||||
// Returns any extra path information after the servlet name but before
|
||||
// the query string, and translates it to a real path.
|
||||
buffer.append(indentation);
|
||||
buffer.append("Extra translated path information from client: ");
|
||||
buffer.append(pRequest.getPathTranslated());
|
||||
buffer.append("\n");
|
||||
|
||||
// Returns the login of the user making this request, if the user has
|
||||
// been authenticated, or null if the user has not been authenticated.
|
||||
buffer.append(indentation);
|
||||
String userInfo = pRequest.getRemoteUser();
|
||||
|
||||
if (StringUtil.isEmpty(userInfo)) {
|
||||
buffer.append("User is not authenticated");
|
||||
}
|
||||
else {
|
||||
buffer.append("User logint: ");
|
||||
buffer.append(userInfo);
|
||||
}
|
||||
buffer.append("\n");
|
||||
|
||||
// Returns the session ID specified by the client.
|
||||
buffer.append(indentation);
|
||||
buffer.append("Session ID from client: ");
|
||||
buffer.append(pRequest.getRequestedSessionId());
|
||||
buffer.append("\n");
|
||||
|
||||
// Returns the server name.
|
||||
buffer.append(indentation);
|
||||
buffer.append("Server name: ");
|
||||
buffer.append(pRequest.getServerName());
|
||||
buffer.append("\n");
|
||||
|
||||
// Returns the part of this request's URL from the protocol name up
|
||||
// to the query string in the first line of the HTTP request.
|
||||
buffer.append(indentation);
|
||||
buffer.append("Request URI: ").append(pRequest.getRequestURI());
|
||||
buffer.append("\n");
|
||||
|
||||
// Returns the path info.
|
||||
buffer.append(indentation);
|
||||
buffer.append("Path information: ").append(pRequest.getPathInfo());
|
||||
buffer.append("\n");
|
||||
|
||||
// Returns the part of this request's URL that calls the servlet.
|
||||
buffer.append(indentation);
|
||||
buffer.append("Servlet path: ").append(pRequest.getServletPath());
|
||||
buffer.append("\n");
|
||||
|
||||
// Returns the query string that is contained in the request URL after
|
||||
// the path.
|
||||
buffer.append(indentation);
|
||||
buffer.append("Query string: ").append(pRequest.getQueryString());
|
||||
buffer.append("\n");
|
||||
|
||||
// Returns an enumeration of all the parameters bound to this request.
|
||||
buffer.append(indentation);
|
||||
buffer.append("Parameters:");
|
||||
buffer.append("\n");
|
||||
Enumeration parameterNames = pRequest.getParameterNames();
|
||||
while (parameterNames.hasMoreElements()) {
|
||||
String parameterName = (String) parameterNames.nextElement();
|
||||
|
||||
buffer.append(indentation);
|
||||
buffer.append(indentation);
|
||||
buffer.append(parameterName);
|
||||
buffer.append(": ");
|
||||
buffer.append(pRequest.getParameter(parameterName));
|
||||
buffer.append("\n");
|
||||
}
|
||||
|
||||
// Returns an enumeration of all the attribute objects bound to this
|
||||
// request.
|
||||
buffer.append(indentation);
|
||||
buffer.append("Attributes:");
|
||||
buffer.append("\n");
|
||||
Enumeration attributeNames = pRequest.getAttributeNames();
|
||||
while (attributeNames.hasMoreElements()) {
|
||||
String attributeName = (String) attributeNames.nextElement();
|
||||
|
||||
buffer.append(indentation);
|
||||
buffer.append(indentation);
|
||||
buffer.append(attributeName);
|
||||
buffer.append(": ");
|
||||
buffer.append(pRequest.getAttribute(attributeName).toString());
|
||||
buffer.append("\n");
|
||||
}
|
||||
pPrintStream.println(buffer.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints an excerpt of the residing information in a
|
||||
* {@code javax.servlet.http.HttpServletRequest} object to
|
||||
* {@code System.out}.
|
||||
*
|
||||
* @param pRequest The HTTP servlet request object.
|
||||
*/
|
||||
public static void printDebug(final HttpServletRequest pRequest) {
|
||||
printDebug(pRequest, System.out);
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints an excerpt of a {@code javax.servlet.http.HttpSession} object
|
||||
* to a {@code java.io.PrintStream}.
|
||||
*
|
||||
* @param pHttpSession The HTTP Session object.
|
||||
* @param pPrintStream The {@code java.io.PrintStream} for flushing
|
||||
* the results.
|
||||
*/
|
||||
public static void printDebug(final HttpSession pHttpSession, final PrintStream pPrintStream) {
|
||||
String indentation = " ";
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
|
||||
if (pHttpSession == null) {
|
||||
buffer.append(indentation);
|
||||
buffer.append("No session object available");
|
||||
buffer.append("\n");
|
||||
}
|
||||
else {
|
||||
|
||||
// Returns a string containing the unique identifier assigned to
|
||||
//this session
|
||||
buffer.append(indentation);
|
||||
buffer.append("Session ID: ").append(pHttpSession.getId());
|
||||
buffer.append("\n");
|
||||
|
||||
// Returns the last time the client sent a request associated with
|
||||
// this session, as the number of milliseconds since midnight
|
||||
// January 1, 1970 GMT, and marked by the time the container
|
||||
// recieved the request
|
||||
buffer.append(indentation);
|
||||
buffer.append("Last accessed time: ");
|
||||
buffer.append(new Date(pHttpSession.getLastAccessedTime()));
|
||||
buffer.append("\n");
|
||||
|
||||
// Returns the time when this session was created, measured in
|
||||
// milliseconds since midnight January 1, 1970 GMT
|
||||
buffer.append(indentation);
|
||||
buffer.append("Creation time: ");
|
||||
buffer.append(new Date(pHttpSession.getCreationTime()));
|
||||
buffer.append("\n");
|
||||
|
||||
// Returns true if the client does not yet know about the session
|
||||
// or if the client chooses not to join the session
|
||||
buffer.append(indentation);
|
||||
buffer.append("New session?: ");
|
||||
buffer.append(pHttpSession.isNew());
|
||||
buffer.append("\n");
|
||||
|
||||
// Returns the maximum time interval, in seconds, that the servlet
|
||||
// container will keep this session open between client accesses
|
||||
buffer.append(indentation);
|
||||
buffer.append("Max inactive interval: ");
|
||||
buffer.append(pHttpSession.getMaxInactiveInterval());
|
||||
buffer.append("\n");
|
||||
|
||||
// Returns an enumeration of all the attribute objects bound to
|
||||
// this session
|
||||
buffer.append(indentation);
|
||||
buffer.append("Attributes:");
|
||||
buffer.append("\n");
|
||||
Enumeration attributeNames = pHttpSession.getAttributeNames();
|
||||
|
||||
while (attributeNames.hasMoreElements()) {
|
||||
String attributeName = (String) attributeNames.nextElement();
|
||||
|
||||
buffer.append(indentation);
|
||||
buffer.append(indentation);
|
||||
buffer.append(attributeName);
|
||||
buffer.append(": ");
|
||||
buffer.append(pHttpSession.getAttribute(attributeName).toString());
|
||||
buffer.append("\n");
|
||||
}
|
||||
}
|
||||
pPrintStream.println(buffer.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints an excerpt of a {@code javax.servlet.http.HttpSession}
|
||||
* object to {@code System.out}.
|
||||
* <p/>
|
||||
*
|
||||
* @param pHttpSession The HTTP Session object.
|
||||
*/
|
||||
public static void printDebug(final HttpSession pHttpSession) {
|
||||
printDebug(pHttpSession, System.out);
|
||||
}
|
||||
|
||||
private static class HttpServletResponseHandler implements InvocationHandler {
|
||||
private ServletResponse mResponse;
|
||||
private HttpServletResponse mHttpResponse;
|
||||
private final ServletResponseWrapper response;
|
||||
|
||||
HttpServletResponseHandler(ServletResponseWrapper pResponse) {
|
||||
mResponse = pResponse;
|
||||
mHttpResponse = (HttpServletResponse) pResponse.getResponse();
|
||||
HttpServletResponseHandler(final ServletResponseWrapper pResponse) {
|
||||
response = pResponse;
|
||||
}
|
||||
|
||||
public Object invoke(Object pProxy, Method pMethod, Object[] pArgs) throws Throwable {
|
||||
public Object invoke(final Object pProxy, final Method pMethod, final Object[] pArgs) throws Throwable {
|
||||
try {
|
||||
if (pMethod.getDeclaringClass().isInstance(mResponse)) {
|
||||
//System.out.println("Invoking " + pMethod + " on wrapper");
|
||||
return pMethod.invoke(mResponse, pArgs);
|
||||
// TODO: Allow partial implementing?
|
||||
if (pMethod.getDeclaringClass().isInstance(response)) {
|
||||
return pMethod.invoke(response, pArgs);
|
||||
}
|
||||
|
||||
// Method is not implemented in wrapper
|
||||
//System.out.println("Invoking " + pMethod + " on wrapped object");
|
||||
return pMethod.invoke(mHttpResponse, pArgs);
|
||||
return pMethod.invoke(response.getResponse(), pArgs);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
// Unwrap, to avoid UndeclaredThrowableException...
|
||||
@@ -1032,23 +730,21 @@ public final class ServletUtil {
|
||||
}
|
||||
|
||||
private static class HttpServletRequestHandler implements InvocationHandler {
|
||||
private ServletRequest mRequest;
|
||||
private HttpServletRequest mHttpRequest;
|
||||
private final ServletRequestWrapper request;
|
||||
|
||||
HttpServletRequestHandler(ServletRequestWrapper pRequest) {
|
||||
mRequest = pRequest;
|
||||
mHttpRequest = (HttpServletRequest) pRequest.getRequest();
|
||||
HttpServletRequestHandler(final ServletRequestWrapper pRequest) {
|
||||
request = pRequest;
|
||||
}
|
||||
|
||||
public Object invoke(Object pProxy, Method pMethod, Object[] pArgs) throws Throwable {
|
||||
public Object invoke(final Object pProxy, final Method pMethod, final Object[] pArgs) throws Throwable {
|
||||
try {
|
||||
if (pMethod.getDeclaringClass().isInstance(mRequest)) {
|
||||
//System.out.println("Invoking " + pMethod + " on wrapper");
|
||||
return pMethod.invoke(mRequest, pArgs);
|
||||
// TODO: Allow partial implementing?
|
||||
if (pMethod.getDeclaringClass().isInstance(request)) {
|
||||
return pMethod.invoke(request, pArgs);
|
||||
}
|
||||
|
||||
// Method is not implemented in wrapper
|
||||
//System.out.println("Invoking " + pMethod + " on wrapped object");
|
||||
return pMethod.invoke(mHttpRequest, pArgs);
|
||||
return pMethod.invoke(request.getRequest(), pArgs);
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
// Unwrap, to avoid UndeclaredThrowableException...
|
||||
|
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* Copyright (c) 2011, Harald Kuhr
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name "TwelveMonkeys" nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.servlet;
|
||||
|
||||
import com.twelvemonkeys.io.FileUtil;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* A minimal servlet that can serve static files. Also from outside the web application.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: StaticContentServlet.java,v 1.0 12.12.11 15:09 haraldk Exp$
|
||||
*
|
||||
* @see #setRoot(java.io.File)
|
||||
*/
|
||||
public final class StaticContentServlet extends HttpServlet {
|
||||
|
||||
private File root;
|
||||
|
||||
/**
|
||||
* Configures the file system {@code root} for this servlet.
|
||||
* If {@code root} is a directory, files will be served relative to the directory.
|
||||
* If {@code root} is a file, only this file may be served
|
||||
*
|
||||
* @param root the file system root.
|
||||
*/
|
||||
@InitParam(name = "root")
|
||||
public void setRoot(final File root) {
|
||||
this.root = root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() throws ServletException {
|
||||
if (root == null) {
|
||||
throw new ServletConfigException("File system root not configured, check 'root' init-param");
|
||||
}
|
||||
else if (!root.exists()) {
|
||||
throw new ServletConfigException(
|
||||
String.format("File system root '%s' does not exist, check 'root' init-param", root.getAbsolutePath())
|
||||
);
|
||||
}
|
||||
|
||||
log(String.format("Serving %s '%s'", root.isDirectory() ? "files from directory" : "single file", root.getAbsolutePath()));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected long getLastModified(final HttpServletRequest request) {
|
||||
File file = findFileForRequest(request);
|
||||
|
||||
return file.exists() ? file.lastModified() : -1L;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws IOException {
|
||||
File file = findFileForRequest(request);
|
||||
|
||||
if (file.isFile() && file.canRead()) {
|
||||
// Normal file, all ok
|
||||
response.setStatus(HttpServletResponse.SC_OK);
|
||||
String contentType = getServletContext().getMimeType(file.getName());
|
||||
response.setContentType(contentType != null ? contentType : "application/octet-stream");
|
||||
if (file.length() <= Integer.MAX_VALUE) {
|
||||
response.setContentLength((int) file.length());
|
||||
}
|
||||
else {
|
||||
response.setHeader("Content-Length", String.valueOf(file.length()));
|
||||
}
|
||||
response.setDateHeader("Last-Modified", file.lastModified());
|
||||
|
||||
InputStream in = new FileInputStream(file);
|
||||
|
||||
try {
|
||||
FileUtil.copy(in, response.getOutputStream());
|
||||
}
|
||||
finally {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (file.exists()) {
|
||||
// Attempted directory listing or non-readable file
|
||||
response.sendError(HttpServletResponse.SC_FORBIDDEN, request.getRequestURI());
|
||||
}
|
||||
else {
|
||||
// No such file
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND, request.getRequestURI());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private File findFileForRequest(final HttpServletRequest request) {
|
||||
String relativePath = request.getPathInfo();
|
||||
|
||||
return relativePath != null ? new File(root, relativePath) : root;
|
||||
}
|
||||
}
|
@@ -46,19 +46,16 @@ import java.util.Map;
|
||||
|
||||
/**
|
||||
* ThrottleFilter, a filter for easing server during heavy load.
|
||||
* <!--
|
||||
* Renamed from LoadShutoffFilter...
|
||||
* Happened to be listening to Xploding Plastix' Shakedown Shutoff at the time..
|
||||
* -->
|
||||
* Intercepts requests, and returns HTTP response code 503
|
||||
* (Service Unavailable), if there are more than a given number of concurrent
|
||||
* <p/>
|
||||
* Intercepts requests, and returns HTTP response code {@code 503 (Service Unavailable)},
|
||||
* if there are more than a given number of concurrent
|
||||
* requests, to avoid large backlogs. The number of concurrent requests and the
|
||||
* response messages sent to the user agent, is configurable from the web
|
||||
* descriptor.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/ThrottleFilter.java#1 $
|
||||
* @version $Id: ThrottleFilter.java#1 $
|
||||
* @see #setMaxConcurrentThreadCount
|
||||
* @see #setResponseMessages
|
||||
*/
|
||||
@@ -67,13 +64,13 @@ public class ThrottleFilter extends GenericFilter {
|
||||
/**
|
||||
* Minimum free thread count, defaults to {@code 10}
|
||||
*/
|
||||
protected int mMaxConcurrentThreadCount = 10;
|
||||
protected int maxConcurrentThreadCount = 10;
|
||||
|
||||
/**
|
||||
* The number of running request threads
|
||||
*/
|
||||
private int mRunningThreads = 0;
|
||||
private final Object mRunningThreadsLock = new Object();
|
||||
private int runningThreads = 0;
|
||||
private final Object runningThreadsLock = new Object();
|
||||
|
||||
/**
|
||||
* Default response message sent to user agents, if the request is rejected
|
||||
@@ -89,17 +86,17 @@ public class ThrottleFilter extends GenericFilter {
|
||||
/**
|
||||
* The reposne message sent to user agenta, if the request is rejected
|
||||
*/
|
||||
private Map mResponseMessageNames = new HashMap(10);
|
||||
private Map<String, String> responseMessageNames = new HashMap<String, String>(10);
|
||||
|
||||
/**
|
||||
* The reposne message sent to user agents, if the request is rejected
|
||||
*/
|
||||
private String[] mResponseMessageTypes = null;
|
||||
private String[] responseMessageTypes = null;
|
||||
|
||||
/**
|
||||
* Cache for response messages
|
||||
*/
|
||||
private Map mResponseCache = new HashMap(10);
|
||||
private Map<String, CacheEntry> responseCache = new HashMap<String, CacheEntry>(10);
|
||||
|
||||
|
||||
/**
|
||||
@@ -110,7 +107,7 @@ public class ThrottleFilter extends GenericFilter {
|
||||
public void setMaxConcurrentThreadCount(String pMaxConcurrentThreadCount) {
|
||||
if (!StringUtil.isEmpty(pMaxConcurrentThreadCount)) {
|
||||
try {
|
||||
mMaxConcurrentThreadCount = Integer.parseInt(pMaxConcurrentThreadCount);
|
||||
maxConcurrentThreadCount = Integer.parseInt(pMaxConcurrentThreadCount);
|
||||
}
|
||||
catch (NumberFormatException nfe) {
|
||||
// Use default
|
||||
@@ -133,23 +130,24 @@ public class ThrottleFilter extends GenericFilter {
|
||||
public void setResponseMessages(String pResponseMessages) {
|
||||
// Split string in type=filename pairs
|
||||
String[] mappings = StringUtil.toStringArray(pResponseMessages, ", \r\n\t");
|
||||
List types = new ArrayList();
|
||||
List<String> types = new ArrayList<String>();
|
||||
|
||||
for (int i = 0; i < mappings.length; i++) {
|
||||
for (String pair : mappings) {
|
||||
// Split pairs on '='
|
||||
String[] mapping = StringUtil.toStringArray(mappings[i], "= ");
|
||||
String[] mapping = StringUtil.toStringArray(pair, "= ");
|
||||
|
||||
// Test for wrong mapping
|
||||
if ((mapping == null) || (mapping.length < 2)) {
|
||||
log("Error in init param \"responseMessages\": " + pResponseMessages);
|
||||
continue;
|
||||
}
|
||||
|
||||
types.add(mapping[0]);
|
||||
mResponseMessageNames.put(mapping[0], mapping[1]);
|
||||
responseMessageNames.put(mapping[0], mapping[1]);
|
||||
}
|
||||
|
||||
// Create arrays
|
||||
mResponseMessageTypes = (String[]) types.toArray(new String[types.size()]);
|
||||
responseMessageTypes = types.toArray(new String[types.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,8 +157,7 @@ public class ThrottleFilter extends GenericFilter {
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
protected void doFilterImpl(ServletRequest pRequest, ServletResponse pResponse, FilterChain pChain)
|
||||
throws IOException, ServletException {
|
||||
protected void doFilterImpl(ServletRequest pRequest, ServletResponse pResponse, FilterChain pChain) throws IOException, ServletException {
|
||||
try {
|
||||
if (beginRequest()) {
|
||||
// Continue request
|
||||
@@ -195,21 +192,22 @@ public class ThrottleFilter extends GenericFilter {
|
||||
/**
|
||||
* Marks the beginning of a request
|
||||
*
|
||||
* @return <CODE>true<CODE> if the request should be handled.
|
||||
* @return {@code true} if the request should be handled.
|
||||
*/
|
||||
private boolean beginRequest() {
|
||||
synchronized (mRunningThreadsLock) {
|
||||
mRunningThreads++;
|
||||
synchronized (runningThreadsLock) {
|
||||
runningThreads++;
|
||||
}
|
||||
return (mRunningThreads <= mMaxConcurrentThreadCount);
|
||||
|
||||
return (runningThreads <= maxConcurrentThreadCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks the end of the request
|
||||
*/
|
||||
private void doneRequest() {
|
||||
synchronized (mRunningThreadsLock) {
|
||||
mRunningThreads--;
|
||||
synchronized (runningThreadsLock) {
|
||||
runningThreads--;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -220,12 +218,10 @@ public class ThrottleFilter extends GenericFilter {
|
||||
* @return the content type
|
||||
*/
|
||||
private String getContentType(HttpServletRequest pRequest) {
|
||||
if (mResponseMessageTypes != null) {
|
||||
if (responseMessageTypes != null) {
|
||||
String accept = pRequest.getHeader("Accept");
|
||||
|
||||
for (int i = 0; i < mResponseMessageTypes.length; i++) {
|
||||
String type = mResponseMessageTypes[i];
|
||||
|
||||
for (String type : responseMessageTypes) {
|
||||
// Note: This is not 100% correct way of doing content negotiation
|
||||
// But we just want a compatible result, quick, so this is okay
|
||||
if (StringUtil.contains(accept, type)) {
|
||||
@@ -245,17 +241,16 @@ public class ThrottleFilter extends GenericFilter {
|
||||
* @return the message
|
||||
*/
|
||||
private String getMessage(String pContentType) {
|
||||
|
||||
String fileName = (String) mResponseMessageNames.get(pContentType);
|
||||
String fileName = responseMessageNames.get(pContentType);
|
||||
|
||||
// Get cached value
|
||||
CacheEntry entry = (CacheEntry) mResponseCache.get(fileName);
|
||||
CacheEntry entry = responseCache.get(fileName);
|
||||
|
||||
if ((entry == null) || entry.isExpired()) {
|
||||
|
||||
// Create and add or replace cached value
|
||||
entry = new CacheEntry(readMessage(fileName));
|
||||
mResponseCache.put(fileName, entry);
|
||||
responseCache.put(fileName, entry);
|
||||
}
|
||||
|
||||
// Return value
|
||||
@@ -292,20 +287,20 @@ public class ThrottleFilter extends GenericFilter {
|
||||
* Keeps track of Cached objects
|
||||
*/
|
||||
private static class CacheEntry {
|
||||
private Object mValue;
|
||||
private long mTimestamp = -1;
|
||||
private Object value;
|
||||
private long timestamp = -1;
|
||||
|
||||
CacheEntry(Object pValue) {
|
||||
mValue = pValue;
|
||||
mTimestamp = System.currentTimeMillis();
|
||||
value = pValue;
|
||||
timestamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
Object getValue() {
|
||||
return mValue;
|
||||
return value;
|
||||
}
|
||||
|
||||
boolean isExpired() {
|
||||
return (System.currentTimeMillis() - mTimestamp) > 60000; // Cache 1 minute
|
||||
return (System.currentTimeMillis() - timestamp) > 60000; // Cache 1 minute
|
||||
}
|
||||
}
|
||||
}
|
@@ -40,11 +40,11 @@ import java.io.IOException;
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/TimingFilter.java#1 $
|
||||
* @version $Id: TimingFilter.java#1 $
|
||||
*/
|
||||
public class TimingFilter extends GenericFilter {
|
||||
|
||||
private String mAttribUsage = null;
|
||||
private String attribUsage = null;
|
||||
|
||||
/**
|
||||
* Method init
|
||||
@@ -52,7 +52,7 @@ public class TimingFilter extends GenericFilter {
|
||||
* @throws ServletException
|
||||
*/
|
||||
public void init() throws ServletException {
|
||||
mAttribUsage = getFilterName() + ".timerDelta";
|
||||
attribUsage = getFilterName() + ".timerDelta";
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -66,13 +66,13 @@ public class TimingFilter extends GenericFilter {
|
||||
protected void doFilterImpl(ServletRequest pRequest, ServletResponse pResponse, FilterChain pChain)
|
||||
throws IOException, ServletException {
|
||||
// Get total usage of earlier filters on same level
|
||||
Object usageAttrib = pRequest.getAttribute(mAttribUsage);
|
||||
Object usageAttrib = pRequest.getAttribute(attribUsage);
|
||||
long total = 0;
|
||||
|
||||
if (usageAttrib instanceof Long) {
|
||||
// If set, get value, and remove attribute for nested resources
|
||||
total = ((Long) usageAttrib).longValue();
|
||||
pRequest.removeAttribute(mAttribUsage);
|
||||
total = (Long) usageAttrib;
|
||||
pRequest.removeAttribute(attribUsage);
|
||||
}
|
||||
|
||||
// Start timing
|
||||
@@ -87,10 +87,10 @@ public class TimingFilter extends GenericFilter {
|
||||
long end = System.currentTimeMillis();
|
||||
|
||||
// Get time usage of included resources, add to total usage
|
||||
usageAttrib = pRequest.getAttribute(mAttribUsage);
|
||||
usageAttrib = pRequest.getAttribute(attribUsage);
|
||||
long usage = 0;
|
||||
if (usageAttrib instanceof Long) {
|
||||
usage = ((Long) usageAttrib).longValue();
|
||||
usage = (Long) usageAttrib;
|
||||
}
|
||||
|
||||
// Get the name of the included resource
|
||||
@@ -102,12 +102,11 @@ public class TimingFilter extends GenericFilter {
|
||||
}
|
||||
long delta = end - start;
|
||||
|
||||
log("Request processing time for resource \"" + resourceURI + "\": " +
|
||||
(delta - usage) + " ms (accumulated: " + delta + " ms).");
|
||||
log(String.format("Request processing time for resource \"%s\": %d ms (accumulated: %d ms).", resourceURI, (delta - usage), delta));
|
||||
|
||||
// Store total usage
|
||||
total += delta;
|
||||
pRequest.setAttribute(mAttribUsage, new Long(total));
|
||||
pRequest.setAttribute(attribUsage, total);
|
||||
}
|
||||
}
|
||||
}
|
@@ -109,32 +109,32 @@ import java.io.FilterOutputStream;
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/TrimWhiteSpaceFilter.java#2 $
|
||||
* @version $Id: TrimWhiteSpaceFilter.java#2 $
|
||||
*/
|
||||
public class TrimWhiteSpaceFilter extends GenericFilter {
|
||||
|
||||
private boolean mAutoFlush = true;
|
||||
private boolean autoFlush = true;
|
||||
|
||||
@InitParam
|
||||
public void setAutoFlush(final boolean pAutoFlush) {
|
||||
mAutoFlush = pAutoFlush;
|
||||
autoFlush = pAutoFlush;
|
||||
}
|
||||
|
||||
public void init() throws ServletException {
|
||||
super.init();
|
||||
log("Automatic flushing is " + (mAutoFlush ? "enabled" : "disabled"));
|
||||
log("Automatic flushing is " + (autoFlush ? "enabled" : "disabled"));
|
||||
}
|
||||
|
||||
protected void doFilterImpl(ServletRequest pRequest, ServletResponse pResponse, FilterChain pChain) throws IOException, ServletException {
|
||||
ServletResponseWrapper wrapped = new TrimWSServletResponseWrapper(pResponse);
|
||||
pChain.doFilter(pRequest, ServletUtil.createWrapper(wrapped));
|
||||
if (mAutoFlush) {
|
||||
if (autoFlush) {
|
||||
wrapped.flushBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
static final class TrimWSFilterOutputStream extends FilterOutputStream {
|
||||
boolean mLastWasWS = true; // Avoids leading WS by init to true
|
||||
boolean lastWasWS = true; // Avoids leading WS by init to true
|
||||
|
||||
public TrimWSFilterOutputStream(OutputStream pOut) {
|
||||
super(pOut);
|
||||
@@ -175,12 +175,12 @@ public class TrimWhiteSpaceFilter extends GenericFilter {
|
||||
if (!Character.isWhitespace((char) pByte)) {
|
||||
// If char is not WS, just store
|
||||
super.write(pByte);
|
||||
mLastWasWS = false;
|
||||
lastWasWS = false;
|
||||
}
|
||||
else {
|
||||
// TODO: Consider writing only 0x0a (LF) and 0x20 (space)
|
||||
// Else, if char is WS, store first, skip the rest
|
||||
if (!mLastWasWS) {
|
||||
if (!lastWasWS) {
|
||||
if (pByte == 0x0d) { // Convert all CR/LF's to 0x0a
|
||||
super.write(0x0a);
|
||||
}
|
||||
@@ -188,7 +188,7 @@ public class TrimWhiteSpaceFilter extends GenericFilter {
|
||||
super.write(pByte);
|
||||
}
|
||||
}
|
||||
mLastWasWS = true;
|
||||
lastWasWS = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -199,23 +199,23 @@ public class TrimWhiteSpaceFilter extends GenericFilter {
|
||||
}
|
||||
|
||||
protected OutputStream createOutputStream() throws IOException {
|
||||
return new TrimWSFilterOutputStream(mResponse.getOutputStream());
|
||||
return new TrimWSFilterOutputStream(response.getOutputStream());
|
||||
}
|
||||
}
|
||||
|
||||
static class TrimWSServletResponseWrapper extends ServletResponseWrapper {
|
||||
private final ServletResponseStreamDelegate mStreamDelegate = new TrimWSStreamDelegate(getResponse());
|
||||
private final ServletResponseStreamDelegate streamDelegate = new TrimWSStreamDelegate(getResponse());
|
||||
|
||||
public TrimWSServletResponseWrapper(ServletResponse pResponse) {
|
||||
super(pResponse);
|
||||
}
|
||||
|
||||
public ServletOutputStream getOutputStream() throws IOException {
|
||||
return mStreamDelegate.getOutputStream();
|
||||
return streamDelegate.getOutputStream();
|
||||
}
|
||||
|
||||
public PrintWriter getWriter() throws IOException {
|
||||
return mStreamDelegate.getWriter();
|
||||
return streamDelegate.getWriter();
|
||||
}
|
||||
|
||||
public void setContentLength(int pLength) {
|
||||
@@ -224,12 +224,12 @@ public class TrimWhiteSpaceFilter extends GenericFilter {
|
||||
|
||||
@Override
|
||||
public void flushBuffer() throws IOException {
|
||||
mStreamDelegate.flushBuffer();
|
||||
streamDelegate.flushBuffer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetBuffer() {
|
||||
mStreamDelegate.resetBuffer();
|
||||
streamDelegate.resetBuffer();
|
||||
}
|
||||
|
||||
// TODO: Consider picking up content-type/encoding, as we can only
|
||||
|
@@ -1,6 +1,7 @@
|
||||
package com.twelvemonkeys.servlet.cache;
|
||||
|
||||
import java.io.File;
|
||||
import com.twelvemonkeys.lang.Validate;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
/**
|
||||
@@ -8,30 +9,23 @@ import java.net.URI;
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/cache/AbstractCacheRequest.java#1 $
|
||||
* @version $Id: AbstractCacheRequest.java#1 $
|
||||
*/
|
||||
public abstract class AbstractCacheRequest implements CacheRequest {
|
||||
private final URI mRequestURI;
|
||||
private final String mMethod;
|
||||
private final URI requestURI;
|
||||
private final String method;
|
||||
|
||||
protected AbstractCacheRequest(final URI pRequestURI, final String pMethod) {
|
||||
if (pRequestURI == null) {
|
||||
throw new IllegalArgumentException("request URI == null");
|
||||
}
|
||||
if (pMethod == null) {
|
||||
throw new IllegalArgumentException("method == null");
|
||||
}
|
||||
|
||||
mRequestURI = pRequestURI;
|
||||
mMethod = pMethod;
|
||||
requestURI = Validate.notNull(pRequestURI, "requestURI");
|
||||
method = Validate.notNull(pMethod, "method");
|
||||
}
|
||||
|
||||
public URI getRequestURI() {
|
||||
return mRequestURI;
|
||||
return requestURI;
|
||||
}
|
||||
|
||||
public String getMethod() {
|
||||
return mMethod;
|
||||
return method;
|
||||
}
|
||||
|
||||
// TODO: Consider overriding equals/hashcode
|
||||
@@ -39,7 +33,7 @@ public abstract class AbstractCacheRequest implements CacheRequest {
|
||||
@Override
|
||||
public String toString() {
|
||||
return new StringBuilder(getClass().getSimpleName())
|
||||
.append("[URI=").append(mRequestURI)
|
||||
.append("[URI=").append(requestURI)
|
||||
.append(", parameters=").append(getParameters())
|
||||
.append(", headers=").append(getHeaders())
|
||||
.append("]").toString();
|
||||
|
@@ -7,19 +7,19 @@ import java.util.*;
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/cache/AbstractCacheResponse.java#1 $
|
||||
* @version $Id: AbstractCacheResponse.java#1 $
|
||||
*/
|
||||
public abstract class AbstractCacheResponse implements CacheResponse {
|
||||
private int mStatus;
|
||||
private final Map<String, List<String>> mHeaders = new LinkedHashMap<String, List<String>>(); // Insertion order
|
||||
private final Map<String, List<String>> mReadableHeaders = Collections.unmodifiableMap(mHeaders);
|
||||
private int status;
|
||||
private final Map<String, List<String>> headers = new LinkedHashMap<String, List<String>>(); // Insertion order
|
||||
private final Map<String, List<String>> readableHeaders = Collections.unmodifiableMap(headers);
|
||||
|
||||
public int getStatus() {
|
||||
return mStatus;
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(int pStatusCode) {
|
||||
mStatus = pStatusCode;
|
||||
status = pStatusCode;
|
||||
}
|
||||
|
||||
public void addHeader(String pHeaderName, String pHeaderValue) {
|
||||
@@ -31,15 +31,17 @@ public abstract class AbstractCacheResponse implements CacheResponse {
|
||||
}
|
||||
|
||||
private void setHeader(String pHeaderName, String pHeaderValue, boolean pAdd) {
|
||||
List<String> values = pAdd ? mHeaders.get(pHeaderName) : null;
|
||||
List<String> values = pAdd ? headers.get(pHeaderName) : null;
|
||||
|
||||
if (values == null) {
|
||||
values = new ArrayList<String>();
|
||||
mHeaders.put(pHeaderName, values);
|
||||
headers.put(pHeaderName, values);
|
||||
}
|
||||
|
||||
values.add(pHeaderValue);
|
||||
}
|
||||
|
||||
public Map<String, List<String>> getHeaders() {
|
||||
return mReadableHeaders;
|
||||
return readableHeaders;
|
||||
}
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@ package com.twelvemonkeys.servlet.cache;
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/cache/CacheException.java#1 $
|
||||
* @version $Id: CacheException.java#1 $
|
||||
*/
|
||||
public class CacheException extends Exception {
|
||||
public CacheException(Throwable pCause) {
|
||||
|
@@ -52,12 +52,12 @@ import java.util.logging.Logger;
|
||||
* @author Jayson Falkner
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/cache/CacheFilter.java#4 $
|
||||
* @version $Id: CacheFilter.java#4 $
|
||||
*
|
||||
*/
|
||||
public class CacheFilter extends GenericFilter {
|
||||
|
||||
HTTPCache mCache;
|
||||
HTTPCache cache;
|
||||
|
||||
/**
|
||||
* Initializes the filter
|
||||
@@ -67,7 +67,7 @@ public class CacheFilter extends GenericFilter {
|
||||
public void init() throws ServletException {
|
||||
FilterConfig config = getFilterConfig();
|
||||
|
||||
// Default don't delete cache files on exit (peristent cache)
|
||||
// Default don't delete cache files on exit (persistent cache)
|
||||
boolean deleteCacheOnExit = "TRUE".equalsIgnoreCase(config.getInitParameter("deleteCacheOnExit"));
|
||||
|
||||
// Default expiry time 10 minutes
|
||||
@@ -76,6 +76,7 @@ public class CacheFilter extends GenericFilter {
|
||||
String expiryTimeStr = config.getInitParameter("expiryTime");
|
||||
if (!StringUtil.isEmpty(expiryTimeStr)) {
|
||||
try {
|
||||
// TODO: This is insane.. :-P Let the expiry time be in minutes or seconds..
|
||||
expiryTime = Integer.parseInt(expiryTimeStr);
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
@@ -99,7 +100,7 @@ public class CacheFilter extends GenericFilter {
|
||||
int maxCachedEntites = 10000;
|
||||
|
||||
try {
|
||||
mCache = new HTTPCache(
|
||||
cache = new HTTPCache(
|
||||
getTempFolder(),
|
||||
expiryTime,
|
||||
memCacheSize * 1024 * 1024,
|
||||
@@ -120,7 +121,7 @@ public class CacheFilter extends GenericFilter {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
log("Created cache: " + mCache);
|
||||
log("Created cache: " + cache);
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
throw new ServletConfigException("Could not create cache: " + e.toString(), e);
|
||||
@@ -136,8 +137,8 @@ public class CacheFilter extends GenericFilter {
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
log("Destroying cache: " + mCache);
|
||||
mCache = null;
|
||||
log("Destroying cache: " + cache);
|
||||
cache = null;
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
@@ -155,7 +156,7 @@ public class CacheFilter extends GenericFilter {
|
||||
|
||||
// Render fast
|
||||
try {
|
||||
mCache.doCached(cacheRequest, cacheResponse, resolver);
|
||||
cache.doCached(cacheRequest, cacheResponse, resolver);
|
||||
}
|
||||
catch (CacheException e) {
|
||||
if (e.getCause() instanceof ServletException) {
|
||||
@@ -179,21 +180,21 @@ public class CacheFilter extends GenericFilter {
|
||||
// TODO: Extract, complete and document this class, might be useful in other cases
|
||||
// Maybe add it to the ServletUtil class
|
||||
static class ServletContextLoggerAdapter extends Logger {
|
||||
private final ServletContext mContext;
|
||||
private final ServletContext context;
|
||||
|
||||
public ServletContextLoggerAdapter(String pName, ServletContext pContext) {
|
||||
super(pName, null);
|
||||
mContext = pContext;
|
||||
context = pContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(Level pLevel, String pMessage) {
|
||||
mContext.log(pMessage);
|
||||
context.log(pMessage);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void log(Level pLevel, String pMessage, Throwable pThrowable) {
|
||||
mContext.log(pMessage, pThrowable);
|
||||
context.log(pMessage, pThrowable);
|
||||
}
|
||||
}
|
||||
}
|
@@ -9,7 +9,7 @@ import java.util.Map;
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/cache/CacheRequest.java#1 $
|
||||
* @version $Id: CacheRequest.java#1 $
|
||||
*/
|
||||
public interface CacheRequest {
|
||||
URI getRequestURI();
|
||||
|
@@ -10,7 +10,7 @@ import java.util.Map;
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/cache/CacheResponse.java#1 $
|
||||
* @version $Id: CacheResponse.java#1 $
|
||||
*/
|
||||
public interface CacheResponse {
|
||||
OutputStream getOutputStream() throws IOException;
|
||||
|
@@ -49,45 +49,45 @@ import java.io.PrintWriter;
|
||||
* @author Jayson Falkner
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/cache/CacheResponseWrapper.java#3 $
|
||||
* @version $Id: CacheResponseWrapper.java#3 $
|
||||
*/
|
||||
class CacheResponseWrapper extends HttpServletResponseWrapper {
|
||||
private ServletResponseStreamDelegate mStreamDelegate;
|
||||
private ServletResponseStreamDelegate streamDelegate;
|
||||
|
||||
private CacheResponse mResponse;
|
||||
private CachedEntity mCached;
|
||||
private WritableCachedResponse mCachedResponse;
|
||||
private CacheResponse response;
|
||||
private CachedEntity cached;
|
||||
private WritableCachedResponse cachedResponse;
|
||||
|
||||
private Boolean mCachable;
|
||||
private int mStatus;
|
||||
private Boolean cacheable;
|
||||
private int status;
|
||||
|
||||
public CacheResponseWrapper(final ServletCacheResponse pResponse, final CachedEntity pCached) {
|
||||
super(pResponse.getResponse());
|
||||
mResponse = pResponse;
|
||||
mCached = pCached;
|
||||
response = pResponse;
|
||||
cached = pCached;
|
||||
init();
|
||||
}
|
||||
|
||||
/*
|
||||
NOTE: This class defers determining if a response is cachable until the
|
||||
NOTE: This class defers determining if a response is cacheable until the
|
||||
output stream is needed.
|
||||
This it the reason for the somewhat complicated logic in the add/setHeader
|
||||
methods below.
|
||||
*/
|
||||
private void init() {
|
||||
mCachable = null;
|
||||
mStatus = SC_OK;
|
||||
mCachedResponse = mCached.createCachedResponse();
|
||||
mStreamDelegate = new ServletResponseStreamDelegate(this) {
|
||||
cacheable = null;
|
||||
status = SC_OK;
|
||||
cachedResponse = cached.createCachedResponse();
|
||||
streamDelegate = new ServletResponseStreamDelegate(this) {
|
||||
protected OutputStream createOutputStream() throws IOException {
|
||||
// Test if this request is really cachable, otherwise,
|
||||
// Test if this request is really cacheable, otherwise,
|
||||
// just write through to underlying response, and don't cache
|
||||
if (isCachable()) {
|
||||
return mCachedResponse.getOutputStream();
|
||||
if (isCacheable()) {
|
||||
return cachedResponse.getOutputStream();
|
||||
}
|
||||
else {
|
||||
mCachedResponse.setStatus(mStatus);
|
||||
mCachedResponse.writeHeadersTo(CacheResponseWrapper.this.mResponse);
|
||||
cachedResponse.setStatus(status);
|
||||
cachedResponse.writeHeadersTo(CacheResponseWrapper.this.response);
|
||||
return super.getOutputStream();
|
||||
}
|
||||
}
|
||||
@@ -95,25 +95,25 @@ class CacheResponseWrapper extends HttpServletResponseWrapper {
|
||||
}
|
||||
|
||||
CachedResponse getCachedResponse() {
|
||||
return mCachedResponse.getCachedResponse();
|
||||
return cachedResponse.getCachedResponse();
|
||||
}
|
||||
|
||||
public boolean isCachable() {
|
||||
public boolean isCacheable() {
|
||||
// NOTE: Intentionally not synchronized
|
||||
if (mCachable == null) {
|
||||
mCachable = isCachableImpl();
|
||||
if (cacheable == null) {
|
||||
cacheable = isCacheableImpl();
|
||||
}
|
||||
|
||||
return mCachable;
|
||||
return cacheable;
|
||||
}
|
||||
|
||||
private boolean isCachableImpl() {
|
||||
if (mStatus != SC_OK) {
|
||||
private boolean isCacheableImpl() {
|
||||
if (status != SC_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Vary: *
|
||||
String[] values = mCachedResponse.getHeaderValues(HTTPCache.HEADER_VARY);
|
||||
String[] values = cachedResponse.getHeaderValues(HTTPCache.HEADER_VARY);
|
||||
if (values != null) {
|
||||
for (String value : values) {
|
||||
if ("*".equals(value)) {
|
||||
@@ -123,7 +123,7 @@ class CacheResponseWrapper extends HttpServletResponseWrapper {
|
||||
}
|
||||
|
||||
// Cache-Control: no-cache, no-store, must-revalidate
|
||||
values = mCachedResponse.getHeaderValues(HTTPCache.HEADER_CACHE_CONTROL);
|
||||
values = cachedResponse.getHeaderValues(HTTPCache.HEADER_CACHE_CONTROL);
|
||||
if (values != null) {
|
||||
for (String value : values) {
|
||||
if (StringUtil.contains(value, "no-cache")
|
||||
@@ -135,7 +135,7 @@ class CacheResponseWrapper extends HttpServletResponseWrapper {
|
||||
}
|
||||
|
||||
// Pragma: no-cache
|
||||
values = mCachedResponse.getHeaderValues(HTTPCache.HEADER_PRAGMA);
|
||||
values = cachedResponse.getHeaderValues(HTTPCache.HEADER_PRAGMA);
|
||||
if (values != null) {
|
||||
for (String value : values) {
|
||||
if (StringUtil.contains(value, "no-cache")) {
|
||||
@@ -148,43 +148,43 @@ class CacheResponseWrapper extends HttpServletResponseWrapper {
|
||||
}
|
||||
|
||||
public void flushBuffer() throws IOException {
|
||||
mStreamDelegate.flushBuffer();
|
||||
streamDelegate.flushBuffer();
|
||||
}
|
||||
|
||||
public void resetBuffer() {
|
||||
// Servlet 2.3
|
||||
mStreamDelegate.resetBuffer();
|
||||
streamDelegate.resetBuffer();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
if (Boolean.FALSE.equals(mCachable)) {
|
||||
if (Boolean.FALSE.equals(cacheable)) {
|
||||
super.reset();
|
||||
}
|
||||
// No else, might be cachable after all..
|
||||
// No else, might be cacheable after all..
|
||||
init();
|
||||
}
|
||||
|
||||
public ServletOutputStream getOutputStream() throws IOException {
|
||||
return mStreamDelegate.getOutputStream();
|
||||
return streamDelegate.getOutputStream();
|
||||
}
|
||||
|
||||
public PrintWriter getWriter() throws IOException {
|
||||
return mStreamDelegate.getWriter();
|
||||
return streamDelegate.getWriter();
|
||||
}
|
||||
|
||||
public boolean containsHeader(String name) {
|
||||
return mCachedResponse.getHeaderValues(name) != null;
|
||||
return cachedResponse.getHeaderValues(name) != null;
|
||||
}
|
||||
|
||||
public void sendError(int pStatusCode, String msg) throws IOException {
|
||||
// NOT cachable
|
||||
mStatus = pStatusCode;
|
||||
// NOT cacheable
|
||||
status = pStatusCode;
|
||||
super.sendError(pStatusCode, msg);
|
||||
}
|
||||
|
||||
public void sendError(int pStatusCode) throws IOException {
|
||||
// NOT cachable
|
||||
mStatus = pStatusCode;
|
||||
// NOT cacheable
|
||||
status = pStatusCode;
|
||||
super.sendError(pStatusCode);
|
||||
}
|
||||
|
||||
@@ -194,65 +194,65 @@ class CacheResponseWrapper extends HttpServletResponseWrapper {
|
||||
}
|
||||
|
||||
public void setStatus(int pStatusCode) {
|
||||
// NOT cachable unless pStatusCode == 200 (or a FEW others?)
|
||||
// NOT cacheable unless pStatusCode == 200 (or a FEW others?)
|
||||
if (pStatusCode != SC_OK) {
|
||||
mStatus = pStatusCode;
|
||||
status = pStatusCode;
|
||||
super.setStatus(pStatusCode);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendRedirect(String pLocation) throws IOException {
|
||||
// NOT cachable
|
||||
mStatus = SC_MOVED_TEMPORARILY;
|
||||
// NOT cacheable
|
||||
status = SC_MOVED_TEMPORARILY;
|
||||
super.sendRedirect(pLocation);
|
||||
}
|
||||
|
||||
public void setDateHeader(String pName, long pValue) {
|
||||
// If in write-trough-mode, set headers directly
|
||||
if (Boolean.FALSE.equals(mCachable)) {
|
||||
if (Boolean.FALSE.equals(cacheable)) {
|
||||
super.setDateHeader(pName, pValue);
|
||||
}
|
||||
mCachedResponse.setHeader(pName, NetUtil.formatHTTPDate(pValue));
|
||||
cachedResponse.setHeader(pName, NetUtil.formatHTTPDate(pValue));
|
||||
}
|
||||
|
||||
public void addDateHeader(String pName, long pValue) {
|
||||
// If in write-trough-mode, set headers directly
|
||||
if (Boolean.FALSE.equals(mCachable)) {
|
||||
if (Boolean.FALSE.equals(cacheable)) {
|
||||
super.addDateHeader(pName, pValue);
|
||||
}
|
||||
mCachedResponse.addHeader(pName, NetUtil.formatHTTPDate(pValue));
|
||||
cachedResponse.addHeader(pName, NetUtil.formatHTTPDate(pValue));
|
||||
}
|
||||
|
||||
public void setHeader(String pName, String pValue) {
|
||||
// If in write-trough-mode, set headers directly
|
||||
if (Boolean.FALSE.equals(mCachable)) {
|
||||
if (Boolean.FALSE.equals(cacheable)) {
|
||||
super.setHeader(pName, pValue);
|
||||
}
|
||||
mCachedResponse.setHeader(pName, pValue);
|
||||
cachedResponse.setHeader(pName, pValue);
|
||||
}
|
||||
|
||||
public void addHeader(String pName, String pValue) {
|
||||
// If in write-trough-mode, set headers directly
|
||||
if (Boolean.FALSE.equals(mCachable)) {
|
||||
if (Boolean.FALSE.equals(cacheable)) {
|
||||
super.addHeader(pName, pValue);
|
||||
}
|
||||
mCachedResponse.addHeader(pName, pValue);
|
||||
cachedResponse.addHeader(pName, pValue);
|
||||
}
|
||||
|
||||
public void setIntHeader(String pName, int pValue) {
|
||||
// If in write-trough-mode, set headers directly
|
||||
if (Boolean.FALSE.equals(mCachable)) {
|
||||
if (Boolean.FALSE.equals(cacheable)) {
|
||||
super.setIntHeader(pName, pValue);
|
||||
}
|
||||
mCachedResponse.setHeader(pName, String.valueOf(pValue));
|
||||
cachedResponse.setHeader(pName, String.valueOf(pValue));
|
||||
}
|
||||
|
||||
public void addIntHeader(String pName, int pValue) {
|
||||
// If in write-trough-mode, set headers directly
|
||||
if (Boolean.FALSE.equals(mCachable)) {
|
||||
if (Boolean.FALSE.equals(cacheable)) {
|
||||
super.addIntHeader(pName, pValue);
|
||||
}
|
||||
mCachedResponse.addHeader(pName, String.valueOf(pValue));
|
||||
cachedResponse.addHeader(pName, String.valueOf(pValue));
|
||||
}
|
||||
|
||||
public final void setContentType(String type) {
|
||||
|
@@ -34,7 +34,7 @@ import java.io.IOException;
|
||||
* CachedEntity
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/cache/CachedEntity.java#3 $
|
||||
* @version $Id: CachedEntity.java#3 $
|
||||
*/
|
||||
interface CachedEntity {
|
||||
|
||||
|
@@ -28,6 +28,8 @@
|
||||
|
||||
package com.twelvemonkeys.servlet.cache;
|
||||
|
||||
import com.twelvemonkeys.lang.Validate;
|
||||
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
@@ -36,24 +38,20 @@ import java.util.List;
|
||||
* CachedEntity
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/cache/CachedEntityImpl.java#3 $
|
||||
* @version $Id: CachedEntityImpl.java#3 $
|
||||
*/
|
||||
class CachedEntityImpl implements CachedEntity {
|
||||
private String mCacheURI;
|
||||
private HTTPCache mCache;
|
||||
private String cacheURI;
|
||||
private HTTPCache cache;
|
||||
|
||||
CachedEntityImpl(String pCacheURI, HTTPCache pCache) {
|
||||
if (pCacheURI == null) {
|
||||
throw new IllegalArgumentException("cacheURI == null");
|
||||
}
|
||||
|
||||
mCacheURI = pCacheURI;
|
||||
mCache = pCache;
|
||||
cacheURI = Validate.notNull(pCacheURI, "cacheURI");
|
||||
cache = pCache;
|
||||
}
|
||||
|
||||
public void render(CacheRequest pRequest, CacheResponse pResponse) throws IOException {
|
||||
// Get cached content
|
||||
CachedResponse cached = mCache.getContent(mCacheURI, pRequest);
|
||||
CachedResponse cached = cache.getContent(cacheURI, pRequest);
|
||||
|
||||
// Sanity check
|
||||
if (cached == null) {
|
||||
@@ -93,7 +91,7 @@ class CachedEntityImpl implements CachedEntity {
|
||||
}
|
||||
catch (IllegalArgumentException e) {
|
||||
// Seems to be a bug in FireFox 1.0.2..?!
|
||||
mCache.log("Error in date header from user-agent. User-Agent: " + pRequest.getHeaders().get("User-Agent"), e);
|
||||
cache.log("Error in date header from user-agent. User-Agent: " + pRequest.getHeaders().get("User-Agent"), e);
|
||||
}
|
||||
|
||||
if (lastModified == -1L || (ifModifiedSince < (lastModified / 1000L) * 1000L)) {
|
||||
@@ -133,9 +131,9 @@ class CachedEntityImpl implements CachedEntity {
|
||||
//
|
||||
// CacheResponseWrapper response = (CacheResponseWrapper) pResponse;
|
||||
|
||||
// if (response.isCachable()) {
|
||||
mCache.registerContent(
|
||||
mCacheURI,
|
||||
// if (response.isCacheable()) {
|
||||
cache.registerContent(
|
||||
cacheURI,
|
||||
pRequest,
|
||||
pResponse instanceof WritableCachedResponse ? ((WritableCachedResponse) pResponse).getCachedResponse() : pResponse
|
||||
);
|
||||
@@ -149,7 +147,7 @@ class CachedEntityImpl implements CachedEntity {
|
||||
}
|
||||
|
||||
public boolean isStale(CacheRequest pRequest) {
|
||||
return mCache.isContentStale(mCacheURI, pRequest);
|
||||
return cache.isContentStale(cacheURI, pRequest);
|
||||
}
|
||||
|
||||
public WritableCachedResponse createCachedResponse() {
|
||||
@@ -157,16 +155,16 @@ class CachedEntityImpl implements CachedEntity {
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return (mCacheURI != null ? mCacheURI.hashCode() : 0) + 1397;
|
||||
return (cacheURI != null ? cacheURI.hashCode() : 0) + 1397;
|
||||
}
|
||||
|
||||
public boolean equals(Object pOther) {
|
||||
return pOther instanceof CachedEntityImpl &&
|
||||
((mCacheURI == null && ((CachedEntityImpl) pOther).mCacheURI == null) ||
|
||||
mCacheURI != null && mCacheURI.equals(((CachedEntityImpl) pOther).mCacheURI));
|
||||
((cacheURI == null && ((CachedEntityImpl) pOther).cacheURI == null) ||
|
||||
cacheURI != null && cacheURI.equals(((CachedEntityImpl) pOther).cacheURI));
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "CachedEntity[URI=" + mCacheURI + "]";
|
||||
return "CachedEntity[URI=" + cacheURI + "]";
|
||||
}
|
||||
}
|
@@ -35,7 +35,7 @@ import java.io.OutputStream;
|
||||
* CachedResponse
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/cache/CachedResponse.java#3 $
|
||||
* @version $Id: CachedResponse.java#3 $
|
||||
*/
|
||||
interface CachedResponse {
|
||||
/**
|
||||
|
@@ -29,45 +29,39 @@
|
||||
package com.twelvemonkeys.servlet.cache;
|
||||
|
||||
import com.twelvemonkeys.io.FastByteArrayOutputStream;
|
||||
import com.twelvemonkeys.util.LinkedMap;
|
||||
import com.twelvemonkeys.lang.Validate;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* CachedResponseImpl
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/cache/CachedResponseImpl.java#4 $
|
||||
* @version $Id: CachedResponseImpl.java#4 $
|
||||
*/
|
||||
class CachedResponseImpl implements CachedResponse {
|
||||
final protected Map<String, List<String>> mHeaders;
|
||||
protected int mHeadersSize;
|
||||
protected ByteArrayOutputStream mContent = null;
|
||||
int mStatus;
|
||||
final protected Map<String, List<String>> headers;
|
||||
protected int headersSize;
|
||||
protected ByteArrayOutputStream content = null;
|
||||
int status;
|
||||
|
||||
protected CachedResponseImpl() {
|
||||
mHeaders = new LinkedMap<String, List<String>>(); // Keep headers in insertion order
|
||||
headers = new LinkedHashMap<String, List<String>>(); // Keep headers in insertion order
|
||||
}
|
||||
|
||||
// For use by HTTPCache, when recreating CachedResponses from disk cache
|
||||
CachedResponseImpl(final int pStatus, final LinkedMap<String, List<String>> pHeaders, final int pHeaderSize, final byte[] pContent) {
|
||||
if (pHeaders == null) {
|
||||
throw new IllegalArgumentException("headers == null");
|
||||
}
|
||||
mStatus = pStatus;
|
||||
mHeaders = pHeaders;
|
||||
mHeadersSize = pHeaderSize;
|
||||
mContent = new FastByteArrayOutputStream(pContent);
|
||||
CachedResponseImpl(final int pStatus, final LinkedHashMap<String, List<String>> pHeaders, final int pHeaderSize, final byte[] pContent) {
|
||||
status = pStatus;
|
||||
headers = Validate.notNull(pHeaders, "headers");
|
||||
headersSize = pHeaderSize;
|
||||
content = new FastByteArrayOutputStream(pContent);
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return mStatus;
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,12 +78,13 @@ class CachedResponseImpl implements CachedResponse {
|
||||
continue;
|
||||
}
|
||||
|
||||
// TODO: Replace Last-Modified with X-Cached-At? See CachedEntityImpl, line 50
|
||||
// TODO: Replace Last-Modified with X-Cached-At? See CachedEntityImpl
|
||||
|
||||
String[] headerValues = getHeaderValues(header);
|
||||
|
||||
for (int i = 0; i < headerValues.length; i++) {
|
||||
String headerValue = headerValues[i];
|
||||
|
||||
if (i == 0) {
|
||||
pResponse.setHeader(header, headerValue);
|
||||
}
|
||||
@@ -101,17 +96,17 @@ class CachedResponseImpl implements CachedResponse {
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the cahced content to the response
|
||||
* Writes the cached content to the response
|
||||
*
|
||||
* @param pStream the response stream
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public void writeContentsTo(final OutputStream pStream) throws IOException {
|
||||
if (mContent == null) {
|
||||
if (content == null) {
|
||||
throw new IOException("Cache is null, no content to write.");
|
||||
}
|
||||
|
||||
mContent.writeTo(pStream);
|
||||
content.writeTo(pStream);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,7 +115,8 @@ class CachedResponseImpl implements CachedResponse {
|
||||
* @return an array of {@code String}s
|
||||
*/
|
||||
public String[] getHeaderNames() {
|
||||
Set<String> headers = mHeaders.keySet();
|
||||
Set<String> headers = this.headers.keySet();
|
||||
|
||||
return headers.toArray(new String[headers.size()]);
|
||||
}
|
||||
|
||||
@@ -133,13 +129,9 @@ class CachedResponseImpl implements CachedResponse {
|
||||
* such header in this response.
|
||||
*/
|
||||
public String[] getHeaderValues(final String pHeaderName) {
|
||||
List<String> values = mHeaders.get(pHeaderName);
|
||||
if (values == null) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
return values.toArray(new String[values.size()]);
|
||||
}
|
||||
List<String> values = headers.get(pHeaderName);
|
||||
|
||||
return values == null ? null : values.toArray(new String[values.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,13 +145,14 @@ class CachedResponseImpl implements CachedResponse {
|
||||
* such header in this response.
|
||||
*/
|
||||
public String getHeaderValue(final String pHeaderName) {
|
||||
List<String> values = mHeaders.get(pHeaderName);
|
||||
List<String> values = headers.get(pHeaderName);
|
||||
|
||||
return (values != null && values.size() > 0) ? values.get(0) : null;
|
||||
}
|
||||
|
||||
public int size() {
|
||||
// mContent.size() is exact size in bytes, mHeadersSize is an estimate
|
||||
return (mContent != null ? mContent.size() : 0) + mHeadersSize;
|
||||
// content.size() is exact size in bytes, headersSize is an estimate
|
||||
return (content != null ? content.size() : 0) + headersSize;
|
||||
}
|
||||
|
||||
public boolean equals(final Object pOther) {
|
||||
@@ -180,9 +173,9 @@ class CachedResponseImpl implements CachedResponse {
|
||||
}
|
||||
|
||||
private boolean equalsImpl(final CachedResponseImpl pOther) {
|
||||
return mHeadersSize == pOther.mHeadersSize &&
|
||||
(mContent == null ? pOther.mContent == null : mContent.equals(pOther.mContent)) &&
|
||||
mHeaders.equals(pOther.mHeaders);
|
||||
return headersSize == pOther.headersSize &&
|
||||
(content == null ? pOther.content == null : content.equals(pOther.content)) &&
|
||||
headers.equals(pOther.headers);
|
||||
}
|
||||
|
||||
private boolean equalsGeneric(final CachedResponse pOther) {
|
||||
@@ -212,9 +205,9 @@ class CachedResponseImpl implements CachedResponse {
|
||||
|
||||
public int hashCode() {
|
||||
int result;
|
||||
result = mHeaders.hashCode();
|
||||
result = 29 * result + mHeadersSize;
|
||||
result = 37 * result + (mContent != null ? mContent.hashCode() : 0);
|
||||
result = headers.hashCode();
|
||||
result = 29 * result + headersSize;
|
||||
result = 37 * result + (content != null ? content.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@@ -10,16 +10,16 @@ import java.util.Map;
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/cache/ClientCacheRequest.java#1 $
|
||||
* @version $Id: ClientCacheRequest.java#1 $
|
||||
*/
|
||||
public final class ClientCacheRequest extends AbstractCacheRequest {
|
||||
private Map<String, List<String>> mParameters;
|
||||
private Map<String, List<String>> mHeaders;
|
||||
private Map<String, List<String>> parameters;
|
||||
private Map<String, List<String>> headers;
|
||||
|
||||
public ClientCacheRequest(final URI pRequestURI,final Map<String, List<String>> pParameters, final Map<String, List<String>> pHeaders) {
|
||||
super(pRequestURI, "GET"); // TODO: Consider supporting more than get? At least HEAD and OPTIONS...
|
||||
mParameters = normalizeMap(pParameters);
|
||||
mHeaders = normalizeMap(pHeaders);
|
||||
parameters = normalizeMap(pParameters);
|
||||
headers = normalizeMap(pHeaders);
|
||||
}
|
||||
|
||||
private <K, V> Map<K, V> normalizeMap(Map<K, V> pMap) {
|
||||
@@ -27,11 +27,11 @@ public final class ClientCacheRequest extends AbstractCacheRequest {
|
||||
}
|
||||
|
||||
public Map<String, List<String>> getParameters() {
|
||||
return mParameters;
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public Map<String, List<String>> getHeaders() {
|
||||
return mHeaders;
|
||||
return headers;
|
||||
}
|
||||
|
||||
public String getServerName() {
|
||||
|
@@ -9,10 +9,10 @@ import java.io.OutputStream;
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/cache/ClientCacheResponse.java#2 $
|
||||
* @version $Id: ClientCacheResponse.java#2 $
|
||||
*/
|
||||
public final class ClientCacheResponse extends AbstractCacheResponse {
|
||||
// It's quite useless to cahce the data either on disk or in memory, as it already is cached in the client's cache...
|
||||
// It's quite useless to cache the data either on disk or in memory, as it already is cached in the client's cache...
|
||||
// It would be nice if we could bypass that...
|
||||
|
||||
public OutputStream getOutputStream() throws IOException {
|
||||
|
@@ -30,13 +30,14 @@ package com.twelvemonkeys.servlet.cache;
|
||||
|
||||
import com.twelvemonkeys.io.FileUtil;
|
||||
import com.twelvemonkeys.lang.StringUtil;
|
||||
import com.twelvemonkeys.lang.Validate;
|
||||
import com.twelvemonkeys.net.MIMEUtil;
|
||||
import com.twelvemonkeys.net.NetUtil;
|
||||
import com.twelvemonkeys.util.LRUHashMap;
|
||||
import com.twelvemonkeys.util.LinkedMap;
|
||||
import com.twelvemonkeys.util.NullMap;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.logging.Level;
|
||||
@@ -47,7 +48,7 @@ import java.util.logging.Logger;
|
||||
* <p/>
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/cache/HTTPCache.java#4 $
|
||||
* @version $Id: HTTPCache.java#4 $
|
||||
* @todo OMPTIMIZE: Cache parsed vary-info objects, not the properties-files
|
||||
* @todo BUG: Better filename handling, as some filenames become too long..
|
||||
* - Use a mix of parameters and hashcode + lenght with fixed (max) lenght?
|
||||
@@ -148,35 +149,33 @@ public class HTTPCache {
|
||||
*/
|
||||
protected static final String FILE_EXT_VARY = ".vary";
|
||||
|
||||
protected static final int STATUS_OK = 200;
|
||||
|
||||
/**
|
||||
* The directory used for the disk-based cache
|
||||
*/
|
||||
private File mTempDir;
|
||||
private File tempDir;
|
||||
|
||||
/**
|
||||
* Indicates wether the disk-based cache should be deleted when the
|
||||
* container shuts down/VM exits
|
||||
*/
|
||||
private boolean mDeleteCacheOnExit;
|
||||
private boolean deleteCacheOnExit;
|
||||
|
||||
/**
|
||||
* In-memory content cache
|
||||
*/
|
||||
private final Map<String, CachedResponse> mContentCache;
|
||||
private final Map<String, CachedResponse> contentCache;
|
||||
/**
|
||||
* In-memory enity cache
|
||||
*/
|
||||
private final Map<String, CachedEntity> mEntityCache;
|
||||
private final Map<String, CachedEntity> entityCache;
|
||||
/**
|
||||
* In-memory varyiation-info cache
|
||||
*/
|
||||
private final Map<String, Properties> mVaryCache;
|
||||
private final Map<String, Properties> varyCache;
|
||||
|
||||
private long mDefaultExpiryTime = -1;
|
||||
private long defaultExpiryTime = -1;
|
||||
|
||||
private final Logger mLogger;
|
||||
private final Logger logger;
|
||||
|
||||
// Internal constructor for sublcasses only
|
||||
protected HTTPCache(
|
||||
@@ -187,44 +186,33 @@ public class HTTPCache {
|
||||
final boolean pDeleteCacheOnExit,
|
||||
final Logger pLogger
|
||||
) {
|
||||
if (pTempFolder == null) {
|
||||
throw new IllegalArgumentException("temp folder == null");
|
||||
}
|
||||
if (!pTempFolder.exists() && !pTempFolder.mkdirs()) {
|
||||
throw new IllegalArgumentException("Could not create required temp directory: " + mTempDir.getAbsolutePath());
|
||||
}
|
||||
if (!(pTempFolder.canRead() && pTempFolder.canWrite())) {
|
||||
throw new IllegalArgumentException("Must have read/write access to temp folder: " + mTempDir.getAbsolutePath());
|
||||
}
|
||||
if (pDefaultCacheExpiryTime < 0) {
|
||||
throw new IllegalArgumentException("Negative expiry time");
|
||||
}
|
||||
if (pMaxMemCacheSize < 0) {
|
||||
throw new IllegalArgumentException("Negative maximum memory cache size");
|
||||
}
|
||||
if (pMaxCachedEntites < 0) {
|
||||
throw new IllegalArgumentException("Negative maximum number of cached entries");
|
||||
}
|
||||
Validate.notNull(pTempFolder, "temp folder");
|
||||
Validate.isTrue(pTempFolder.exists() || pTempFolder.mkdirs(), pTempFolder.getAbsolutePath(), "Could not create required temp directory: %s");
|
||||
Validate.isTrue(pTempFolder.canRead() && pTempFolder.canWrite(), pTempFolder.getAbsolutePath(), "Must have read/write access to temp folder: %s");
|
||||
|
||||
mDefaultExpiryTime = pDefaultCacheExpiryTime;
|
||||
Validate.isTrue(pDefaultCacheExpiryTime >= 0, pDefaultCacheExpiryTime, "Negative expiry time: %d");
|
||||
Validate.isTrue(pMaxMemCacheSize >= 0, pDefaultCacheExpiryTime, "Negative maximum memory cache size: %d");
|
||||
Validate.isTrue(pMaxCachedEntites >= 0, pDefaultCacheExpiryTime, "Negative maximum number of cached entries: %d");
|
||||
|
||||
defaultExpiryTime = pDefaultCacheExpiryTime;
|
||||
|
||||
if (pMaxMemCacheSize > 0) {
|
||||
// Map backing = new SizedLRUMap(pMaxMemCacheSize); // size in bytes
|
||||
// mContentCache = new TimeoutMap(backing, null, pDefaultCacheExpiryTime);
|
||||
mContentCache = new SizedLRUMap<String, CachedResponse>(pMaxMemCacheSize); // size in bytes
|
||||
// contentCache = new TimeoutMap(backing, null, pDefaultCacheExpiryTime);
|
||||
contentCache = new SizedLRUMap<String, CachedResponse>(pMaxMemCacheSize); // size in bytes
|
||||
}
|
||||
else {
|
||||
mContentCache = new NullMap<String, CachedResponse>();
|
||||
contentCache = new NullMap<String, CachedResponse>();
|
||||
}
|
||||
|
||||
mEntityCache = new LRUHashMap<String, CachedEntity>(pMaxCachedEntites);
|
||||
mVaryCache = new LRUHashMap<String, Properties>(pMaxCachedEntites);
|
||||
entityCache = new LRUHashMap<String, CachedEntity>(pMaxCachedEntites);
|
||||
varyCache = new LRUHashMap<String, Properties>(pMaxCachedEntites);
|
||||
|
||||
mDeleteCacheOnExit = pDeleteCacheOnExit;
|
||||
deleteCacheOnExit = pDeleteCacheOnExit;
|
||||
|
||||
mTempDir = pTempFolder;
|
||||
tempDir = pTempFolder;
|
||||
|
||||
mLogger = pLogger != null ? pLogger : Logger.getLogger(getClass().getName());
|
||||
logger = pLogger != null ? pLogger : Logger.getLogger(getClass().getName());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -289,19 +277,15 @@ public class HTTPCache {
|
||||
}
|
||||
|
||||
private static File getTempFolder(String pName, ServletContext pContext) {
|
||||
if (pName == null) {
|
||||
throw new IllegalArgumentException("name == null");
|
||||
}
|
||||
if (pName.trim().length() == 0) {
|
||||
throw new IllegalArgumentException("Empty name");
|
||||
}
|
||||
if (pContext == null) {
|
||||
throw new IllegalArgumentException("servlet context == null");
|
||||
}
|
||||
Validate.notNull(pName, "name");
|
||||
Validate.isTrue(!StringUtil.isEmpty(pName), pName, "empty name: '%s'");
|
||||
Validate.notNull(pContext, "context");
|
||||
|
||||
File tempRoot = (File) pContext.getAttribute("javax.servlet.context.tempdir");
|
||||
if (tempRoot == null) {
|
||||
throw new IllegalStateException("Missing context attribute \"javax.servlet.context.tempdir\"");
|
||||
}
|
||||
|
||||
return new File(tempRoot, pName);
|
||||
}
|
||||
|
||||
@@ -309,36 +293,36 @@ public class HTTPCache {
|
||||
StringBuilder buf = new StringBuilder(getClass().getSimpleName());
|
||||
buf.append("[");
|
||||
buf.append("Temp dir: ");
|
||||
buf.append(mTempDir.getAbsolutePath());
|
||||
if (mDeleteCacheOnExit) {
|
||||
buf.append(tempDir.getAbsolutePath());
|
||||
if (deleteCacheOnExit) {
|
||||
buf.append(" (non-persistent)");
|
||||
}
|
||||
else {
|
||||
buf.append(" (persistent)");
|
||||
}
|
||||
buf.append(", EntityCache: {");
|
||||
buf.append(mEntityCache.size());
|
||||
buf.append(entityCache.size());
|
||||
buf.append(" entries in a ");
|
||||
buf.append(mEntityCache.getClass().getName());
|
||||
buf.append(entityCache.getClass().getName());
|
||||
buf.append("}, VaryCache: {");
|
||||
buf.append(mVaryCache.size());
|
||||
buf.append(varyCache.size());
|
||||
buf.append(" entries in a ");
|
||||
buf.append(mVaryCache.getClass().getName());
|
||||
buf.append(varyCache.getClass().getName());
|
||||
buf.append("}, ContentCache: {");
|
||||
buf.append(mContentCache.size());
|
||||
buf.append(contentCache.size());
|
||||
buf.append(" entries in a ");
|
||||
buf.append(mContentCache.getClass().getName());
|
||||
buf.append(contentCache.getClass().getName());
|
||||
buf.append("}]");
|
||||
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
void log(final String pMessage) {
|
||||
mLogger.log(Level.INFO, pMessage);
|
||||
logger.log(Level.INFO, pMessage);
|
||||
}
|
||||
|
||||
void log(final String pMessage, Throwable pException) {
|
||||
mLogger.log(Level.WARNING, pMessage, pException);
|
||||
logger.log(Level.WARNING, pMessage, pException);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -363,16 +347,15 @@ public class HTTPCache {
|
||||
|
||||
// Get/create cached entity
|
||||
CachedEntity cached;
|
||||
synchronized (mEntityCache) {
|
||||
cached = mEntityCache.get(cacheURI);
|
||||
synchronized (entityCache) {
|
||||
cached = entityCache.get(cacheURI);
|
||||
if (cached == null) {
|
||||
cached = new CachedEntityImpl(cacheURI, this);
|
||||
mEntityCache.put(cacheURI, cached);
|
||||
entityCache.put(cacheURI, cached);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// else if (not cached ||<7C>stale), resolve through wrapped (caching) response
|
||||
// else if (not cached || stale), resolve through wrapped (caching) response
|
||||
// else render to response
|
||||
|
||||
// TODO: This is a bottleneck for uncachable resources. Should not
|
||||
@@ -412,11 +395,11 @@ public class HTTPCache {
|
||||
|
||||
// Get/create cached entity
|
||||
CachedEntity cached;
|
||||
synchronized (mEntityCache) {
|
||||
cached = mEntityCache.get(cacheURI);
|
||||
synchronized (entityCache) {
|
||||
cached = entityCache.get(cacheURI);
|
||||
if (cached != null) {
|
||||
// TODO; Remove all variants
|
||||
mEntityCache.remove(cacheURI);
|
||||
entityCache.remove(cacheURI);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -461,7 +444,7 @@ public class HTTPCache {
|
||||
}
|
||||
|
||||
private boolean isCachable(final CacheResponse pResponse) {
|
||||
if (pResponse.getStatus() != STATUS_OK) {
|
||||
if (pResponse.getStatus() != HttpServletResponse.SC_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -531,7 +514,7 @@ public class HTTPCache {
|
||||
File file = null;
|
||||
|
||||
// Get base dir
|
||||
File base = new File(mTempDir, "./" + pCacheURI);
|
||||
File base = new File(tempDir, "./" + pCacheURI);
|
||||
final String basePath = base.getAbsolutePath();
|
||||
File directory = base.getParentFile();
|
||||
|
||||
@@ -603,7 +586,7 @@ public class HTTPCache {
|
||||
synchronized (pVariations) {
|
||||
try {
|
||||
File file = getVaryPropertiesFile(pCacheURI);
|
||||
if (!file.exists() && mDeleteCacheOnExit) {
|
||||
if (!file.exists() && deleteCacheOnExit) {
|
||||
file.deleteOnExit();
|
||||
}
|
||||
|
||||
@@ -624,11 +607,11 @@ public class HTTPCache {
|
||||
private Properties getVaryProperties(final String pCacheURI) {
|
||||
Properties variations;
|
||||
|
||||
synchronized (mVaryCache) {
|
||||
variations = mVaryCache.get(pCacheURI);
|
||||
synchronized (varyCache) {
|
||||
variations = varyCache.get(pCacheURI);
|
||||
if (variations == null) {
|
||||
variations = loadVaryProperties(pCacheURI);
|
||||
mVaryCache.put(pCacheURI, variations);
|
||||
varyCache.put(pCacheURI, variations);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -657,7 +640,7 @@ public class HTTPCache {
|
||||
}
|
||||
|
||||
private File getVaryPropertiesFile(final String pCacheURI) {
|
||||
return new File(mTempDir, "./" + pCacheURI + FILE_EXT_VARY);
|
||||
return new File(tempDir, "./" + pCacheURI + FILE_EXT_VARY);
|
||||
}
|
||||
|
||||
private static String generateCacheURI(final CacheRequest pRequest) {
|
||||
@@ -769,18 +752,18 @@ public class HTTPCache {
|
||||
extension = "[NULL]";
|
||||
}
|
||||
|
||||
synchronized (mContentCache) {
|
||||
mContentCache.put(pCacheURI + '.' + extension, pCachedResponse);
|
||||
synchronized (contentCache) {
|
||||
contentCache.put(pCacheURI + '.' + extension, pCachedResponse);
|
||||
|
||||
// This will be the default version
|
||||
if (!mContentCache.containsKey(pCacheURI)) {
|
||||
mContentCache.put(pCacheURI, pCachedResponse);
|
||||
if (!contentCache.containsKey(pCacheURI)) {
|
||||
contentCache.put(pCacheURI, pCachedResponse);
|
||||
}
|
||||
}
|
||||
|
||||
// Write the cached content to disk
|
||||
File content = new File(mTempDir, "./" + pCacheURI + '.' + extension);
|
||||
if (mDeleteCacheOnExit && !content.exists()) {
|
||||
File content = new File(tempDir, "./" + pCacheURI + '.' + extension);
|
||||
if (deleteCacheOnExit && !content.exists()) {
|
||||
content.deleteOnExit();
|
||||
}
|
||||
|
||||
@@ -809,7 +792,7 @@ public class HTTPCache {
|
||||
|
||||
// Write the cached headers to disk (in pseudo-properties-format)
|
||||
File headers = new File(content.getAbsolutePath() + FILE_EXT_HEADERS);
|
||||
if (mDeleteCacheOnExit && !headers.exists()) {
|
||||
if (deleteCacheOnExit && !headers.exists()) {
|
||||
headers.deleteOnExit();
|
||||
}
|
||||
|
||||
@@ -872,13 +855,13 @@ public class HTTPCache {
|
||||
String extension = getVaryExtension(pCacheURI, pRequest);
|
||||
|
||||
CachedResponse response;
|
||||
synchronized (mContentCache) {
|
||||
// System.out.println(" ## HTTPCache ## Looking up content with ext: \"" + extension + "\" from memory cache (" + mContentCache /*.size()*/ + " entries)...");
|
||||
synchronized (contentCache) {
|
||||
// System.out.println(" ## HTTPCache ## Looking up content with ext: \"" + extension + "\" from memory cache (" + contentCache /*.size()*/ + " entries)...");
|
||||
if ("ANY".equals(extension)) {
|
||||
response = mContentCache.get(pCacheURI);
|
||||
response = contentCache.get(pCacheURI);
|
||||
}
|
||||
else {
|
||||
response = mContentCache.get(pCacheURI + '.' + extension);
|
||||
response = contentCache.get(pCacheURI + '.' + extension);
|
||||
}
|
||||
|
||||
if (response == null) {
|
||||
@@ -913,7 +896,7 @@ public class HTTPCache {
|
||||
int headerSize = (int) headers.length();
|
||||
|
||||
BufferedReader reader = new BufferedReader(new FileReader(headers));
|
||||
LinkedMap<String, List<String>> headerMap = new LinkedMap<String, List<String>>();
|
||||
LinkedHashMap<String, List<String>> headerMap = new LinkedHashMap<String, List<String>>();
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
int colIdx = line.indexOf(':');
|
||||
@@ -931,8 +914,8 @@ public class HTTPCache {
|
||||
headerMap.put(name, Arrays.asList(StringUtil.toStringArray(value, "\\")));
|
||||
}
|
||||
|
||||
response = new CachedResponseImpl(STATUS_OK, headerMap, headerSize, contents);
|
||||
mContentCache.put(pCacheURI + '.' + FileUtil.getExtension(content), response);
|
||||
response = new CachedResponseImpl(HttpServletResponse.SC_OK, headerMap, headerSize, contents);
|
||||
contentCache.put(pCacheURI + '.' + FileUtil.getExtension(content), response);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
@@ -997,7 +980,7 @@ public class HTTPCache {
|
||||
// If Cache-Control: max-age is present, use it, otherwise default
|
||||
int maxAge = getIntHeader(response, HEADER_CACHE_CONTROL, "max-age");
|
||||
if (maxAge == -1) {
|
||||
expires = lastModified + mDefaultExpiryTime;
|
||||
expires = lastModified + defaultExpiryTime;
|
||||
//// System.out.println(" ## HTTPCache ## Expires is " + NetUtil.formatHTTPDate(expires) + ", using lastModified + defaultExpiry");
|
||||
}
|
||||
else {
|
||||
|
@@ -7,7 +7,7 @@ import java.io.IOException;
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/cache/ResponseResolver.java#2 $
|
||||
* @version $Id: ResponseResolver.java#2 $
|
||||
*/
|
||||
public interface ResponseResolver {
|
||||
void resolve(CacheRequest pRequest, CacheResponse pResponse) throws IOException, CacheException;
|
||||
|
@@ -52,42 +52,42 @@ import java.util.Map;
|
||||
* @author Jayson Falkner
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/cache/SerlvetCacheResponseWrapper.java#2 $
|
||||
* @version $Id: SerlvetCacheResponseWrapper.java#2 $
|
||||
*/
|
||||
class SerlvetCacheResponseWrapper extends HttpServletResponseWrapper {
|
||||
private ServletResponseStreamDelegate mStreamDelegate;
|
||||
private ServletResponseStreamDelegate streamDelegate;
|
||||
|
||||
private CacheResponse mCacheResponse;
|
||||
private CacheResponse cacheResponse;
|
||||
|
||||
private Boolean mCachable;
|
||||
private int mStatus;
|
||||
private Boolean cacheable;
|
||||
private int status;
|
||||
|
||||
public SerlvetCacheResponseWrapper(final HttpServletResponse pServletResponse, final CacheResponse pResponse) {
|
||||
super(pServletResponse);
|
||||
mCacheResponse = pResponse;
|
||||
cacheResponse = pResponse;
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
NOTE: This class defers determining if a response is cachable until the
|
||||
NOTE: This class defers determining if a response is cacheable until the
|
||||
output stream is needed.
|
||||
This it the reason for the somewhat complicated logic in the add/setHeader
|
||||
methods below.
|
||||
*/
|
||||
private void init() {
|
||||
mCachable = null;
|
||||
mStatus = SC_OK;
|
||||
mStreamDelegate = new ServletResponseStreamDelegate(this) {
|
||||
cacheable = null;
|
||||
status = SC_OK;
|
||||
streamDelegate = new ServletResponseStreamDelegate(this) {
|
||||
protected OutputStream createOutputStream() throws IOException {
|
||||
// Test if this request is really cachable, otherwise,
|
||||
// Test if this request is really cacheable, otherwise,
|
||||
// just write through to underlying response, and don't cache
|
||||
if (isCachable()) {
|
||||
return mCacheResponse.getOutputStream();
|
||||
if (isCacheable()) {
|
||||
return cacheResponse.getOutputStream();
|
||||
}
|
||||
else {
|
||||
// TODO: We need to tell the cache about this, somehow...
|
||||
writeHeaders(mCacheResponse, (HttpServletResponse) getResponse());
|
||||
writeHeaders(cacheResponse, (HttpServletResponse) getResponse());
|
||||
return super.getOutputStream();
|
||||
}
|
||||
}
|
||||
@@ -109,23 +109,23 @@ class SerlvetCacheResponseWrapper extends HttpServletResponseWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isCachable() {
|
||||
public boolean isCacheable() {
|
||||
// NOTE: Intentionally not synchronized
|
||||
if (mCachable == null) {
|
||||
mCachable = isCachableImpl();
|
||||
if (cacheable == null) {
|
||||
cacheable = isCacheableImpl();
|
||||
}
|
||||
|
||||
return mCachable;
|
||||
return cacheable;
|
||||
}
|
||||
|
||||
private boolean isCachableImpl() {
|
||||
private boolean isCacheableImpl() {
|
||||
// TODO: This code is duped in the cache...
|
||||
if (mStatus != SC_OK) {
|
||||
if (status != SC_OK) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Vary: *
|
||||
List<String> values = mCacheResponse.getHeaders().get(HTTPCache.HEADER_VARY);
|
||||
List<String> values = cacheResponse.getHeaders().get(HTTPCache.HEADER_VARY);
|
||||
if (values != null) {
|
||||
for (String value : values) {
|
||||
if ("*".equals(value)) {
|
||||
@@ -135,7 +135,7 @@ class SerlvetCacheResponseWrapper extends HttpServletResponseWrapper {
|
||||
}
|
||||
|
||||
// Cache-Control: no-cache, no-store, must-revalidate
|
||||
values = mCacheResponse.getHeaders().get(HTTPCache.HEADER_CACHE_CONTROL);
|
||||
values = cacheResponse.getHeaders().get(HTTPCache.HEADER_CACHE_CONTROL);
|
||||
if (values != null) {
|
||||
for (String value : values) {
|
||||
if (StringUtil.contains(value, "no-cache")
|
||||
@@ -147,7 +147,7 @@ class SerlvetCacheResponseWrapper extends HttpServletResponseWrapper {
|
||||
}
|
||||
|
||||
// Pragma: no-cache
|
||||
values = mCacheResponse.getHeaders().get(HTTPCache.HEADER_PRAGMA);
|
||||
values = cacheResponse.getHeaders().get(HTTPCache.HEADER_PRAGMA);
|
||||
if (values != null) {
|
||||
for (String value : values) {
|
||||
if (StringUtil.contains(value, "no-cache")) {
|
||||
@@ -160,43 +160,43 @@ class SerlvetCacheResponseWrapper extends HttpServletResponseWrapper {
|
||||
}
|
||||
|
||||
public void flushBuffer() throws IOException {
|
||||
mStreamDelegate.flushBuffer();
|
||||
streamDelegate.flushBuffer();
|
||||
}
|
||||
|
||||
public void resetBuffer() {
|
||||
// Servlet 2.3
|
||||
mStreamDelegate.resetBuffer();
|
||||
streamDelegate.resetBuffer();
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
if (Boolean.FALSE.equals(mCachable)) {
|
||||
if (Boolean.FALSE.equals(cacheable)) {
|
||||
super.reset();
|
||||
}
|
||||
// No else, might be cachable after all..
|
||||
// No else, might be cacheable after all..
|
||||
init();
|
||||
}
|
||||
|
||||
public ServletOutputStream getOutputStream() throws IOException {
|
||||
return mStreamDelegate.getOutputStream();
|
||||
return streamDelegate.getOutputStream();
|
||||
}
|
||||
|
||||
public PrintWriter getWriter() throws IOException {
|
||||
return mStreamDelegate.getWriter();
|
||||
return streamDelegate.getWriter();
|
||||
}
|
||||
|
||||
public boolean containsHeader(String name) {
|
||||
return mCacheResponse.getHeaders().get(name) != null;
|
||||
return cacheResponse.getHeaders().get(name) != null;
|
||||
}
|
||||
|
||||
public void sendError(int pStatusCode, String msg) throws IOException {
|
||||
// NOT cachable
|
||||
mStatus = pStatusCode;
|
||||
// NOT cacheable
|
||||
status = pStatusCode;
|
||||
super.sendError(pStatusCode, msg);
|
||||
}
|
||||
|
||||
public void sendError(int pStatusCode) throws IOException {
|
||||
// NOT cachable
|
||||
mStatus = pStatusCode;
|
||||
// NOT cacheable
|
||||
status = pStatusCode;
|
||||
super.sendError(pStatusCode);
|
||||
}
|
||||
|
||||
@@ -206,65 +206,65 @@ class SerlvetCacheResponseWrapper extends HttpServletResponseWrapper {
|
||||
}
|
||||
|
||||
public void setStatus(int pStatusCode) {
|
||||
// NOT cachable unless pStatusCode == 200 (or a FEW others?)
|
||||
// NOT cacheable unless pStatusCode == 200 (or a FEW others?)
|
||||
if (pStatusCode != SC_OK) {
|
||||
mStatus = pStatusCode;
|
||||
status = pStatusCode;
|
||||
super.setStatus(pStatusCode);
|
||||
}
|
||||
}
|
||||
|
||||
public void sendRedirect(String pLocation) throws IOException {
|
||||
// NOT cachable
|
||||
mStatus = SC_MOVED_TEMPORARILY;
|
||||
// NOT cacheable
|
||||
status = SC_MOVED_TEMPORARILY;
|
||||
super.sendRedirect(pLocation);
|
||||
}
|
||||
|
||||
public void setDateHeader(String pName, long pValue) {
|
||||
// If in write-trough-mode, set headers directly
|
||||
if (Boolean.FALSE.equals(mCachable)) {
|
||||
if (Boolean.FALSE.equals(cacheable)) {
|
||||
super.setDateHeader(pName, pValue);
|
||||
}
|
||||
mCacheResponse.setHeader(pName, NetUtil.formatHTTPDate(pValue));
|
||||
cacheResponse.setHeader(pName, NetUtil.formatHTTPDate(pValue));
|
||||
}
|
||||
|
||||
public void addDateHeader(String pName, long pValue) {
|
||||
// If in write-trough-mode, set headers directly
|
||||
if (Boolean.FALSE.equals(mCachable)) {
|
||||
if (Boolean.FALSE.equals(cacheable)) {
|
||||
super.addDateHeader(pName, pValue);
|
||||
}
|
||||
mCacheResponse.addHeader(pName, NetUtil.formatHTTPDate(pValue));
|
||||
cacheResponse.addHeader(pName, NetUtil.formatHTTPDate(pValue));
|
||||
}
|
||||
|
||||
public void setHeader(String pName, String pValue) {
|
||||
// If in write-trough-mode, set headers directly
|
||||
if (Boolean.FALSE.equals(mCachable)) {
|
||||
if (Boolean.FALSE.equals(cacheable)) {
|
||||
super.setHeader(pName, pValue);
|
||||
}
|
||||
mCacheResponse.setHeader(pName, pValue);
|
||||
cacheResponse.setHeader(pName, pValue);
|
||||
}
|
||||
|
||||
public void addHeader(String pName, String pValue) {
|
||||
// If in write-trough-mode, set headers directly
|
||||
if (Boolean.FALSE.equals(mCachable)) {
|
||||
if (Boolean.FALSE.equals(cacheable)) {
|
||||
super.addHeader(pName, pValue);
|
||||
}
|
||||
mCacheResponse.addHeader(pName, pValue);
|
||||
cacheResponse.addHeader(pName, pValue);
|
||||
}
|
||||
|
||||
public void setIntHeader(String pName, int pValue) {
|
||||
// If in write-trough-mode, set headers directly
|
||||
if (Boolean.FALSE.equals(mCachable)) {
|
||||
if (Boolean.FALSE.equals(cacheable)) {
|
||||
super.setIntHeader(pName, pValue);
|
||||
}
|
||||
mCacheResponse.setHeader(pName, String.valueOf(pValue));
|
||||
cacheResponse.setHeader(pName, String.valueOf(pValue));
|
||||
}
|
||||
|
||||
public void addIntHeader(String pName, int pValue) {
|
||||
// If in write-trough-mode, set headers directly
|
||||
if (Boolean.FALSE.equals(mCachable)) {
|
||||
if (Boolean.FALSE.equals(cacheable)) {
|
||||
super.addIntHeader(pName, pValue);
|
||||
}
|
||||
mCacheResponse.addHeader(pName, String.valueOf(pValue));
|
||||
cacheResponse.addHeader(pName, String.valueOf(pValue));
|
||||
}
|
||||
|
||||
public final void setContentType(String type) {
|
||||
|
@@ -12,45 +12,45 @@ import java.util.Map;
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/cache/ServletCacheRequest.java#1 $
|
||||
* @version $Id: ServletCacheRequest.java#1 $
|
||||
*/
|
||||
public final class ServletCacheRequest extends AbstractCacheRequest {
|
||||
private final HttpServletRequest mRequest;
|
||||
private final HttpServletRequest request;
|
||||
|
||||
private Map<String, List<String>> mHeaders;
|
||||
private Map<String, List<String>> mParameters;
|
||||
private Map<String, List<String>> headers;
|
||||
private Map<String, List<String>> parameters;
|
||||
|
||||
protected ServletCacheRequest(final HttpServletRequest pRequest) {
|
||||
super(URI.create(pRequest.getRequestURI()), pRequest.getMethod());
|
||||
mRequest = pRequest;
|
||||
request = pRequest;
|
||||
}
|
||||
|
||||
public Map<String, List<String>> getHeaders() {
|
||||
if (mHeaders == null) {
|
||||
mHeaders = ServletUtil.headersAsMap(mRequest);
|
||||
if (headers == null) {
|
||||
headers = ServletUtil.headersAsMap(request);
|
||||
}
|
||||
|
||||
return mHeaders;
|
||||
return headers;
|
||||
}
|
||||
|
||||
public Map<String, List<String>> getParameters() {
|
||||
if (mParameters == null) {
|
||||
mParameters = ServletUtil.parametersAsMap(mRequest);
|
||||
if (parameters == null) {
|
||||
parameters = ServletUtil.parametersAsMap(request);
|
||||
}
|
||||
|
||||
return mParameters;
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public String getServerName() {
|
||||
return mRequest.getServerName();
|
||||
return request.getServerName();
|
||||
}
|
||||
|
||||
public int getServerPort() {
|
||||
return mRequest.getServerPort();
|
||||
return request.getServerPort();
|
||||
}
|
||||
|
||||
HttpServletRequest getRequest() {
|
||||
return mRequest;
|
||||
return request;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -9,38 +9,38 @@ import java.io.OutputStream;
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/cache/ServletCacheResponse.java#2 $
|
||||
* @version $Id: ServletCacheResponse.java#2 $
|
||||
*/
|
||||
public final class ServletCacheResponse extends AbstractCacheResponse {
|
||||
private HttpServletResponse mResponse;
|
||||
private HttpServletResponse response;
|
||||
|
||||
public ServletCacheResponse(HttpServletResponse pResponse) {
|
||||
mResponse = pResponse;
|
||||
response = pResponse;
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream() throws IOException {
|
||||
return mResponse.getOutputStream();
|
||||
return response.getOutputStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setStatus(int pStatusCode) {
|
||||
mResponse.setStatus(pStatusCode);
|
||||
response.setStatus(pStatusCode);
|
||||
super.setStatus(pStatusCode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addHeader(String pHeaderName, String pHeaderValue) {
|
||||
mResponse.addHeader(pHeaderName, pHeaderValue);
|
||||
response.addHeader(pHeaderName, pHeaderValue);
|
||||
super.addHeader(pHeaderName, pHeaderValue);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeader(String pHeaderName, String pHeaderValue) {
|
||||
mResponse.setHeader(pHeaderName, pHeaderValue);
|
||||
response.setHeader(pHeaderName, pHeaderValue);
|
||||
super.setHeader(pHeaderName, pHeaderValue);
|
||||
}
|
||||
|
||||
HttpServletResponse getResponse() {
|
||||
return mResponse;
|
||||
return response;
|
||||
}
|
||||
}
|
||||
|
@@ -10,25 +10,25 @@ import java.io.IOException;
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/cache/ServletResponseResolver.java#2 $
|
||||
* @version $Id: ServletResponseResolver.java#2 $
|
||||
*/
|
||||
final class ServletResponseResolver implements ResponseResolver {
|
||||
final private ServletCacheRequest mRequest;
|
||||
final private ServletCacheResponse mResponse;
|
||||
final private FilterChain mChain;
|
||||
final private ServletCacheRequest request;
|
||||
final private ServletCacheResponse response;
|
||||
final private FilterChain chain;
|
||||
|
||||
ServletResponseResolver(final ServletCacheRequest pRequest, final ServletCacheResponse pResponse, final FilterChain pChain) {
|
||||
mRequest = pRequest;
|
||||
mResponse = pResponse;
|
||||
mChain = pChain;
|
||||
request = pRequest;
|
||||
response = pResponse;
|
||||
chain = pChain;
|
||||
}
|
||||
|
||||
public void resolve(final CacheRequest pRequest, final CacheResponse pResponse) throws IOException, CacheException {
|
||||
// Need only wrap if pResponse is not mResponse...
|
||||
HttpServletResponse response = pResponse == mResponse ? mResponse.getResponse() : new SerlvetCacheResponseWrapper(mResponse.getResponse(), pResponse);
|
||||
// Need only wrap if pResponse is not response...
|
||||
HttpServletResponse response = pResponse == this.response ? this.response.getResponse() : new SerlvetCacheResponseWrapper(this.response.getResponse(), pResponse);
|
||||
|
||||
try {
|
||||
mChain.doFilter(mRequest.getRequest(), response);
|
||||
chain.doFilter(request.getRequest(), response);
|
||||
}
|
||||
catch (ServletException e) {
|
||||
throw new CacheException(e);
|
||||
|
@@ -34,7 +34,7 @@ import java.io.OutputStream;
|
||||
* WritableCachedResponse
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/cache/WritableCachedResponse.java#2 $
|
||||
* @version $Id: WritableCachedResponse.java#2 $
|
||||
*/
|
||||
public interface WritableCachedResponse extends CachedResponse, CacheResponse {
|
||||
/**
|
||||
|
@@ -42,22 +42,22 @@ import java.util.Map;
|
||||
* WritableCachedResponseImpl
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/cache/WritableCachedResponseImpl.java#3 $
|
||||
* @version $Id: WritableCachedResponseImpl.java#3 $
|
||||
*/
|
||||
class WritableCachedResponseImpl implements WritableCachedResponse {
|
||||
private final CachedResponseImpl mCachedResponse;
|
||||
private final CachedResponseImpl cachedResponse;
|
||||
|
||||
/**
|
||||
* Creates a {@code WritableCachedResponseImpl}.
|
||||
*/
|
||||
protected WritableCachedResponseImpl() {
|
||||
mCachedResponse = new CachedResponseImpl();
|
||||
cachedResponse = new CachedResponseImpl();
|
||||
// Hmmm..
|
||||
setHeader(HTTPCache.HEADER_CACHED_TIME, NetUtil.formatHTTPDate(System.currentTimeMillis()));
|
||||
}
|
||||
|
||||
public CachedResponse getCachedResponse() {
|
||||
return mCachedResponse;
|
||||
return cachedResponse;
|
||||
}
|
||||
|
||||
public void setHeader(String pName, String pValue) {
|
||||
@@ -69,7 +69,7 @@ class WritableCachedResponseImpl implements WritableCachedResponse {
|
||||
}
|
||||
|
||||
public Map<String, List<String>> getHeaders() {
|
||||
return mCachedResponse.mHeaders;
|
||||
return cachedResponse.headers;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,28 +81,26 @@ class WritableCachedResponseImpl implements WritableCachedResponse {
|
||||
private void setHeader(String pName, String pValue, boolean pAdd) {
|
||||
// System.out.println(" ++ CachedResponse ++ " + (pAdd ? "addHeader(" : "setHeader(") + pName + ", " + pValue + ")");
|
||||
// If adding, get list and append, otherwise replace list
|
||||
List<String> values = null;
|
||||
if (pAdd) {
|
||||
values = mCachedResponse.mHeaders.get(pName);
|
||||
}
|
||||
List<String> values = pAdd ? cachedResponse.headers.get(pName) : null;
|
||||
|
||||
if (values == null) {
|
||||
values = new ArrayList<String>();
|
||||
|
||||
if (pAdd) {
|
||||
// Add length of pName
|
||||
mCachedResponse.mHeadersSize += (pName != null ? pName.length() : 0);
|
||||
cachedResponse.headersSize += (pName != null ? pName.length() : 0);
|
||||
}
|
||||
else {
|
||||
// Remove length of potential replaced old values + pName
|
||||
String[] oldValues = getHeaderValues(pName);
|
||||
|
||||
if (oldValues != null) {
|
||||
for (String oldValue : oldValues) {
|
||||
mCachedResponse.mHeadersSize -= oldValue.length();
|
||||
cachedResponse.headersSize -= oldValue.length();
|
||||
}
|
||||
}
|
||||
else {
|
||||
mCachedResponse.mHeadersSize += (pName != null ? pName.length() : 0);
|
||||
cachedResponse.headersSize += (pName != null ? pName.length() : 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,31 +110,31 @@ class WritableCachedResponseImpl implements WritableCachedResponse {
|
||||
values.add(pValue);
|
||||
|
||||
// Add length of pValue
|
||||
mCachedResponse.mHeadersSize += pValue.length();
|
||||
cachedResponse.headersSize += pValue.length();
|
||||
}
|
||||
|
||||
// Always add to headers
|
||||
mCachedResponse.mHeaders.put(pName, values);
|
||||
cachedResponse.headers.put(pName, values);
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream() {
|
||||
// TODO: Hmm.. Smells like DCL..?
|
||||
if (mCachedResponse.mContent == null) {
|
||||
if (cachedResponse.content == null) {
|
||||
createOutputStream();
|
||||
}
|
||||
return mCachedResponse.mContent;
|
||||
return cachedResponse.content;
|
||||
}
|
||||
|
||||
public void setStatus(int pStatusCode) {
|
||||
mCachedResponse.mStatus = pStatusCode;
|
||||
cachedResponse.status = pStatusCode;
|
||||
}
|
||||
|
||||
public int getStatus() {
|
||||
return mCachedResponse.getStatus();
|
||||
return cachedResponse.getStatus();
|
||||
}
|
||||
|
||||
private synchronized void createOutputStream() {
|
||||
ByteArrayOutputStream cache = mCachedResponse.mContent;
|
||||
ByteArrayOutputStream cache = cachedResponse.content;
|
||||
if (cache == null) {
|
||||
String contentLengthStr = getHeaderValue("Content-Length");
|
||||
if (contentLengthStr != null) {
|
||||
@@ -146,43 +144,43 @@ class WritableCachedResponseImpl implements WritableCachedResponse {
|
||||
else {
|
||||
cache = new FastByteArrayOutputStream(1024);
|
||||
}
|
||||
mCachedResponse.mContent = cache;
|
||||
cachedResponse.content = cache;
|
||||
}
|
||||
}
|
||||
|
||||
public void writeHeadersTo(CacheResponse pResponse) {
|
||||
mCachedResponse.writeHeadersTo(pResponse);
|
||||
cachedResponse.writeHeadersTo(pResponse);
|
||||
}
|
||||
|
||||
public void writeContentsTo(OutputStream pStream) throws IOException {
|
||||
mCachedResponse.writeContentsTo(pStream);
|
||||
cachedResponse.writeContentsTo(pStream);
|
||||
}
|
||||
|
||||
public String[] getHeaderNames() {
|
||||
return mCachedResponse.getHeaderNames();
|
||||
return cachedResponse.getHeaderNames();
|
||||
}
|
||||
|
||||
public String[] getHeaderValues(String pHeaderName) {
|
||||
return mCachedResponse.getHeaderValues(pHeaderName);
|
||||
return cachedResponse.getHeaderValues(pHeaderName);
|
||||
}
|
||||
|
||||
public String getHeaderValue(String pHeaderName) {
|
||||
return mCachedResponse.getHeaderValue(pHeaderName);
|
||||
return cachedResponse.getHeaderValue(pHeaderName);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return mCachedResponse.size();
|
||||
return cachedResponse.size();
|
||||
}
|
||||
|
||||
public boolean equals(Object pOther) {
|
||||
if (pOther instanceof WritableCachedResponse) {
|
||||
// Take advantage of faster implementation
|
||||
return mCachedResponse.equals(((WritableCachedResponse) pOther).getCachedResponse());
|
||||
return cachedResponse.equals(((WritableCachedResponse) pOther).getCachedResponse());
|
||||
}
|
||||
return mCachedResponse.equals(pOther);
|
||||
return cachedResponse.equals(pOther);
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
return mCachedResponse.hashCode();
|
||||
return cachedResponse.hashCode();
|
||||
}
|
||||
}
|
@@ -33,7 +33,7 @@ package com.twelvemonkeys.servlet.fileupload;
|
||||
* <p/>
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/fileupload/FileSizeExceededException.java#1 $
|
||||
* @version $Id: FileSizeExceededException.java#1 $
|
||||
*/
|
||||
public class FileSizeExceededException extends FileUploadException {
|
||||
public FileSizeExceededException(Throwable pCause) {
|
||||
|
@@ -35,7 +35,7 @@ import javax.servlet.ServletException;
|
||||
* <p/>
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/fileupload/FileUploadException.java#1 $
|
||||
* @version $Id: FileUploadException.java#1 $
|
||||
*/
|
||||
public class FileUploadException extends ServletException {
|
||||
public FileUploadException(String pMessage) {
|
||||
|
@@ -51,11 +51,11 @@ import java.net.MalformedURLException;
|
||||
* @see HttpFileUploadRequest
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/fileupload/FileUploadFilter.java#1 $
|
||||
* @version $Id: FileUploadFilter.java#1 $
|
||||
*/
|
||||
public class FileUploadFilter extends GenericFilter {
|
||||
private File mUploadDir;
|
||||
private long mMaxFileSize = 1024 * 1024; // 1 MByte
|
||||
private File uploadDir;
|
||||
private long maxFileSize = 1024 * 1024; // 1 MByte
|
||||
|
||||
/**
|
||||
* This method is called by the server before the filter goes into service,
|
||||
@@ -66,17 +66,19 @@ public class FileUploadFilter extends GenericFilter {
|
||||
public void init() throws ServletException {
|
||||
// Get the name of the upload directory.
|
||||
String uploadDirParam = getInitParameter("uploadDir");
|
||||
|
||||
if (!StringUtil.isEmpty(uploadDirParam)) {
|
||||
try {
|
||||
URL uploadDirURL = getServletContext().getResource(uploadDirParam);
|
||||
mUploadDir = FileUtil.toFile(uploadDirURL);
|
||||
uploadDir = FileUtil.toFile(uploadDirURL);
|
||||
}
|
||||
catch (MalformedURLException e) {
|
||||
throw new ServletException(e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
if (mUploadDir == null) {
|
||||
mUploadDir = ServletUtil.getTempDir(getServletContext());
|
||||
|
||||
if (uploadDir == null) {
|
||||
uploadDir = ServletUtil.getTempDir(getServletContext());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,23 +88,9 @@ public class FileUploadFilter extends GenericFilter {
|
||||
*
|
||||
* @param pMaxSize
|
||||
*/
|
||||
// public void setMaxFileSize(String pMaxSize) {
|
||||
// try {
|
||||
// setMaxFileSize(Long.parseLong(pMaxSize));
|
||||
// }
|
||||
// catch (NumberFormatException e) {
|
||||
// log("Error setting maxFileSize, using default: " + mMaxFileSize, e);
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Sets max filesize allowed for upload.
|
||||
*
|
||||
* @param pMaxSize
|
||||
*/
|
||||
public void setMaxFileSize(long pMaxSize) {
|
||||
log("maxFileSize=" + pMaxSize);
|
||||
mMaxFileSize = pMaxSize;
|
||||
maxFileSize = pMaxSize;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -125,7 +113,7 @@ public class FileUploadFilter extends GenericFilter {
|
||||
|
||||
// If the content type is multipart, wrap
|
||||
if (isMultipartFileUpload(contentType)) {
|
||||
pRequest = new HttpFileUploadRequestWrapper(request, mUploadDir, mMaxFileSize);
|
||||
pRequest = new HttpFileUploadRequestWrapper(request, uploadDir, maxFileSize);
|
||||
}
|
||||
|
||||
pChain.doFilter(pRequest, pResponse);
|
||||
|
@@ -35,7 +35,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||
* <a href="http://www.ietf.org/rfc/rfc1867.txt">Form-based File Upload in HTML (RFC1867)</a>.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/fileupload/HttpFileUploadRequest.java#1 $
|
||||
* @version $Id: HttpFileUploadRequest.java#1 $
|
||||
*/
|
||||
public interface HttpFileUploadRequest extends HttpServletRequest {
|
||||
/**
|
||||
|
@@ -43,12 +43,12 @@ import java.util.*;
|
||||
* <a href="http://jakarta.apache.org/commons/fileupload/">Jakarta Commons FileUpload</a>.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/fileupload/HttpFileUploadRequestWrapper.java#1 $
|
||||
* @version $Id: HttpFileUploadRequestWrapper.java#1 $
|
||||
*/
|
||||
class HttpFileUploadRequestWrapper extends HttpServletRequestWrapper implements HttpFileUploadRequest {
|
||||
|
||||
private final Map<String, String[]> mParameters = new HashMap<String, String[]>();
|
||||
private final Map<String, UploadedFile[]> mFiles = new HashMap<String, UploadedFile[]>();
|
||||
private final Map<String, String[]> parameters = new HashMap<String, String[]>();
|
||||
private final Map<String, UploadedFile[]> files = new HashMap<String, UploadedFile[]>();
|
||||
|
||||
public HttpFileUploadRequestWrapper(HttpServletRequest pRequest, File pUploadDir, long pMaxSize) throws ServletException {
|
||||
super(pRequest);
|
||||
@@ -86,7 +86,7 @@ class HttpFileUploadRequestWrapper extends HttpServletRequestWrapper implements
|
||||
String name = pItem.getFieldName();
|
||||
|
||||
UploadedFile[] values;
|
||||
UploadedFile[] oldValues = mFiles.get(name);
|
||||
UploadedFile[] oldValues = files.get(name);
|
||||
|
||||
if (oldValues != null) {
|
||||
values = new UploadedFile[oldValues.length + 1];
|
||||
@@ -97,7 +97,7 @@ class HttpFileUploadRequestWrapper extends HttpServletRequestWrapper implements
|
||||
values = new UploadedFile[] {value};
|
||||
}
|
||||
|
||||
mFiles.put(name, values);
|
||||
files.put(name, values);
|
||||
|
||||
// Also add to normal fields
|
||||
processFormField(name, value.getName());
|
||||
@@ -108,7 +108,7 @@ class HttpFileUploadRequestWrapper extends HttpServletRequestWrapper implements
|
||||
// probably faster to just use arrays...
|
||||
// TODO: Research and document...
|
||||
String[] values;
|
||||
String[] oldValues = mParameters.get(pName);
|
||||
String[] oldValues = parameters.get(pName);
|
||||
|
||||
if (oldValues != null) {
|
||||
values = new String[oldValues.length + 1];
|
||||
@@ -119,17 +119,17 @@ class HttpFileUploadRequestWrapper extends HttpServletRequestWrapper implements
|
||||
values = new String[] {pValue};
|
||||
}
|
||||
|
||||
mParameters.put(pName, values);
|
||||
parameters.put(pName, values);
|
||||
}
|
||||
|
||||
public Map getParameterMap() {
|
||||
// TODO: The spec dicates immutable map, but what about the value arrays?!
|
||||
// Probably just leave as-is, for performance
|
||||
return Collections.unmodifiableMap(mParameters);
|
||||
return Collections.unmodifiableMap(parameters);
|
||||
}
|
||||
|
||||
public Enumeration getParameterNames() {
|
||||
return Collections.enumeration(mParameters.keySet());
|
||||
return Collections.enumeration(parameters.keySet());
|
||||
}
|
||||
|
||||
public String getParameter(String pString) {
|
||||
@@ -139,7 +139,7 @@ class HttpFileUploadRequestWrapper extends HttpServletRequestWrapper implements
|
||||
|
||||
public String[] getParameterValues(String pString) {
|
||||
// TODO: Optimize?
|
||||
return mParameters.get(pString).clone();
|
||||
return parameters.get(pString).clone();
|
||||
}
|
||||
|
||||
public UploadedFile getUploadedFile(String pName) {
|
||||
@@ -149,6 +149,6 @@ class HttpFileUploadRequestWrapper extends HttpServletRequestWrapper implements
|
||||
|
||||
public UploadedFile[] getUploadedFiles(String pName) {
|
||||
// TODO: Optimize?
|
||||
return mFiles.get(pName).clone();
|
||||
return files.get(pName).clone();
|
||||
}
|
||||
}
|
@@ -36,7 +36,7 @@ import java.io.IOException;
|
||||
* This class represents an uploaded file.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/fileupload/UploadedFile.java#1 $
|
||||
* @version $Id: UploadedFile.java#1 $
|
||||
*/
|
||||
public interface UploadedFile {
|
||||
/**
|
||||
|
@@ -40,38 +40,38 @@ import java.io.File;
|
||||
* <a href="http://jakarta.apache.org/commons/fileupload/">Jakarta Commons FileUpload</a>.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/fileupload/UploadedFileImpl.java#1 $
|
||||
* @version $Id: UploadedFileImpl.java#1 $
|
||||
*/
|
||||
class UploadedFileImpl implements UploadedFile {
|
||||
private final FileItem mItem;
|
||||
private final FileItem item;
|
||||
|
||||
public UploadedFileImpl(FileItem pItem) {
|
||||
if (pItem == null) {
|
||||
throw new IllegalArgumentException("fileitem == null");
|
||||
}
|
||||
|
||||
mItem = pItem;
|
||||
item = pItem;
|
||||
}
|
||||
|
||||
public String getContentType() {
|
||||
return mItem.getContentType();
|
||||
return item.getContentType();
|
||||
}
|
||||
|
||||
public InputStream getInputStream() throws IOException {
|
||||
return mItem.getInputStream();
|
||||
return item.getInputStream();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return mItem.getName();
|
||||
return item.getName();
|
||||
}
|
||||
|
||||
public long length() {
|
||||
return mItem.getSize();
|
||||
return item.getSize();
|
||||
}
|
||||
|
||||
public void writeTo(File pFile) throws IOException {
|
||||
try {
|
||||
mItem.write(pFile);
|
||||
item.write(pFile);
|
||||
}
|
||||
catch(RuntimeException e) {
|
||||
throw e;
|
||||
|
@@ -104,12 +104,12 @@ import java.io.IOException;
|
||||
* @author Jayson Falkner
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/gzip/GZIPFilter.java#1 $
|
||||
* @version $Id: GZIPFilter.java#1 $
|
||||
*/
|
||||
public class GZIPFilter extends GenericFilter {
|
||||
|
||||
{
|
||||
mOncePerRequest = true;
|
||||
oncePerRequest = true;
|
||||
}
|
||||
|
||||
protected void doFilterImpl(ServletRequest pRequest, ServletResponse pResponse, FilterChain pChain) throws IOException, ServletException {
|
||||
@@ -120,22 +120,22 @@ public class GZIPFilter extends GenericFilter {
|
||||
|
||||
// If GZIP is supported, use compression
|
||||
String accept = request.getHeader("Accept-Encoding");
|
||||
if (accept != null && accept.indexOf("gzip") != -1) {
|
||||
if (accept != null && accept.contains("gzip")) {
|
||||
//System.out.println("GZIP supported, compressing.");
|
||||
// TODO: Set Vary: Accept-Encoding ?!
|
||||
|
||||
GZIPResponseWrapper wrapped = new GZIPResponseWrapper(response);
|
||||
|
||||
try {
|
||||
pChain.doFilter(pRequest, wrapped);
|
||||
}
|
||||
finally {
|
||||
wrapped.flushResponse();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Else, contiue chain
|
||||
// Else, continue chain
|
||||
pChain.doFilter(pRequest, pResponse);
|
||||
}
|
||||
}
|
||||
|
@@ -48,99 +48,100 @@ import java.util.zip.GZIPOutputStream;
|
||||
* @author Jayson Falkner
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/gzip/GZIPResponseWrapper.java#1 $
|
||||
* @version $Id: GZIPResponseWrapper.java#1 $
|
||||
*/
|
||||
public class GZIPResponseWrapper extends HttpServletResponseWrapper {
|
||||
protected ServletOutputStream mOut = null;
|
||||
protected PrintWriter mWriter = null;
|
||||
protected GZIPOutputStream mGZIPOut = null;
|
||||
protected int mContentLength = -1;
|
||||
// TODO: Remove/update ETags if needed? Read the spec (RFC 2616) on Vary/ETag for caching
|
||||
|
||||
public GZIPResponseWrapper(HttpServletResponse response) {
|
||||
protected ServletOutputStream out;
|
||||
protected PrintWriter writer;
|
||||
protected GZIPOutputStream gzipOut;
|
||||
protected int contentLength = -1;
|
||||
|
||||
public GZIPResponseWrapper(final HttpServletResponse response) {
|
||||
super(response);
|
||||
|
||||
response.addHeader("Content-Encoding", "gzip");
|
||||
response.addHeader("Vary", "Accept");
|
||||
}
|
||||
|
||||
public ServletOutputStream createOutputStream() throws IOException {
|
||||
// FIX: Write directly to servlet output stream, for faster responses.
|
||||
// Relies on chunked streams, or buffering in the servlet engine.
|
||||
if (mContentLength >= 0) {
|
||||
mGZIPOut = new GZIPOutputStream(getResponse().getOutputStream(), mContentLength);
|
||||
if (contentLength >= 0) {
|
||||
gzipOut = new GZIPOutputStream(getResponse().getOutputStream(), contentLength);
|
||||
}
|
||||
else {
|
||||
mGZIPOut = new GZIPOutputStream(getResponse().getOutputStream());
|
||||
gzipOut = new GZIPOutputStream(getResponse().getOutputStream());
|
||||
}
|
||||
|
||||
// Wrap in ServletOutputStream and return
|
||||
return new OutputStreamAdapter(mGZIPOut);
|
||||
return new OutputStreamAdapter(gzipOut);
|
||||
}
|
||||
|
||||
// TODO: Move this to flushbuffer or something? Hmmm..
|
||||
public void flushResponse() {
|
||||
public void flushResponse() throws IOException {
|
||||
try {
|
||||
try {
|
||||
// Finish GZIP encodig
|
||||
if (mGZIPOut != null) {
|
||||
mGZIPOut.finish();
|
||||
}
|
||||
// Finish GZIP encodig
|
||||
if (gzipOut != null) {
|
||||
gzipOut.finish();
|
||||
}
|
||||
|
||||
flushBuffer();
|
||||
}
|
||||
finally {
|
||||
// Close stream
|
||||
if (mWriter != null) {
|
||||
mWriter.close();
|
||||
}
|
||||
else {
|
||||
if (mOut != null) {
|
||||
mOut.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
flushBuffer();
|
||||
}
|
||||
catch (IOException e) {
|
||||
// TODO: Fix this one...
|
||||
e.printStackTrace();
|
||||
finally {
|
||||
// Close stream
|
||||
if (writer != null) {
|
||||
writer.close();
|
||||
}
|
||||
else {
|
||||
if (out != null) {
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void flushBuffer() throws IOException {
|
||||
if (mWriter != null) {
|
||||
mWriter.flush();
|
||||
if (writer != null) {
|
||||
writer.flush();
|
||||
}
|
||||
else if (mOut != null) {
|
||||
mOut.flush();
|
||||
else if (out != null) {
|
||||
out.flush();
|
||||
}
|
||||
}
|
||||
|
||||
public ServletOutputStream getOutputStream() throws IOException {
|
||||
if (mWriter != null) {
|
||||
if (writer != null) {
|
||||
throw new IllegalStateException("getWriter() has already been called!");
|
||||
}
|
||||
|
||||
if (mOut == null) {
|
||||
mOut = createOutputStream();
|
||||
if (out == null) {
|
||||
out = createOutputStream();
|
||||
}
|
||||
return (mOut);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
public PrintWriter getWriter() throws IOException {
|
||||
if (mWriter != null) {
|
||||
return (mWriter);
|
||||
if (writer != null) {
|
||||
return (writer);
|
||||
}
|
||||
|
||||
if (mOut != null) {
|
||||
if (out != null) {
|
||||
throw new IllegalStateException("getOutputStream() has already been called!");
|
||||
}
|
||||
|
||||
mOut = createOutputStream();
|
||||
// TODO: This is wrong. Should use getCharacterEncoding() or "ISO-8859-1" if gCE returns null.
|
||||
mWriter = new PrintWriter(new OutputStreamWriter(mOut, "UTF-8"));
|
||||
return (mWriter);
|
||||
out = createOutputStream();
|
||||
|
||||
// TODO: This is wrong. Should use getCharacterEncoding() or "ISO-8859-1" if getCE returns null.
|
||||
writer = new PrintWriter(new OutputStreamWriter(out, "UTF-8"));
|
||||
|
||||
return writer;
|
||||
}
|
||||
|
||||
public void setContentLength(int pLength) {
|
||||
// NOTE: Do not call super, as we will shrink the size.
|
||||
mContentLength = pLength;
|
||||
contentLength = pLength;
|
||||
}
|
||||
}
|
||||
|
@@ -38,18 +38,18 @@ import java.awt.image.RenderedImage;
|
||||
/**
|
||||
* AWTImageFilterAdapter
|
||||
*
|
||||
* @author $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/image/AWTImageFilterAdapter.java#1 $
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: AWTImageFilterAdapter.java#1 $
|
||||
*
|
||||
*/
|
||||
public class AWTImageFilterAdapter extends ImageFilter {
|
||||
|
||||
private java.awt.image.ImageFilter mFilter = null;
|
||||
private java.awt.image.ImageFilter imageFilter = null;
|
||||
|
||||
public void setImageFilter(String pFilterClass) {
|
||||
try {
|
||||
Class filterClass = Class.forName(pFilterClass);
|
||||
mFilter = (java.awt.image.ImageFilter) filterClass.newInstance();
|
||||
imageFilter = (java.awt.image.ImageFilter) filterClass.newInstance();
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
log("Could not load filter class.", e);
|
||||
@@ -64,9 +64,9 @@ public class AWTImageFilterAdapter extends ImageFilter {
|
||||
|
||||
protected RenderedImage doFilter(BufferedImage pImage, ServletRequest pRequest, ImageServletResponse pResponse) {
|
||||
// Filter
|
||||
Image img = ImageUtil.filter(pImage, mFilter);
|
||||
Image img = ImageUtil.filter(pImage, imageFilter);
|
||||
|
||||
// Create BufferedImage & return
|
||||
return ImageUtil.toBuffered(img, BufferedImage.TYPE_INT_RGB); // TODO: This is for JPEG only...
|
||||
return ImageUtil.toBuffered(img, BufferedImage.TYPE_INT_RGB); // TODO: This is ok for JPEG only...
|
||||
}
|
||||
}
|
||||
|
@@ -36,18 +36,18 @@ import java.awt.image.RenderedImage;
|
||||
/**
|
||||
* BufferedImageOpAdapter
|
||||
*
|
||||
* @author $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/image/BufferedImageOpAdapter.java#1 $
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: BufferedImageOpAdapter.java#1 $
|
||||
*
|
||||
*/
|
||||
public class BufferedImageOpAdapter extends ImageFilter {
|
||||
|
||||
private BufferedImageOp mFilter = null;
|
||||
private BufferedImageOp filter = null;
|
||||
|
||||
public void setImageFilter(String pFilterClass) {
|
||||
try {
|
||||
Class filterClass = Class.forName(pFilterClass);
|
||||
mFilter = (BufferedImageOp) filterClass.newInstance();
|
||||
filter = (BufferedImageOp) filterClass.newInstance();
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
log("Could not instantiate filter class.", e);
|
||||
@@ -62,6 +62,6 @@ public class BufferedImageOpAdapter extends ImageFilter {
|
||||
|
||||
protected RenderedImage doFilter(BufferedImage pImage, ServletRequest pRequest, ImageServletResponse pResponse) {
|
||||
// Filter & return
|
||||
return mFilter.filter(pImage, null);
|
||||
return filter.filter(pImage, null);
|
||||
}
|
||||
}
|
||||
|
@@ -47,7 +47,7 @@ import java.util.zip.CRC32;
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/image/ColorServlet.java#2 $
|
||||
* @version $Id: ColorServlet.java#2 $
|
||||
*/
|
||||
public class ColorServlet extends GenericServlet {
|
||||
private final static String RGB_PARAME = "color";
|
||||
@@ -87,7 +87,7 @@ public class ColorServlet extends GenericServlet {
|
||||
private final static int GREEN_IDX = RED_IDX + 1;
|
||||
private final static int BLUE_IDX = GREEN_IDX + 1;
|
||||
|
||||
private final CRC32 mCRC = new CRC32();
|
||||
private final CRC32 crc = new CRC32();
|
||||
|
||||
/**
|
||||
* Creates a ColorDroplet.
|
||||
@@ -108,7 +108,6 @@ public class ColorServlet extends GenericServlet {
|
||||
* @throws ServletException
|
||||
*/
|
||||
public void service(ServletRequest pRequest, ServletResponse pResponse) throws IOException, ServletException {
|
||||
|
||||
int red = 0;
|
||||
int green = 0;
|
||||
int blue = 0;
|
||||
@@ -172,10 +171,10 @@ public class ColorServlet extends GenericServlet {
|
||||
private void updateCRC(byte[] pBytes, int pOff, int pLen) {
|
||||
int value;
|
||||
|
||||
synchronized (mCRC) {
|
||||
mCRC.reset();
|
||||
mCRC.update(pBytes, pOff, pLen);
|
||||
value = (int) mCRC.getValue();
|
||||
synchronized (crc) {
|
||||
crc.reset();
|
||||
crc.update(pBytes, pOff, pLen);
|
||||
value = (int) crc.getValue();
|
||||
}
|
||||
|
||||
pBytes[pOff + pLen ] = (byte) ((value >> 24) & 0xff);
|
||||
|
@@ -38,7 +38,7 @@ import java.io.IOException;
|
||||
* <p/>
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/image/ComposeFilter.java#1 $
|
||||
* @version $Id: ComposeFilter.java#1 $
|
||||
*/
|
||||
public class ComposeFilter extends ImageFilter {
|
||||
protected RenderedImage doFilter(BufferedImage pImage, ServletRequest pRequest, ImageServletResponse pResponse) throws IOException {
|
||||
|
@@ -54,6 +54,9 @@ import java.util.*;
|
||||
* unneccessary conversion (as IE supports PNG, the latests FireFox supports
|
||||
* JPEG and GIF, etc. even though they both don't explicitly list these formats
|
||||
* in their Accept headers).
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: ContentNegotiationFilter.java#1 $
|
||||
*/
|
||||
public class ContentNegotiationFilter extends ImageFilter {
|
||||
|
||||
@@ -72,12 +75,12 @@ public class ContentNegotiationFilter extends ImageFilter {
|
||||
private final static String[] sKnownFormats = new String[] {
|
||||
FORMAT_JPEG, FORMAT_PNG, FORMAT_GIF, FORMAT_WBMP
|
||||
};
|
||||
private float[] mKnownFormatQuality = new float[] {
|
||||
private float[] knownFormatQuality = new float[] {
|
||||
1f, 1f, 0.99f, 0.5f
|
||||
};
|
||||
|
||||
private HashMap<String, Float> mFormatQuality; // HashMap, as I need to clone this for each request
|
||||
private final Object mLock = new Object();
|
||||
private HashMap<String, Float> formatQuality; // HashMap, as I need to clone this for each request
|
||||
private final Object lock = new Object();
|
||||
|
||||
/*
|
||||
private Pattern[] mKnownAgentPatterns;
|
||||
@@ -86,7 +89,7 @@ public class ContentNegotiationFilter extends ImageFilter {
|
||||
{
|
||||
// Hack: Make sure the filter don't trigger all the time
|
||||
// See: super.trigger(ServletRequest)
|
||||
mTriggerParams = new String[] {};
|
||||
triggerParams = new String[] {};
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -242,9 +245,9 @@ public class ContentNegotiationFilter extends ImageFilter {
|
||||
}
|
||||
|
||||
private Map<String, Float> getFormatQualityMapping() {
|
||||
synchronized(mLock) {
|
||||
if (mFormatQuality == null) {
|
||||
mFormatQuality = new HashMap<String, Float>();
|
||||
synchronized(lock) {
|
||||
if (formatQuality == null) {
|
||||
formatQuality = new HashMap<String, Float>();
|
||||
|
||||
// Use ImageIO to find formats we can actually write
|
||||
String[] formats = ImageIO.getWriterMIMETypes();
|
||||
@@ -252,12 +255,12 @@ public class ContentNegotiationFilter extends ImageFilter {
|
||||
// All known formats qs are initially 1.0
|
||||
// Others should be 0.1 or something like that...
|
||||
for (String format : formats) {
|
||||
mFormatQuality.put(format, getKnownFormatQuality(format));
|
||||
formatQuality.put(format, getKnownFormatQuality(format));
|
||||
}
|
||||
}
|
||||
}
|
||||
//noinspection unchecked
|
||||
return (Map<String, Float>) mFormatQuality.clone();
|
||||
return (Map<String, Float>) formatQuality.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -428,7 +431,7 @@ public class ContentNegotiationFilter extends ImageFilter {
|
||||
private float getKnownFormatQuality(String pFormat) {
|
||||
for (int i = 0; i < sKnownFormats.length; i++) {
|
||||
if (pFormat.equals(sKnownFormats[i])) {
|
||||
return mKnownFormatQuality[i];
|
||||
return knownFormatQuality[i];
|
||||
}
|
||||
}
|
||||
return 0.1f;
|
||||
|
@@ -91,7 +91,7 @@ import java.awt.image.RenderedImage;
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/image/CropFilter.java#1 $
|
||||
* @version $Id: CropFilter.java#1 $
|
||||
*/
|
||||
public class CropFilter extends ScaleFilter {
|
||||
/** {@code cropX}*/
|
||||
|
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Harald Kuhr
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name "TwelveMonkeys" nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.servlet.image;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.imageio.spi.IIORegistry;
|
||||
import javax.imageio.spi.ServiceRegistry;
|
||||
import javax.servlet.ServletContextEvent;
|
||||
import javax.servlet.ServletContextListener;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Takes care of registering and de-registering local ImageIO plugins (service providers) for the servlet context.
|
||||
* <p/>
|
||||
* Registers all available plugins on {@code contextInitialized} event, using {@code ImageIO.scanForPlugins()}, to make
|
||||
* sure they are available to the current servlet context.
|
||||
* De-registers all plugins which have the {@link Thread#getContextClassLoader() current thread's context class loader}
|
||||
* as its class loader on {@code contextDestroyed} event, to avoid class/resource leak.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haraldk$
|
||||
* @version $Id: IIOProviderContextListener.java,v 1.0 14.02.12 21:53 haraldk Exp$
|
||||
* @see javax.imageio.ImageIO#scanForPlugins()
|
||||
*/
|
||||
public final class IIOProviderContextListener implements ServletContextListener {
|
||||
|
||||
public void contextInitialized(final ServletContextEvent event) {
|
||||
// Registers all locally available IIO plugins.
|
||||
ImageIO.scanForPlugins();
|
||||
}
|
||||
|
||||
public void contextDestroyed(final ServletContextEvent event) {
|
||||
// De-register any locally registered IIO plugins. Relies on each web app having its own context class loader.
|
||||
final IIORegistry registry = IIORegistry.getDefaultInstance();
|
||||
final LocalFilter localFilter = new LocalFilter(Thread.currentThread().getContextClassLoader()); // scanForPlugins uses context class loader
|
||||
|
||||
Iterator<Class<?>> categories = registry.getCategories();
|
||||
|
||||
while (categories.hasNext()) {
|
||||
Class<?> category = categories.next();
|
||||
Iterator<?> providers = registry.getServiceProviders(category, localFilter, false);
|
||||
|
||||
while (providers.hasNext()) {
|
||||
Object provider = providers.next();
|
||||
registry.deregisterServiceProvider(provider);
|
||||
event.getServletContext().log(String.format("Unregistered locally installed provider class: %s", provider.getClass()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class LocalFilter implements ServiceRegistry.Filter {
|
||||
private final ClassLoader loader;
|
||||
|
||||
public LocalFilter(ClassLoader loader) {
|
||||
this.loader = loader;
|
||||
}
|
||||
|
||||
public boolean filter(Object provider) {
|
||||
return provider.getClass().getClassLoader() == loader;
|
||||
}
|
||||
}
|
||||
}
|
@@ -33,6 +33,7 @@ import com.twelvemonkeys.lang.StringUtil;
|
||||
import com.twelvemonkeys.servlet.GenericFilter;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.awt.image.RenderedImage;
|
||||
import java.io.IOException;
|
||||
@@ -44,21 +45,25 @@ import java.io.IOException;
|
||||
* @see #doFilter(java.awt.image.BufferedImage,javax.servlet.ServletRequest,ImageServletResponse)
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/image/ImageFilter.java#2 $
|
||||
* @version $Id: ImageFilter.java#2 $
|
||||
*
|
||||
*/
|
||||
public abstract class ImageFilter extends GenericFilter {
|
||||
// TODO: Take the design back to the drawing board (see ImageServletResponseImpl)
|
||||
// - Allow multiple filters to set size attribute
|
||||
// - Allow a later filter to reset, to get pass-through given certain criteria...
|
||||
// - Or better yet, allow a filter to decide if it wants to decode, based on image metadata on the original image (ie: width/height)
|
||||
|
||||
protected String[] mTriggerParams = null;
|
||||
protected String[] triggerParams = null;
|
||||
|
||||
/**
|
||||
* The {@code doFilterImpl} method is called once, or each time a
|
||||
* request/response pair is passed through the chain, depending on the
|
||||
* {@link #mOncePerRequest} member variable.
|
||||
* {@link #oncePerRequest} member variable.
|
||||
*
|
||||
* @see #mOncePerRequest
|
||||
* @see com.twelvemonkeys.servlet.GenericFilter#doFilterImpl doFilter
|
||||
* @see Filter#doFilter Filter.doFilter
|
||||
* @see #oncePerRequest
|
||||
* @see com.twelvemonkeys.servlet.GenericFilter#doFilterImpl(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain) doFilter
|
||||
* @see Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain) Filter.doFilter
|
||||
*
|
||||
* @param pRequest the servlet request
|
||||
* @param pResponse the servlet response
|
||||
@@ -67,7 +72,7 @@ public abstract class ImageFilter extends GenericFilter {
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
protected void doFilterImpl(ServletRequest pRequest, ServletResponse pResponse, FilterChain pChain)
|
||||
protected void doFilterImpl(final ServletRequest pRequest, final ServletResponse pResponse, final FilterChain pChain)
|
||||
throws IOException, ServletException {
|
||||
|
||||
//System.out.println("Starting filtering...");
|
||||
@@ -78,19 +83,12 @@ public abstract class ImageFilter extends GenericFilter {
|
||||
pChain.doFilter(pRequest, pResponse);
|
||||
}
|
||||
else {
|
||||
// If already wrapped, the image will be encoded later in the chain
|
||||
// Or, if this is first filter in chain, we must encode when done
|
||||
boolean encode = !(pResponse instanceof ImageServletResponse);
|
||||
|
||||
// For images, we do post filtering only and need to wrap the response
|
||||
ImageServletResponse imageResponse;
|
||||
boolean encode;
|
||||
if (pResponse instanceof ImageServletResponse) {
|
||||
//System.out.println("Allready ImageServletResponse");
|
||||
imageResponse = (ImageServletResponse) pResponse;
|
||||
encode = false; // Allready wrapped, will be encoded later in the chain
|
||||
}
|
||||
else {
|
||||
//System.out.println("Wrapping in ImageServletResponse");
|
||||
imageResponse = new ImageServletResponseImpl(pRequest, pResponse, getServletContext());
|
||||
encode = true; // This is first filter in chain, must encode when done
|
||||
}
|
||||
ImageServletResponse imageResponse = createImageServletResponse(pRequest, pResponse);
|
||||
|
||||
//System.out.println("Passing request on to next in chain...");
|
||||
// Pass the request on
|
||||
@@ -113,36 +111,55 @@ public abstract class ImageFilter extends GenericFilter {
|
||||
//System.out.println("Done filtering.");
|
||||
|
||||
//System.out.println("Making image available...");
|
||||
// Make image available to other filters (avoid unnecessary
|
||||
// serializing/deserializing)
|
||||
// Make image available to other filters (avoid unnecessary serializing/deserializing)
|
||||
imageResponse.setImage(image);
|
||||
//System.out.println("Done.");
|
||||
|
||||
if (encode) {
|
||||
//System.out.println("Encoding image...");
|
||||
// Encode image to original repsonse
|
||||
if (image != null) {
|
||||
// TODO: Be smarter than this...
|
||||
// TODO: Make sure ETag is same, if image content is the same...
|
||||
// Use ETag of original response (or derived from)
|
||||
// Use last modified of original response? Or keep original resource's, don't set at all?
|
||||
// TODO: Why weak ETag?
|
||||
String etag = "W/\"" + Integer.toHexString(hashCode()) + "-" + Integer.toHexString(image.hashCode()) + "\"";
|
||||
((ImageServletResponseImpl) imageResponse).setHeader("ETag", etag);
|
||||
((ImageServletResponseImpl) imageResponse).setDateHeader("Last-Modified", (System.currentTimeMillis() / 1000) * 1000);
|
||||
imageResponse.flush();
|
||||
}
|
||||
//System.out.println("Done encoding.");
|
||||
}
|
||||
if (encode) {
|
||||
//System.out.println("Encoding image...");
|
||||
// Encode image to original response
|
||||
if (image != null) {
|
||||
// TODO: Be smarter than this...
|
||||
// TODO: Make sure ETag is same, if image content is the same...
|
||||
// Use ETag of original response (or derived from)
|
||||
// Use last modified of original response? Or keep original resource's, don't set at all?
|
||||
// TODO: Why weak ETag?
|
||||
String etag = "W/\"" + Integer.toHexString(hashCode()) + "-" + Integer.toHexString(image.hashCode()) + "\"";
|
||||
// TODO: This breaks for wrapped instances, need to either unwrap or test for HttpSR...
|
||||
((HttpServletResponse) pResponse).setHeader("ETag", etag);
|
||||
((HttpServletResponse) pResponse).setDateHeader("Last-Modified", (System.currentTimeMillis() / 1000) * 1000);
|
||||
}
|
||||
|
||||
imageResponse.flush();
|
||||
//System.out.println("Done encoding.");
|
||||
}
|
||||
}
|
||||
//System.out.println("Filtering done.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the image servlet response for this response.
|
||||
*
|
||||
* @param pResponse the original response
|
||||
* @param pRequest the original request
|
||||
* @return the new response, or {@code pResponse} if the response is already wrapped
|
||||
*
|
||||
* @see com.twelvemonkeys.servlet.image.ImageServletResponseWrapper
|
||||
*/
|
||||
private ImageServletResponse createImageServletResponse(final ServletRequest pRequest, final ServletResponse pResponse) {
|
||||
if (pResponse instanceof ImageServletResponseImpl) {
|
||||
ImageServletResponseImpl response = (ImageServletResponseImpl) pResponse;
|
||||
// response.setRequest(pRequest);
|
||||
return response;
|
||||
}
|
||||
|
||||
return new ImageServletResponseImpl(pRequest, pResponse, getServletContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the filter should do image filtering/processing.
|
||||
* <P/>
|
||||
* This default implementation uses {@link #mTriggerParams} to test if:
|
||||
* This default implementation uses {@link #triggerParams} to test if:
|
||||
* <dl>
|
||||
* <dt>{@code mTriggerParams == null}</dt>
|
||||
* <dd>{@code return true}</dd>
|
||||
@@ -157,14 +174,14 @@ public abstract class ImageFilter extends GenericFilter {
|
||||
* @param pRequest the servlet request
|
||||
* @return {@code true} if the filter should do image filtering
|
||||
*/
|
||||
protected boolean trigger(ServletRequest pRequest) {
|
||||
protected boolean trigger(final ServletRequest pRequest) {
|
||||
// If triggerParams not set, assume always trigger
|
||||
if (mTriggerParams == null) {
|
||||
if (triggerParams == null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Trigger only for certain request parameters
|
||||
for (String triggerParam : mTriggerParams) {
|
||||
for (String triggerParam : triggerParams) {
|
||||
if (pRequest.getParameter(triggerParam) != null) {
|
||||
return true;
|
||||
}
|
||||
@@ -181,8 +198,9 @@ public abstract class ImageFilter extends GenericFilter {
|
||||
*
|
||||
* @param pTriggerParams a comma-separated string of parameter names.
|
||||
*/
|
||||
public void setTriggerParams(String pTriggerParams) {
|
||||
mTriggerParams = StringUtil.toStringArray(pTriggerParams);
|
||||
// TODO: Make it an @InitParam, and make sure we may set String[]/Collection<String> as parameter?
|
||||
public void setTriggerParams(final String pTriggerParams) {
|
||||
triggerParams = StringUtil.toStringArray(pTriggerParams);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -31,13 +31,13 @@ package com.twelvemonkeys.servlet.image;
|
||||
import javax.servlet.*;
|
||||
|
||||
/**
|
||||
* This excpetion is a subclass of ServletException, and acts just as a marker
|
||||
* for excpetions thrown by the ImageServlet API.
|
||||
* This exception is a subclass of ServletException, and acts just as a marker
|
||||
* for exceptions thrown by the ImageServlet API.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
*
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/image/ImageServletException.java#2 $
|
||||
* @version $Id: ImageServletException.java#2 $
|
||||
*/
|
||||
public class ImageServletException extends ServletException {
|
||||
|
||||
|
@@ -41,7 +41,7 @@ import java.awt.image.BufferedImage;
|
||||
* {@link #getImage()} to have any effect.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/image/ImageServletResponse.java#4 $
|
||||
* @version $Id: ImageServletResponse.java#4 $
|
||||
*/
|
||||
public interface ImageServletResponse extends ServletResponse {
|
||||
/**
|
||||
|
@@ -60,29 +60,31 @@ import java.util.Iterator;
|
||||
* This {@link ImageServletResponse} implementation can be used with image
|
||||
* requests, to have the image immediately decoded to a {@code BufferedImage}.
|
||||
* The image may be optionally subsampled, scaled and/or cropped.
|
||||
* The response also automtically handles writing the image back to the underlying response stream
|
||||
* The response also automatically handles writing the image back to the underlying response stream
|
||||
* in the preferred format, when the response is flushed.
|
||||
* <p>
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/image/ImageServletResponseImpl.java#10 $
|
||||
* @version $Id: ImageServletResponseImpl.java#10 $
|
||||
*
|
||||
*/
|
||||
// TODO: Refactor out HTTP specifcs (if possible).
|
||||
// TODO: Refactor out HTTP specifics (if possible).
|
||||
// TODO: Is it a good ide to throw IIOException?
|
||||
// TODO: This implementation has a problem if two filters does scaling, as the second will overwrite the SIZE attribute
|
||||
// TODO: Allow different scaling algorithm based on input image (use case: IndexColorModel does not scale well using default, smooth may be slow for large images)
|
||||
class ImageServletResponseImpl extends HttpServletResponseWrapper implements ImageServletResponse {
|
||||
|
||||
private final ServletRequest mOriginalRequest;
|
||||
private final ServletContext mContext;
|
||||
private final ServletResponseStreamDelegate mStreamDelegate;
|
||||
private ServletRequest originalRequest;
|
||||
private final ServletContext context;
|
||||
private final ServletResponseStreamDelegate streamDelegate;
|
||||
|
||||
private FastByteArrayOutputStream mBufferedOut;
|
||||
private FastByteArrayOutputStream bufferedOut;
|
||||
|
||||
private RenderedImage mImage;
|
||||
private String mOutputContentType;
|
||||
private RenderedImage image;
|
||||
private String outputContentType;
|
||||
|
||||
private String mOriginalContentType;
|
||||
private int mOriginalContentLength = -1;
|
||||
private String originalContentType;
|
||||
private int originalContentLength = -1;
|
||||
|
||||
/**
|
||||
* Creates an {@code ImageServletResponseImpl}.
|
||||
@@ -93,21 +95,21 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
||||
*/
|
||||
public ImageServletResponseImpl(final HttpServletRequest pRequest, final HttpServletResponse pResponse, final ServletContext pContext) {
|
||||
super(pResponse);
|
||||
mOriginalRequest = pRequest;
|
||||
mStreamDelegate = new ServletResponseStreamDelegate(pResponse) {
|
||||
originalRequest = pRequest;
|
||||
streamDelegate = new ServletResponseStreamDelegate(pResponse) {
|
||||
@Override
|
||||
protected OutputStream createOutputStream() throws IOException {
|
||||
if (mOriginalContentLength >= 0) {
|
||||
mBufferedOut = new FastByteArrayOutputStream(mOriginalContentLength);
|
||||
if (originalContentLength >= 0) {
|
||||
bufferedOut = new FastByteArrayOutputStream(originalContentLength);
|
||||
}
|
||||
else {
|
||||
mBufferedOut = new FastByteArrayOutputStream(0);
|
||||
bufferedOut = new FastByteArrayOutputStream(0);
|
||||
}
|
||||
|
||||
return mBufferedOut;
|
||||
return bufferedOut;
|
||||
}
|
||||
};
|
||||
mContext = pContext;
|
||||
context = pContext;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,11 +134,11 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
||||
*/
|
||||
public void setContentType(final String pMimeType) {
|
||||
// Throw exception is already set
|
||||
if (mOriginalContentType != null) {
|
||||
if (originalContentType != null) {
|
||||
throw new IllegalStateException("ContentType already set.");
|
||||
}
|
||||
|
||||
mOriginalContentType = pMimeType;
|
||||
originalContentType = pMimeType;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,7 +148,7 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
||||
* @throws IOException
|
||||
*/
|
||||
public ServletOutputStream getOutputStream() throws IOException {
|
||||
return mStreamDelegate.getOutputStream();
|
||||
return streamDelegate.getOutputStream();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -156,7 +158,7 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
||||
* @throws IOException
|
||||
*/
|
||||
public PrintWriter getWriter() throws IOException {
|
||||
return mStreamDelegate.getWriter();
|
||||
return streamDelegate.getWriter();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -165,11 +167,25 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
||||
* @param pLength the content length
|
||||
*/
|
||||
public void setContentLength(final int pLength) {
|
||||
if (mOriginalContentLength != -1) {
|
||||
if (originalContentLength != -1) {
|
||||
throw new IllegalStateException("ContentLength already set.");
|
||||
}
|
||||
|
||||
mOriginalContentLength = pLength;
|
||||
originalContentLength = pLength;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHeader(String name, String value) {
|
||||
// NOTE: Clients could also specify content type/content length using the setHeader method, special handling
|
||||
if (name != null && name.equals("Content-Length")) {
|
||||
setContentLength(Integer.valueOf(value)); // Value might be too large, but we don't support that anyway
|
||||
}
|
||||
else if (name != null && name.equals("Content-Type")) {
|
||||
setContentType(value);
|
||||
}
|
||||
else {
|
||||
super.setHeader(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,60 +199,79 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
||||
String outputType = getOutputContentType();
|
||||
|
||||
// Force transcoding, if no other filtering is done
|
||||
if (!outputType.equals(mOriginalContentType)) {
|
||||
if (outputType != null && !outputType.equals(originalContentType)) {
|
||||
getImage();
|
||||
}
|
||||
|
||||
// For known formats that don't support transparency, convert to opaque
|
||||
if (("image/jpeg".equals(outputType) || "image/jpg".equals(outputType)
|
||||
|| "image/bmp".equals(outputType) || "image/x-bmp".equals(outputType)) &&
|
||||
mImage.getColorModel().getTransparency() != Transparency.OPAQUE) {
|
||||
mImage = ImageUtil.toBuffered(mImage, BufferedImage.TYPE_INT_RGB);
|
||||
}
|
||||
|
||||
if (mImage != null) {
|
||||
if (image != null) {
|
||||
Iterator writers = ImageIO.getImageWritersByMIMEType(outputType);
|
||||
if (writers.hasNext()) {
|
||||
super.setContentType(outputType);
|
||||
OutputStream out = super.getOutputStream();
|
||||
|
||||
ImageWriter writer = (ImageWriter) writers.next();
|
||||
try {
|
||||
ImageWriteParam param = writer.getDefaultWriteParam();
|
||||
|
||||
Float requestQuality = (Float) mOriginalRequest.getAttribute(ImageServletResponse.ATTRIB_OUTPUT_QUALITY);
|
||||
|
||||
// The default JPEG quality is not good enough, so always apply compression
|
||||
if ((requestQuality != null || "jpeg".equalsIgnoreCase(getFormatNameSafe(writer))) && param.canWriteCompressed()) {
|
||||
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
|
||||
param.setCompressionQuality(requestQuality != null ? requestQuality : 0.8f);
|
||||
}
|
||||
|
||||
ImageOutputStream stream = ImageIO.createImageOutputStream(out);
|
||||
|
||||
writer.setOutput(stream);
|
||||
ImageWriter writer = (ImageWriter) writers.next();
|
||||
try {
|
||||
writer.write(null, new IIOImage(mImage, null, null), param);
|
||||
ImageWriteParam param = writer.getDefaultWriteParam();
|
||||
///////////////////
|
||||
// POST-PROCESS
|
||||
// For known formats that don't support transparency, convert to opaque
|
||||
if (isNonAlphaFormat(outputType) && image.getColorModel().getTransparency() != Transparency.OPAQUE) {
|
||||
image = ImageUtil.toBuffered(image, BufferedImage.TYPE_INT_RGB);
|
||||
}
|
||||
|
||||
Float requestQuality = (Float) originalRequest.getAttribute(ImageServletResponse.ATTRIB_OUTPUT_QUALITY);
|
||||
|
||||
// The default JPEG quality is not good enough, so always adjust compression/quality
|
||||
if ((requestQuality != null || "jpeg".equalsIgnoreCase(getFormatNameSafe(writer))) && param.canWriteCompressed()) {
|
||||
param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);
|
||||
|
||||
// WORKAROUND: Known bug in GIFImageWriter in certain JDK versions, compression type is not set by default
|
||||
if (param.getCompressionTypes() != null && param.getCompressionType() == null) {
|
||||
param.setCompressionType(param.getCompressionTypes()[0]); // Just choose any, to keep param happy
|
||||
}
|
||||
|
||||
param.setCompressionQuality(requestQuality != null ? requestQuality : 0.8f);
|
||||
}
|
||||
|
||||
if ("gif".equalsIgnoreCase(getFormatNameSafe(writer)) && !(image.getColorModel() instanceof IndexColorModel)
|
||||
&& image.getColorModel().getTransparency() != Transparency.OPAQUE) {
|
||||
// WORKAROUND: Bug in GIFImageWriter may throw NPE if transparent pixels
|
||||
// See: http://bugs.sun.com/view_bug.do?bug_id=6287936
|
||||
image = ImageUtil.createIndexed(ImageUtil.toBuffered(image), 256, null, ImageUtil.TRANSPARENCY_BITMASK | ImageUtil.DITHER_DIFFUSION_ALTSCANS);
|
||||
}
|
||||
//////////////////
|
||||
ImageOutputStream stream = ImageIO.createImageOutputStream(out);
|
||||
|
||||
writer.setOutput(stream);
|
||||
try {
|
||||
writer.write(null, new IIOImage(image, null, null), param);
|
||||
}
|
||||
finally {
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
stream.close();
|
||||
writer.dispose();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
writer.dispose();
|
||||
out.flush();
|
||||
}
|
||||
}
|
||||
else {
|
||||
mContext.log("ERROR: No writer for content-type: " + outputType);
|
||||
context.log("ERROR: No writer for content-type: " + outputType);
|
||||
throw new IIOException("Unable to transcode image: No suitable image writer found (content-type: " + outputType + ").");
|
||||
}
|
||||
}
|
||||
else {
|
||||
super.setContentType(mOriginalContentType);
|
||||
super.setContentType(originalContentType);
|
||||
|
||||
ServletOutputStream out = super.getOutputStream();
|
||||
|
||||
try {
|
||||
mBufferedOut.writeTo(out);
|
||||
if (bufferedOut != null) {
|
||||
bufferedOut.writeTo(out);
|
||||
}
|
||||
}
|
||||
finally {
|
||||
out.flush();
|
||||
@@ -244,6 +279,11 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isNonAlphaFormat(String outputType) {
|
||||
return "image/jpeg".equals(outputType) || "image/jpg".equals(outputType) ||
|
||||
"image/bmp".equals(outputType) || "image/x-bmp".equals(outputType);
|
||||
}
|
||||
|
||||
private String getFormatNameSafe(final ImageWriter pWriter) {
|
||||
try {
|
||||
return pWriter.getOriginatingProvider().getFormatNames()[0];
|
||||
@@ -255,11 +295,11 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
||||
}
|
||||
|
||||
public String getOutputContentType() {
|
||||
return mOutputContentType != null ? mOutputContentType : mOriginalContentType;
|
||||
return outputContentType != null ? outputContentType : originalContentType;
|
||||
}
|
||||
|
||||
public void setOutputContentType(final String pImageFormat) {
|
||||
mOutputContentType = pImageFormat;
|
||||
outputContentType = pImageFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -269,7 +309,7 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
||||
* response stream
|
||||
*/
|
||||
public void setImage(final RenderedImage pImage) {
|
||||
mImage = pImage;
|
||||
image = pImage;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -281,14 +321,14 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
||||
* @throws java.io.IOException if an I/O exception occurs during reading
|
||||
*/
|
||||
public BufferedImage getImage() throws IOException {
|
||||
if (mImage == null) {
|
||||
if (image == null) {
|
||||
// No content, no image
|
||||
if (mBufferedOut == null) {
|
||||
if (bufferedOut == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Read from the byte buffer
|
||||
InputStream byteStream = mBufferedOut.createInputStream();
|
||||
InputStream byteStream = bufferedOut.createInputStream();
|
||||
ImageInputStream input = null;
|
||||
try {
|
||||
input = ImageIO.createImageInputStream(byteStream);
|
||||
@@ -304,26 +344,31 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
||||
// Get default size
|
||||
int originalWidth = reader.getWidth(0);
|
||||
int originalHeight = reader.getHeight(0);
|
||||
|
||||
//////////////////
|
||||
// PRE-PROCESS (prepare): param, size, format?, request, response?
|
||||
// TODO: AOI strategy?
|
||||
// Extract AOI from request
|
||||
Rectangle aoi = extractAOIFromRequest(originalWidth, originalHeight);
|
||||
Rectangle aoi = extractAOIFromRequest(originalWidth, originalHeight, originalRequest);
|
||||
|
||||
if (aoi != null) {
|
||||
param.setSourceRegion(aoi);
|
||||
originalWidth = aoi.width;
|
||||
originalHeight = aoi.height;
|
||||
}
|
||||
|
||||
// TODO: Size and subsampling strategy?
|
||||
// If possible, extract size from request
|
||||
Dimension size = extractSizeFromRequest(originalWidth, originalHeight);
|
||||
double readSubSamplingFactor = getReadSubsampleFactorFromRequest();
|
||||
Dimension size = extractSizeFromRequest(originalWidth, originalHeight, originalRequest);
|
||||
double readSubSamplingFactor = getReadSubsampleFactorFromRequest(originalRequest);
|
||||
|
||||
if (size != null) {
|
||||
//System.out.println("Size: " + size);
|
||||
if (param.canSetSourceRenderSize()) {
|
||||
param.setSourceRenderSize(size);
|
||||
}
|
||||
else {
|
||||
int subX = (int) Math.max(originalWidth / (double) (size.width * readSubSamplingFactor), 1.0);
|
||||
int subY = (int) Math.max(originalHeight / (double) (size.height * readSubSamplingFactor), 1.0);
|
||||
int subX = (int) Math.max(originalWidth / (size.width * readSubSamplingFactor), 1.0);
|
||||
int subY = (int) Math.max(originalHeight / (size.height * readSubSamplingFactor), 1.0);
|
||||
|
||||
if (subX > 1 || subY > 1) {
|
||||
param.setSourceSubsampling(subX, subY, subX > 1 ? subX / 2 : 0, subY > 1 ? subY / 2 : 0);
|
||||
@@ -334,43 +379,36 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
||||
// Need base URI for SVG with links/stylesheets etc
|
||||
maybeSetBaseURIFromRequest(param);
|
||||
|
||||
/////////////////////
|
||||
|
||||
// Finally, read the image using the supplied parameter
|
||||
BufferedImage image = reader.read(0, param);
|
||||
|
||||
// If reader doesn't support dynamic sizing, scale now
|
||||
if (image != null && size != null
|
||||
&& (image.getWidth() != size.width || image.getHeight() != size.height)) {
|
||||
// TODO: If we sub-sampled, it would be a good idea to blur before resampling,
|
||||
// to avoid jagged lines artifacts
|
||||
|
||||
int resampleAlgorithm = getResampleAlgorithmFromRequest();
|
||||
// NOTE: Only use createScaled if IndexColorModel,
|
||||
// as it's more expensive due to color conversion
|
||||
if (image.getColorModel() instanceof IndexColorModel) {
|
||||
image = ImageUtil.createScaled(image, size.width, size.height, resampleAlgorithm);
|
||||
}
|
||||
else {
|
||||
image = ImageUtil.createResampled(image, size.width, size.height, resampleAlgorithm);
|
||||
}
|
||||
}
|
||||
// If reader doesn't support dynamic sizing, scale now
|
||||
image = resampleImage(image, size);
|
||||
|
||||
// Fill bgcolor behind image, if transparent
|
||||
extractAndSetBackgroundColor(image);
|
||||
extractAndSetBackgroundColor(image); // TODO: Move to flush/POST-PROCESS
|
||||
|
||||
// Set image
|
||||
mImage = image;
|
||||
this.image = image;
|
||||
}
|
||||
finally {
|
||||
reader.dispose();
|
||||
}
|
||||
}
|
||||
else {
|
||||
mContext.log("ERROR: No suitable image reader found (content-type: " + mOriginalContentType + ").");
|
||||
mContext.log("ERROR: Available formats: " + getFormatsString());
|
||||
context.log("ERROR: No suitable image reader found (content-type: " + originalContentType + ").");
|
||||
context.log("ERROR: Available formats: " + getFormatsString());
|
||||
|
||||
throw new IIOException("Unable to transcode image: No suitable image reader found (content-type: " + mOriginalContentType + ").");
|
||||
throw new IIOException("Unable to transcode image: No suitable image reader found (content-type: " + originalContentType + ").");
|
||||
}
|
||||
|
||||
// Free resources, as the image is now either read, or unreadable
|
||||
mBufferedOut = null;
|
||||
bufferedOut = null;
|
||||
}
|
||||
finally {
|
||||
if (input != null) {
|
||||
@@ -380,37 +418,49 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
||||
}
|
||||
|
||||
// Image is usually a BufferedImage, but may also be a RenderedImage
|
||||
return mImage != null ? ImageUtil.toBuffered(mImage) : null;
|
||||
return image != null ? ImageUtil.toBuffered(image) : null;
|
||||
}
|
||||
|
||||
private BufferedImage resampleImage(final BufferedImage image, final Dimension size) {
|
||||
if (image != null && size != null && (image.getWidth() != size.width || image.getHeight() != size.height)) {
|
||||
int resampleAlgorithm = getResampleAlgorithmFromRequest();
|
||||
|
||||
// NOTE: Only use createScaled if IndexColorModel, as it's more expensive due to color conversion
|
||||
if (image.getColorModel() instanceof IndexColorModel) {
|
||||
return ImageUtil.createScaled(image, size.width, size.height, resampleAlgorithm);
|
||||
}
|
||||
else {
|
||||
return ImageUtil.createResampled(image, size.width, size.height, resampleAlgorithm);
|
||||
}
|
||||
}
|
||||
return image;
|
||||
}
|
||||
|
||||
private int getResampleAlgorithmFromRequest() {
|
||||
int resampleAlgoithm;
|
||||
|
||||
Object algorithm = mOriginalRequest.getAttribute(ATTRIB_IMAGE_RESAMPLE_ALGORITHM);
|
||||
Object algorithm = originalRequest.getAttribute(ATTRIB_IMAGE_RESAMPLE_ALGORITHM);
|
||||
if (algorithm instanceof Integer && ((Integer) algorithm == Image.SCALE_SMOOTH || (Integer) algorithm == Image.SCALE_FAST || (Integer) algorithm == Image.SCALE_DEFAULT)) {
|
||||
resampleAlgoithm = (Integer) algorithm;
|
||||
return (Integer) algorithm;
|
||||
}
|
||||
else {
|
||||
if (algorithm != null) {
|
||||
mContext.log("WARN: Illegal image resampling algorithm: " + algorithm);
|
||||
context.log("WARN: Illegal image resampling algorithm: " + algorithm);
|
||||
}
|
||||
resampleAlgoithm = BufferedImage.SCALE_DEFAULT;
|
||||
return BufferedImage.SCALE_DEFAULT;
|
||||
}
|
||||
|
||||
return resampleAlgoithm;
|
||||
}
|
||||
|
||||
private double getReadSubsampleFactorFromRequest() {
|
||||
private double getReadSubsampleFactorFromRequest(final ServletRequest pOriginalRequest) {
|
||||
double subsampleFactor;
|
||||
|
||||
Object factor = mOriginalRequest.getAttribute(ATTRIB_READ_SUBSAMPLING_FACTOR);
|
||||
Object factor = pOriginalRequest.getAttribute(ATTRIB_READ_SUBSAMPLING_FACTOR);
|
||||
if (factor instanceof Number && ((Number) factor).doubleValue() >= 1.0) {
|
||||
subsampleFactor = ((Number) factor).doubleValue();
|
||||
}
|
||||
else {
|
||||
if (factor != null) {
|
||||
mContext.log("WARN: Illegal read subsampling factor: " + factor);
|
||||
context.log("WARN: Illegal read subsampling factor: " + factor);
|
||||
}
|
||||
|
||||
subsampleFactor = 2.0;
|
||||
}
|
||||
|
||||
@@ -420,7 +470,7 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
||||
private void extractAndSetBackgroundColor(final BufferedImage pImage) {
|
||||
// TODO: bgColor request attribute instead of parameter?
|
||||
if (pImage.getColorModel().hasAlpha()) {
|
||||
String bgColor = mOriginalRequest.getParameter("bg.color");
|
||||
String bgColor = originalRequest.getParameter("bg.color");
|
||||
if (bgColor != null) {
|
||||
Color color = StringUtil.toColor(bgColor);
|
||||
|
||||
@@ -451,7 +501,7 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
||||
}
|
||||
|
||||
private void maybeSetBaseURIFromRequest(final ImageReadParam pParam) {
|
||||
if (mOriginalRequest instanceof HttpServletRequest) {
|
||||
if (originalRequest instanceof HttpServletRequest) {
|
||||
try {
|
||||
// If there's a setBaseURI method, we'll try to use that (uses reflection, to avoid dependency on plugins)
|
||||
Method setBaseURI;
|
||||
@@ -463,42 +513,43 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
||||
}
|
||||
|
||||
// Get URL for resource and set as base
|
||||
String baseURI = ServletUtil.getContextRelativeURI((HttpServletRequest) mOriginalRequest);
|
||||
String baseURI = ServletUtil.getContextRelativeURI((HttpServletRequest) originalRequest);
|
||||
|
||||
URL resourceURL = context.getResource(baseURI);
|
||||
|
||||
URL resourceURL = mContext.getResource(baseURI);
|
||||
if (resourceURL == null) {
|
||||
resourceURL = ServletUtil.getRealURL(mContext, baseURI);
|
||||
resourceURL = ServletUtil.getRealURL(context, baseURI);
|
||||
}
|
||||
|
||||
if (resourceURL != null) {
|
||||
setBaseURI.invoke(pParam, resourceURL.toExternalForm());
|
||||
}
|
||||
else {
|
||||
mContext.log("WARN: Resource URL not found for URI: " + baseURI);
|
||||
context.log("WARN: Resource URL not found for URI: " + baseURI);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
mContext.log("WARN: Could not set base URI: ", e);
|
||||
context.log("WARN: Could not set base URI: ", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Dimension extractSizeFromRequest(final int pDefaultWidth, final int pDefaultHeight) {
|
||||
private Dimension extractSizeFromRequest(final int pDefaultWidth, final int pDefaultHeight, final ServletRequest pOriginalRequest) {
|
||||
// TODO: Allow extraction from request parameters
|
||||
/*
|
||||
int sizeW = ServletUtil.getIntParameter(mOriginalRequest, "size.w", -1);
|
||||
int sizeH = ServletUtil.getIntParameter(mOriginalRequest, "size.h", -1);
|
||||
boolean sizePercent = ServletUtil.getBooleanParameter(mOriginalRequest, "size.percent", false);
|
||||
boolean sizeUniform = ServletUtil.getBooleanParameter(mOriginalRequest, "size.uniform", true);
|
||||
int sizeW = ServletUtil.getIntParameter(originalRequest, "size.w", -1);
|
||||
int sizeH = ServletUtil.getIntParameter(originalRequest, "size.h", -1);
|
||||
boolean sizePercent = ServletUtil.getBooleanParameter(originalRequest, "size.percent", false);
|
||||
boolean sizeUniform = ServletUtil.getBooleanParameter(originalRequest, "size.uniform", true);
|
||||
*/
|
||||
Dimension size = (Dimension) mOriginalRequest.getAttribute(ATTRIB_SIZE);
|
||||
Dimension size = (Dimension) pOriginalRequest.getAttribute(ATTRIB_SIZE);
|
||||
int sizeW = size != null ? size.width : -1;
|
||||
int sizeH = size != null ? size.height : -1;
|
||||
|
||||
Boolean b = (Boolean) mOriginalRequest.getAttribute(ATTRIB_SIZE_PERCENT);
|
||||
Boolean b = (Boolean) pOriginalRequest.getAttribute(ATTRIB_SIZE_PERCENT);
|
||||
boolean sizePercent = b != null && b; // default: false
|
||||
|
||||
b = (Boolean) mOriginalRequest.getAttribute(ATTRIB_SIZE_UNIFORM);
|
||||
b = (Boolean) pOriginalRequest.getAttribute(ATTRIB_SIZE_UNIFORM);
|
||||
boolean sizeUniform = b == null || b; // default: true
|
||||
|
||||
if (sizeW >= 0 || sizeH >= 0) {
|
||||
@@ -508,26 +559,26 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
||||
return size;
|
||||
}
|
||||
|
||||
private Rectangle extractAOIFromRequest(final int pDefaultWidth, final int pDefaultHeight) {
|
||||
private Rectangle extractAOIFromRequest(final int pDefaultWidth, final int pDefaultHeight, final ServletRequest pOriginalRequest) {
|
||||
// TODO: Allow extraction from request parameters
|
||||
/*
|
||||
int aoiX = ServletUtil.getIntParameter(mOriginalRequest, "aoi.x", -1);
|
||||
int aoiY = ServletUtil.getIntParameter(mOriginalRequest, "aoi.y", -1);
|
||||
int aoiW = ServletUtil.getIntParameter(mOriginalRequest, "aoi.w", -1);
|
||||
int aoiH = ServletUtil.getIntParameter(mOriginalRequest, "aoi.h", -1);
|
||||
boolean aoiPercent = ServletUtil.getBooleanParameter(mOriginalRequest, "aoi.percent", false);
|
||||
boolean aoiUniform = ServletUtil.getBooleanParameter(mOriginalRequest, "aoi.uniform", false);
|
||||
int aoiX = ServletUtil.getIntParameter(originalRequest, "aoi.x", -1);
|
||||
int aoiY = ServletUtil.getIntParameter(originalRequest, "aoi.y", -1);
|
||||
int aoiW = ServletUtil.getIntParameter(originalRequest, "aoi.w", -1);
|
||||
int aoiH = ServletUtil.getIntParameter(originalRequest, "aoi.h", -1);
|
||||
boolean aoiPercent = ServletUtil.getBooleanParameter(originalRequest, "aoi.percent", false);
|
||||
boolean aoiUniform = ServletUtil.getBooleanParameter(originalRequest, "aoi.uniform", false);
|
||||
*/
|
||||
Rectangle aoi = (Rectangle) mOriginalRequest.getAttribute(ATTRIB_AOI);
|
||||
Rectangle aoi = (Rectangle) pOriginalRequest.getAttribute(ATTRIB_AOI);
|
||||
int aoiX = aoi != null ? aoi.x : -1;
|
||||
int aoiY = aoi != null ? aoi.y : -1;
|
||||
int aoiW = aoi != null ? aoi.width : -1;
|
||||
int aoiH = aoi != null ? aoi.height : -1;
|
||||
|
||||
Boolean b = (Boolean) mOriginalRequest.getAttribute(ATTRIB_AOI_PERCENT);
|
||||
Boolean b = (Boolean) pOriginalRequest.getAttribute(ATTRIB_AOI_PERCENT);
|
||||
boolean aoiPercent = b != null && b; // default: false
|
||||
|
||||
b = (Boolean) mOriginalRequest.getAttribute(ATTRIB_AOI_UNIFORM);
|
||||
b = (Boolean) pOriginalRequest.getAttribute(ATTRIB_AOI_UNIFORM);
|
||||
boolean aoiUniform = b != null && b; // default: false
|
||||
|
||||
if (aoiX >= 0 || aoiY >= 0 || aoiW >= 0 || aoiH >= 0) {
|
||||
@@ -552,18 +603,18 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
||||
* @param pHeight the new height of the image, or -1 if unknown
|
||||
* @param pPercent the constant specifying units for width and height
|
||||
* parameter (UNITS_PIXELS or UNITS_PERCENT)
|
||||
* @param pUniformScale boolean specifying uniform scale or not
|
||||
* @param pUniform boolean specifying uniform scale or not
|
||||
* @return a Dimension object, with the correct width and heigth
|
||||
* in pixels, for the scaled version of the image.
|
||||
*/
|
||||
protected static Dimension getSize(int pOriginalWidth, int pOriginalHeight,
|
||||
static Dimension getSize(int pOriginalWidth, int pOriginalHeight,
|
||||
int pWidth, int pHeight,
|
||||
boolean pPercent, boolean pUniformScale) {
|
||||
boolean pPercent, boolean pUniform) {
|
||||
|
||||
// If uniform, make sure width and height are scaled the same ammount
|
||||
// If uniform, make sure width and height are scaled the same amount
|
||||
// (use ONLY height or ONLY width).
|
||||
//
|
||||
// Algoritm:
|
||||
// Algorithm:
|
||||
// if uniform
|
||||
// if newHeight not set
|
||||
// find ratio newWidth / oldWidth
|
||||
@@ -602,7 +653,7 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
||||
// Else: No scale
|
||||
}
|
||||
else {
|
||||
if (pUniformScale) {
|
||||
if (pUniform) {
|
||||
if (pWidth >= 0 && pHeight >= 0) {
|
||||
// Compute both ratios
|
||||
ratio = (float) pWidth / (float) pOriginalWidth;
|
||||
@@ -616,7 +667,6 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
||||
else {
|
||||
pHeight = Math.round((float) pOriginalHeight * ratio);
|
||||
}
|
||||
|
||||
}
|
||||
else if (pWidth >= 0) {
|
||||
// Find ratio from pWidth
|
||||
@@ -644,10 +694,10 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
||||
return new Dimension(pWidth, pHeight);
|
||||
}
|
||||
|
||||
protected static Rectangle getAOI(int pOriginalWidth, int pOriginalHeight,
|
||||
static Rectangle getAOI(int pOriginalWidth, int pOriginalHeight,
|
||||
int pX, int pY, int pWidth, int pHeight,
|
||||
boolean pPercent, boolean pUniform) {
|
||||
// Algoritm:
|
||||
boolean pPercent, boolean pMaximizeToAspect) {
|
||||
// Algorithm:
|
||||
// Try to get x and y (default 0,0).
|
||||
// Try to get width and height (default width-x, height-y)
|
||||
//
|
||||
@@ -669,7 +719,6 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
||||
ratio = (float) pWidth / 100f;
|
||||
pWidth = Math.round((float) pOriginalWidth * ratio);
|
||||
pHeight = Math.round((float) pOriginalHeight * ratio);
|
||||
|
||||
}
|
||||
else if (pHeight >= 0) {
|
||||
// Find ratio from pHeight
|
||||
@@ -681,7 +730,7 @@ class ImageServletResponseImpl extends HttpServletResponseWrapper implements Ima
|
||||
}
|
||||
else {
|
||||
// Uniform
|
||||
if (pUniform) {
|
||||
if (pMaximizeToAspect) {
|
||||
if (pWidth >= 0 && pHeight >= 0) {
|
||||
// Compute both ratios
|
||||
ratio = (float) pWidth / (float) pHeight;
|
||||
|
@@ -35,8 +35,8 @@ import java.awt.image.RenderedImage;
|
||||
/**
|
||||
* An {@code ImageFilter} that does nothing. Useful for debugging purposes.
|
||||
*
|
||||
* @author $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/image/NullImageFilter.java#2 $
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: NullImageFilter.java $
|
||||
*
|
||||
*/
|
||||
public final class NullImageFilter extends ImageFilter {
|
||||
|
@@ -29,7 +29,6 @@
|
||||
package com.twelvemonkeys.servlet.image;
|
||||
|
||||
import com.twelvemonkeys.image.ImageUtil;
|
||||
import com.twelvemonkeys.lang.MathUtil;
|
||||
import com.twelvemonkeys.lang.StringUtil;
|
||||
import com.twelvemonkeys.servlet.ServletUtil;
|
||||
|
||||
@@ -78,7 +77,7 @@ import java.awt.image.RenderedImage;
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/image/RotateFilter.java#1 $
|
||||
* @version $Id: RotateFilter.java#1 $
|
||||
*/
|
||||
|
||||
public class RotateFilter extends ImageFilter {
|
||||
@@ -159,7 +158,7 @@ public class RotateFilter extends ImageFilter {
|
||||
str = pReq.getParameter(PARAM_ANGLE_UNITS);
|
||||
if (!StringUtil.isEmpty(str)
|
||||
&& ANGLE_DEGREES.equalsIgnoreCase(str)) {
|
||||
angle = MathUtil.toRadians(angle);
|
||||
angle = Math.toRadians(angle);
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -69,7 +69,7 @@ import java.lang.reflect.Field;
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/image/ScaleFilter.java#1 $
|
||||
* @version $Id: ScaleFilter.java#1 $
|
||||
*
|
||||
* @example <IMG src="/scale/test.jpg?scaleX=500&scaleUniform=false">
|
||||
* @example <IMG src="/scale/test.png?scaleY=50&scaleUnits=PERCENT">
|
||||
@@ -123,7 +123,7 @@ public class ScaleFilter extends ImageFilter {
|
||||
protected final static String PARAM_IMAGE = "image";
|
||||
|
||||
/** */
|
||||
protected int mDefaultScaleQuality = Image.SCALE_DEFAULT;
|
||||
protected int defaultScaleQuality = Image.SCALE_DEFAULT;
|
||||
|
||||
/**
|
||||
* Reads the image from the requested URL, scales it, and returns it in the
|
||||
@@ -188,11 +188,11 @@ public class ScaleFilter extends ImageFilter {
|
||||
}
|
||||
}
|
||||
|
||||
return mDefaultScaleQuality;
|
||||
return defaultScaleQuality;
|
||||
}
|
||||
|
||||
public void setDefaultScaleQuality(String pDefaultScaleQuality) {
|
||||
mDefaultScaleQuality = getQuality(pDefaultScaleQuality);
|
||||
defaultScaleQuality = getQuality(pDefaultScaleQuality);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -21,69 +21,69 @@ import java.io.IOException;
|
||||
* @see ImageServletResponse#ATTRIB_AOI
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/image/SourceRenderFilter.java#1 $
|
||||
* @version $Id: SourceRenderFilter.java#1 $
|
||||
*/
|
||||
public class SourceRenderFilter extends ImageFilter {
|
||||
private String mSizeWidthParam = "size.w";
|
||||
private String mSizeHeightParam = "size.h";
|
||||
private String mSizePercentParam = "size.percent";
|
||||
private String mSizeUniformParam = "size.uniform";
|
||||
private String sizeWidthParam = "size.w";
|
||||
private String sizeHeightParam = "size.h";
|
||||
private String sizePercentParam = "size.percent";
|
||||
private String sizeUniformParam = "size.uniform";
|
||||
|
||||
private String mRegionWidthParam = "aoi.w";
|
||||
private String mRegionHeightParam = "aoi.h";
|
||||
private String mRegionLeftParam = "aoi.x";
|
||||
private String mRegionTopParam = "aoi.y";
|
||||
private String mRegionPercentParam = "aoi.percent";
|
||||
private String mRegionUniformParam = "aoi.uniform";
|
||||
private String regionWidthParam = "aoi.w";
|
||||
private String regionHeightParam = "aoi.h";
|
||||
private String regionLeftParam = "aoi.x";
|
||||
private String regionTopParam = "aoi.y";
|
||||
private String regionPercentParam = "aoi.percent";
|
||||
private String regionUniformParam = "aoi.uniform";
|
||||
|
||||
public void setRegionHeightParam(String pRegionHeightParam) {
|
||||
mRegionHeightParam = pRegionHeightParam;
|
||||
regionHeightParam = pRegionHeightParam;
|
||||
}
|
||||
|
||||
public void setRegionWidthParam(String pRegionWidthParam) {
|
||||
mRegionWidthParam = pRegionWidthParam;
|
||||
regionWidthParam = pRegionWidthParam;
|
||||
}
|
||||
|
||||
public void setRegionLeftParam(String pRegionLeftParam) {
|
||||
mRegionLeftParam = pRegionLeftParam;
|
||||
regionLeftParam = pRegionLeftParam;
|
||||
}
|
||||
|
||||
public void setRegionTopParam(String pRegionTopParam) {
|
||||
mRegionTopParam = pRegionTopParam;
|
||||
regionTopParam = pRegionTopParam;
|
||||
}
|
||||
|
||||
public void setSizeHeightParam(String pSizeHeightParam) {
|
||||
mSizeHeightParam = pSizeHeightParam;
|
||||
sizeHeightParam = pSizeHeightParam;
|
||||
}
|
||||
|
||||
public void setSizeWidthParam(String pSizeWidthParam) {
|
||||
mSizeWidthParam = pSizeWidthParam;
|
||||
sizeWidthParam = pSizeWidthParam;
|
||||
}
|
||||
|
||||
public void setRegionPercentParam(String pRegionPercentParam) {
|
||||
mRegionPercentParam = pRegionPercentParam;
|
||||
regionPercentParam = pRegionPercentParam;
|
||||
}
|
||||
|
||||
public void setRegionUniformParam(String pRegionUniformParam) {
|
||||
mRegionUniformParam = pRegionUniformParam;
|
||||
regionUniformParam = pRegionUniformParam;
|
||||
}
|
||||
|
||||
public void setSizePercentParam(String pSizePercentParam) {
|
||||
mSizePercentParam = pSizePercentParam;
|
||||
sizePercentParam = pSizePercentParam;
|
||||
}
|
||||
|
||||
public void setSizeUniformParam(String pSizeUniformParam) {
|
||||
mSizeUniformParam = pSizeUniformParam;
|
||||
sizeUniformParam = pSizeUniformParam;
|
||||
}
|
||||
|
||||
public void init() throws ServletException {
|
||||
if (mTriggerParams == null) {
|
||||
if (triggerParams == null) {
|
||||
// Add all params as triggers
|
||||
mTriggerParams = new String[]{mSizeWidthParam, mSizeHeightParam,
|
||||
mSizeUniformParam, mSizePercentParam,
|
||||
mRegionLeftParam, mRegionTopParam,
|
||||
mRegionWidthParam, mRegionHeightParam,
|
||||
mRegionUniformParam, mRegionPercentParam};
|
||||
triggerParams = new String[]{sizeWidthParam, sizeHeightParam,
|
||||
sizeUniformParam, sizePercentParam,
|
||||
regionLeftParam, regionTopParam,
|
||||
regionWidthParam, regionHeightParam,
|
||||
regionUniformParam, regionPercentParam};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,37 +101,37 @@ public class SourceRenderFilter extends ImageFilter {
|
||||
// TODO: Max size configuration, to avoid DOS attacks? OutOfMemory
|
||||
|
||||
// Size parameters
|
||||
int width = ServletUtil.getIntParameter(pRequest, mSizeWidthParam, -1);
|
||||
int height = ServletUtil.getIntParameter(pRequest, mSizeHeightParam, -1);
|
||||
int width = ServletUtil.getIntParameter(pRequest, sizeWidthParam, -1);
|
||||
int height = ServletUtil.getIntParameter(pRequest, sizeHeightParam, -1);
|
||||
if (width > 0 || height > 0) {
|
||||
pRequest.setAttribute(ImageServletResponse.ATTRIB_SIZE, new Dimension(width, height));
|
||||
}
|
||||
|
||||
// Size uniform/percent
|
||||
boolean uniform = ServletUtil.getBooleanParameter(pRequest, mSizeUniformParam, true);
|
||||
boolean uniform = ServletUtil.getBooleanParameter(pRequest, sizeUniformParam, true);
|
||||
if (!uniform) {
|
||||
pRequest.setAttribute(ImageServletResponse.ATTRIB_SIZE_UNIFORM, Boolean.FALSE);
|
||||
}
|
||||
boolean percent = ServletUtil.getBooleanParameter(pRequest, mSizePercentParam, false);
|
||||
boolean percent = ServletUtil.getBooleanParameter(pRequest, sizePercentParam, false);
|
||||
if (percent) {
|
||||
pRequest.setAttribute(ImageServletResponse.ATTRIB_SIZE_PERCENT, Boolean.TRUE);
|
||||
}
|
||||
|
||||
// Area of interest parameters
|
||||
int x = ServletUtil.getIntParameter(pRequest, mRegionLeftParam, -1); // Default is center
|
||||
int y = ServletUtil.getIntParameter(pRequest, mRegionTopParam, -1); // Default is center
|
||||
width = ServletUtil.getIntParameter(pRequest, mRegionWidthParam, -1);
|
||||
height = ServletUtil.getIntParameter(pRequest, mRegionHeightParam, -1);
|
||||
int x = ServletUtil.getIntParameter(pRequest, regionLeftParam, -1); // Default is center
|
||||
int y = ServletUtil.getIntParameter(pRequest, regionTopParam, -1); // Default is center
|
||||
width = ServletUtil.getIntParameter(pRequest, regionWidthParam, -1);
|
||||
height = ServletUtil.getIntParameter(pRequest, regionHeightParam, -1);
|
||||
if (width > 0 || height > 0) {
|
||||
pRequest.setAttribute(ImageServletResponse.ATTRIB_AOI, new Rectangle(x, y, width, height));
|
||||
}
|
||||
|
||||
// AOI uniform/percent
|
||||
uniform = ServletUtil.getBooleanParameter(pRequest, mRegionUniformParam, false);
|
||||
uniform = ServletUtil.getBooleanParameter(pRequest, regionUniformParam, false);
|
||||
if (uniform) {
|
||||
pRequest.setAttribute(ImageServletResponse.ATTRIB_SIZE_UNIFORM, Boolean.TRUE);
|
||||
}
|
||||
percent = ServletUtil.getBooleanParameter(pRequest, mRegionPercentParam, false);
|
||||
percent = ServletUtil.getBooleanParameter(pRequest, regionPercentParam, false);
|
||||
if (percent) {
|
||||
pRequest.setAttribute(ImageServletResponse.ATTRIB_SIZE_PERCENT, Boolean.TRUE);
|
||||
}
|
||||
|
@@ -1,348 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2008, Harald Kuhr
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name "TwelveMonkeys" nor the
|
||||
* names of its contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.servlet.image;
|
||||
|
||||
import com.twelvemonkeys.lang.MathUtil;
|
||||
import com.twelvemonkeys.lang.StringUtil;
|
||||
import com.twelvemonkeys.servlet.ServletUtil;
|
||||
|
||||
import javax.servlet.ServletRequest;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.awt.*;
|
||||
import java.awt.geom.Rectangle2D;
|
||||
|
||||
/**
|
||||
* This servlet is capable of rendereing a text string and output it as an
|
||||
* image. The text can be rendered in any given font, size,
|
||||
* style or color, into an image, and output it as a GIF, JPEG or PNG image,
|
||||
* with optional caching of the rendered image files.
|
||||
*
|
||||
* <P><HR><P>
|
||||
*
|
||||
* <A name="parameters"></A><STRONG>Parameters:</STRONG><BR>
|
||||
* <DL>
|
||||
* <DT>{@code text}</DT>
|
||||
* <DD>string, the text string to render.
|
||||
* <DT>{@code width}</DT>
|
||||
* <DD>integer, the width of the image
|
||||
* <DT>{@code height}</DT>
|
||||
* <DD>integer, the height of the image
|
||||
* <DT>{@code fontFamily}</DT>
|
||||
* <DD>string, the name of the font family.
|
||||
* Default is {@code "Helvetica"}.
|
||||
* <DT>{@code fontSize}</DT>
|
||||
* <DD>integer, the size of the font. Default is {@code 12}.
|
||||
* <DT>{@code fontStyle}</DT>
|
||||
* <DD>string, the tyle of the font. Can be one of the constants
|
||||
* {@code plain} (default), {@code bold}, {@code italic} or
|
||||
* {@code bolditalic}. Any other will result in {@code plain}.
|
||||
* <DT>{@code fgcolor}</DT>
|
||||
* <DD>color (HTML form, {@code #RRGGBB}), or color constant from
|
||||
* {@link java.awt.Color}, default is {@code "black"}.
|
||||
* <DT>{@code bgcolor}</DT>
|
||||
* <DD>color (HTML form, {@code #RRGGBB}), or color constant from
|
||||
* {@link java.awt.Color}, default is {@code "transparent"}.
|
||||
* Note that the hash character ({@code "#"}) used in colors must be
|
||||
* escaped as {@code %23} in the query string. See
|
||||
* {@link StringUtil#toColor(String)}, <A href="#examples">examples</A>.
|
||||
*
|
||||
* <!-- inherited from ImageServlet below: -->
|
||||
*
|
||||
* <DT>{@code cache}</DT>
|
||||
* <DD>boolean, {@code true} if you want to cache the result
|
||||
* to disk (default).
|
||||
*
|
||||
* <DT>{@code compression}</DT>
|
||||
* <DD>float, the optional compression ratio for the output image. For JPEG
|
||||
* images, the quality is the inverse of the compression ratio. See
|
||||
* {@link #JPEG_DEFAULT_COMPRESSION_LEVEL},
|
||||
* {@link #PNG_DEFAULT_COMPRESSION_LEVEL}.
|
||||
* <DD>Applies to JPEG and PNG images only.
|
||||
*
|
||||
* <DT>{@code dither}</DT>
|
||||
* <DD>enumerated, one of {@code NONE}, {@code DEFAULT} or
|
||||
* {@code FS}, if you want to dither the result ({@code DEFAULT} is
|
||||
* default).
|
||||
* {@code FS} will produce the best results, but it's slower.
|
||||
* <DD>Use in conjuction with {@code indexed}, {@code palette}
|
||||
* and {@code websafe}.
|
||||
* <DD>Applies to GIF and PNG images only.
|
||||
*
|
||||
* <DT>{@code fileName}</DT>
|
||||
* <DD>string, an optional filename. If not set, the path after the servlet
|
||||
* ({@link HttpServletRequest#getPathInfo}) will be used for the cache
|
||||
* filename. See {@link #getCacheFile(ServletRequest)},
|
||||
* {@link #getCacheRoot}.
|
||||
*
|
||||
* <DT>{@code height}</DT>
|
||||
* <DD>integer, the height of the image.
|
||||
*
|
||||
* <DT>{@code width}</DT>
|
||||
* <DD>integer, the width of the image.
|
||||
*
|
||||
* <DT>{@code indexed}</DT>
|
||||
* <DD>integer, the number of colors in the resulting image, or -1 (default).
|
||||
* If the value is set and positive, the image will use an
|
||||
* {@code IndexColorModel} with
|
||||
* the number of colors specified. Otherwise the image will be true color.
|
||||
* <DD>Applies to GIF and PNG images only.
|
||||
*
|
||||
* <DT>{@code palette}</DT>
|
||||
* <DD>string, an optional filename. If set, the image will use IndexColorModel
|
||||
* with a palette read from the given file.
|
||||
* <DD>Applies to GIF and PNG images only.
|
||||
*
|
||||
* <DT>{@code websafe}</DT>
|
||||
* <DD>boolean, {@code true} if you want the result to use the 216 color
|
||||
* websafe palette (default is false).
|
||||
* <DD>Applies to GIF and PNG images only.
|
||||
* </DL>
|
||||
*
|
||||
* @example
|
||||
* <IMG src="/text/test.gif?height=40&width=600
|
||||
* &fontFamily=TimesRoman&fontSize=30&fontStyle=italic&fgcolor=%23990033
|
||||
* &bgcolor=%23cccccc&text=the%20quick%20brown%20fox%20jumps%20over%20the
|
||||
* %20lazy%20dog&cache=false" />
|
||||
*
|
||||
* @example
|
||||
* <IMG src="/text/test.jpg?height=40&width=600
|
||||
* &fontFamily=TimesRoman&fontSize=30&fontStyle=italic&fgcolor=black
|
||||
* &bgcolor=%23cccccc&text=the%20quick%20brown%20fox%20jumps%20over%20the
|
||||
* %20lazy%20dog&compression=3&cache=false" />
|
||||
*
|
||||
* @example
|
||||
* <IMG src="/text/test.png?height=40&width=600
|
||||
* &fontFamily=TimesRoman&fontSize=30&fontStyle=italic&fgcolor=%23336699
|
||||
* &bgcolor=%23cccccc&text=the%20quick%20brown%20fox%20jumps%20over%20the
|
||||
* %20lazy%20dog&cache=true" />
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/image/TextRenderer.java#2 $
|
||||
*/
|
||||
|
||||
class TextRenderer /*extends ImageServlet implements ImagePainterServlet*/ {
|
||||
// TODO: Create something useable out of this piece of old junk.. ;-)
|
||||
// It just needs a graphics object to write onto
|
||||
// Alternatively, defer, and compute the size needed
|
||||
// Or, make it a filter...
|
||||
|
||||
/** {@code "italic"} */
|
||||
public final static String FONT_STYLE_ITALIC = "italic";
|
||||
/** {@code "plain"} */
|
||||
public final static String FONT_STYLE_PLAIN = "plain";
|
||||
/** {@code "bold"} */
|
||||
public final static String FONT_STYLE_BOLD = "bold";
|
||||
|
||||
/** {@code text} */
|
||||
public final static String PARAM_TEXT = "text";
|
||||
/** {@code marginLeft} */
|
||||
public final static String PARAM_MARGIN_LEFT = "marginLeft";
|
||||
/** {@code marginTop} */
|
||||
public final static String PARAM_MARGIN_TOP = "marginTop";
|
||||
/** {@code fontFamily} */
|
||||
public final static String PARAM_FONT_FAMILY = "fontFamily";
|
||||
/** {@code fontSize} */
|
||||
public final static String PARAM_FONT_SIZE = "fontSize";
|
||||
/** {@code fontStyle} */
|
||||
public final static String PARAM_FONT_STYLE = "fontStyle";
|
||||
/** {@code textRotation} */
|
||||
public final static String PARAM_TEXT_ROTATION = "textRotation";
|
||||
/** {@code textRotation} */
|
||||
public final static String PARAM_TEXT_ROTATION_UNITS = "textRotationUnits";
|
||||
|
||||
/** {@code bgcolor} */
|
||||
public final static String PARAM_BGCOLOR = "bgcolor";
|
||||
/** {@code fgcolor} */
|
||||
public final static String PARAM_FGCOLOR = "fgcolor";
|
||||
|
||||
protected final static String ROTATION_DEGREES = "DEGREES";
|
||||
protected final static String ROTATION_RADIANS = "RADIANS";
|
||||
|
||||
/**
|
||||
* Creates the TextRender servlet.
|
||||
*/
|
||||
|
||||
public TextRenderer() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the text string for this servlet request.
|
||||
*/
|
||||
private void paint(ServletRequest pReq, Graphics2D pRes,
|
||||
int pWidth, int pHeight)
|
||||
throws ImageServletException {
|
||||
|
||||
// Get parameters
|
||||
String text = pReq.getParameter(PARAM_TEXT);
|
||||
String[] lines = StringUtil.toStringArray(text, "\n\r");
|
||||
|
||||
String fontFamily = pReq.getParameter(PARAM_FONT_FAMILY);
|
||||
String fontSize = pReq.getParameter(PARAM_FONT_SIZE);
|
||||
String fontStyle = pReq.getParameter(PARAM_FONT_STYLE);
|
||||
|
||||
String bgcolor = pReq.getParameter(PARAM_BGCOLOR);
|
||||
String fgcolor = pReq.getParameter(PARAM_FGCOLOR);
|
||||
|
||||
// TODO: Make them static..
|
||||
pRes.addRenderingHints(new RenderingHints(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON));
|
||||
pRes.addRenderingHints(new RenderingHints(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY));
|
||||
pRes.addRenderingHints(new RenderingHints(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY));
|
||||
// pRes.addRenderingHints(new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON));
|
||||
|
||||
//System.out.println(pRes.getBackground());
|
||||
|
||||
// Clear area with bgcolor
|
||||
if (!StringUtil.isEmpty(bgcolor)) {
|
||||
pRes.setBackground(StringUtil.toColor(bgcolor));
|
||||
pRes.clearRect(0, 0, pWidth, pHeight);
|
||||
|
||||
//System.out.println(pRes.getBackground());
|
||||
}
|
||||
|
||||
// Create and set font
|
||||
Font font = new Font((fontFamily != null ? fontFamily : "Helvetica"),
|
||||
getFontStyle(fontStyle),
|
||||
(fontSize != null ? Integer.parseInt(fontSize)
|
||||
: 12));
|
||||
pRes.setFont(font);
|
||||
|
||||
// Set rotation
|
||||
double angle = getAngle(pReq);
|
||||
pRes.rotate(angle, pWidth / 2.0, pHeight / 2.0);
|
||||
|
||||
// Draw string in fgcolor
|
||||
pRes.setColor(fgcolor != null ? StringUtil.toColor(fgcolor)
|
||||
: Color.black);
|
||||
|
||||
float x = ServletUtil.getFloatParameter(pReq, PARAM_MARGIN_LEFT,
|
||||
Float.MIN_VALUE);
|
||||
Rectangle2D[] bounds = new Rectangle2D[lines.length];
|
||||
if (x <= Float.MIN_VALUE) {
|
||||
// Center
|
||||
float longest = 0f;
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
bounds[i] = font.getStringBounds(lines[i],
|
||||
pRes.getFontRenderContext());
|
||||
if (bounds[i].getWidth() > longest) {
|
||||
longest = (float) bounds[i].getWidth();
|
||||
}
|
||||
}
|
||||
|
||||
//x = (float) ((pWidth - bounds.getWidth()) / 2f);
|
||||
x = (float) ((pWidth - longest) / 2f);
|
||||
|
||||
//System.out.println("marginLeft: " + x);
|
||||
}
|
||||
//else {
|
||||
//System.out.println("marginLeft (from param): " + x);
|
||||
//}
|
||||
|
||||
float y = ServletUtil.getFloatParameter(pReq, PARAM_MARGIN_TOP,
|
||||
Float.MIN_VALUE);
|
||||
float lineHeight = (float) (bounds[0] != null ? bounds[0].getHeight() :
|
||||
font.getStringBounds(lines[0],
|
||||
pRes.getFontRenderContext()).getHeight());
|
||||
|
||||
if (y <= Float.MIN_VALUE) {
|
||||
// Center
|
||||
y = (float) ((pHeight - lineHeight) / 2f)
|
||||
- (lineHeight * (lines.length - 2.5f) / 2f);
|
||||
|
||||
//System.out.println("marginTop: " + y);
|
||||
}
|
||||
else {
|
||||
// Todo: Correct for font height?
|
||||
y += font.getSize2D();
|
||||
//System.out.println("marginTop (from param):" + y);
|
||||
|
||||
}
|
||||
|
||||
//System.out.println("Font size: " + font.getSize2D());
|
||||
//System.out.println("Line height: " + lineHeight);
|
||||
|
||||
// Draw
|
||||
for (int i = 0; i < lines.length; i++) {
|
||||
pRes.drawString(lines[i], x, y + lineHeight * i);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the font style constant.
|
||||
*
|
||||
* @param pStyle a string containing either the word {@code "plain"} or one
|
||||
* or more of {@code "bold"} and {@code italic}.
|
||||
* @return the font style constant as defined in {@link Font}.
|
||||
*
|
||||
* @see Font#PLAIN
|
||||
* @see Font#BOLD
|
||||
* @see Font#ITALIC
|
||||
*/
|
||||
private int getFontStyle(String pStyle) {
|
||||
if (pStyle == null
|
||||
|| StringUtil.containsIgnoreCase(pStyle, FONT_STYLE_PLAIN)) {
|
||||
return Font.PLAIN;
|
||||
}
|
||||
|
||||
// Try to find bold/italic
|
||||
int style = Font.PLAIN;
|
||||
if (StringUtil.containsIgnoreCase(pStyle, FONT_STYLE_BOLD)) {
|
||||
style |= Font.BOLD;
|
||||
}
|
||||
if (StringUtil.containsIgnoreCase(pStyle, FONT_STYLE_ITALIC)) {
|
||||
style |= Font.ITALIC;
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the angle of rotation from the request.
|
||||
*
|
||||
* @param pRequest the servlet request to get parameters from
|
||||
* @return the angle in radians.
|
||||
*/
|
||||
private double getAngle(ServletRequest pRequest) {
|
||||
// Get angle
|
||||
double angle =
|
||||
ServletUtil.getDoubleParameter(pRequest, PARAM_TEXT_ROTATION, 0.0);
|
||||
|
||||
// Convert to radians, if needed
|
||||
String units = pRequest.getParameter(PARAM_TEXT_ROTATION_UNITS);
|
||||
if (!StringUtil.isEmpty(units)
|
||||
&& ROTATION_DEGREES.equalsIgnoreCase(units)) {
|
||||
angle = MathUtil.toRadians(angle);
|
||||
}
|
||||
|
||||
return angle;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@@ -1,7 +1,6 @@
|
||||
/**
|
||||
* Contains various image-outputting servlets, that should run under any servlet engine. To create your own image servlet, simply subclass the servlet
|
||||
* {@code ImageServlet}. Optionally implement the interface
|
||||
* {@code ImagePainterServlet}, if you want to do painting.
|
||||
* Contains various image-outputting filters, that should run under any
|
||||
* servlet engine.
|
||||
* <P>
|
||||
* Some of these methods may require use of the native graphics libraries
|
||||
* supported by the JVM, like the X libraries on Unix systems, and should be
|
||||
@@ -13,8 +12,8 @@
|
||||
* <A href="http://java.sun.com/j2se/1.4/docs/guide/awt/AWTChanges.html#headless">AWT Enhancements</A> and bugtraq report
|
||||
* <A href="http://developer.java.sun.com/developer/bugParade/bugs/4281163.html">4281163</A> for more information on this issue.
|
||||
* <P>
|
||||
* If you cannot use JRE 1.4 for any reason, or do not want to use the X
|
||||
* libraries, a possibilty is to use the
|
||||
* If you cannot use JRE 1.4 or later, or do not want to use the X
|
||||
* libraries, one possibility is to use the
|
||||
* <A href="http://www.eteks.com/pja/en/">PJA package</A> (com.eteks.pja),
|
||||
* and start the JVM with the following options:
|
||||
* <DL>
|
||||
|
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2002 TwelveMonkeys.
|
||||
* All rights reserved.
|
||||
*
|
||||
* $Log: Droplet.java,v $
|
||||
* Revision 1.3 2003/10/06 14:25:19 WMHAKUR
|
||||
* Code clean-up only.
|
||||
*
|
||||
* Revision 1.2 2002/10/18 14:12:16 WMHAKUR
|
||||
* Now, it even compiles. :-/
|
||||
*
|
||||
* Revision 1.1 2002/10/18 14:02:16 WMHAKUR
|
||||
* Moved to com.twelvemonkeys.servlet.jsp.droplet
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.servlet.jsp.droplet;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.*;
|
||||
import javax.servlet.jsp.*;
|
||||
|
||||
import com.twelvemonkeys.servlet.jsp.droplet.taglib.*;
|
||||
|
||||
/**
|
||||
* Dynamo Droplet like Servlet.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
*
|
||||
* @version $Revision: #1 $, ($Date: 2008/05/05 $)
|
||||
*
|
||||
*/
|
||||
public abstract class Droplet extends HttpServlet implements JspFragment {
|
||||
|
||||
// Copy doc
|
||||
public abstract void service(PageContext pPageContext)
|
||||
throws ServletException, IOException;
|
||||
|
||||
/**
|
||||
* Services a parameter. Programatically equivalent to the
|
||||
* <d:valueof param="pParameter"/> JSP tag.
|
||||
*/
|
||||
public void serviceParameter(String pParameter, PageContext pPageContext)
|
||||
throws ServletException, IOException {
|
||||
Object param = pPageContext.getRequest().getAttribute(pParameter);
|
||||
|
||||
if (param != null) {
|
||||
if (param instanceof Param) {
|
||||
((Param) param).service(pPageContext);
|
||||
}
|
||||
else {
|
||||
pPageContext.getOut().print(param);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Try to get value from parameters
|
||||
Object obj = pPageContext.getRequest().getParameter(pParameter);
|
||||
|
||||
// Print parameter or default value
|
||||
pPageContext.getOut().print((obj != null) ? obj : "");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* "There's no need to override this method." :-)
|
||||
*/
|
||||
final public void service(HttpServletRequest pRequest,
|
||||
HttpServletResponse pResponse)
|
||||
throws ServletException, IOException {
|
||||
PageContext pageContext =
|
||||
(PageContext) pRequest.getAttribute(IncludeTag.PAGE_CONTEXT);
|
||||
|
||||
// TODO: What if pageContext == null
|
||||
service(pageContext);
|
||||
}
|
||||
}
|
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2002 TwelveMonkeys.
|
||||
* All rights reserved.
|
||||
*
|
||||
* $Log: JspFragment.java,v $
|
||||
* Revision 1.2 2003/10/06 14:25:36 WMHAKUR
|
||||
* Code clean-up only.
|
||||
*
|
||||
* Revision 1.1 2002/10/18 14:02:16 WMHAKUR
|
||||
* Moved to com.twelvemonkeys.servlet.jsp.droplet
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.servlet.jsp.droplet;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.jsp.*;
|
||||
|
||||
/**
|
||||
* Interface for JSP sub pages or page fragments to implement.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
*
|
||||
* @version $Revision: #1 $, ($Date: 2008/05/05 $)
|
||||
*/
|
||||
public interface JspFragment {
|
||||
|
||||
/**
|
||||
* Services a sub page or a page fragment inside another page
|
||||
* (or PageContext).
|
||||
*
|
||||
* @param pContext the PageContext that is used to render the subpage.
|
||||
*
|
||||
* @throws ServletException if an exception occurs that interferes with the
|
||||
* subpage's normal operation
|
||||
* @throws IOException if an input or output exception occurs
|
||||
*/
|
||||
public void service(PageContext pContext)
|
||||
throws ServletException, IOException;
|
||||
}
|
@@ -1,29 +0,0 @@
|
||||
|
||||
package com.twelvemonkeys.servlet.jsp.droplet;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.jsp.*;
|
||||
|
||||
/**
|
||||
* Oparam (Open parameter)
|
||||
*/
|
||||
public class Oparam extends Param implements JspFragment {
|
||||
/**
|
||||
* Creates an Oparam.
|
||||
*
|
||||
* @param pValue the value of the parameter
|
||||
*/
|
||||
public Oparam(String pValue) {
|
||||
super(pValue);
|
||||
}
|
||||
|
||||
public void service(PageContext pContext)
|
||||
throws ServletException, IOException {
|
||||
pContext.getServletContext().log("Service subpage " + pContext.getServletContext().getRealPath(mValue));
|
||||
|
||||
pContext.include(mValue);
|
||||
}
|
||||
}
|
||||
|
@@ -1,42 +0,0 @@
|
||||
|
||||
package com.twelvemonkeys.servlet.jsp.droplet;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.jsp.*;
|
||||
|
||||
/**
|
||||
* Param
|
||||
*/
|
||||
public class Param implements JspFragment {
|
||||
|
||||
/** The value member field. */
|
||||
protected String mValue = null;
|
||||
|
||||
/**
|
||||
* Creates a Param.
|
||||
*
|
||||
* @param pValue the value of the parameter
|
||||
*/
|
||||
public Param(String pValue) {
|
||||
mValue = pValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the parameter.
|
||||
*/
|
||||
public String getValue() {
|
||||
return mValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Services the page fragment. This version simply prints the value of
|
||||
* this parameter to teh PageContext's out.
|
||||
*/
|
||||
public void service(PageContext pContext)
|
||||
throws ServletException, IOException {
|
||||
JspWriter writer = pContext.getOut();
|
||||
writer.print(mValue);
|
||||
}
|
||||
}
|
@@ -1,10 +0,0 @@
|
||||
/**
|
||||
* Dynamo Droplet-like functionality for JSP.
|
||||
*
|
||||
* This package is early beta, not for commercial use! :-)
|
||||
* Read: The interfaces and classes in this package (and subpackages) will be
|
||||
* developed and modified for a while.
|
||||
*
|
||||
* TODO: Insert taglib-descriptor here?
|
||||
*/
|
||||
package com.twelvemonkeys.servlet.jsp.droplet;
|
@@ -1,214 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2002 TwelveMonkeys.
|
||||
* All rights reserved.
|
||||
*
|
||||
* $Log: IncludeTag.java,v $
|
||||
* Revision 1.2 2003/10/06 14:25:36 WMHAKUR
|
||||
* Code clean-up only.
|
||||
*
|
||||
* Revision 1.1 2002/10/18 14:03:09 WMHAKUR
|
||||
* Moved to com.twelvemonkeys.servlet.jsp.droplet.taglib
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.servlet.jsp.droplet.taglib;
|
||||
|
||||
import com.twelvemonkeys.servlet.jsp.taglib.ExTagSupport;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.jsp.JspException;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Include tag tag that emulates ATG Dynamo Droplet tag JHTML behaviour for
|
||||
* JSP.
|
||||
*
|
||||
* @author Thomas Purcell (CSC Australia)
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
*
|
||||
* @version $Revision: #1 $, ($Date: 2008/05/05 $)
|
||||
*
|
||||
*/
|
||||
public class IncludeTag extends ExTagSupport {
|
||||
/**
|
||||
* This will contain the names of all the parameters that have been
|
||||
* added to the PageContext.REQUEST_SCOPE scope by this tag.
|
||||
*/
|
||||
private ArrayList mParameterNames = null;
|
||||
|
||||
/**
|
||||
* If any of the parameters we insert for this tag already exist, then
|
||||
* we back up the older parameter in this {@code HashMap} and
|
||||
* restore them when the tag is finished.
|
||||
*/
|
||||
private HashMap mOldParameters = null;
|
||||
|
||||
/**
|
||||
* This is the URL for the JSP page that the parameters contained in this
|
||||
* tag are to be inserted into.
|
||||
*/
|
||||
private String mPage;
|
||||
|
||||
/**
|
||||
* The name of the PageContext attribute
|
||||
*/
|
||||
public final static String PAGE_CONTEXT = "com.twelvemonkeys.servlet.jsp.PageContext";
|
||||
|
||||
/**
|
||||
* Sets the value for the JSP page to insert the parameters into. This
|
||||
* will be set by the tag attribute within the original JSP page.
|
||||
*
|
||||
* @param pPage The URL for the JSP page to insert parameters into.
|
||||
*/
|
||||
public void setPage(String pPage) {
|
||||
mPage = pPage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a parameter to the {@code PageContext.REQUEST_SCOPE} scope.
|
||||
* If a parameter with the same name as {@code pName} already exists,
|
||||
* then the old parameter is first placed in the {@code OldParameters}
|
||||
* member variable. When this tag is finished, the old value will be
|
||||
* restored.
|
||||
*
|
||||
* @param pName The name of the new parameter to be stored in the
|
||||
* {@code PageContext.REQUEST_SCOPE} scope.
|
||||
* @param pValue The value for the parmeter to be stored in the {@code
|
||||
* PageContext.REQUEST_SCOPE} scope.
|
||||
*/
|
||||
public void addParameter(String pName, Object pValue) {
|
||||
// Check that we haven't already saved this parameter
|
||||
if (!mParameterNames.contains(pName)) {
|
||||
mParameterNames.add(pName);
|
||||
|
||||
// Now check if this parameter already exists in the page.
|
||||
Object obj = getRequest().getAttribute(pName);
|
||||
if (obj != null) {
|
||||
mOldParameters.put(pName, obj);
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, insert the parameter in the request scope.
|
||||
getRequest().setAttribute(pName, pValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the method called when the JSP interpreter first hits the tag
|
||||
* associated with this class. This method will firstly determine whether
|
||||
* the page referenced by the {@code page} attribute exists. If the
|
||||
* page doesn't exist, this method will throw a {@code JspException}.
|
||||
* If the page does exist, this method will hand control over to that JSP
|
||||
* page.
|
||||
*
|
||||
* @exception JspException
|
||||
*/
|
||||
public int doStartTag() throws JspException {
|
||||
mOldParameters = new HashMap();
|
||||
mParameterNames = new ArrayList();
|
||||
|
||||
return EVAL_BODY_INCLUDE;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called when the JSP page compiler hits the end tag. By
|
||||
* now all the data should have been passed and parameters entered into
|
||||
* the {@code PageContext.REQUEST_SCOPE} scope. This method includes
|
||||
* the JSP page whose URL is stored in the {@code mPage} member
|
||||
* variable.
|
||||
*
|
||||
* @exception JspException
|
||||
*/
|
||||
public int doEndTag() throws JspException {
|
||||
String msg;
|
||||
|
||||
try {
|
||||
Iterator iterator;
|
||||
String parameterName;
|
||||
|
||||
// -- Harald K 20020726
|
||||
// Include the page, in place
|
||||
//getDispatcher().include(getRequest(), getResponse());
|
||||
addParameter(PAGE_CONTEXT, pageContext); // Will be cleared later
|
||||
pageContext.include(mPage);
|
||||
|
||||
// Remove all the parameters that were added to the request scope
|
||||
// for this insert tag.
|
||||
iterator = mParameterNames.iterator();
|
||||
|
||||
while (iterator.hasNext()) {
|
||||
parameterName = (String) iterator.next();
|
||||
|
||||
getRequest().removeAttribute(parameterName);
|
||||
}
|
||||
|
||||
iterator = mOldParameters.keySet().iterator();
|
||||
|
||||
// Restore the parameters we temporarily replaced (if any).
|
||||
while (iterator.hasNext()) {
|
||||
parameterName = (String) iterator.next();
|
||||
|
||||
getRequest().setAttribute(parameterName, mOldParameters.get(parameterName));
|
||||
}
|
||||
|
||||
return super.doEndTag();
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
msg = "Caught an IOException while including " + mPage
|
||||
+ "\n" + ioe.toString();
|
||||
log(msg, ioe);
|
||||
throw new JspException(msg);
|
||||
}
|
||||
catch (ServletException se) {
|
||||
msg = "Caught a ServletException while including " + mPage
|
||||
+ "\n" + se.toString();
|
||||
log(msg, se);
|
||||
throw new JspException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Free up the member variables that we've used throughout this tag.
|
||||
*/
|
||||
protected void clearServiceState() {
|
||||
mOldParameters = null;
|
||||
mParameterNames = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the request dispatcher for the JSP page whose URL is stored in
|
||||
* the {@code mPage} member variable.
|
||||
*
|
||||
* @return The RequestDispatcher for the JSP page whose URL is stored in
|
||||
* the {@code mPage} member variable.
|
||||
*/
|
||||
/*
|
||||
private RequestDispatcher getDispatcher() {
|
||||
return getRequest().getRequestDispatcher(mPage);
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* Returns the HttpServletRequest object for the current user request.
|
||||
*
|
||||
* @return The HttpServletRequest object for the current user request.
|
||||
*/
|
||||
private HttpServletRequest getRequest() {
|
||||
return (HttpServletRequest) pageContext.getRequest();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the HttpServletResponse object for the current user request.
|
||||
*
|
||||
* @return The HttpServletResponse object for the current user request.
|
||||
*/
|
||||
private HttpServletResponse getResponse() {
|
||||
return (HttpServletResponse) pageContext.getResponse();
|
||||
}
|
||||
}
|
@@ -1,184 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2002 TwelveMonkeys.
|
||||
* All rights reserved.
|
||||
*
|
||||
* $Log: NestingHandler.java,v $
|
||||
* Revision 1.4 2003/10/06 14:25:44 WMHAKUR
|
||||
* Code clean-up only.
|
||||
*
|
||||
* Revision 1.3 2003/08/04 15:26:30 WMHAKUR
|
||||
* Code clean-up.
|
||||
*
|
||||
* Revision 1.2 2002/10/18 14:28:07 WMHAKUR
|
||||
* Fixed package error.
|
||||
*
|
||||
* Revision 1.1 2002/10/18 14:03:09 WMHAKUR
|
||||
* Moved to com.twelvemonkeys.servlet.jsp.droplet.taglib
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.servlet.jsp.droplet.taglib;
|
||||
|
||||
import com.twelvemonkeys.lang.StringUtil;
|
||||
|
||||
import org.xml.sax.*;
|
||||
import org.xml.sax.helpers.DefaultHandler;
|
||||
|
||||
/**
|
||||
* A SAX handler that returns an exception if the nesting of
|
||||
* {@code param}, {@code oparam}, {@code droplet} and
|
||||
* {@code valueof} is not correct.
|
||||
*
|
||||
* Based on the NestingHandler.java,
|
||||
* taken from More Servlets and JavaServer Pages
|
||||
* from Prentice Hall and Sun Microsystems Press,
|
||||
* http://www.moreservlets.com/.
|
||||
* © 2002 Marty Hall; may be freely used or adapted.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
*
|
||||
* @version $Revision: #1 $, ($Date: 2008/05/05 $)
|
||||
*/
|
||||
|
||||
public class NestingHandler extends DefaultHandler {
|
||||
private String mIncludeTagName = "include";
|
||||
private String mParamTagName = "param";
|
||||
private String mOpenParamTagName = "oparam";
|
||||
|
||||
//private Stack mParents = new Stack();
|
||||
|
||||
private boolean mInIncludeTag = false;
|
||||
|
||||
private String mNamespacePrefix = null;
|
||||
private String mNamespaceURI = null;
|
||||
|
||||
private NestingValidator mValidator = null;
|
||||
|
||||
public NestingHandler(String pNamespacePrefix, String pNameSpaceURI,
|
||||
NestingValidator pValidator) {
|
||||
mNamespacePrefix = pNamespacePrefix;
|
||||
mNamespaceURI = pNameSpaceURI;
|
||||
|
||||
mValidator = pValidator;
|
||||
}
|
||||
|
||||
public void startElement(String pNamespaceURI, String pLocalName,
|
||||
String pQualifiedName, Attributes pAttributes)
|
||||
throws SAXException {
|
||||
String namespacePrefix = !StringUtil.isEmpty(pNamespaceURI)
|
||||
? getNSPrefixFromURI(pNamespaceURI)
|
||||
: getNamespacePrefix(pQualifiedName);
|
||||
|
||||
String localName = !StringUtil.isEmpty(pLocalName)
|
||||
? pLocalName : getLocalName(pQualifiedName);
|
||||
/*
|
||||
if (namespacePrefix.equals(mNamespacePrefix)) {
|
||||
System.out.println("startElement:\nnamespaceURI=" + pNamespaceURI
|
||||
+ " namespacePrefix=" + namespacePrefix
|
||||
+ " localName=" + localName
|
||||
+ " qName=" + pQualifiedName
|
||||
+ " attributes=" + pAttributes);
|
||||
}
|
||||
*/
|
||||
if (localName.equals(mIncludeTagName)) {
|
||||
// include
|
||||
//System.out.println("<" + mNamespacePrefix + ":"
|
||||
// + mIncludeTagName + ">");
|
||||
if (mInIncludeTag) {
|
||||
mValidator.reportError("Cannot nest " + namespacePrefix + ":"
|
||||
+ mIncludeTagName);
|
||||
}
|
||||
mInIncludeTag = true;
|
||||
}
|
||||
else if (localName.equals(mParamTagName)) {
|
||||
// param
|
||||
//System.out.println("<" + mNamespacePrefix + ":"
|
||||
// + mParamTagName + "/>");
|
||||
if (!mInIncludeTag) {
|
||||
mValidator.reportError(mNamespacePrefix + ":"
|
||||
+ mParamTagName
|
||||
+ " can only appear within "
|
||||
+ mNamespacePrefix + ":"
|
||||
+ mIncludeTagName);
|
||||
}
|
||||
}
|
||||
else if (localName.equals(mOpenParamTagName)) {
|
||||
// oparam
|
||||
//System.out.println("<" + mNamespacePrefix + ":"
|
||||
// + mOpenParamTagName + ">");
|
||||
if (!mInIncludeTag) {
|
||||
mValidator.reportError(mNamespacePrefix + ":"
|
||||
+ mOpenParamTagName
|
||||
+ " can only appear within "
|
||||
+ mNamespacePrefix + ":"
|
||||
+ mIncludeTagName);
|
||||
}
|
||||
mInIncludeTag = false;
|
||||
}
|
||||
else {
|
||||
// Only jsp:text allowed inside include!
|
||||
if (mInIncludeTag && !localName.equals("text")) {
|
||||
mValidator.reportError(namespacePrefix + ":" + localName
|
||||
+ " can not appear within "
|
||||
+ mNamespacePrefix + ":"
|
||||
+ mIncludeTagName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void endElement(String pNamespaceURI,
|
||||
String pLocalName,
|
||||
String pQualifiedName)
|
||||
throws SAXException {
|
||||
String namespacePrefix = !StringUtil.isEmpty(pNamespaceURI)
|
||||
? getNSPrefixFromURI(pNamespaceURI)
|
||||
: getNamespacePrefix(pQualifiedName);
|
||||
|
||||
String localName = !StringUtil.isEmpty(pLocalName)
|
||||
? pLocalName : getLocalName(pQualifiedName);
|
||||
/*
|
||||
if (namespacePrefix.equals(mNamespacePrefix)) {
|
||||
System.out.println("endElement:\nnamespaceURI=" + pNamespaceURI
|
||||
+ " namespacePrefix=" + namespacePrefix
|
||||
+ " localName=" + localName
|
||||
+ " qName=" + pQualifiedName);
|
||||
}
|
||||
*/
|
||||
if (namespacePrefix.equals(mNamespacePrefix)
|
||||
&& localName.equals(mIncludeTagName)) {
|
||||
|
||||
//System.out.println("</" + mNamespacePrefix + ":"
|
||||
// + mIncludeTagName + ">");
|
||||
|
||||
mInIncludeTag = false;
|
||||
}
|
||||
else if (namespacePrefix.equals(mNamespacePrefix)
|
||||
&& localName.equals(mOpenParamTagName)) {
|
||||
|
||||
//System.out.println("</" + mNamespacePrefix + ":"
|
||||
// + mOpenParamTagName + ">");
|
||||
|
||||
mInIncludeTag = true; // assuming no errors before this...
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Stupid broken namespace-support "fix"..
|
||||
*/
|
||||
|
||||
private String getNSPrefixFromURI(String pNamespaceURI) {
|
||||
return (pNamespaceURI.equals(mNamespaceURI)
|
||||
? mNamespacePrefix : "");
|
||||
}
|
||||
|
||||
private String getNamespacePrefix(String pQualifiedName) {
|
||||
return pQualifiedName.substring(0, pQualifiedName.indexOf(':'));
|
||||
}
|
||||
|
||||
private String getLocalName(String pQualifiedName) {
|
||||
return pQualifiedName.substring(pQualifiedName.indexOf(':') + 1);
|
||||
}
|
||||
}
|
||||
|
@@ -1,108 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2002 TwelveMonkeys.
|
||||
* All rights reserved.
|
||||
*
|
||||
* $Log: NestingValidator.java,v $
|
||||
* Revision 1.4 2003/08/04 15:26:40 WMHAKUR
|
||||
* Code clean-up.
|
||||
*
|
||||
* Revision 1.3 2002/11/18 14:12:43 WMHAKUR
|
||||
* *** empty log message ***
|
||||
*
|
||||
* Revision 1.2 2002/10/18 14:28:07 WMHAKUR
|
||||
* Fixed package error.
|
||||
*
|
||||
* Revision 1.1 2002/10/18 14:03:09 WMHAKUR
|
||||
* Moved to com.twelvemonkeys.servlet.jsp.droplet.taglib
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.servlet.jsp.droplet.taglib;
|
||||
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import javax.servlet.jsp.tagext.*;
|
||||
import javax.xml.parsers.*;
|
||||
|
||||
import org.xml.sax.*;
|
||||
import org.xml.sax.helpers.*;
|
||||
|
||||
import com.twelvemonkeys.util.*;
|
||||
|
||||
/**
|
||||
* A validator that verifies that tags follow
|
||||
* proper nesting order.
|
||||
* <P>
|
||||
* Based on NestingValidator.java,
|
||||
* taken from More Servlets and JavaServer Pages
|
||||
* from Prentice Hall and Sun Microsystems Press,
|
||||
* http://www.moreservlets.com/.
|
||||
* © 2002 Marty Hall; may be freely used or adapted.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
*
|
||||
* @version $Revision: #1 $, ($Date: 2008/05/05 $)
|
||||
*
|
||||
*/
|
||||
|
||||
public class NestingValidator extends TagLibraryValidator {
|
||||
|
||||
private Vector errors = new Vector();
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
|
||||
public ValidationMessage[] validate(String pPrefix,
|
||||
String pURI,
|
||||
PageData pPage) {
|
||||
|
||||
//System.out.println("Validating " + pPrefix + " (" + pURI + ") for "
|
||||
// + pPage + ".");
|
||||
|
||||
// Pass the parser factory in on the command line with
|
||||
// -D to override the use of the Apache parser.
|
||||
|
||||
DefaultHandler handler = new NestingHandler(pPrefix, pURI, this);
|
||||
SAXParserFactory factory = SAXParserFactory.newInstance();
|
||||
|
||||
try {
|
||||
// FileUtil.copy(pPage.getInputStream(), System.out);
|
||||
|
||||
SAXParser parser = factory.newSAXParser();
|
||||
InputSource source =
|
||||
new InputSource(pPage.getInputStream());
|
||||
|
||||
// Parse, handler will use callback to report errors
|
||||
parser.parse(source, handler);
|
||||
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
String errorMessage = e.getMessage();
|
||||
|
||||
reportError(errorMessage);
|
||||
}
|
||||
|
||||
// Return any errors and exceptions, empty array means okay
|
||||
return (ValidationMessage[])
|
||||
errors.toArray(new ValidationMessage[errors.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback method for the handler to report errors
|
||||
*/
|
||||
|
||||
public void reportError(String pMessage) {
|
||||
// The first argument to the ValidationMessage
|
||||
// constructor can be a tag ID. Since tag IDs
|
||||
// are not universally supported, use null for
|
||||
// portability. The important part is the second
|
||||
// argument: the error message.
|
||||
errors.add(new ValidationMessage(null, pMessage));
|
||||
}
|
||||
}
|
||||
|
@@ -1,238 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2002 TwelveMonkeys.
|
||||
* All rights reserved.
|
||||
*
|
||||
* $Log: OparamTag.java,v $
|
||||
* Revision 1.4 2003/10/06 14:25:53 WMHAKUR
|
||||
* Code clean-up only.
|
||||
*
|
||||
* Revision 1.3 2002/11/18 14:12:43 WMHAKUR
|
||||
* *** empty log message ***
|
||||
*
|
||||
* Revision 1.2 2002/11/07 12:20:14 WMHAKUR
|
||||
* Updated to reflect changes in com.twelvemonkeys.util.*Util
|
||||
*
|
||||
* Revision 1.1 2002/10/18 14:03:09 WMHAKUR
|
||||
* Moved to com.twelvemonkeys.servlet.jsp.droplet.taglib
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.servlet.jsp.droplet.taglib;
|
||||
|
||||
import com.twelvemonkeys.io.FileUtil;
|
||||
import com.twelvemonkeys.lang.StringUtil;
|
||||
import com.twelvemonkeys.servlet.jsp.droplet.Oparam;
|
||||
import com.twelvemonkeys.servlet.jsp.taglib.BodyReaderTag;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.jsp.JspException;
|
||||
import javax.servlet.jsp.tagext.BodyTag;
|
||||
import javax.servlet.jsp.tagext.Tag;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
/**
|
||||
* Open parameter tag that emulates ATG Dynamo JHTML behaviour for JSP.
|
||||
*
|
||||
* @author Thomas Purcell (CSC Australia)
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
*
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/jsp/droplet/taglib/OparamTag.java#1 $
|
||||
*/
|
||||
|
||||
public class OparamTag extends BodyReaderTag {
|
||||
|
||||
protected final static String COUNTER = "com.twelvemonkeys.servlet.jsp.taglib.OparamTag.counter";
|
||||
|
||||
|
||||
private File mSubpage = null;
|
||||
|
||||
/**
|
||||
* This is the name of the parameter to be inserted into the {@code
|
||||
* PageContext.REQUEST_SCOPE} scope.
|
||||
*/
|
||||
|
||||
private String mParameterName = null;
|
||||
|
||||
private String mLanguage = null;
|
||||
|
||||
private String mPrefix = null;
|
||||
|
||||
/**
|
||||
* This method allows the JSP page to set the name for the parameter by
|
||||
* using the {@code name} tag attribute.
|
||||
*
|
||||
* @param pName The name for the parameter to insert into the {@code
|
||||
* PageContext.REQUEST_SCOPE} scope.
|
||||
*/
|
||||
|
||||
public void setName(String pName) {
|
||||
mParameterName = pName;
|
||||
}
|
||||
|
||||
public void setLanguage(String pLanguage) {
|
||||
//System.out.println("setLanguage:"+pLanguage);
|
||||
mLanguage = pLanguage;
|
||||
}
|
||||
|
||||
public void setPrefix(String pPrefix) {
|
||||
//System.out.println("setPrefix:"+pPrefix);
|
||||
mPrefix = pPrefix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the tag implemented by this class is enclosed by an {@code
|
||||
* IncludeTag}. If the tag is not enclosed by an
|
||||
* {@code IncludeTag} then a {@code JspException} is thrown.
|
||||
*
|
||||
* @return If this tag is enclosed within an {@code IncludeTag}, then
|
||||
* the default return value from this method is the {@code
|
||||
* TagSupport.EVAL_BODY_TAG} value.
|
||||
* @exception JspException
|
||||
*/
|
||||
|
||||
public int doStartTag() throws JspException {
|
||||
//checkEnclosedInIncludeTag(); // Moved to TagLibValidator
|
||||
|
||||
// Get request
|
||||
HttpServletRequest request = (HttpServletRequest) pageContext.getRequest();
|
||||
|
||||
// Get filename
|
||||
mSubpage = createFileNameFromRequest(request);
|
||||
|
||||
// Get include tag, and add to parameters
|
||||
IncludeTag includeTag = (IncludeTag) getParent();
|
||||
includeTag.addParameter(mParameterName, new Oparam(mSubpage.getName()));
|
||||
|
||||
// if ! subpage.exist || jsp newer than subpage, write new
|
||||
File jsp = new File(pageContext.getServletContext()
|
||||
.getRealPath(request.getServletPath()));
|
||||
|
||||
if (!mSubpage.exists() || jsp.lastModified() > mSubpage.lastModified()) {
|
||||
return BodyTag.EVAL_BODY_BUFFERED;
|
||||
}
|
||||
|
||||
// No need to evaluate body again!
|
||||
return Tag.SKIP_BODY;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the method responsible for actually testing that the tag
|
||||
* implemented by this class is enclosed within an {@code IncludeTag}.
|
||||
*
|
||||
* @exception JspException
|
||||
*/
|
||||
/*
|
||||
protected void checkEnclosedInIncludeTag() throws JspException {
|
||||
Tag parentTag = getParent();
|
||||
|
||||
if ((parentTag != null) && (parentTag instanceof IncludeTag)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String msg = "A class that extends EnclosedIncludeBodyReaderTag " +
|
||||
"is not enclosed within an IncludeTag.";
|
||||
log(msg);
|
||||
throw new JspException(msg);
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* This method cleans up the member variables for this tag in preparation
|
||||
* for being used again. This method is called when the tag finishes it's
|
||||
* current call with in the page but could be called upon again within this
|
||||
* same page. This method is also called in the release stage of the tag
|
||||
* life cycle just in case a JspException was thrown during the tag
|
||||
* execution.
|
||||
*/
|
||||
|
||||
protected void clearServiceState() {
|
||||
mParameterName = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the method responsible for taking the result of the JSP code
|
||||
* that forms the body of this tag and inserts it as a parameter into the
|
||||
* request scope session. If any problems occur while loading the body
|
||||
* into the session scope then a {@code JspException} will be thrown.
|
||||
*
|
||||
* @param pContent The body of the tag as a String.
|
||||
*
|
||||
* @exception JspException
|
||||
*/
|
||||
|
||||
protected void processBody(String pContent) throws JspException {
|
||||
// Okay, we have the content, we need to write it to disk somewhere
|
||||
String content = pContent;
|
||||
|
||||
if (!StringUtil.isEmpty(mLanguage)) {
|
||||
content = "<%@page language=\"" + mLanguage + "\" %>" + content;
|
||||
}
|
||||
|
||||
if (!StringUtil.isEmpty(mPrefix)) {
|
||||
content = "<%@taglib uri=\"/twelvemonkeys-common\" prefix=\"" + mPrefix + "\" %>" + content;
|
||||
}
|
||||
|
||||
// Write the content of the oparam to disk
|
||||
try {
|
||||
log("Processing subpage " + mSubpage.getPath());
|
||||
FileUtil.write(mSubpage, content.getBytes());
|
||||
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
throw new JspException(ioe);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a unique filename for each (nested) oparam
|
||||
*/
|
||||
private File createFileNameFromRequest(HttpServletRequest pRequest) {
|
||||
//System.out.println("ServletPath" + pRequest.getServletPath());
|
||||
String path = pRequest.getServletPath();
|
||||
|
||||
// Find last '/'
|
||||
int splitIndex = path.lastIndexOf("/");
|
||||
|
||||
// Split -> path + name
|
||||
String name = path.substring(splitIndex + 1);
|
||||
path = path.substring(0, splitIndex);
|
||||
|
||||
// Replace special chars in name with '_'
|
||||
name = name.replace('.', '_');
|
||||
String param = mParameterName.replace('.', '_');
|
||||
param = param.replace('/', '_');
|
||||
param = param.replace('\\', '_');
|
||||
param = param.replace(':', '_');
|
||||
|
||||
// tempfile = realPath(path) + name + "_oparam_" + number + ".jsp"
|
||||
int count = getOparamCountFromRequest(pRequest);
|
||||
|
||||
// Hmm.. Would be great, but seems like I can't serve pages from within the temp dir
|
||||
//File temp = (File) getServletContext().getAttribute("javax.servlet.context.tempdir");
|
||||
//return new File(new File(temp, path), name + "_oparam_" + count + "_" + param + ".jsp");
|
||||
|
||||
return new File(new File(pageContext.getServletContext().getRealPath(path)), name + "_oparam_" + count + "_" + param + ".jsp");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current oparam count for this request
|
||||
*/
|
||||
private int getOparamCountFromRequest(HttpServletRequest pRequest) {
|
||||
// Use request.attribute for incrementing oparam counter
|
||||
Integer count = (Integer) pRequest.getAttribute(COUNTER);
|
||||
if (count == null)
|
||||
count = new Integer(0);
|
||||
else
|
||||
count = new Integer(count.intValue() + 1);
|
||||
|
||||
// ... and set it back
|
||||
pRequest.setAttribute(COUNTER, count);
|
||||
|
||||
return count.intValue();
|
||||
}
|
||||
|
||||
}
|
@@ -1,141 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2002 TwelveMonkeys.
|
||||
* All rights reserved.
|
||||
*
|
||||
* $Log: ParamTag.java,v $
|
||||
* Revision 1.2 2003/10/06 14:26:00 WMHAKUR
|
||||
* Code clean-up only.
|
||||
*
|
||||
* Revision 1.1 2002/10/18 14:03:09 WMHAKUR
|
||||
* Moved to com.twelvemonkeys.servlet.jsp.droplet.taglib
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.servlet.jsp.droplet.taglib;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.jsp.*;
|
||||
import javax.servlet.jsp.tagext.*;
|
||||
|
||||
import com.twelvemonkeys.servlet.jsp.droplet.*;
|
||||
import com.twelvemonkeys.servlet.jsp.taglib.*;
|
||||
|
||||
/**
|
||||
* Parameter tag that emulates ATG Dynamo JHTML behaviour for JSP.
|
||||
*
|
||||
* @author Thomas Purcell (CSC Australia)
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
*
|
||||
* @version $Revision: #1 $, ($Date: 2008/05/05 $)
|
||||
*
|
||||
*/
|
||||
|
||||
public class ParamTag extends ExTagSupport {
|
||||
|
||||
/**
|
||||
* This is the name of the parameter to be inserted into the {@code
|
||||
* PageContext.REQUEST_SCOPE} scope.
|
||||
*/
|
||||
|
||||
private String mParameterName;
|
||||
|
||||
/**
|
||||
* This is the value for the parameter to be inserted into the {@code
|
||||
* PageContext.REQUEST_SCOPE} scope.
|
||||
*/
|
||||
|
||||
private Object mParameterValue;
|
||||
|
||||
/**
|
||||
* This method allows the JSP page to set the name for the parameter by
|
||||
* using the {@code name} tag attribute.
|
||||
*
|
||||
* @param pName The name for the parameter to insert into the {@code
|
||||
* PageContext.REQUEST_SCOPE} scope.
|
||||
*/
|
||||
|
||||
public void setName(String pName) {
|
||||
mParameterName = pName;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method allows the JSP page to set the value for hte parameter by
|
||||
* using the {@code value} tag attribute.
|
||||
*
|
||||
* @param pValue The value for the parameter to insert into the <code>
|
||||
* PageContext.REQUEST_SCOPE</page> scope.
|
||||
*/
|
||||
|
||||
public void setValue(String pValue) {
|
||||
mParameterValue = new Param(pValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure that the tag implemented by this class is enclosed by an {@code
|
||||
* IncludeTag}. If the tag is not enclosed by an
|
||||
* {@code IncludeTag} then a {@code JspException} is thrown.
|
||||
*
|
||||
* @return If this tag is enclosed within an {@code IncludeTag}, then
|
||||
* the default return value from this method is the {@code
|
||||
* TagSupport.SKIP_BODY} value.
|
||||
* @exception JspException
|
||||
*/
|
||||
|
||||
public int doStartTag() throws JspException {
|
||||
//checkEnclosedInIncludeTag();
|
||||
|
||||
addParameter();
|
||||
|
||||
return SKIP_BODY;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the method responsible for actually testing that the tag
|
||||
* implemented by this class is enclosed within an {@code IncludeTag}.
|
||||
*
|
||||
* @exception JspException
|
||||
*/
|
||||
/*
|
||||
protected void checkEnclosedInIncludeTag() throws JspException {
|
||||
Tag parentTag = getParent();
|
||||
|
||||
if ((parentTag != null) && (parentTag instanceof IncludeTag)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String msg = "A class that extends EnclosedIncludeBodyReaderTag " +
|
||||
"is not enclosed within an IncludeTag.";
|
||||
log(msg);
|
||||
throw new JspException(msg);
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* This method adds the parameter whose name and value were passed to this
|
||||
* object via the tag attributes to the parent {@code Include} tag.
|
||||
*/
|
||||
|
||||
private void addParameter() {
|
||||
IncludeTag includeTag = (IncludeTag) getParent();
|
||||
|
||||
includeTag.addParameter(mParameterName, mParameterValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* This method cleans up the member variables for this tag in preparation
|
||||
* for being used again. This method is called when the tag finishes it's
|
||||
* current call with in the page but could be called upon again within this
|
||||
* same page. This method is also called in the release stage of the tag
|
||||
* life cycle just in case a JspException was thrown during the tag
|
||||
* execution.
|
||||
*/
|
||||
|
||||
protected void clearServiceState() {
|
||||
mParameterName = null;
|
||||
mParameterValue = null;
|
||||
}
|
||||
}
|
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2002 TwelveMonkeys.
|
||||
* All rights reserved.
|
||||
*
|
||||
* $Log: ValueOfTEI.java,v $
|
||||
* Revision 1.3 2003/10/06 14:26:07 WMHAKUR
|
||||
* Code clean-up only.
|
||||
*
|
||||
* Revision 1.2 2002/10/18 14:28:07 WMHAKUR
|
||||
* Fixed package error.
|
||||
*
|
||||
* Revision 1.1 2002/10/18 14:03:52 WMHAKUR
|
||||
* Moved to com.twelvemonkeys.servlet.jsp.droplet.taglib
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.servlet.jsp.droplet.taglib;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.jsp.*;
|
||||
import javax.servlet.jsp.tagext.*;
|
||||
|
||||
/**
|
||||
* TagExtraInfo for ValueOf.
|
||||
* @todo More meaningful response to the user.
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
*
|
||||
* @version $Revision: #1 $, ($Date: 2008/05/05 $)
|
||||
*
|
||||
*/
|
||||
|
||||
public class ValueOfTEI extends TagExtraInfo {
|
||||
|
||||
public boolean isValid(TagData pTagData) {
|
||||
Object nameAttr = pTagData.getAttribute("name");
|
||||
Object paramAttr = pTagData.getAttribute("param");
|
||||
|
||||
if ((nameAttr != null && paramAttr == null) ||
|
||||
(nameAttr == null && paramAttr != null)) {
|
||||
return true; // Exactly one of name or param set
|
||||
}
|
||||
|
||||
// Either both or none,
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -1,147 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2002 TwelveMonkeys.
|
||||
* All rights reserved.
|
||||
*
|
||||
* $Log: ValueOfTag.java,v $
|
||||
* Revision 1.2 2003/10/06 14:26:14 WMHAKUR
|
||||
* Code clean-up only.
|
||||
*
|
||||
* Revision 1.1 2002/10/18 14:03:52 WMHAKUR
|
||||
* Moved to com.twelvemonkeys.servlet.jsp.droplet.taglib
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.servlet.jsp.droplet.taglib;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.jsp.*;
|
||||
|
||||
import com.twelvemonkeys.servlet.jsp.droplet.*;
|
||||
import com.twelvemonkeys.servlet.jsp.taglib.*;
|
||||
|
||||
/**
|
||||
* ValueOf tag that emulates ATG Dynamo JHTML behaviour for JSP.
|
||||
*
|
||||
* @author Thomas Purcell (CSC Australia)
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @author last modified by $Author: haku $
|
||||
*
|
||||
* @version $Revision: #1 $, ($Date: 2008/05/05 $)
|
||||
*/
|
||||
public class ValueOfTag extends ExTagSupport {
|
||||
|
||||
/**
|
||||
* This is the name of the parameter whose value is to be inserted into
|
||||
* the current JSP page. This value will be set via the {@code name}
|
||||
* attribute.
|
||||
*/
|
||||
private String mParameterName;
|
||||
|
||||
/**
|
||||
* This is the value of the parameter read from the {@code
|
||||
* PageContext.REQUEST_SCOPE} scope. If the parameter doesn't exist,
|
||||
* then this will be null.
|
||||
*/
|
||||
private Object mParameterValue;
|
||||
|
||||
/**
|
||||
* This method is called as part of the initialisation phase of the tag
|
||||
* life cycle. It sets the parameter name to be read from the {@code
|
||||
* PageContext.REQUEST_SCOPE} scope.
|
||||
*
|
||||
* @param pName The name of the parameter to be read from the {@code
|
||||
* PageContext.REQUEST_SCOPE} scope.
|
||||
*/
|
||||
public void setName(String pName) {
|
||||
mParameterName = pName;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called as part of the initialisation phase of the tag
|
||||
* life cycle. It sets the parameter name to be read from the {@code
|
||||
* PageContext.REQUEST_SCOPE} scope. This is just a synonym for
|
||||
* setName, to be more like ATG Dynamo.
|
||||
*
|
||||
* @param pName The name of the parameter to be read from the {@code
|
||||
* PageContext.REQUEST_SCOPE} scope.
|
||||
*/
|
||||
public void setParam(String pName) {
|
||||
mParameterName = pName;
|
||||
}
|
||||
|
||||
/**
|
||||
* This method looks in the session scope for the session-scoped attribute
|
||||
* whose name matches the {@code name} tag attribute for this tag.
|
||||
* If it finds it, then it replaces this tag with the value for the
|
||||
* session-scoped attribute. If it fails to find the session-scoped
|
||||
* attribute, it displays the body for this tag.
|
||||
*
|
||||
* @return If the session-scoped attribute is found, then this method will
|
||||
* return {@code TagSupport.SKIP_BODY}, otherwise it will return
|
||||
* {@code TagSupport.EVAL_BODY_INCLUDE}.
|
||||
* @exception JspException
|
||||
*
|
||||
*/
|
||||
public int doStartTag() throws JspException {
|
||||
try {
|
||||
if (parameterExists()) {
|
||||
if (mParameterValue instanceof JspFragment) {
|
||||
// OPARAM or PARAM
|
||||
((JspFragment) mParameterValue).service(pageContext);
|
||||
/*
|
||||
log("Service subpage " + pageContext.getServletContext().getRealPath(((Oparam) mParameterValue).getName()));
|
||||
|
||||
pageContext.include(((Oparam) mParameterValue).getName());
|
||||
*/
|
||||
}
|
||||
else {
|
||||
// Normal JSP parameter value
|
||||
JspWriter writer = pageContext.getOut();
|
||||
writer.print(mParameterValue);
|
||||
}
|
||||
|
||||
return SKIP_BODY;
|
||||
}
|
||||
else {
|
||||
return EVAL_BODY_INCLUDE;
|
||||
}
|
||||
}
|
||||
catch (ServletException se) {
|
||||
log(se.getMessage(), se);
|
||||
throw new JspException(se);
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
String msg = "Caught an IOException in ValueOfTag.doStartTag()\n"
|
||||
+ ioe.toString();
|
||||
log(msg, ioe);
|
||||
throw new JspException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is used to determine whether the parameter whose name is
|
||||
* stored in {@code mParameterName} exists within the {@code
|
||||
* PageContext.REQUEST_SCOPE} scope. If the parameter does exist,
|
||||
* then this method will return {@code true}, otherwise it returns
|
||||
* {@code false}. This method has the side affect of loading the
|
||||
* parameter value into {@code mParameterValue} if the parameter
|
||||
* does exist.
|
||||
*
|
||||
* @return {@code true} if the parameter whose name is in {@code
|
||||
* mParameterName} exists in the {@code PageContext.REQUEST_SCOPE
|
||||
* } scope, {@code false} otherwise.
|
||||
*/
|
||||
private boolean parameterExists() {
|
||||
mParameterValue = pageContext.getAttribute(mParameterName, PageContext.REQUEST_SCOPE);
|
||||
|
||||
// -- Harald K 20020726
|
||||
if (mParameterValue == null) {
|
||||
mParameterValue = pageContext.getRequest().getParameter(mParameterName);
|
||||
}
|
||||
|
||||
return (mParameterValue != null);
|
||||
}
|
||||
}
|
@@ -1,10 +0,0 @@
|
||||
<HTML>
|
||||
|
||||
<BODY>
|
||||
The TwelveMonkeys droplet TagLib.
|
||||
|
||||
TODO: Insert taglib-descriptor here?
|
||||
|
||||
</BODY>
|
||||
|
||||
</HTML>
|
||||
|
@@ -1,4 +0,0 @@
|
||||
/**
|
||||
* JSP support.
|
||||
*/
|
||||
package com.twelvemonkeys.servlet.jsp;
|
@@ -1,43 +0,0 @@
|
||||
|
||||
package com.twelvemonkeys.servlet.jsp.taglib;
|
||||
|
||||
import javax.servlet.jsp.JspException;
|
||||
|
||||
/**
|
||||
*
|
||||
*
|
||||
* @author Thomas Purcell (CSC Australia)
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public abstract class BodyReaderTag extends ExBodyTagSupport {
|
||||
/**
|
||||
* This is the method called by the JSP engine when the body for a tag
|
||||
* has been parsed and is ready for inclusion in this current tag. This
|
||||
* method takes the content as a string and passes it to the {@code
|
||||
* processBody} method.
|
||||
*
|
||||
* @return This method returns the {@code BodyTagSupport.SKIP_BODY}
|
||||
* constant. This means that the body of the tag will only be
|
||||
* processed the one time.
|
||||
* @exception JspException
|
||||
*/
|
||||
|
||||
public int doAfterBody() throws JspException {
|
||||
processBody(bodyContent.getString());
|
||||
return SKIP_BODY;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the method that child classes must implement. It takes the
|
||||
* body of the tag converted to a String as it's parameter. The body of
|
||||
* the tag will have been interpreted to a String by the JSP engine before
|
||||
* this method is called.
|
||||
*
|
||||
* @param pContent The body for the custom tag converted to a String.
|
||||
* @exception JscException
|
||||
*/
|
||||
|
||||
protected abstract void processBody(String pContent) throws JspException;
|
||||
}
|
@@ -1,240 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2002 TwelveMonkeys.
|
||||
* All rights reserved.
|
||||
*
|
||||
* $Log: CSVToTableTag.java,v $
|
||||
* Revision 1.3 2003/10/06 14:24:50 WMHAKUR
|
||||
* Code clean-up only.
|
||||
*
|
||||
* Revision 1.2 2002/11/26 17:33:49 WMHAKUR
|
||||
* Added documentation & removed System.out.println()s.
|
||||
*
|
||||
* Revision 1.1 2002/11/19 10:50:10 WMHAKUR
|
||||
* Renamed from CSVToTable, to follow naming conventions.
|
||||
*
|
||||
* Revision 1.1 2002/11/18 22:11:16 WMHAKUR
|
||||
* Tag to convert CSV to HTML table.
|
||||
* Can be further transformed, using XSLT.
|
||||
*
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.servlet.jsp.taglib;
|
||||
|
||||
import java.util.*;
|
||||
import java.io.*;
|
||||
|
||||
import javax.servlet.jsp.*;
|
||||
import javax.servlet.jsp.tagext.*;
|
||||
|
||||
/**
|
||||
* Creates a table from a string of "comma-separated values" (CSV).
|
||||
* The delimiter character can be any character (or combination of characters).
|
||||
* The default delimiter is TAB ({@code \t}).
|
||||
*
|
||||
* <P/>
|
||||
* <HR/>
|
||||
* <P/>
|
||||
*
|
||||
* The input may look like this:
|
||||
* <PRE>
|
||||
* <c:totable firstRowIsHeader="true" delimiter=";">
|
||||
* header A;header B
|
||||
* data 1A; data 1B
|
||||
* data 2A; data 2B
|
||||
* </c:totable>
|
||||
* </PRE>
|
||||
*
|
||||
* The output (source) will look like this:
|
||||
* <PRE>
|
||||
* <TABLE>
|
||||
* <TR>
|
||||
* <TH>header A</TH><TH>header B</TH>
|
||||
* </TR>
|
||||
* <TR>
|
||||
* <TD>data 1A</TD><TD>data 1B</TD>
|
||||
* </TR>
|
||||
* <TR>
|
||||
* <TD>data 2A</TD><TD>data 2B</TD>
|
||||
* </TR>
|
||||
* </TABLE>
|
||||
* </PRE>
|
||||
* You wil probably want to use XSLT to make the final output look nicer. :-)
|
||||
*
|
||||
* @see StringTokenizer
|
||||
* @see <A href="http://www.w3.org/TR/xslt">XSLT spec</A>
|
||||
*
|
||||
* @author Harald Kuhr
|
||||
*
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/jsp/taglib/CSVToTableTag.java#1 $
|
||||
*/
|
||||
|
||||
public class CSVToTableTag extends ExBodyTagSupport {
|
||||
|
||||
public final static String TAB = "\t";
|
||||
|
||||
protected String mDelimiter = null;
|
||||
protected boolean mFirstRowIsHeader = false;
|
||||
protected boolean mFirstColIsHeader = false;
|
||||
|
||||
public void setDelimiter(String pDelimiter) {
|
||||
mDelimiter = pDelimiter;
|
||||
}
|
||||
|
||||
public String getDelimiter() {
|
||||
return mDelimiter != null ? mDelimiter : TAB;
|
||||
}
|
||||
|
||||
public void setFirstRowIsHeader(String pBoolean) {
|
||||
mFirstRowIsHeader = Boolean.valueOf(pBoolean).booleanValue();
|
||||
}
|
||||
|
||||
public void setFirstColIsHeader(String pBoolean) {
|
||||
mFirstColIsHeader = Boolean.valueOf(pBoolean).booleanValue();
|
||||
}
|
||||
|
||||
|
||||
public int doEndTag() throws JspException {
|
||||
BodyContent content = getBodyContent();
|
||||
|
||||
try {
|
||||
Table table =
|
||||
Table.parseContent(content.getReader(), getDelimiter());
|
||||
|
||||
JspWriter out = pageContext.getOut();
|
||||
|
||||
//System.out.println("CSVToTable: " + table.getRows() + " rows, "
|
||||
// + table.getCols() + " cols.");
|
||||
|
||||
if (table.getRows() > 0) {
|
||||
out.println("<TABLE>");
|
||||
// Loop over rows
|
||||
for (int row = 0; row < table.getRows(); row++) {
|
||||
out.println("<TR>");
|
||||
|
||||
// Loop over cells in each row
|
||||
for (int col = 0; col < table.getCols(); col++) {
|
||||
// Test if we are using headers, else normal cell
|
||||
if (mFirstRowIsHeader && row == 0
|
||||
|| mFirstColIsHeader && col == 0) {
|
||||
out.println("<TH>" + table.get(row, col)
|
||||
+ " </TH>");
|
||||
}
|
||||
else {
|
||||
out.println("<TD>" + table.get(row, col)
|
||||
+ " </TD>");
|
||||
}
|
||||
}
|
||||
|
||||
out.println("</TR>");
|
||||
|
||||
}
|
||||
out.println("</TABLE>");
|
||||
}
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
throw new JspException(ioe);
|
||||
}
|
||||
|
||||
return super.doEndTag();
|
||||
}
|
||||
|
||||
static class Table {
|
||||
List mRows = null;
|
||||
int mCols = 0;
|
||||
|
||||
private Table(List pRows, int pCols) {
|
||||
mRows = pRows;
|
||||
mCols = pCols;
|
||||
}
|
||||
|
||||
int getRows() {
|
||||
return mRows != null ? mRows.size() : 0;
|
||||
}
|
||||
|
||||
int getCols() {
|
||||
return mCols;
|
||||
}
|
||||
|
||||
List getTableRows() {
|
||||
return mRows;
|
||||
}
|
||||
|
||||
List getTableRow(int pRow) {
|
||||
return mRows != null
|
||||
? (List) mRows.get(pRow)
|
||||
: Collections.EMPTY_LIST;
|
||||
}
|
||||
|
||||
String get(int pRow, int pCol) {
|
||||
List row = getTableRow(pRow);
|
||||
// Rows may contain unequal number of cols
|
||||
return (row.size() > pCol) ? (String) row.get(pCol) : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a BodyContent to a table.
|
||||
*
|
||||
*/
|
||||
|
||||
static Table parseContent(Reader pContent, String pDelim)
|
||||
throws IOException {
|
||||
ArrayList tableRows = new ArrayList();
|
||||
int tdsPerTR = 0;
|
||||
|
||||
// Loop through TRs
|
||||
BufferedReader reader = new BufferedReader(pContent);
|
||||
String tr = null;
|
||||
while ((tr = reader.readLine()) != null) {
|
||||
// Discard blank lines
|
||||
if (tr != null
|
||||
&& tr.trim().length() <= 0 && tr.indexOf(pDelim) < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
//System.out.println("CSVToTable: read LINE=\"" + tr + "\"");
|
||||
|
||||
ArrayList tableDatas = new ArrayList();
|
||||
StringTokenizer tableRow = new StringTokenizer(tr, pDelim,
|
||||
true);
|
||||
|
||||
boolean lastWasDelim = false;
|
||||
while (tableRow.hasMoreTokens()) {
|
||||
String td = tableRow.nextToken();
|
||||
|
||||
//System.out.println("CSVToTable: read data=\"" + td + "\"");
|
||||
|
||||
// Test if we have empty TD
|
||||
if (td.equals(pDelim)) {
|
||||
if (lastWasDelim) {
|
||||
// Add empty TD
|
||||
tableDatas.add("");
|
||||
}
|
||||
|
||||
// We just read a delimitter
|
||||
lastWasDelim = true;
|
||||
}
|
||||
else {
|
||||
// No tab, normal data
|
||||
lastWasDelim = false;
|
||||
|
||||
// Add normal TD
|
||||
tableDatas.add(td);
|
||||
}
|
||||
} // end while (tableRow.hasNext())
|
||||
|
||||
// Store max TD count
|
||||
if (tableDatas.size() > tdsPerTR) {
|
||||
tdsPerTR = tableDatas.size();
|
||||
}
|
||||
|
||||
// Add a table row
|
||||
tableRows.add(tableDatas);
|
||||
}
|
||||
|
||||
// Return TABLE
|
||||
return new Table(tableRows, tdsPerTR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -1,286 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2002 TwelveMonkeys.
|
||||
* All rights reserved.
|
||||
*
|
||||
* $Log: ExBodyTagSupport.java,v $
|
||||
* Revision 1.3 2003/10/06 14:24:57 WMHAKUR
|
||||
* Code clean-up only.
|
||||
*
|
||||
* Revision 1.2 2002/11/18 22:10:27 WMHAKUR
|
||||
* *** empty log message ***
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.servlet.jsp.taglib;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.*;
|
||||
import javax.servlet.jsp.*;
|
||||
import javax.servlet.jsp.tagext.*;
|
||||
|
||||
/**
|
||||
* This is the class that should be extended by all jsp pages that do use their
|
||||
* body. It contains a lot of helper methods for simplifying common tasks.
|
||||
*
|
||||
* @author Thomas Purcell (CSC Australia)
|
||||
* @author Harald Kuhr
|
||||
*
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/jsp/taglib/ExBodyTagSupport.java#1 $
|
||||
*/
|
||||
|
||||
public class ExBodyTagSupport extends BodyTagSupport implements ExTag {
|
||||
/**
|
||||
* writeHtml ensures that the text being outputted appears as it was
|
||||
* entered. This prevents users from hacking the system by entering
|
||||
* html or jsp code into an entry form where that value will be displayed
|
||||
* later in the site.
|
||||
*
|
||||
* @param pOut The JspWriter to write the output to.
|
||||
* @param pHtml The original html to filter and output to the user.
|
||||
* @throws IOException If the user clicks Stop in the browser, or their
|
||||
* browser crashes, then the JspWriter will throw an IOException when
|
||||
* the jsp tries to write to it.
|
||||
*/
|
||||
|
||||
public void writeHtml(JspWriter pOut, String pHtml) throws IOException {
|
||||
StringTokenizer parser = new StringTokenizer(pHtml, "<>&", true);
|
||||
|
||||
while (parser.hasMoreTokens()) {
|
||||
String token = parser.nextToken();
|
||||
|
||||
if (token.equals("<")) {
|
||||
pOut.print("<");
|
||||
}
|
||||
else if (token.equals(">")) {
|
||||
pOut.print(">");
|
||||
}
|
||||
else if (token.equals("&")) {
|
||||
pOut.print("&");
|
||||
}
|
||||
else {
|
||||
pOut.print(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a message to the servlet context.
|
||||
*
|
||||
* @param pMsg The error message to log.
|
||||
*/
|
||||
|
||||
public void log(String pMsg) {
|
||||
getServletContext().log(pMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a message to the servlet context and include the exception that is
|
||||
* passed in as the second parameter.
|
||||
*
|
||||
* @param pMsg The error message to log.
|
||||
* @param pException The exception that caused this error message to be
|
||||
* logged.
|
||||
*/
|
||||
|
||||
public void log(String pMsg, Throwable pException) {
|
||||
getServletContext().log(pMsg, pException);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the ServletContext object associated with the current
|
||||
* PageContext object.
|
||||
*
|
||||
* @return The ServletContext object associated with the current
|
||||
* PageContext object.
|
||||
*/
|
||||
|
||||
public ServletContext getServletContext() {
|
||||
return pageContext.getServletContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the tag has finished running. Any clean up that needs
|
||||
* to be done between calls to this tag but within the same JSP page is
|
||||
* called in the {@code clearServiceState()} method call.
|
||||
*
|
||||
* @exception JspException
|
||||
*/
|
||||
|
||||
public int doEndTag() throws JspException {
|
||||
clearServiceState();
|
||||
return super.doEndTag();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a tag's role in the current JSP page is finished. After
|
||||
* the {@code clearProperties()} method is called, the custom tag
|
||||
* should be in an identical state as when it was first created. The
|
||||
* {@code clearServiceState()} method is called here just in case an
|
||||
* exception was thrown in the custom tag. If an exception was thrown,
|
||||
* then the {@code doEndTag()} method will not have been called and
|
||||
* the tag might not have been cleaned up properly.
|
||||
*/
|
||||
|
||||
public void release() {
|
||||
clearServiceState();
|
||||
|
||||
clearProperties();
|
||||
super.release();
|
||||
}
|
||||
|
||||
/**
|
||||
* The default implementation for the {@code clearProperties()}. Not
|
||||
* all tags will need to overload this method call. By implementing it
|
||||
* here, all classes that extend this object are able to call {@code
|
||||
* super.clearProperties()}. So, if the class extends a different
|
||||
* tag, or this one, the parent method should always be called. This
|
||||
* method will be called when the tag is to be released. That is, the
|
||||
* tag has finished for the current page and should be returned to it's
|
||||
* initial state.
|
||||
*/
|
||||
|
||||
protected void clearProperties() {
|
||||
}
|
||||
|
||||
/**
|
||||
* The default implementation for the {@code clearServiceState()}.
|
||||
* Not all tags will need to overload this method call. By implementing it
|
||||
* here, all classes that extend this object are able to call {@code
|
||||
* super.clearServiceState()}. So, if the class extends a different
|
||||
* tag, or this one, the parent method should always be called. This
|
||||
* method will be called when the tag has finished it's current tag
|
||||
* within the page, but may be called upon again in this same JSP page.
|
||||
*/
|
||||
|
||||
protected void clearServiceState() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the initialisation parameter from the {@code
|
||||
* PageContext.APPLICATION_SCOPE} scope. These initialisation
|
||||
* parameters are defined in the {@code web.xml} configuration file.
|
||||
*
|
||||
* @param pName The name of the initialisation parameter to return the
|
||||
* value for.
|
||||
* @return The value for the parameter whose name was passed in as a
|
||||
* parameter. If the parameter does not exist, then {@code null}
|
||||
* will be returned.
|
||||
*/
|
||||
|
||||
public String getInitParameter(String pName) {
|
||||
return getInitParameter(pName, PageContext.APPLICATION_SCOPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an Enumeration containing all the names for all the
|
||||
* initialisation parametes defined in the {@code
|
||||
* PageContext.APPLICATION_SCOPE} scope.
|
||||
*
|
||||
* @return An {@code Enumeration} containing all the names for all the
|
||||
* initialisation parameters.
|
||||
*/
|
||||
|
||||
public Enumeration getInitParameterNames() {
|
||||
return getInitParameterNames(PageContext.APPLICATION_SCOPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the initialisation parameter from the scope specified with the
|
||||
* name specified.
|
||||
*
|
||||
* @param pName The name of the initialisation parameter to return the
|
||||
* value for.
|
||||
* @param pScope The scope to search for the initialisation parameter
|
||||
* within.
|
||||
* @return The value of the parameter found. If no parameter with the
|
||||
* name specified is found in the scope specified, then {@code null
|
||||
* } is returned.
|
||||
*/
|
||||
|
||||
public String getInitParameter(String pName, int pScope) {
|
||||
switch (pScope) {
|
||||
case PageContext.PAGE_SCOPE:
|
||||
return getServletConfig().getInitParameter(pName);
|
||||
case PageContext.APPLICATION_SCOPE:
|
||||
return getServletContext().getInitParameter(pName);
|
||||
default:
|
||||
throw new IllegalArgumentException("Illegal scope.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an enumeration containing all the parameters defined in the
|
||||
* scope specified by the parameter.
|
||||
*
|
||||
* @param pScope The scope to return the names of all the parameters
|
||||
* defined within.
|
||||
* @return An {@code Enumeration} containing all the names for all the
|
||||
* parameters defined in the scope passed in as a parameter.
|
||||
*/
|
||||
|
||||
public Enumeration getInitParameterNames(int pScope) {
|
||||
switch (pScope) {
|
||||
case PageContext.PAGE_SCOPE:
|
||||
return getServletConfig().getInitParameterNames();
|
||||
case PageContext.APPLICATION_SCOPE:
|
||||
return getServletContext().getInitParameterNames();
|
||||
default:
|
||||
throw new IllegalArgumentException("Illegal scope");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the servlet config associated with the current JSP page request.
|
||||
*
|
||||
* @return The {@code ServletConfig} associated with the current
|
||||
* request.
|
||||
*/
|
||||
|
||||
public ServletConfig getServletConfig() {
|
||||
return pageContext.getServletConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the context path associated with the current JSP page request.
|
||||
* If the request is not a HttpServletRequest, this method will
|
||||
* return "/".
|
||||
*
|
||||
* @return a path relative to the current context's root, or
|
||||
* {@code "/"} if this is not a HTTP request.
|
||||
*/
|
||||
|
||||
public String getContextPath() {
|
||||
ServletRequest request = pageContext.getRequest();
|
||||
if (request instanceof HttpServletRequest) {
|
||||
return ((HttpServletRequest) request).getContextPath();
|
||||
}
|
||||
return "/";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the resource associated with the given relative path for the
|
||||
* current JSP page request.
|
||||
* The path may be absolute, or relative to the current context root.
|
||||
*
|
||||
* @param pPath the path
|
||||
*
|
||||
* @return a path relative to the current context root
|
||||
*/
|
||||
|
||||
public InputStream getResourceAsStream(String pPath) {
|
||||
// throws MalformedURLException {
|
||||
String path = pPath;
|
||||
|
||||
if (pPath != null && !pPath.startsWith("/")) {
|
||||
path = getContextPath() + pPath;
|
||||
}
|
||||
|
||||
return pageContext.getServletContext().getResourceAsStream(path);
|
||||
}
|
||||
|
||||
}
|
@@ -1,162 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2002 TwelveMonkeys.
|
||||
* All rights reserved.
|
||||
*
|
||||
* $Log: ExTag.java,v $
|
||||
* Revision 1.2 2003/10/06 14:25:05 WMHAKUR
|
||||
* Code clean-up only.
|
||||
*
|
||||
* Revision 1.1 2002/11/18 22:10:27 WMHAKUR
|
||||
* *** empty log message ***
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.servlet.jsp.taglib;
|
||||
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.jsp.*;
|
||||
import javax.servlet.jsp.tagext.*;
|
||||
|
||||
/**
|
||||
* This interface contains a lot of helper methods for simplifying common
|
||||
* taglib related tasks.
|
||||
*
|
||||
* @author Harald Kuhr
|
||||
*
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/jsp/taglib/ExTag.java#1 $
|
||||
*/
|
||||
|
||||
public interface ExTag extends Tag {
|
||||
|
||||
/**
|
||||
* writeHtml ensures that the text being outputted appears as it was
|
||||
* entered. This prevents users from hacking the system by entering
|
||||
* html or jsp code into an entry form where that value will be displayed
|
||||
* later in the site.
|
||||
*
|
||||
* @param pOut The JspWriter to write the output to.
|
||||
* @param pHtml The original html to filter and output to the user.
|
||||
* @throws IOException If the user clicks Stop in the browser, or their
|
||||
* browser crashes, then the JspWriter will throw an IOException when
|
||||
* the jsp tries to write to it.
|
||||
*/
|
||||
|
||||
public void writeHtml(JspWriter pOut, String pHtml) throws IOException;
|
||||
|
||||
/**
|
||||
* Log a message to the servlet context.
|
||||
*
|
||||
* @param pMsg The error message to log.
|
||||
*/
|
||||
|
||||
public void log(String pMsg);
|
||||
|
||||
/**
|
||||
* Logs a message to the servlet context and include the exception that is
|
||||
* passed in as the second parameter.
|
||||
*
|
||||
* @param pMsg The error message to log.
|
||||
* @param pException The exception that caused this error message to be
|
||||
* logged.
|
||||
*/
|
||||
|
||||
public void log(String pMsg, Throwable pException);
|
||||
|
||||
/**
|
||||
* Retrieves the ServletContext object associated with the current
|
||||
* PageContext object.
|
||||
*
|
||||
* @return The ServletContext object associated with the current
|
||||
* PageContext object.
|
||||
*/
|
||||
|
||||
public ServletContext getServletContext();
|
||||
|
||||
/**
|
||||
* Returns the initialisation parameter from the {@code
|
||||
* PageContext.APPLICATION_SCOPE} scope. These initialisation
|
||||
* parameters are defined in the {@code web.xml} configuration file.
|
||||
*
|
||||
* @param pName The name of the initialisation parameter to return the
|
||||
* value for.
|
||||
* @return The value for the parameter whose name was passed in as a
|
||||
* parameter. If the parameter does not exist, then {@code null}
|
||||
* will be returned.
|
||||
*/
|
||||
|
||||
public String getInitParameter(String pName);
|
||||
|
||||
/**
|
||||
* Returns an Enumeration containing all the names for all the
|
||||
* initialisation parametes defined in the {@code
|
||||
* PageContext.APPLICATION_SCOPE} scope.
|
||||
*
|
||||
* @return An {@code Enumeration} containing all the names for all the
|
||||
* initialisation parameters.
|
||||
*/
|
||||
|
||||
public Enumeration getInitParameterNames();
|
||||
|
||||
/**
|
||||
* Returns the initialisation parameter from the scope specified with the
|
||||
* name specified.
|
||||
*
|
||||
* @param pName The name of the initialisation parameter to return the
|
||||
* value for.
|
||||
* @param pScope The scope to search for the initialisation parameter
|
||||
* within.
|
||||
* @return The value of the parameter found. If no parameter with the
|
||||
* name specified is found in the scope specified, then {@code null
|
||||
* } is returned.
|
||||
*/
|
||||
|
||||
public String getInitParameter(String pName, int pScope);
|
||||
|
||||
/**
|
||||
* Returns an enumeration containing all the parameters defined in the
|
||||
* scope specified by the parameter.
|
||||
*
|
||||
* @param pScope The scope to return the names of all the parameters
|
||||
* defined within.
|
||||
* @return An {@code Enumeration} containing all the names for all the
|
||||
* parameters defined in the scope passed in as a parameter.
|
||||
*/
|
||||
|
||||
public Enumeration getInitParameterNames(int pScope);
|
||||
|
||||
/**
|
||||
* Returns the servlet config associated with the current JSP page request.
|
||||
*
|
||||
* @return The {@code ServletConfig} associated with the current
|
||||
* request.
|
||||
*/
|
||||
|
||||
public ServletConfig getServletConfig();
|
||||
|
||||
/**
|
||||
* Gets the context path associated with the current JSP page request.
|
||||
*
|
||||
* @return a path relative to the current context's root.
|
||||
*/
|
||||
|
||||
public String getContextPath();
|
||||
|
||||
|
||||
/**
|
||||
* Gets the resource associated with the given relative path for the
|
||||
* current JSP page request.
|
||||
* The path may be absolute, or relative to the current context root.
|
||||
*
|
||||
* @param pPath the path
|
||||
*
|
||||
* @return a path relative to the current context root
|
||||
*/
|
||||
|
||||
public InputStream getResourceAsStream(String pPath);
|
||||
|
||||
}
|
@@ -1,289 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2002 TwelveMonkeys.
|
||||
* All rights reserved.
|
||||
*
|
||||
* $Log: ExTagSupport.java,v $
|
||||
* Revision 1.3 2003/10/06 14:25:11 WMHAKUR
|
||||
* Code clean-up only.
|
||||
*
|
||||
* Revision 1.2 2002/11/18 22:10:27 WMHAKUR
|
||||
* *** empty log message ***
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.servlet.jsp.taglib;
|
||||
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.util.*;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.*;
|
||||
import javax.servlet.jsp.*;
|
||||
import javax.servlet.jsp.tagext.*;
|
||||
|
||||
/**
|
||||
* This is the class that should be extended by all jsp pages that don't use
|
||||
* their body. It contains a lot of helper methods for simplifying common
|
||||
* tasks.
|
||||
*
|
||||
* @author Thomas Purcell (CSC Australia)
|
||||
* @author Harald Kuhr
|
||||
*
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/jsp/taglib/ExTagSupport.java#1 $
|
||||
*/
|
||||
|
||||
public class ExTagSupport extends TagSupport implements ExTag {
|
||||
/**
|
||||
* writeHtml ensures that the text being outputted appears as it was
|
||||
* entered. This prevents users from hacking the system by entering
|
||||
* html or jsp code into an entry form where that value will be displayed
|
||||
* later in the site.
|
||||
*
|
||||
* @param pOut The JspWriter to write the output to.
|
||||
* @param pHtml The original html to filter and output to the user.
|
||||
* @throws IOException If the user clicks Stop in the browser, or their
|
||||
* browser crashes, then the JspWriter will throw an IOException when
|
||||
* the jsp tries to write to it.
|
||||
*/
|
||||
|
||||
public void writeHtml(JspWriter pOut, String pHtml) throws IOException {
|
||||
StringTokenizer parser = new StringTokenizer(pHtml, "<>&", true);
|
||||
|
||||
while (parser.hasMoreTokens()) {
|
||||
String token = parser.nextToken();
|
||||
|
||||
if (token.equals("<")) {
|
||||
pOut.print("<");
|
||||
}
|
||||
else if (token.equals(">")) {
|
||||
pOut.print(">");
|
||||
}
|
||||
else if (token.equals("&")) {
|
||||
pOut.print("&");
|
||||
}
|
||||
else {
|
||||
pOut.print(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a message to the servlet context.
|
||||
*
|
||||
* @param pMsg The error message to log.
|
||||
*/
|
||||
|
||||
public void log(String pMsg) {
|
||||
getServletContext().log(pMsg);
|
||||
}
|
||||
|
||||
/**
|
||||
* Log a message to the servlet context and include the exception that is
|
||||
* passed in as the second parameter.
|
||||
*
|
||||
* @param pMsg The error message to log.
|
||||
* @param pException The exception that caused this error message to be
|
||||
* logged.
|
||||
*/
|
||||
|
||||
public void log(String pMsg, Throwable pException) {
|
||||
getServletContext().log(pMsg, pException);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the ServletContext object associated with the current
|
||||
* PageContext object.
|
||||
*
|
||||
* @return The ServletContext object associated with the current
|
||||
* PageContext object.
|
||||
*/
|
||||
|
||||
public ServletContext getServletContext() {
|
||||
return pageContext.getServletContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the tag has finished running. Any clean up that needs
|
||||
* to be done between calls to this tag but within the same JSP page is
|
||||
* called in the {@code clearServiceState()} method call.
|
||||
*
|
||||
* @exception JspException
|
||||
*/
|
||||
|
||||
public int doEndTag() throws JspException {
|
||||
clearServiceState();
|
||||
return super.doEndTag();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a tag's role in the current JSP page is finished. After
|
||||
* the {@code clearProperties()} method is called, the custom tag
|
||||
* should be in an identical state as when it was first created. The
|
||||
* {@code clearServiceState()} method is called here just in case an
|
||||
* exception was thrown in the custom tag. If an exception was thrown,
|
||||
* then the {@code doEndTag()} method will not have been called and
|
||||
* the tag might not have been cleaned up properly.
|
||||
*/
|
||||
|
||||
public void release() {
|
||||
clearServiceState();
|
||||
|
||||
clearProperties();
|
||||
super.release();
|
||||
}
|
||||
|
||||
/**
|
||||
* The default implementation for the {@code clearProperties()}. Not
|
||||
* all tags will need to overload this method call. By implementing it
|
||||
* here, all classes that extend this object are able to call {@code
|
||||
* super.clearProperties()}. So, if the class extends a different
|
||||
* tag, or this one, the parent method should always be called. This
|
||||
* method will be called when the tag is to be released. That is, the
|
||||
* tag has finished for the current page and should be returned to it's
|
||||
* initial state.
|
||||
*/
|
||||
|
||||
protected void clearProperties() {
|
||||
}
|
||||
|
||||
/**
|
||||
* The default implementation for the {@code clearServiceState()}.
|
||||
* Not all tags will need to overload this method call. By implementing it
|
||||
* here, all classes that extend this object are able to call {@code
|
||||
* super.clearServiceState()}. So, if the class extends a different
|
||||
* tag, or this one, the parent method should always be called. This
|
||||
* method will be called when the tag has finished it's current tag
|
||||
* within the page, but may be called upon again in this same JSP page.
|
||||
*/
|
||||
|
||||
protected void clearServiceState() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the initialisation parameter from the {@code
|
||||
* PageContext.APPLICATION_SCOPE} scope. These initialisation
|
||||
* parameters are defined in the {@code web.xml} configuration file.
|
||||
*
|
||||
* @param pName The name of the initialisation parameter to return the
|
||||
* value for.
|
||||
* @return The value for the parameter whose name was passed in as a
|
||||
* parameter. If the parameter does not exist, then {@code null}
|
||||
* will be returned.
|
||||
*/
|
||||
|
||||
public String getInitParameter(String pName) {
|
||||
return getInitParameter(pName, PageContext.APPLICATION_SCOPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an Enumeration containing all the names for all the
|
||||
* initialisation parametes defined in the {@code
|
||||
* PageContext.APPLICATION_SCOPE} scope.
|
||||
*
|
||||
* @return An {@code Enumeration} containing all the names for all the
|
||||
* initialisation parameters.
|
||||
*/
|
||||
|
||||
public Enumeration getInitParameterNames() {
|
||||
return getInitParameterNames(PageContext.APPLICATION_SCOPE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the initialisation parameter from the scope specified with the
|
||||
* name specified.
|
||||
*
|
||||
* @param pName The name of the initialisation parameter to return the
|
||||
* value for.
|
||||
* @param pScope The scope to search for the initialisation parameter
|
||||
* within.
|
||||
* @return The value of the parameter found. If no parameter with the
|
||||
* name specified is found in the scope specified, then {@code null
|
||||
* } is returned.
|
||||
*/
|
||||
|
||||
public String getInitParameter(String pName, int pScope) {
|
||||
switch (pScope) {
|
||||
case PageContext.PAGE_SCOPE:
|
||||
return getServletConfig().getInitParameter(pName);
|
||||
case PageContext.APPLICATION_SCOPE:
|
||||
return getServletContext().getInitParameter(pName);
|
||||
default:
|
||||
throw new IllegalArgumentException("Illegal scope.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an enumeration containing all the parameters defined in the
|
||||
* scope specified by the parameter.
|
||||
*
|
||||
* @param pScope The scope to return the names of all the parameters
|
||||
* defined within.
|
||||
* @return An {@code Enumeration} containing all the names for all the
|
||||
* parameters defined in the scope passed in as a parameter.
|
||||
*/
|
||||
|
||||
public Enumeration getInitParameterNames(int pScope) {
|
||||
switch (pScope) {
|
||||
case PageContext.PAGE_SCOPE:
|
||||
return getServletConfig().getInitParameterNames();
|
||||
case PageContext.APPLICATION_SCOPE:
|
||||
return getServletContext().getInitParameterNames();
|
||||
default:
|
||||
throw new IllegalArgumentException("Illegal scope");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the servlet config associated with the current JSP page request.
|
||||
*
|
||||
* @return The {@code ServletConfig} associated with the current
|
||||
* request.
|
||||
*/
|
||||
|
||||
public ServletConfig getServletConfig() {
|
||||
return pageContext.getServletConfig();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the context path associated with the current JSP page request.
|
||||
* If the request is not a HttpServletRequest, this method will
|
||||
* return "/".
|
||||
*
|
||||
* @return a path relative to the current context's root, or
|
||||
* {@code "/"} if this is not a HTTP request.
|
||||
*/
|
||||
|
||||
public String getContextPath() {
|
||||
ServletRequest request = pageContext.getRequest();
|
||||
if (request instanceof HttpServletRequest) {
|
||||
return ((HttpServletRequest) request).getContextPath();
|
||||
}
|
||||
return "/";
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the resource associated with the given relative path for the
|
||||
* current JSP page request.
|
||||
* The path may be absolute, or relative to the current context root.
|
||||
*
|
||||
* @param pPath the path
|
||||
*
|
||||
* @return a path relative to the current context root
|
||||
*/
|
||||
|
||||
public InputStream getResourceAsStream(String pPath) {
|
||||
//throws MalformedURLException {
|
||||
String path = pPath;
|
||||
|
||||
if (pPath != null && !pPath.startsWith("/")) {
|
||||
path = getContextPath() + pPath;
|
||||
}
|
||||
|
||||
return pageContext.getServletContext().getResourceAsStream(path);
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -1,21 +0,0 @@
|
||||
|
||||
package com.twelvemonkeys.servlet.jsp.taglib;
|
||||
|
||||
import javax.servlet.jsp.*;
|
||||
import javax.servlet.jsp.tagext.*;
|
||||
|
||||
/**
|
||||
* TagExtraInfo for LastModifiedTag
|
||||
*
|
||||
* @author Harald Kuhr
|
||||
*
|
||||
* @version 1.1
|
||||
*/
|
||||
|
||||
public class LastModifiedTEI extends TagExtraInfo {
|
||||
public VariableInfo[] getVariableInfo(TagData pData) {
|
||||
return new VariableInfo[]{
|
||||
new VariableInfo("lastModified", "java.lang.String", true, VariableInfo.NESTED),
|
||||
};
|
||||
}
|
||||
}
|
@@ -1,54 +0,0 @@
|
||||
|
||||
package com.twelvemonkeys.servlet.jsp.taglib;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Date;
|
||||
|
||||
import javax.servlet.http.*;
|
||||
import javax.servlet.jsp.*;
|
||||
import javax.servlet.jsp.tagext.*;
|
||||
|
||||
import com.twelvemonkeys.util.convert.*;
|
||||
|
||||
/**
|
||||
* Prints the last modified
|
||||
*/
|
||||
|
||||
public class LastModifiedTag extends TagSupport {
|
||||
private String mFileName = null;
|
||||
private String mFormat = null;
|
||||
|
||||
public void setFile(String pFileName) {
|
||||
mFileName = pFileName;
|
||||
}
|
||||
|
||||
public void setFormat(String pFormat) {
|
||||
mFormat = pFormat;
|
||||
}
|
||||
|
||||
public int doStartTag() throws JspException {
|
||||
File file = null;
|
||||
|
||||
if (mFileName != null) {
|
||||
file = new File(pageContext.getServletContext()
|
||||
.getRealPath(mFileName));
|
||||
}
|
||||
else {
|
||||
HttpServletRequest request =
|
||||
(HttpServletRequest) pageContext.getRequest();
|
||||
|
||||
// Get the file containing the servlet
|
||||
file = new File(pageContext.getServletContext()
|
||||
.getRealPath(request.getServletPath()));
|
||||
}
|
||||
|
||||
Date lastModified = new Date(file.lastModified());
|
||||
Converter conv = Converter.getInstance();
|
||||
|
||||
// Set the last modified value back
|
||||
pageContext.setAttribute("lastModified",
|
||||
conv.toString(lastModified, mFormat));
|
||||
|
||||
return Tag.EVAL_BODY_INCLUDE;
|
||||
}
|
||||
}
|
||||
|
@@ -1,89 +0,0 @@
|
||||
|
||||
package com.twelvemonkeys.servlet.jsp.taglib;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.jsp.JspException;
|
||||
import javax.servlet.jsp.tagext.BodyTag;
|
||||
|
||||
/**
|
||||
* This tag truncates all consecutive whitespace in sequence inside its body,
|
||||
* to one whitespace character. The first whitespace character in the sequence
|
||||
* will be left untouched (except for CR/LF, which will always leave a LF).
|
||||
*
|
||||
* @author Harald Kuhr
|
||||
*
|
||||
* @version 1.0
|
||||
*/
|
||||
|
||||
public class TrimWhiteSpaceTag extends ExBodyTagSupport {
|
||||
|
||||
/**
|
||||
* doStartTag implementation, simply returns
|
||||
* {@code BodyTag.EVAL_BODY_BUFFERED}.
|
||||
*
|
||||
* @return {@code BodyTag.EVAL_BODY_BUFFERED}
|
||||
*/
|
||||
|
||||
public int doStartTag() throws JspException {
|
||||
return BodyTag.EVAL_BODY_BUFFERED;
|
||||
}
|
||||
|
||||
/**
|
||||
* doEndTag implementation, truncates all whitespace.
|
||||
*
|
||||
* @return {@code super.doEndTag()}
|
||||
*/
|
||||
|
||||
public int doEndTag() throws JspException {
|
||||
// Trim
|
||||
String trimmed = truncateWS(bodyContent.getString());
|
||||
try {
|
||||
// Print trimmed content
|
||||
//pageContext.getOut().print("<!--TWS-->\n");
|
||||
pageContext.getOut().print(trimmed);
|
||||
//pageContext.getOut().print("\n<!--/TWS-->");
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
throw new JspException(ioe);
|
||||
}
|
||||
|
||||
return super.doEndTag();
|
||||
}
|
||||
|
||||
/**
|
||||
* Truncates whitespace from the given string.
|
||||
*
|
||||
* @todo Candidate for StringUtil?
|
||||
*/
|
||||
|
||||
private static String truncateWS(String pStr) {
|
||||
char[] chars = pStr.toCharArray();
|
||||
|
||||
int count = 0;
|
||||
boolean lastWasWS = true; // Avoids leading WS
|
||||
for (int i = 0; i < chars.length; i++) {
|
||||
if (!Character.isWhitespace(chars[i])) {
|
||||
// if char is not WS, just store
|
||||
chars[count++] = chars[i];
|
||||
lastWasWS = false;
|
||||
}
|
||||
else {
|
||||
// else, if char is WS, store first, skip the rest
|
||||
if (!lastWasWS) {
|
||||
if (chars[i] == 0x0d) {
|
||||
chars[count++] = 0x0a; //Always new line
|
||||
}
|
||||
else {
|
||||
chars[count++] = chars[i];
|
||||
}
|
||||
}
|
||||
lastWasWS = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the trucated string
|
||||
return new String(chars, 0, count);
|
||||
}
|
||||
|
||||
}
|
@@ -1,162 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2002 TwelveMonkeys.
|
||||
* All rights reserved.
|
||||
*
|
||||
* $Log: XMLTransformTag.java,v $
|
||||
* Revision 1.2 2003/10/06 14:25:43 WMHAKUR
|
||||
* Code clean-up only.
|
||||
*
|
||||
* Revision 1.1 2002/11/19 10:50:41 WMHAKUR
|
||||
* *** empty log message ***
|
||||
*
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.servlet.jsp.taglib;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.jsp.*;
|
||||
import javax.servlet.jsp.tagext.*;
|
||||
import javax.xml.transform.*;
|
||||
import javax.xml.transform.stream.*;
|
||||
|
||||
import com.twelvemonkeys.servlet.jsp.*;
|
||||
|
||||
/**
|
||||
* This tag performs XSL Transformations (XSLT) on a given XML document or its
|
||||
* body content.
|
||||
*
|
||||
* @author Harald Kuhr
|
||||
*
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/jsp/taglib/XMLTransformTag.java#1 $
|
||||
*/
|
||||
|
||||
public class XMLTransformTag extends ExBodyTagSupport {
|
||||
private String mDocumentURI = null;
|
||||
private String mStylesheetURI = null;
|
||||
|
||||
/**
|
||||
* Sets the document attribute for this tag.
|
||||
*/
|
||||
|
||||
public void setDocumentURI(String pDocumentURI) {
|
||||
mDocumentURI = pDocumentURI;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the stylesheet attribute for this tag.
|
||||
*/
|
||||
|
||||
public void setStylesheetURI(String pStylesheetURI) {
|
||||
mStylesheetURI = pStylesheetURI;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* doStartTag implementation, that performs XML Transformation on the
|
||||
* given document, if any.
|
||||
* If the documentURI attribute is set, then the transformation is
|
||||
* performed on the document at that location, and
|
||||
* {@code Tag.SKIP_BODY} is returned.
|
||||
* Otherwise, this method simply returns
|
||||
* {@code BodyTag.EVAL_BODY_BUFFERED} and leaves the transformation to
|
||||
* the doEndTag.
|
||||
*
|
||||
* @return {@code Tag.SKIP_BODY} if {@code documentURI} is not
|
||||
* {@code null}, otherwise
|
||||
* {@code BodyTag.EVAL_BODY_BUFFERED}.
|
||||
*
|
||||
* @todo Is it really a good idea to allow "inline" XML in a JSP?
|
||||
*/
|
||||
|
||||
public int doStartTag() throws JspException {
|
||||
//log("XML: " + mDocumentURI + " XSL: " + mStylesheetURI);
|
||||
|
||||
if (mDocumentURI != null) {
|
||||
// If document given, transform and skip body...
|
||||
try {
|
||||
transform(getSource(mDocumentURI));
|
||||
}
|
||||
catch (MalformedURLException murle) {
|
||||
throw new JspException(murle.getMessage(), murle);
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
throw new JspException(ioe.getMessage(), ioe);
|
||||
}
|
||||
|
||||
return Tag.SKIP_BODY;
|
||||
}
|
||||
|
||||
// ...else process the body
|
||||
return BodyTag.EVAL_BODY_BUFFERED;
|
||||
}
|
||||
|
||||
/**
|
||||
* doEndTag implementation, that will perform XML Transformation on the
|
||||
* body content.
|
||||
*
|
||||
* @return super.doEndTag()
|
||||
*/
|
||||
|
||||
public int doEndTag() throws JspException {
|
||||
// Get body content (trim is CRUCIAL, as some XML parsers are picky...)
|
||||
String body = bodyContent.getString().trim();
|
||||
|
||||
// Do transformation
|
||||
transform(new StreamSource(new ByteArrayInputStream(body.getBytes())));
|
||||
|
||||
return super.doEndTag();
|
||||
}
|
||||
|
||||
/**
|
||||
* Performs the transformation and writes the result to the JSP writer.
|
||||
*
|
||||
* @param in the source document to transform.
|
||||
*/
|
||||
|
||||
public void transform(Source pIn) throws JspException {
|
||||
try {
|
||||
// Create transformer
|
||||
Transformer transformer = TransformerFactory.newInstance()
|
||||
.newTransformer(getSource(mStylesheetURI));
|
||||
|
||||
// Store temporary output in a bytearray, as the transformer will
|
||||
// usually try to flush the stream (illegal operation from a custom
|
||||
// tag).
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
StreamResult out = new StreamResult(os);
|
||||
|
||||
// Perform the transformation
|
||||
transformer.transform(pIn, out);
|
||||
|
||||
// Write the result back to the JSP writer
|
||||
pageContext.getOut().print(os.toString());
|
||||
}
|
||||
catch (MalformedURLException murle) {
|
||||
throw new JspException(murle.getMessage(), murle);
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
throw new JspException(ioe.getMessage(), ioe);
|
||||
}
|
||||
catch (TransformerException te) {
|
||||
throw new JspException("XSLT Trandformation failed: " + te.getMessage(), te);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a StreamSource object, for the given URI
|
||||
*/
|
||||
|
||||
private StreamSource getSource(String pURI)
|
||||
throws IOException, MalformedURLException {
|
||||
if (pURI != null && pURI.indexOf("://") < 0) {
|
||||
// If local, get as stream
|
||||
return new StreamSource(getResourceAsStream(pURI));
|
||||
}
|
||||
|
||||
// ...else, create from URI string
|
||||
return new StreamSource(pURI);
|
||||
}
|
||||
}
|
@@ -1,140 +0,0 @@
|
||||
/****************************************************
|
||||
* *
|
||||
* (c) 2000-2003 TwelveMonkeys *
|
||||
* All rights reserved *
|
||||
* http://www.twelvemonkeys.no *
|
||||
* *
|
||||
* $RCSfile: ConditionalTagBase.java,v $
|
||||
* @version $Revision: #1 $
|
||||
* $Date: 2008/05/05 $
|
||||
* *
|
||||
* @author Last modified by: $Author: haku $
|
||||
* *
|
||||
****************************************************/
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Produced (p) 2002 TwelveMonkeys
|
||||
* Address : Svovelstikka 1, Box 6432 Etterstad, 0605 Oslo, Norway.
|
||||
* Phone : +47 22 57 70 00
|
||||
* Fax : +47 22 57 70 70
|
||||
*/
|
||||
package com.twelvemonkeys.servlet.jsp.taglib.logic;
|
||||
|
||||
|
||||
import java.lang.*;
|
||||
|
||||
import javax.servlet.jsp.JspException;
|
||||
import javax.servlet.jsp.tagext.TagSupport;
|
||||
|
||||
|
||||
/**
|
||||
* <p>An abstract base class for tags with some kind of conditional presentation of the tag body.</p>
|
||||
*
|
||||
* @version 1.0
|
||||
* @author <a href="mailto:eirik.torske@twelvemonkeys.no">Eirik Torske</a>
|
||||
*/
|
||||
public abstract class ConditionalTagBase extends TagSupport {
|
||||
|
||||
// Members
|
||||
protected String mObjectName;
|
||||
protected String mObjectValue;
|
||||
|
||||
// Properties
|
||||
|
||||
/**
|
||||
* Method getName
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public String getName() {
|
||||
return mObjectName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method setName
|
||||
*
|
||||
*
|
||||
* @param pObjectName
|
||||
*
|
||||
*/
|
||||
public void setName(String pObjectName) {
|
||||
this.mObjectName = pObjectName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method getValue
|
||||
*
|
||||
*
|
||||
* @return
|
||||
*
|
||||
*/
|
||||
public String getValue() {
|
||||
return mObjectValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method setValue
|
||||
*
|
||||
*
|
||||
* @param pObjectValue
|
||||
*
|
||||
*/
|
||||
public void setValue(String pObjectValue) {
|
||||
this.mObjectValue = pObjectValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Perform the test required for this particular tag, and either evaluate or skip the body of this tag.</p>
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* @exception JspException if a JSP exception occurs.
|
||||
*/
|
||||
public int doStartTag() throws JspException {
|
||||
|
||||
if (condition()) {
|
||||
return (EVAL_BODY_INCLUDE);
|
||||
} else {
|
||||
return (SKIP_BODY);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Evaluate the remainder of the current page as normal.</p>
|
||||
*
|
||||
*
|
||||
* @return
|
||||
* @exception JspException if a JSP exception occurs.
|
||||
*/
|
||||
public int doEndTag() throws JspException {
|
||||
return (EVAL_PAGE);
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>Release all allocated resources.</p>
|
||||
*/
|
||||
public void release() {
|
||||
|
||||
super.release();
|
||||
mObjectName = null;
|
||||
mObjectValue = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* <p>The condition that must be met in order to display the body of this tag.</p>
|
||||
*
|
||||
* @exception JspException if a JSP exception occurs.
|
||||
* @return {@code true} if and only if all conditions are met.
|
||||
*/
|
||||
protected abstract boolean condition() throws JspException;
|
||||
}
|
||||
|
||||
|
||||
/*--- Formatted in Sun Java Convention Style on ma, des 1, '03 ---*/
|
||||
|
||||
|
||||
/*------ Formatted by Jindent 3.23 Basic 1.0 --- http://www.jindent.de ------*/
|
@@ -1,170 +0,0 @@
|
||||
/*
|
||||
* Produced (p) 2002 TwelveMonkeys
|
||||
* Address : Svovelstikka 1, Box 6432 Etterstad, 0605 Oslo, Norway.
|
||||
* Phone : +47 22 57 70 00
|
||||
* Fax : +47 22 57 70 70
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.servlet.jsp.taglib.logic;
|
||||
|
||||
|
||||
import java.lang.*;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.jsp.JspException;
|
||||
|
||||
import com.twelvemonkeys.lang.StringUtil;
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Custom tag for testing equality of an attribute against a given value.
|
||||
* The attribute types supported so far is:
|
||||
* <ul>
|
||||
* <li>{@code java.lang.String} (ver. 1.0)
|
||||
* <li>{@code javax.servlet.http.Cookie} (ver. 1.0)
|
||||
* </ul>
|
||||
* </p>
|
||||
* See the implemented <a href="#condition">{@code condition}</a> method for details regarding the equality conditions.
|
||||
*
|
||||
* <p><hr></p>
|
||||
*
|
||||
* <h3>Tag Reference</h3>
|
||||
* <table border="0" cellspacing="3" cellpadding="3" width="90%">
|
||||
* <tr bgcolor="#cccccc">
|
||||
* <td colspan="5" class="body"><b>equal</b></td>
|
||||
* <td width="17%" align="right" class="body">Availability: 1.0</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td colspan="6" class="body"><p>Tag for testing if an attribute is equal to a given value.</p></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td width="15%" class="body"><b>Tag Body</b></td>
|
||||
* <td width="17%" class="body">JSP</td>
|
||||
* <td width="17%" class="body"> </td>
|
||||
* <td width="17%" class="body"> </td>
|
||||
* <td width="17%" class="body"> </td>
|
||||
* <td width="17%" class="body"> </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td class="body"><b>Restrictions</b></td>
|
||||
* <td colspan="5" class="body"><p>None</p></td>
|
||||
* </tr>
|
||||
*
|
||||
* <tr>
|
||||
* <td class="body"><b>Attributes</b></td>
|
||||
* <td class="body">Name</td>
|
||||
* <td class="body">Required</td>
|
||||
* <td colspan="2" class="body">Runtime Expression Evaluation</td>
|
||||
* <td class="body">Availability</td>
|
||||
* </tr>
|
||||
*
|
||||
* <tr bgcolor="#cccccc">
|
||||
* <td bgcolor="#ffffff"> </td>
|
||||
* <td class="body_grey"><b>name</b></td>
|
||||
* <td class="body_grey"> Yes</td>
|
||||
* <td colspan="2" class="body_grey"> Yes</td>
|
||||
* <td class="body_grey"> 1.0</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td bgcolor="#ffffff"> </td>
|
||||
* <td colspan="5" class="body"><p>The attribute name</p></td>
|
||||
* </tr>
|
||||
*
|
||||
* <tr bgcolor="#cccccc">
|
||||
* <td bgcolor="#ffffff"> </td>
|
||||
* <td class="body_grey"><b>value</b></td>
|
||||
* <td class="body_grey"> No</td>
|
||||
* <td colspan="2" class="body_grey"> Yes</td>
|
||||
* <td class="body_grey"> 1.0</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td bgcolor="#ffffff" class="body"> </td>
|
||||
* <td colspan="5" class="body"><p>The value for equality testing</p></td>
|
||||
* </tr>
|
||||
*
|
||||
* <tr>
|
||||
* <td class="body" valign="top"><b>Variables</b></td>
|
||||
* <td colspan="5" class="body">None</td>
|
||||
* </tr>
|
||||
*
|
||||
* <tr>
|
||||
* <td class="body" valign="top"><b>Examples</b></td>
|
||||
* <td colspan="5" class="body">
|
||||
* <pre>
|
||||
*<%@ taglib prefix="twelvemonkeys" uri="twelvemonkeys-logic" %>
|
||||
*<bean:cookie id="logonUsernameCookie"
|
||||
* name="<%= com.strutscommand.Constants.LOGON_USERNAME_COOKIE_NAME %>"
|
||||
* value="no_username_set" />
|
||||
*<twelvemonkeys:equal name="logonUsernameCookie" value="no_username_set">
|
||||
* <html:text property="username" />
|
||||
*</twelvemonkeys:equal>
|
||||
* </pre>
|
||||
* </td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
* <hr>
|
||||
*
|
||||
* @version 1.0
|
||||
* @author <a href="mailto:eirik.torske@twelvemonkeys.no">Eirik Torske</a>
|
||||
* @see <a href="NotEqualTag.html">notEqual</a>
|
||||
*/
|
||||
public class EqualTag extends ConditionalTagBase {
|
||||
|
||||
/**
|
||||
* <a name="condition"></a>
|
||||
*
|
||||
* The conditions that must be met in order to display the body of this tag:
|
||||
* <ol>
|
||||
* <li>The attribute name property ({@code name} -> {@code mObjectName}) must not be empty.
|
||||
* <li>The attribute must exist.
|
||||
* <li>The attribute must be an instance of one of the supported classes:
|
||||
* <ul>
|
||||
* <li>{@code java.lang.String}
|
||||
* <li>{@code javax.servlet.http.Cookie}
|
||||
* </ul>
|
||||
* <li>The value of the attribute must be equal to the object value property ({@code value} -> {@code mObjectValue}).
|
||||
* </ol>
|
||||
* <p>
|
||||
* NB! If the object value property ({@code value} -> {@code mObjectValue}) is empty than {@code true} will be returned.
|
||||
* </p>
|
||||
*
|
||||
* @return {@code true} if and only if all conditions are met.
|
||||
*/
|
||||
protected boolean condition() throws JspException {
|
||||
|
||||
if (StringUtil.isEmpty(mObjectName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (StringUtil.isEmpty(mObjectValue)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Object pageScopedAttribute = pageContext.getAttribute(mObjectName);
|
||||
if (pageScopedAttribute == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String pageScopedStringAttribute;
|
||||
|
||||
// String
|
||||
if (pageScopedAttribute instanceof String) {
|
||||
pageScopedStringAttribute = (String) pageScopedAttribute;
|
||||
|
||||
// Cookie
|
||||
}
|
||||
else if (pageScopedAttribute instanceof Cookie) {
|
||||
pageScopedStringAttribute = ((Cookie) pageScopedAttribute).getValue();
|
||||
|
||||
// Type not yet supported...
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (pageScopedStringAttribute.equals(mObjectValue));
|
||||
}
|
||||
|
||||
}
|
@@ -1,41 +0,0 @@
|
||||
|
||||
package com.twelvemonkeys.servlet.jsp.taglib.logic;
|
||||
|
||||
import javax.servlet.jsp.tagext.*;
|
||||
|
||||
/**
|
||||
* TagExtraInfo class for IteratorProvider tags.
|
||||
*
|
||||
* @author Harald Kuhr
|
||||
* @version $id: $
|
||||
*/
|
||||
public class IteratorProviderTEI extends TagExtraInfo {
|
||||
/**
|
||||
* Gets the variable info for IteratorProvider tags. The attribute with the
|
||||
* name defined by the "id" attribute and type defined by the "type"
|
||||
* attribute is declared with scope {@code VariableInfo.AT_END}.
|
||||
*
|
||||
* @param pData TagData instance provided by container
|
||||
* @return an VariableInfo array of lenght 1, containing the attribute
|
||||
* defined by the id parameter, declared, and with scope
|
||||
* {@code VariableInfo.AT_END}.
|
||||
*/
|
||||
public VariableInfo[] getVariableInfo(TagData pData) {
|
||||
// Get attribute name
|
||||
String attributeName = pData.getId();
|
||||
if (attributeName == null) {
|
||||
attributeName = IteratorProviderTag.getDefaultIteratorName();
|
||||
}
|
||||
|
||||
// Get type
|
||||
String type = pData.getAttributeString(IteratorProviderTag.ATTRIBUTE_TYPE);
|
||||
if (type == null) {
|
||||
type = IteratorProviderTag.getDefaultIteratorType();
|
||||
}
|
||||
|
||||
// Return the variable info
|
||||
return new VariableInfo[]{
|
||||
new VariableInfo(attributeName, type, true, VariableInfo.AT_END),
|
||||
};
|
||||
}
|
||||
}
|
@@ -1,87 +0,0 @@
|
||||
|
||||
package com.twelvemonkeys.servlet.jsp.taglib.logic;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.servlet.jsp.JspException;
|
||||
import javax.servlet.jsp.tagext.*;
|
||||
|
||||
/**
|
||||
* Abstract base class for adding iterators to a page.
|
||||
*
|
||||
* @todo Possible to use same strategy for all types of objects? Rename class
|
||||
* to ObjectProviderTag? Hmmm... Might work.
|
||||
*
|
||||
* @author Harald Kuhr
|
||||
* @version $id: $
|
||||
*/
|
||||
public abstract class IteratorProviderTag extends TagSupport {
|
||||
/** {@code iterator} */
|
||||
protected final static String DEFAULT_ITERATOR_NAME = "iterator";
|
||||
/** {@code java.util.iterator} */
|
||||
protected final static String DEFAULT_ITERATOR_TYPE = "java.util.Iterator";
|
||||
/** {@code type} */
|
||||
public final static String ATTRIBUTE_TYPE = "type";
|
||||
|
||||
/** */
|
||||
private String mType = null;
|
||||
|
||||
/**
|
||||
* Gets the type.
|
||||
*
|
||||
* @return the type (class name)
|
||||
*/
|
||||
public String getType() {
|
||||
return mType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the type.
|
||||
*
|
||||
* @param pType
|
||||
*/
|
||||
|
||||
public void setType(String pType) {
|
||||
mType = pType;
|
||||
}
|
||||
|
||||
/**
|
||||
* doEndTag implementation.
|
||||
*
|
||||
* @return {@code Tag.EVAL_PAGE}
|
||||
* @throws JspException
|
||||
*/
|
||||
|
||||
public int doEndTag() throws JspException {
|
||||
// Set the iterator
|
||||
pageContext.setAttribute(getId(), getIterator());
|
||||
|
||||
return Tag.EVAL_PAGE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the iterator for this tag.
|
||||
*
|
||||
* @return an {@link java.util.Iterator}
|
||||
*/
|
||||
protected abstract Iterator getIterator();
|
||||
|
||||
/**
|
||||
* Gets the default iterator name.
|
||||
*
|
||||
* @return {@link #DEFAULT_ITERATOR_NAME}
|
||||
*/
|
||||
protected static String getDefaultIteratorName() {
|
||||
return DEFAULT_ITERATOR_NAME;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the default iterator type.
|
||||
*
|
||||
* @return {@link #DEFAULT_ITERATOR_TYPE}
|
||||
*/
|
||||
protected static String getDefaultIteratorType() {
|
||||
return DEFAULT_ITERATOR_TYPE;
|
||||
}
|
||||
|
||||
}
|
@@ -1,168 +0,0 @@
|
||||
/*
|
||||
* Produced (p) 2002 TwelveMonkeys
|
||||
* Address : Svovelstikka 1, Box 6432 Etterstad, 0605 Oslo, Norway.
|
||||
* Phone : +47 22 57 70 00
|
||||
* Fax : +47 22 57 70 70
|
||||
*/
|
||||
|
||||
package com.twelvemonkeys.servlet.jsp.taglib.logic;
|
||||
|
||||
|
||||
import com.twelvemonkeys.lang.StringUtil;
|
||||
|
||||
import javax.servlet.http.Cookie;
|
||||
import javax.servlet.jsp.JspException;
|
||||
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Custom tag for testing non-equality of an attribute against a given value.
|
||||
* The attribute types supported so far is:
|
||||
* <ul>
|
||||
* <li>{@code java.lang.String} (ver. 1.0)
|
||||
* <li>{@code javax.servlet.http.Cookie} (ver. 1.0)
|
||||
* </ul>
|
||||
* </p>
|
||||
* See the implemented <a href="#condition">{@code condition}</a> method for details regarding the non-equality conditions.
|
||||
*
|
||||
* <p><hr></p>
|
||||
*
|
||||
* <h3>Tag Reference</h3>
|
||||
* <table border="0" cellspacing="3" cellpadding="3" width="90%">
|
||||
* <tr bgcolor="#cccccc">
|
||||
* <td colspan="5" class="body"><b>notEqual</b></td>
|
||||
* <td width="17%" align="right" class="body">Availability: 1.0</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td colspan="6" class="body"><p>Tag for testing if an attribute is NOT equal to a given value.</p></td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td width="15%" class="body"><b>Tag Body</b></td>
|
||||
* <td width="17%" class="body">JSP</td>
|
||||
* <td width="17%" class="body"> </td>
|
||||
* <td width="17%" class="body"> </td>
|
||||
* <td width="17%" class="body"> </td>
|
||||
* <td width="17%" class="body"> </td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td class="body"><b>Restrictions</b></td>
|
||||
* <td colspan="5" class="body"><p>None</p></td>
|
||||
* </tr>
|
||||
*
|
||||
* <tr>
|
||||
* <td class="body"><b>Attributes</b></td>
|
||||
* <td class="body">Name</td>
|
||||
* <td class="body">Required</td>
|
||||
* <td colspan="2" class="body">Runtime Expression Evaluation</td>
|
||||
* <td class="body">Availability</td>
|
||||
* </tr>
|
||||
*
|
||||
* <tr bgcolor="#cccccc">
|
||||
* <td bgcolor="#ffffff"> </td>
|
||||
* <td class="body_grey"><b>name</b></td>
|
||||
* <td class="body_grey"> Yes</td>
|
||||
* <td colspan="2" class="body_grey"> Yes</td>
|
||||
* <td class="body_grey"> 1.0</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td bgcolor="#ffffff"> </td>
|
||||
* <td colspan="5" class="body"><p>The attribute name</p></td>
|
||||
* </tr>
|
||||
*
|
||||
* <tr bgcolor="#cccccc">
|
||||
* <td bgcolor="#ffffff"> </td>
|
||||
* <td class="body_grey"><b>value</b></td>
|
||||
* <td class="body_grey"> No</td>
|
||||
* <td colspan="2" class="body_grey"> Yes</td>
|
||||
* <td class="body_grey"> 1.0</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td bgcolor="#ffffff" class="body"> </td>
|
||||
* <td colspan="5" class="body"><p>The value for equality testing</p></td>
|
||||
* </tr>
|
||||
*
|
||||
* <tr>
|
||||
* <td class="body" valign="top"><b>Variables</b></td>
|
||||
* <td colspan="5" class="body">None</td>
|
||||
* </tr>
|
||||
*
|
||||
* <tr>
|
||||
* <td class="body" valign="top"><b>Examples</b></td>
|
||||
* <td colspan="5" class="body">
|
||||
* <pre>
|
||||
*<%@ taglib prefix="twelvemonkeys" uri="twelvemonkeys-logic" %>
|
||||
*<bean:cookie id="logonUsernameCookie"
|
||||
* name="<%= com.strutscommand.Constants.LOGON_USERNAME_COOKIE_NAME %>"
|
||||
* value="no_username_set" />
|
||||
*<twelvemonkeys:notEqual name="logonUsernameCookie" value="no_username_set">
|
||||
* <html:text property="username" value="<%= logonUsernameCookie.getValue() %>" />
|
||||
*</twelvemonkeys:notEqual>
|
||||
* </pre>
|
||||
* </td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
* <hr>
|
||||
*
|
||||
* @version 1.0
|
||||
* @author <a href="mailto:eirik.torske@twelvemonkeys.no">Eirik Torske</a>
|
||||
* @see <a href="EqualTag.html">equal</a>
|
||||
*/
|
||||
public class NotEqualTag extends ConditionalTagBase {
|
||||
|
||||
/**
|
||||
* <a name="condition"></a>
|
||||
*
|
||||
* The condition that must be met in order to display the body of this tag:
|
||||
* <ol>
|
||||
* <li>The attribute name property ({@code name} -> {@code mObjectName}) must not be empty.
|
||||
* <li>The attribute must exist.
|
||||
* <li>The attribute must be an instance of one of the supported classes:
|
||||
* <ul>
|
||||
* <li>{@code java.lang.String}
|
||||
* <li>{@code javax.servlet.http.Cookie}
|
||||
* </ul>
|
||||
* <li>The value of the attribute must NOT be equal to the object value property ({@code value} -> {@code mObjectValue}).
|
||||
* </ol>
|
||||
* <p>
|
||||
* NB! If the object value property ({@code value} -> {@code mObjectValue}) is empty than {@code true} will be returned.
|
||||
* </p>
|
||||
*
|
||||
* @return {@code true} if and only if all conditions are met.
|
||||
*/
|
||||
protected boolean condition() throws JspException {
|
||||
|
||||
if (StringUtil.isEmpty(mObjectName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (StringUtil.isEmpty(mObjectValue)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Object pageScopedAttribute = pageContext.getAttribute(mObjectName);
|
||||
if (pageScopedAttribute == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
String pageScopedStringAttribute;
|
||||
|
||||
// String
|
||||
if (pageScopedAttribute instanceof String) {
|
||||
pageScopedStringAttribute = (String) pageScopedAttribute;
|
||||
|
||||
// Cookie
|
||||
}
|
||||
else if (pageScopedAttribute instanceof Cookie) {
|
||||
pageScopedStringAttribute = ((Cookie) pageScopedAttribute).getValue();
|
||||
|
||||
// Type not yet supported...
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
|
||||
return (!(pageScopedStringAttribute.equals(mObjectValue)));
|
||||
}
|
||||
|
||||
}
|
@@ -1,4 +0,0 @@
|
||||
/**
|
||||
* The TwelveMonkeys common TagLib.
|
||||
*/
|
||||
package com.twelvemonkeys.servlet.jsp.taglib;
|
@@ -1,183 +0,0 @@
|
||||
package com.twelvemonkeys.servlet.log4j;
|
||||
|
||||
import org.apache.log4j.Logger;
|
||||
|
||||
import java.util.Enumeration;
|
||||
import java.util.Set;
|
||||
import java.net.URL;
|
||||
import java.net.MalformedURLException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.Servlet;
|
||||
import javax.servlet.ServletException;
|
||||
|
||||
/**
|
||||
* Log4JContextWrapper
|
||||
* <p/>
|
||||
*
|
||||
* @author <a href="mailto:harald.kuhr@gmail.com">Harald Kuhr</a>
|
||||
* @version $Id: //depot/branches/personal/haraldk/twelvemonkeys/release-2/twelvemonkeys-servlet/src/main/java/com/twelvemonkeys/servlet/log4j/Log4JContextWrapper.java#1 $
|
||||
*/
|
||||
final class Log4JContextWrapper implements ServletContext {
|
||||
|
||||
// TODO: This solution sucks...
|
||||
// How about starting to create some kind of pluggable decorator system,
|
||||
// something along the lines of AOP mixins/interceptor pattern..
|
||||
// Probably using a dynamic Proxy, delegating to the mixins and or the
|
||||
// wrapped object based on configuration.
|
||||
// This way we could simply call ServletUtil.decorate(ServletContext):ServletContext
|
||||
// And the context would be decorated with all configured mixins at once,
|
||||
// requiring less bolierplate delegation code, and less layers of wrapping
|
||||
// (alternatively we could decorate the Servlet/FilterConfig objects).
|
||||
// See the ServletUtil.createWrapper methods for some hints..
|
||||
|
||||
|
||||
// Something like this:
|
||||
public static ServletContext wrap(final ServletContext pContext, final Object[] pDelegates, final ClassLoader pLoader) {
|
||||
ClassLoader cl = pLoader != null ? pLoader : Thread.currentThread().getContextClassLoader();
|
||||
|
||||
// TODO: Create a "static" mapping between methods in the ServletContext
|
||||
// and the corresponding delegate
|
||||
|
||||
// TODO: Resolve super-invokations, to delegate to next delegate in
|
||||
// chain, and finally invoke pContext
|
||||
|
||||
return (ServletContext) Proxy.newProxyInstance(cl, new Class[] {ServletContext.class}, new InvocationHandler() {
|
||||
public Object invoke(Object pProxy, Method pMethod, Object[] pArgs) throws Throwable {
|
||||
// TODO: Test if any of the delegates should receive, if so invoke
|
||||
|
||||
// Else, invoke on original object
|
||||
return pMethod.invoke(pContext, pArgs);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private final ServletContext mContext;
|
||||
|
||||
private final Logger mLogger;
|
||||
|
||||
Log4JContextWrapper(ServletContext pContext) {
|
||||
mContext = pContext;
|
||||
|
||||
// TODO: We want a logger per servlet, not per servlet context, right?
|
||||
mLogger = Logger.getLogger(pContext.getServletContextName());
|
||||
|
||||
// TODO: Automatic init/config of Log4J using context parameter for log4j.xml?
|
||||
// See Log4JInit.java
|
||||
|
||||
// TODO: Automatic config of properties in the context wrapper?
|
||||
}
|
||||
|
||||
public final void log(final Exception pException, final String pMessage) {
|
||||
log(pMessage, pException);
|
||||
}
|
||||
|
||||
// TODO: Add more logging methods to interface info/warn/error?
|
||||
// TODO: Implement these mehtods in GenericFilter/GenericServlet?
|
||||
|
||||
public void log(String pMessage) {
|
||||
// TODO: Get logger for caller..
|
||||
// Should be possible using some stack peek hack, but that's slow...
|
||||
// Find a good way...
|
||||
// Maybe just pass it into the constuctor, and have one wrapper per servlet
|
||||
mLogger.info(pMessage);
|
||||
}
|
||||
|
||||
public void log(String pMessage, Throwable pCause) {
|
||||
// TODO: Get logger for caller..
|
||||
|
||||
mLogger.error(pMessage, pCause);
|
||||
}
|
||||
|
||||
public Object getAttribute(String pMessage) {
|
||||
return mContext.getAttribute(pMessage);
|
||||
}
|
||||
|
||||
public Enumeration getAttributeNames() {
|
||||
return mContext.getAttributeNames();
|
||||
}
|
||||
|
||||
public ServletContext getContext(String pMessage) {
|
||||
return mContext.getContext(pMessage);
|
||||
}
|
||||
|
||||
public String getInitParameter(String pMessage) {
|
||||
return mContext.getInitParameter(pMessage);
|
||||
}
|
||||
|
||||
public Enumeration getInitParameterNames() {
|
||||
return mContext.getInitParameterNames();
|
||||
}
|
||||
|
||||
public int getMajorVersion() {
|
||||
return mContext.getMajorVersion();
|
||||
}
|
||||
|
||||
public String getMimeType(String pMessage) {
|
||||
return mContext.getMimeType(pMessage);
|
||||
}
|
||||
|
||||
public int getMinorVersion() {
|
||||
return mContext.getMinorVersion();
|
||||
}
|
||||
|
||||
public RequestDispatcher getNamedDispatcher(String pMessage) {
|
||||
return mContext.getNamedDispatcher(pMessage);
|
||||
}
|
||||
|
||||
public String getRealPath(String pMessage) {
|
||||
return mContext.getRealPath(pMessage);
|
||||
}
|
||||
|
||||
public RequestDispatcher getRequestDispatcher(String pMessage) {
|
||||
return mContext.getRequestDispatcher(pMessage);
|
||||
}
|
||||
|
||||
public URL getResource(String pMessage) throws MalformedURLException {
|
||||
return mContext.getResource(pMessage);
|
||||
}
|
||||
|
||||
public InputStream getResourceAsStream(String pMessage) {
|
||||
return mContext.getResourceAsStream(pMessage);
|
||||
}
|
||||
|
||||
public Set getResourcePaths(String pMessage) {
|
||||
return mContext.getResourcePaths(pMessage);
|
||||
}
|
||||
|
||||
public String getServerInfo() {
|
||||
return mContext.getServerInfo();
|
||||
}
|
||||
|
||||
public Servlet getServlet(String pMessage) throws ServletException {
|
||||
//noinspection deprecation
|
||||
return mContext.getServlet(pMessage);
|
||||
}
|
||||
|
||||
public String getServletContextName() {
|
||||
return mContext.getServletContextName();
|
||||
}
|
||||
|
||||
public Enumeration getServletNames() {
|
||||
//noinspection deprecation
|
||||
return mContext.getServletNames();
|
||||
}
|
||||
|
||||
public Enumeration getServlets() {
|
||||
//noinspection deprecation
|
||||
return mContext.getServlets();
|
||||
}
|
||||
|
||||
public void removeAttribute(String pMessage) {
|
||||
mContext.removeAttribute(pMessage);
|
||||
}
|
||||
|
||||
public void setAttribute(String pMessage, Object pExtension) {
|
||||
mContext.setAttribute(pMessage, pExtension);
|
||||
}
|
||||
}
|
@@ -1,13 +1,15 @@
|
||||
package com.twelvemonkeys.servlet;
|
||||
|
||||
import com.twelvemonkeys.lang.ObjectAbstractTestCase;
|
||||
|
||||
import java.util.*;
|
||||
import java.net.URL;
|
||||
import java.net.MalformedURLException;
|
||||
import java.io.*;
|
||||
import org.junit.Test;
|
||||
|
||||
import javax.servlet.*;
|
||||
import java.io.*;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.*;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* FilterAbstractTestCase
|
||||
@@ -45,6 +47,7 @@ public abstract class FilterAbstractTestCase extends ObjectAbstractTestCase {
|
||||
return new MockFilterChain();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInitNull() {
|
||||
Filter filter = makeFilter();
|
||||
|
||||
@@ -65,6 +68,7 @@ public abstract class FilterAbstractTestCase extends ObjectAbstractTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInit() {
|
||||
Filter filter = makeFilter();
|
||||
|
||||
@@ -79,6 +83,7 @@ public abstract class FilterAbstractTestCase extends ObjectAbstractTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLifeCycle() throws ServletException {
|
||||
Filter filter = makeFilter();
|
||||
|
||||
@@ -90,6 +95,7 @@ public abstract class FilterAbstractTestCase extends ObjectAbstractTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFilterBasic() throws ServletException, IOException {
|
||||
Filter filter = makeFilter();
|
||||
|
||||
@@ -103,22 +109,19 @@ public abstract class FilterAbstractTestCase extends ObjectAbstractTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDestroy() {
|
||||
// TODO: Implement
|
||||
}
|
||||
|
||||
static class MockFilterConfig implements FilterConfig {
|
||||
private final Map mParams;
|
||||
private final Map<String, String> params;
|
||||
|
||||
MockFilterConfig() {
|
||||
this(new HashMap());
|
||||
}
|
||||
|
||||
MockFilterConfig(Map pParams) {
|
||||
MockFilterConfig(Map<String, String> pParams) {
|
||||
if (pParams == null) {
|
||||
throw new IllegalArgumentException("params == null");
|
||||
}
|
||||
mParams = pParams;
|
||||
params = pParams;
|
||||
}
|
||||
|
||||
public String getFilterName() {
|
||||
@@ -126,11 +129,11 @@ public abstract class FilterAbstractTestCase extends ObjectAbstractTestCase {
|
||||
}
|
||||
|
||||
public String getInitParameter(String pName) {
|
||||
return (String) mParams.get(pName);
|
||||
return params.get(pName);
|
||||
}
|
||||
|
||||
public Enumeration getInitParameterNames() {
|
||||
return Collections.enumeration(mParams.keySet());
|
||||
return Collections.enumeration(params.keySet());
|
||||
}
|
||||
|
||||
public ServletContext getServletContext() {
|
||||
@@ -138,20 +141,20 @@ public abstract class FilterAbstractTestCase extends ObjectAbstractTestCase {
|
||||
}
|
||||
|
||||
private static class MockServletContext implements ServletContext {
|
||||
private final Map mAttributes;
|
||||
private final Map mParams;
|
||||
private final Map<String, Object> attributes;
|
||||
private final Map<String, String> params;
|
||||
|
||||
MockServletContext() {
|
||||
mAttributes = new HashMap();
|
||||
mParams = new HashMap();
|
||||
attributes = new HashMap<String, Object>();
|
||||
params = new HashMap<String, String>();
|
||||
}
|
||||
|
||||
public Object getAttribute(String s) {
|
||||
return mAttributes.get(s);
|
||||
return attributes.get(s);
|
||||
}
|
||||
|
||||
public Enumeration getAttributeNames() {
|
||||
return Collections.enumeration(mAttributes.keySet());
|
||||
return Collections.enumeration(attributes.keySet());
|
||||
}
|
||||
|
||||
public ServletContext getContext(String s) {
|
||||
@@ -159,11 +162,11 @@ public abstract class FilterAbstractTestCase extends ObjectAbstractTestCase {
|
||||
}
|
||||
|
||||
public String getInitParameter(String s) {
|
||||
return (String) mParams.get(s);
|
||||
return (String) params.get(s);
|
||||
}
|
||||
|
||||
public Enumeration getInitParameterNames() {
|
||||
return Collections.enumeration(mParams.keySet());
|
||||
return Collections.enumeration(params.keySet());
|
||||
}
|
||||
|
||||
public int getMajorVersion() {
|
||||
@@ -223,40 +226,37 @@ public abstract class FilterAbstractTestCase extends ObjectAbstractTestCase {
|
||||
}
|
||||
|
||||
public void log(Exception exception, String s) {
|
||||
// TODO: Implement
|
||||
}
|
||||
|
||||
public void log(String s) {
|
||||
// TODO: Implement
|
||||
}
|
||||
|
||||
public void log(String s, Throwable throwable) {
|
||||
// TODO: Implement
|
||||
}
|
||||
|
||||
public void removeAttribute(String s) {
|
||||
mAttributes.remove(s);
|
||||
attributes.remove(s);
|
||||
}
|
||||
|
||||
public void setAttribute(String s, Object obj) {
|
||||
mAttributes.put(s, obj);
|
||||
attributes.put(s, obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class MockServletRequest implements ServletRequest {
|
||||
final private Map mAttributes;
|
||||
final private Map<String, Object> attributes;
|
||||
|
||||
public MockServletRequest() {
|
||||
mAttributes = new HashMap();
|
||||
attributes = new HashMap<String, Object>();
|
||||
}
|
||||
|
||||
public Object getAttribute(String pKey) {
|
||||
return mAttributes.get(pKey);
|
||||
return attributes.get(pKey);
|
||||
}
|
||||
|
||||
public Enumeration getAttributeNames() {
|
||||
return Collections.enumeration(mAttributes.keySet());
|
||||
return Collections.enumeration(attributes.keySet());
|
||||
}
|
||||
|
||||
public String getCharacterEncoding() {
|
||||
@@ -324,11 +324,11 @@ public abstract class FilterAbstractTestCase extends ObjectAbstractTestCase {
|
||||
}
|
||||
|
||||
public void setAttribute(String pKey, Object pValue) {
|
||||
mAttributes.put(pKey, pValue);
|
||||
attributes.put(pKey, pValue);
|
||||
}
|
||||
|
||||
public void removeAttribute(String pKey) {
|
||||
mAttributes.remove(pKey);
|
||||
attributes.remove(pKey);
|
||||
}
|
||||
|
||||
public Locale getLocale() {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user