package com.wooki.services.security.spring;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import org.apache.tapestry5.SymbolConstants;
import org.apache.tapestry5.TapestryFilter;
import org.apache.tapestry5.internal.services.RequestImpl;
import org.apache.tapestry5.ioc.Registry;
import org.apache.tapestry5.ioc.services.SymbolSource;
import org.apache.tapestry5.services.ComponentEventLinkEncoder;
import org.apache.tapestry5.services.ComponentEventRequestParameters;
import org.apache.tapestry5.services.PageRenderRequestParameters;
import org.apache.tapestry5.services.RequestGlobals;
import org.apache.tapestry5.services.SessionPersistedObjectAnalyzer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.web.context.ServletContextAware;
/**
* This is used to identify public pages URLs.
*
* @author ccordenier
*/
public abstract class AbstractTapestryUrlPathMatcher implements WookiPathMatcher,
ServletContextAware
{
private ServletContext servletContext;
private Registry tapestryRegistry;
private RequestGlobals globals;
private ComponentEventLinkEncoder encoder;
private String applicationCharset;
private SessionPersistedObjectAnalyzer spoa;
private final Logger logger = LoggerFactory.getLogger(this.getClass());
private String encoding;
private boolean initDone = false;
private boolean productionMode;
/**
* Initialize Tapestry registry.
*/
public void setServletContext(ServletContext servletContext)
{
this.servletContext = servletContext;
this.init();
}
/**
* Init Tapestry registries and services.
*/
protected void init()
{
if (initDone) { return; }
this.tapestryRegistry = (Registry) this.servletContext
.getAttribute(TapestryFilter.REGISTRY_CONTEXT_NAME);
this.encoder = this.tapestryRegistry.getService(ComponentEventLinkEncoder.class);
this.spoa = this.tapestryRegistry.getService(SessionPersistedObjectAnalyzer.class);
this.applicationCharset = this.tapestryRegistry.getService(SymbolSource.class)
.valueForSymbol(SymbolConstants.CHARSET);
this.globals = this.tapestryRegistry.getService(RequestGlobals.class);
this.initDone = true;
}
/**
* Hide Tapestry logic for analyzing URLs
*
* @param request
* @return
*/
protected ComponentEventRequestParameters decodeComponentEventRequest(String path)
{
RequestImpl tapRequest = new RequestImpl(this.createRequestForTapestry(path),
applicationCharset, spoa);
globals.storeRequestResponse(tapRequest, null);
return this.encoder.decodeComponentEventRequest(tapRequest);
}
/**
* Hide Tapestry logic for analyzing URLs
*
* @param request
* @return
*/
protected PageRenderRequestParameters decodePageRenderRequest(String path)
{
RequestImpl tapRequest = new RequestImpl(this.createRequestForTapestry(path),
applicationCharset, spoa);
globals.storeRequestResponse(tapRequest, null);
return this.encoder.decodePageRenderRequest(tapRequest);
}
/**
* Create a mock http request from a path.
*
* @param path
* @return
*/
private HttpServletRequest createRequestForTapestry(String path)
{
MockHttpServletRequest request = new MockHttpServletRequest();
int queryIndex = path.indexOf("?");
if (queryIndex > -1)
{
request.setPathInfo(cleanupPath(path.substring(0, queryIndex)));
String query = path.substring(path.indexOf("?") + 1);
String[] parameters = query.split("&");
if (parameters != null)
{
for (String parameter : parameters)
{
String[] keyValue = parameter.split("=");
if (keyValue != null && keyValue.length == 2)
{
try
{
request.addParameter(keyValue[0], URLDecoder.decode(
keyValue[1],
this.encoding));
}
catch (UnsupportedEncodingException e)
{
logger.error("Cannot decode URL parameter with " + this.encoding
+ " encoding");
request.addParameter(keyValue[0], URLDecoder.decode(keyValue[1]));
}
}
}
}
}
else
{
request.setPathInfo(cleanupPath(path));
}
return request;
}
/**
* Simply remove extra character added by servlet container for JSession id.
*
* @param path
* @return
*/
private String cleanupPath(String path)
{
if (path.contains(";")) { return path.substring(0, path.indexOf(";")); }
return path;
}
public String getEncoding()
{
return encoding;
}
public void setEncoding(String encoding)
{
this.encoding = encoding;
}
public boolean isProductionMode()
{
return productionMode;
}
public void setProductionMode(boolean productionMode)
{
this.productionMode = productionMode;
}
}