com.hfg.webapp.ServletRequestDispatcher Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of com_hfg Show documentation
Show all versions of com_hfg Show documentation
com.hfg xml, html, svg, and bioinformatics utility library
package com.hfg.webapp;
import java.lang.reflect.Constructor;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.hfg.exception.ProgrammingException;
import com.hfg.util.StringUtil;
import com.hfg.util.collection.CollectionUtil;
//------------------------------------------------------------------------------
/**
Dispatcher for dealing with servlet requests.
Example servlet code:
private ServletRequestDispatcher mRequestDispatcher = new ServletRequestDispatcher();
//---------------------------------------------------------------------------
public void init()
{
mRequestDispatcher.registerDefaultHandler(MainPage.class); // Handler invoked if there are no params
mRequestDispatcher.registerHandler(PAGE, MAIN_PAGE, MainPage.class);
}
//---------------------------------------------------------------------------
public void doGet(HttpServletRequest inRequest, HttpServletResponse inResponse)
{
handleRequest(inRequest, inResponse);
}
//---------------------------------------------------------------------------
public void doPost(HttpServletRequest inRequest, HttpServletResponse inResponse)
{
handleRequest(inRequest, inResponse);
}
//---------------------------------------------------------------------------
private void handleRequest(HttpServletRequest inRequest, HttpServletResponse inResponse)
{
try
{
mRequestDispatcher.dispatch(inRequest, inResponse);
}
catch (Throwable e)
{
e.printStackTrace();
}
}
@author J. Alex Taylor, hairyfatguy.com
*/
//------------------------------------------------------------------------------
// com.hfg XML/HTML Coding Library
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// J. Alex Taylor, President, Founder, CEO, COO, CFO, OOPS hairyfatguy.com
// [email protected]
//------------------------------------------------------------------------------
public class ServletRequestDispatcher
{
private Class mDefaultHandlerClass;
private Class mInvalidPathtHandlerClass = DefaultInvalidPathHandler.class;
private Map mPathHandlerMap;
private Map> mParamHandlerMap = new HashMap<>(25);
private boolean mAllowPartialPathMatches = true;
//###########################################################################
// PUBLIC METHODS
//###########################################################################
//---------------------------------------------------------------------------
public ServletRequestDispatcher registerDefaultHandler(Class inValue)
{
mDefaultHandlerClass = inValue;
return this;
}
//---------------------------------------------------------------------------
public ServletRequestDispatcher registerInvalidPathHandler(Class inValue)
{
mInvalidPathtHandlerClass = inValue;
return this;
}
//---------------------------------------------------------------------------
public ServletRequestDispatcher registerPathHandler(String inPath, Class inHandlerClass)
{
if (! ServletRequestHandler.class.isAssignableFrom(inHandlerClass))
{
throw new ProgrammingException("The specified handler class " + StringUtil.singleQuote(inHandlerClass.getSimpleName())
+ " does not implement " + ServletRequestHandler.class.getSimpleName() + "!");
}
if (null == mPathHandlerMap)
{
mPathHandlerMap = new HashMap<>(10);
}
mPathHandlerMap.put(inPath, inHandlerClass);
return this;
}
//---------------------------------------------------------------------------
public ServletRequestDispatcher registerParamHandler(String inParam, String inValue, Class inHandlerClass)
{
if (! ServletRequestHandler.class.isAssignableFrom(inHandlerClass))
{
throw new ProgrammingException("The specified handler class " + StringUtil.singleQuote(inHandlerClass.getSimpleName())
+ " does not implement " + ServletRequestHandler.class.getSimpleName() + "!");
}
Map paramMap = mParamHandlerMap.get(inParam);
if (null == paramMap)
{
paramMap = new HashMap<>(25);
mParamHandlerMap.put(inParam, paramMap);
}
paramMap.put(inValue, inHandlerClass);
return this;
}
//---------------------------------------------------------------------------
/**
Specifies whether or not registered path values can be matched to the start of
requested paths as broken by the path separator '/'.
If true, '/foo/bar' would be routed to the registered path '/foo'
but '/food' would not.
* @param inValue whether or not registered path values can be matched to the start of
requested paths as broken by the path separator '/'.
* @return this servlet request dispatcher object to enable method chaining
*/
public ServletRequestDispatcher setAllowPartialPathMatches(boolean inValue)
{
mAllowPartialPathMatches = inValue;
return this;
}
//---------------------------------------------------------------------------
public boolean getAllowPartialPathMatches()
{
return mAllowPartialPathMatches;
}
//---------------------------------------------------------------------------
public void dispatch(HttpServletRequest inRequest, HttpServletResponse inResponse)
throws Exception
{
Class handlerClass;
String path = inRequest.getPathInfo();
if (path != null
&& path.endsWith("/")) // Remove trailing slashes
{
path = path.substring(0, path.length() - 1);
}
// Does the request map to a path handler?
handlerClass = getPathHandler(path);
if (null == handlerClass) // No path handler assigned?
{
if (CollectionUtil.hasValues(inRequest.getParameterMap()))
{
// Does the request map to a param handler?
for (String param : mParamHandlerMap.keySet())
{
String[] values = inRequest.getParameterValues(param);
if (values != null)
{
Map paramMap = mParamHandlerMap.get(param);
if (1 == paramMap.size()
&& null == paramMap.keySet().iterator().next())
{
// null indicates all requests w/ the specified param use the same handler
handlerClass = paramMap.get(null);
}
else
{
for (String value : values)
{
handlerClass = paramMap.get(value);
if (handlerClass != null)
{
break;
}
}
}
}
if (handlerClass != null)
{
break;
}
}
}
}
if (null == handlerClass)
{
handlerClass = mDefaultHandlerClass;
}
if (handlerClass != null)
{
ServletRequestHandler handler = instantiateHandler(handlerClass);
handler.handleRequest(inRequest, inResponse);
}
}
//###########################################################################
// PRIVATE METHODS
//###########################################################################
//---------------------------------------------------------------------------
private Class getPathHandler(String inPath)
{
Class handlerClass = null;
if (mPathHandlerMap != null)
{
handlerClass = mPathHandlerMap.get(inPath);
if (null == handlerClass
&& mAllowPartialPathMatches
&& inPath != null)
{
// Does a registered path match the beginning of the requested path?
int bestPathLength = 0;
for (String key : mPathHandlerMap.keySet())
{
if (inPath.startsWith(key + "/"))
{
if (key.length() > bestPathLength)
{
bestPathLength = key.length();
handlerClass = mPathHandlerMap.get(key);
}
}
}
}
}
if (null == handlerClass
&& StringUtil.isSet(inPath))
{
handlerClass = mInvalidPathtHandlerClass;
}
return handlerClass;
}
//---------------------------------------------------------------------------
private ServletRequestHandler instantiateHandler(Class inHandlerClass)
{
ServletRequestHandler handler;
try
{
Constructor constructor = inHandlerClass.getConstructor();
handler = (ServletRequestHandler) constructor.newInstance();
}
catch (NoSuchMethodException e)
{
throw new ProgrammingException("Handler class " + StringUtil.singleQuote(inHandlerClass.getSimpleName()) + " doesn't have a default Constructor!", e);
}
catch (Exception e)
{
throw new ProgrammingException("Problem initializing handler class " + StringUtil.singleQuote(inHandlerClass.getSimpleName()) + "!", e);
}
return handler;
}
}