org.eclipse.jetty.server.Dispatcher 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-2018 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.server;
import java.io.IOException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import javax.servlet.DispatcherType;
import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.http.HttpURI;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.Attributes;
import org.eclipse.jetty.util.MultiMap;
public class Dispatcher implements RequestDispatcher
{
public final static String __ERROR_DISPATCH="org.eclipse.jetty.server.Dispatcher.ERROR";
/** Dispatch include attribute names */
public final static String __INCLUDE_PREFIX="javax.servlet.include.";
/** Dispatch include attribute names */
public final static String __FORWARD_PREFIX="javax.servlet.forward.";
private final ContextHandler _contextHandler;
private final HttpURI _uri;
private final String _pathInContext;
private final String _named;
public Dispatcher(ContextHandler contextHandler, HttpURI uri, String pathInContext)
{
_contextHandler=contextHandler;
_uri=uri;
_pathInContext=pathInContext;
_named=null;
}
public Dispatcher(ContextHandler contextHandler, String name) throws IllegalStateException
{
_contextHandler=contextHandler;
_uri=null;
_pathInContext=null;
_named=name;
}
@Override
public void forward(ServletRequest request, ServletResponse response) throws ServletException, IOException
{
forward(request, response, DispatcherType.FORWARD);
}
public void error(ServletRequest request, ServletResponse response) throws ServletException, IOException
{
try
{
request.setAttribute(__ERROR_DISPATCH,Boolean.TRUE);
forward(request, response, DispatcherType.ERROR);
}
finally
{
request.setAttribute(__ERROR_DISPATCH,null);
}
}
@Override
public void include(ServletRequest request, ServletResponse response) throws ServletException, IOException
{
Request baseRequest=Request.getBaseRequest(request);
if (!(request instanceof HttpServletRequest))
request = new ServletRequestHttpWrapper(request);
if (!(response instanceof HttpServletResponse))
response = new ServletResponseHttpWrapper(response);
final DispatcherType old_type = baseRequest.getDispatcherType();
final Attributes old_attr=baseRequest.getAttributes();
final MultiMap old_query_params=baseRequest.getQueryParameters();
try
{
baseRequest.setDispatcherType(DispatcherType.INCLUDE);
baseRequest.getResponse().include();
if (_named!=null)
{
_contextHandler.handle(_named,baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
}
else
{
IncludeAttributes attr = new IncludeAttributes(old_attr);
attr._requestURI=_uri.getPath();
attr._contextPath=_contextHandler.getContextPath();
attr._servletPath=null; // set by ServletHandler
attr._pathInfo=_pathInContext;
attr._query=_uri.getQuery();
if (attr._query!=null)
baseRequest.mergeQueryParameters(baseRequest.getQueryString(),attr._query, false);
baseRequest.setAttributes(attr);
_contextHandler.handle(_pathInContext, baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
}
}
finally
{
baseRequest.setAttributes(old_attr);
baseRequest.getResponse().included();
baseRequest.setQueryParameters(old_query_params);
baseRequest.resetParameters();
baseRequest.setDispatcherType(old_type);
}
}
protected void forward(ServletRequest request, ServletResponse response, DispatcherType dispatch) throws ServletException, IOException
{
Request baseRequest=Request.getBaseRequest(request);
Response base_response=baseRequest.getResponse();
base_response.resetForForward();
if (!(request instanceof HttpServletRequest))
request = new ServletRequestHttpWrapper(request);
if (!(response instanceof HttpServletResponse))
response = new ServletResponseHttpWrapper(response);
final HttpURI old_uri=baseRequest.getHttpURI();
final String old_context_path=baseRequest.getContextPath();
final String old_servlet_path=baseRequest.getServletPath();
final String old_path_info=baseRequest.getPathInfo();
final MultiMap old_query_params=baseRequest.getQueryParameters();
final Attributes old_attr=baseRequest.getAttributes();
final DispatcherType old_type=baseRequest.getDispatcherType();
try
{
baseRequest.setDispatcherType(dispatch);
if (_named!=null)
{
_contextHandler.handle(_named, baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
}
else
{
ForwardAttributes attr = new ForwardAttributes(old_attr);
//If we have already been forwarded previously, then keep using the established
//original value. Otherwise, this is the first forward and we need to establish the values.
//Note: the established value on the original request for pathInfo and
//for queryString is allowed to be null, but cannot be null for the other values.
if (old_attr.getAttribute(FORWARD_REQUEST_URI) != null)
{
attr._pathInfo=(String)old_attr.getAttribute(FORWARD_PATH_INFO);
attr._query=(String)old_attr.getAttribute(FORWARD_QUERY_STRING);
attr._requestURI=(String)old_attr.getAttribute(FORWARD_REQUEST_URI);
attr._contextPath=(String)old_attr.getAttribute(FORWARD_CONTEXT_PATH);
attr._servletPath=(String)old_attr.getAttribute(FORWARD_SERVLET_PATH);
}
else
{
attr._pathInfo=old_path_info;
attr._query=old_uri.getQuery();
attr._requestURI=old_uri.getPath();
attr._contextPath=old_context_path;
attr._servletPath=old_servlet_path;
}
HttpURI uri = new HttpURI(old_uri.getScheme(),old_uri.getHost(),old_uri.getPort(),
_uri.getPath(),_uri.getParam(),_uri.getQuery(),_uri.getFragment());
baseRequest.setHttpURI(uri);
baseRequest.setContextPath(_contextHandler.getContextPath());
baseRequest.setServletPath(null);
baseRequest.setPathInfo(_pathInContext);
if (_uri.getQuery()!=null || old_uri.getQuery()!=null)
baseRequest.mergeQueryParameters(old_uri.getQuery(),_uri.getQuery(), true);
baseRequest.setAttributes(attr);
_contextHandler.handle(_pathInContext, baseRequest, (HttpServletRequest)request, (HttpServletResponse)response);
if (!baseRequest.getHttpChannelState().isAsync())
commitResponse(response,baseRequest);
}
}
finally
{
baseRequest.setHttpURI(old_uri);
baseRequest.setContextPath(old_context_path);
baseRequest.setServletPath(old_servlet_path);
baseRequest.setPathInfo(old_path_info);
baseRequest.setQueryParameters(old_query_params);
baseRequest.resetParameters();
baseRequest.setAttributes(old_attr);
baseRequest.setDispatcherType(old_type);
}
}
@Override
public String toString()
{
return String.format("Dispatcher@0x%x{%s,%s}",hashCode(),_named,_uri);
}
@SuppressWarnings("Duplicates")
private void commitResponse(ServletResponse response, Request baseRequest) throws IOException, ServletException
{
if (baseRequest.getResponse().isWriting())
{
try
{
// Try closing Writer first (based on knowledge in Response obj)
response.getWriter().close();
}
catch (IllegalStateException e1)
{
try
{
// Try closing OutputStream as alternate route
// This path is possible due to badly behaving Response wrappers
response.getOutputStream().close();
}
catch(IllegalStateException e2)
{
ServletException servletException = new ServletException("Unable to commit the response", e2);
servletException.addSuppressed(e1);
throw servletException;
}
}
}
else
{
try
{
// Try closing OutputStream first (based on knowledge in Response obj)
response.getOutputStream().close();
}
catch (IllegalStateException e1)
{
try
{
// Try closing Writer as alternate route
// This path is possible due to badly behaving Response wrappers
response.getWriter().close();
}
catch(IllegalStateException e2)
{
ServletException servletException = new ServletException("Unable to commit the response", e2);
servletException.addSuppressed(e1);
throw servletException;
}
}
}
}
private class ForwardAttributes implements Attributes
{
final Attributes _attr;
String _requestURI;
String _contextPath;
String _servletPath;
String _pathInfo;
String _query;
ForwardAttributes(Attributes attributes)
{
_attr=attributes;
}
/* ------------------------------------------------------------ */
@Override
public Object getAttribute(String key)
{
if (Dispatcher.this._named==null)
{
if (key.equals(FORWARD_PATH_INFO))
return _pathInfo;
if (key.equals(FORWARD_REQUEST_URI))
return _requestURI;
if (key.equals(FORWARD_SERVLET_PATH))
return _servletPath;
if (key.equals(FORWARD_CONTEXT_PATH))
return _contextPath;
if (key.equals(FORWARD_QUERY_STRING))
return _query;
}
if (key.startsWith(__INCLUDE_PREFIX))
return null;
return _attr.getAttribute(key);
}
@Override
public Enumeration getAttributeNames()
{
HashSet set=new HashSet<>();
Enumeration e=_attr.getAttributeNames();
while(e.hasMoreElements())
{
String name=e.nextElement();
if (!name.startsWith(__INCLUDE_PREFIX) &&
!name.startsWith(__FORWARD_PREFIX))
set.add(name);
}
if (_named==null)
{
if (_pathInfo!=null)
set.add(FORWARD_PATH_INFO);
else
set.remove(FORWARD_PATH_INFO);
set.add(FORWARD_REQUEST_URI);
set.add(FORWARD_SERVLET_PATH);
set.add(FORWARD_CONTEXT_PATH);
if (_query!=null)
set.add(FORWARD_QUERY_STRING);
else
set.remove(FORWARD_QUERY_STRING);
}
return Collections.enumeration(set);
}
@Override
public void setAttribute(String key, Object value)
{
if (_named==null && key.startsWith("javax.servlet."))
{
if (key.equals(FORWARD_PATH_INFO))
_pathInfo=(String)value;
else if (key.equals(FORWARD_REQUEST_URI))
_requestURI=(String)value;
else if (key.equals(FORWARD_SERVLET_PATH))
_servletPath=(String)value;
else if (key.equals(FORWARD_CONTEXT_PATH))
_contextPath=(String)value;
else if (key.equals(FORWARD_QUERY_STRING))
_query=(String)value;
else if (value==null)
_attr.removeAttribute(key);
else
_attr.setAttribute(key,value);
}
else if (value==null)
_attr.removeAttribute(key);
else
_attr.setAttribute(key,value);
}
@Override
public String toString()
{
return "FORWARD+"+_attr.toString();
}
@Override
public void clearAttributes()
{
throw new IllegalStateException();
}
@Override
public void removeAttribute(String name)
{
setAttribute(name,null);
}
}
private class IncludeAttributes implements Attributes
{
final Attributes _attr;
String _requestURI;
String _contextPath;
String _servletPath;
String _pathInfo;
String _query;
IncludeAttributes(Attributes attributes)
{
_attr=attributes;
}
@Override
public Object getAttribute(String key)
{
if (Dispatcher.this._named==null)
{
if (key.equals(INCLUDE_PATH_INFO)) return _pathInfo;
if (key.equals(INCLUDE_SERVLET_PATH)) return _servletPath;
if (key.equals(INCLUDE_CONTEXT_PATH)) return _contextPath;
if (key.equals(INCLUDE_QUERY_STRING)) return _query;
if (key.equals(INCLUDE_REQUEST_URI)) return _requestURI;
}
else if (key.startsWith(__INCLUDE_PREFIX))
return null;
return _attr.getAttribute(key);
}
@Override
public Enumeration getAttributeNames()
{
HashSet set=new HashSet<>();
Enumeration e=_attr.getAttributeNames();
while(e.hasMoreElements())
{
String name=e.nextElement();
if (!name.startsWith(__INCLUDE_PREFIX))
set.add(name);
}
if (_named==null)
{
if (_pathInfo!=null)
set.add(INCLUDE_PATH_INFO);
else
set.remove(INCLUDE_PATH_INFO);
set.add(INCLUDE_REQUEST_URI);
set.add(INCLUDE_SERVLET_PATH);
set.add(INCLUDE_CONTEXT_PATH);
if (_query!=null)
set.add(INCLUDE_QUERY_STRING);
else
set.remove(INCLUDE_QUERY_STRING);
}
return Collections.enumeration(set);
}
@Override
public void setAttribute(String key, Object value)
{
if (_named==null && key.startsWith("javax.servlet."))
{
if (key.equals(INCLUDE_PATH_INFO)) _pathInfo=(String)value;
else if (key.equals(INCLUDE_REQUEST_URI)) _requestURI=(String)value;
else if (key.equals(INCLUDE_SERVLET_PATH)) _servletPath=(String)value;
else if (key.equals(INCLUDE_CONTEXT_PATH)) _contextPath=(String)value;
else if (key.equals(INCLUDE_QUERY_STRING)) _query=(String)value;
else if (value==null)
_attr.removeAttribute(key);
else
_attr.setAttribute(key,value);
}
else if (value==null)
_attr.removeAttribute(key);
else
_attr.setAttribute(key,value);
}
@Override
public String toString()
{
return "INCLUDE+"+_attr.toString();
}
@Override
public void clearAttributes()
{
throw new IllegalStateException();
}
@Override
public void removeAttribute(String name)
{
setAttribute(name,null);
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy