org.eclipse.jetty.servlet.Invoker Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of ehcache Show documentation
Show all versions of ehcache Show documentation
Ehcache is an open source, standards-based cache used to boost performance,
offload the database and simplify scalability. Ehcache is robust, proven and full-featured and
this has made it the most widely-used Java-based cache.
//
// ========================================================================
// Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.servlet;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.AbstractHttpConnection;
import org.eclipse.jetty.server.Dispatcher;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import org.eclipse.jetty.util.LazyList;
import org.eclipse.jetty.util.URIUtil;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
/* ------------------------------------------------------------ */
/** Dynamic Servlet Invoker.
* This servlet invokes anonymous servlets that have not been defined
* in the web.xml or by other means. The first element of the pathInfo
* of a request passed to the envoker is treated as a servlet name for
* an existing servlet, or as a class name of a new servlet.
* This servlet is normally mapped to /servlet/*
* This servlet support the following initParams:
*
* nonContextServlets If false, the invoker can only load
* servlets from the contexts classloader.
* This is false by default and setting this
* to true may have security implications.
*
* verbose If true, log dynamic loads
*
* * All other parameters are copied to the
* each dynamic servlet as init parameters
*
* @version $Id: Invoker.java 4780 2009-03-17 15:36:08Z jesse $
*
*/
public class Invoker extends HttpServlet
{
private static final Logger LOG = Log.getLogger(Invoker.class);
private ContextHandler _contextHandler;
private ServletHandler _servletHandler;
private Map.Entry _invokerEntry;
private Map _parameters;
private boolean _nonContextServlets;
private boolean _verbose;
/* ------------------------------------------------------------ */
public void init()
{
ServletContext config=getServletContext();
_contextHandler=((ContextHandler.Context)config).getContextHandler();
Handler handler=_contextHandler.getHandler();
while (handler!=null && !(handler instanceof ServletHandler) && (handler instanceof HandlerWrapper))
handler=((HandlerWrapper)handler).getHandler();
_servletHandler = (ServletHandler)handler;
Enumeration e = getInitParameterNames();
while(e.hasMoreElements())
{
String param=(String)e.nextElement();
String value=getInitParameter(param);
String lvalue=value.toLowerCase(Locale.ENGLISH);
if ("nonContextServlets".equals(param))
{
_nonContextServlets=value.length()>0 && lvalue.startsWith("t");
}
if ("verbose".equals(param))
{
_verbose=value.length()>0 && lvalue.startsWith("t");
}
else
{
if (_parameters==null)
_parameters=new HashMap();
_parameters.put(param,value);
}
}
}
/* ------------------------------------------------------------ */
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
// Get the requested path and info
boolean included=false;
String servlet_path=(String)request.getAttribute(Dispatcher.INCLUDE_SERVLET_PATH);
if (servlet_path==null)
servlet_path=request.getServletPath();
else
included=true;
String path_info = (String)request.getAttribute(Dispatcher.INCLUDE_PATH_INFO);
if (path_info==null)
path_info=request.getPathInfo();
// Get the servlet class
String servlet = path_info;
if (servlet==null || servlet.length()<=1 )
{
response.sendError(404);
return;
}
int i0=servlet.charAt(0)=='/'?1:0;
int i1=servlet.indexOf('/',i0);
servlet=i1<0?servlet.substring(i0):servlet.substring(i0,i1);
// look for a named holder
ServletHolder[] holders = _servletHandler.getServlets();
ServletHolder holder = getHolder (holders, servlet);
if (holder!=null)
{
// Found a named servlet (from a user's web.xml file) so
// now we add a mapping for it
if (LOG.isDebugEnabled())
LOG.debug("Adding servlet mapping for named servlet:"+servlet+":"+URIUtil.addPaths(servlet_path,servlet)+"/*");
ServletMapping mapping = new ServletMapping();
mapping.setServletName(servlet);
mapping.setPathSpec(URIUtil.addPaths(servlet_path,servlet)+"/*");
_servletHandler.setServletMappings((ServletMapping[])LazyList.addToArray(_servletHandler.getServletMappings(), mapping, ServletMapping.class));
}
else
{
// look for a class mapping
if (servlet.endsWith(".class"))
servlet=servlet.substring(0,servlet.length()-6);
if (servlet==null || servlet.length()==0)
{
response.sendError(404);
return;
}
synchronized(_servletHandler)
{
// find the entry for the invoker (me)
_invokerEntry=_servletHandler.getHolderEntry(servlet_path);
// Check for existing mapping (avoid threaded race).
String path=URIUtil.addPaths(servlet_path,servlet);
Map.Entry entry = _servletHandler.getHolderEntry(path);
if (entry!=null && !entry.equals(_invokerEntry))
{
// Use the holder
holder=(ServletHolder)entry.getValue();
}
else
{
// Make a holder
if (LOG.isDebugEnabled())
LOG.debug("Making new servlet="+servlet+" with path="+path+"/*");
holder=_servletHandler.addServletWithMapping(servlet, path+"/*");
if (_parameters!=null)
holder.setInitParameters(_parameters);
try {holder.start();}
catch (Exception e)
{
LOG.debug(e);
throw new UnavailableException(e.toString());
}
// Check it is from an allowable classloader
if (!_nonContextServlets)
{
Object s=holder.getServlet();
if (_contextHandler.getClassLoader()!=
s.getClass().getClassLoader())
{
try
{
holder.stop();
}
catch (Exception e)
{
LOG.ignore(e);
}
LOG.warn("Dynamic servlet "+s+
" not loaded from context "+
request.getContextPath());
throw new UnavailableException("Not in context");
}
}
if (_verbose && LOG.isDebugEnabled())
LOG.debug("Dynamic load '"+servlet+"' at "+path);
}
}
}
if (holder!=null)
{
final Request baseRequest=(request instanceof Request)?((Request)request):AbstractHttpConnection.getCurrentConnection().getRequest();
holder.handle(baseRequest,
new InvokedRequest(request,included,servlet,servlet_path,path_info),
response);
}
else
{
LOG.info("Can't find holder for servlet: "+servlet);
response.sendError(404);
}
}
/* ------------------------------------------------------------ */
class InvokedRequest extends HttpServletRequestWrapper
{
String _servletPath;
String _pathInfo;
boolean _included;
/* ------------------------------------------------------------ */
InvokedRequest(HttpServletRequest request,
boolean included,
String name,
String servletPath,
String pathInfo)
{
super(request);
_included=included;
_servletPath=URIUtil.addPaths(servletPath,name);
_pathInfo=pathInfo.substring(name.length()+1);
if (_pathInfo.length()==0)
_pathInfo=null;
}
/* ------------------------------------------------------------ */
public String getServletPath()
{
if (_included)
return super.getServletPath();
return _servletPath;
}
/* ------------------------------------------------------------ */
public String getPathInfo()
{
if (_included)
return super.getPathInfo();
return _pathInfo;
}
/* ------------------------------------------------------------ */
public Object getAttribute(String name)
{
if (_included)
{
if (name.equals(Dispatcher.INCLUDE_REQUEST_URI))
return URIUtil.addPaths(URIUtil.addPaths(getContextPath(),_servletPath),_pathInfo);
if (name.equals(Dispatcher.INCLUDE_PATH_INFO))
return _pathInfo;
if (name.equals(Dispatcher.INCLUDE_SERVLET_PATH))
return _servletPath;
}
return super.getAttribute(name);
}
}
private ServletHolder getHolder(ServletHolder[] holders, String servlet)
{
if (holders == null)
return null;
ServletHolder holder = null;
for (int i=0; holder==null && i