|
Jetty example source code file (DefaultServlet.java)
The Jetty DefaultServlet.java source code// ========================================================================
// Copyright 199-2004 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ========================================================================
package org.mortbay.jetty.servlet;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.util.Enumeration;
import java.util.List;
import javax.servlet.RequestDispatcher;
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.HttpServletResponse;
import org.mortbay.io.Buffer;
import org.mortbay.io.ByteArrayBuffer;
import org.mortbay.io.WriterOutputStream;
import org.mortbay.io.nio.NIOBuffer;
import org.mortbay.jetty.Connector;
import org.mortbay.jetty.HttpConnection;
import org.mortbay.jetty.HttpContent;
import org.mortbay.jetty.HttpFields;
import org.mortbay.jetty.HttpHeaderValues;
import org.mortbay.jetty.HttpHeaders;
import org.mortbay.jetty.HttpMethods;
import org.mortbay.jetty.InclusiveByteRange;
import org.mortbay.jetty.MimeTypes;
import org.mortbay.jetty.ResourceCache;
import org.mortbay.jetty.Response;
import org.mortbay.jetty.handler.ContextHandler;
import org.mortbay.jetty.nio.NIOConnector;
import org.mortbay.log.Log;
import org.mortbay.resource.Resource;
import org.mortbay.resource.ResourceFactory;
import org.mortbay.util.IO;
import org.mortbay.util.MultiPartOutputStream;
import org.mortbay.util.TypeUtil;
import org.mortbay.util.URIUtil;
/* ------------------------------------------------------------ */
/** The default servlet.
* This servlet, normally mapped to /, provides the handling for static
* content, OPTION and TRACE methods for the context.
* The following initParameters are supported, these can be set either
* on the servlet itself or as ServletContext initParameters with a prefix
* of org.mortbay.jetty.servlet.Default. :
* <PRE>
* acceptRanges If true, range requests and responses are
* supported
*
* dirAllowed If true, directory listings are returned if no
* welcome file is found. Else 403 Forbidden.
*
* redirectWelcome If true, welcome files are redirected rather than
* forwarded to.
*
* gzip If set to true, then static content will be served as
* gzip content encoded if a matching resource is
* found ending with ".gz"
*
* resourceBase Set to replace the context resource base
*
* relativeResourceBase
* Set with a pathname relative to the base of the
* servlet context root. Useful for only serving static content out
* of only specific subdirectories.
*
* aliases If True, aliases of resources are allowed (eg. symbolic
* links and caps variations). May bypass security constraints.
*
* maxCacheSize The maximum total size of the cache or 0 for no cache.
* maxCachedFileSize The maximum size of a file to cache
* maxCachedFiles The maximum number of files to cache
* cacheType Set to "bio", "nio" or "both" to determine the type resource cache.
* A bio cached buffer may be used by nio but is not as efficient as an
* nio buffer. An nio cached buffer may not be used by bio.
*
* useFileMappedBuffer
* If set to true, it will use mapped file buffer to serve static content
* when using NIO connector. Setting this value to false means that
* a direct buffer will be used instead of a mapped file buffer.
* By default, this is set to true.
*
* cacheControl If set, all static content will have this value set as the cache-control
* header.
*
*
* </PRE>
*
*
* @author Greg Wilkins (gregw)
* @author Nigel Canonizado
*/
public class DefaultServlet extends HttpServlet implements ResourceFactory
{
private ContextHandler.SContext _context;
private boolean _acceptRanges=true;
private boolean _dirAllowed=true;
private boolean _redirectWelcome=false;
private boolean _gzip=true;
private Resource _resourceBase;
private NIOResourceCache _nioCache;
private ResourceCache _bioCache;
private MimeTypes _mimeTypes;
private String[] _welcomes;
private boolean _aliases=false;
private boolean _useFileMappedBuffer=false;
ByteArrayBuffer _cacheControl;
/* ------------------------------------------------------------ */
public void init()
throws UnavailableException
{
ServletContext config=getServletContext();
_context = (ContextHandler.SContext)config;
_mimeTypes = _context.getContextHandler().getMimeTypes();
_welcomes = _context.getContextHandler().getWelcomeFiles();
if (_welcomes==null)
_welcomes=new String[] {"index.jsp","index.html"};
_acceptRanges=getInitBoolean("acceptRanges",_acceptRanges);
_dirAllowed=getInitBoolean("dirAllowed",_dirAllowed);
_redirectWelcome=getInitBoolean("redirectWelcome",_redirectWelcome);
_gzip=getInitBoolean("gzip",_gzip);
_aliases=getInitBoolean("aliases",_aliases);
_useFileMappedBuffer=getInitBoolean("useFileMappedBuffer",_useFileMappedBuffer);
String rrb = getInitParameter("relativeResourceBase");
if (rrb!=null)
{
try
{
_resourceBase=Resource.newResource(_context.getResource(URIUtil.SLASH)).addPath(rrb);
}
catch (Exception e)
{
Log.warn(Log.EXCEPTION,e);
throw new UnavailableException(e.toString());
}
}
String rb=getInitParameter("resourceBase");
if (rrb != null && rb != null)
throw new UnavailableException("resourceBase & relativeResourceBase");
if (rb!=null)
{
try{_resourceBase=Resource.newResource(rb);}
catch (Exception e)
{
Log.warn(Log.EXCEPTION,e);
throw new UnavailableException(e.toString());
}
}
String t=getInitParameter("cacheControl");
if (t!=null)
_cacheControl=new ByteArrayBuffer(t);
try
{
if (_resourceBase==null)
_resourceBase=Resource.newResource(_context.getResource(URIUtil.SLASH));
String cache_type =getInitParameter("cacheType");
int max_cache_size=getInitInt("maxCacheSize", -2);
int max_cached_file_size=getInitInt("maxCachedFileSize", -2);
int max_cached_files=getInitInt("maxCachedFiles", -2);
if (cache_type==null || "nio".equals(cache_type)|| "both".equals(cache_type))
{
if (max_cache_size==-2 || max_cache_size>0)
{
_nioCache=new NIOResourceCache(_mimeTypes);
if (max_cache_size>0)
_nioCache.setMaxCacheSize(max_cache_size);
if (max_cached_file_size>=-1)
_nioCache.setMaxCachedFileSize(max_cached_file_size);
if (max_cached_files>=-1)
_nioCache.setMaxCachedFiles(max_cached_files);
_nioCache.start();
}
}
if ("bio".equals(cache_type)|| "both".equals(cache_type))
{
if (max_cache_size==-2 || max_cache_size>0)
{
_bioCache=new ResourceCache(_mimeTypes);
if (max_cache_size>0)
_bioCache.setMaxCacheSize(max_cache_size);
if (max_cached_file_size>=-1)
_bioCache.setMaxCachedFileSize(max_cached_file_size);
if (max_cached_files>=-1)
_bioCache.setMaxCachedFiles(max_cached_files);
_bioCache.start();
}
}
if (_nioCache==null)
_bioCache=null;
}
catch (Exception e)
{
Log.warn(Log.EXCEPTION,e);
throw new UnavailableException(e.toString());
}
if (Log.isDebugEnabled()) Log.debug("resource base = "+_resourceBase);
}
/* ------------------------------------------------------------ */
public String getInitParameter(String name)
{
String value=getServletContext().getInitParameter("org.mortbay.jetty.servlet.Default."+name);
if (value==null)
value=super.getInitParameter(name);
return value;
}
/* ------------------------------------------------------------ */
private boolean getInitBoolean(String name, boolean dft)
{
String value=getInitParameter(name);
if (value==null || value.length()==0)
return dft;
return (value.startsWith("t")||
value.startsWith("T")||
value.startsWith("y")||
value.startsWith("Y")||
value.startsWith("1"));
}
/* ------------------------------------------------------------ */
private int getInitInt(String name, int dft)
{
String value=getInitParameter(name);
if (value==null)
value=getInitParameter(name);
if (value!=null && value.length()>0)
return Integer.parseInt(value);
return dft;
}
/* ------------------------------------------------------------ */
/** get Resource to serve.
* Map a path to a resource. The default implementation calls
* HttpContext.getResource but derived servlets may provide
* their own mapping.
* @param pathInContext The path to find a resource for.
* @return The resource to serve.
*/
public Resource getResource(String pathInContext)
{
if (_resourceBase==null)
return null;
Resource r=null;
try
{
r = _resourceBase.addPath(pathInContext);
if (!_aliases && r.getAlias()!=null)
{
if (r.exists())
Log.warn("Aliased resource: "+r+"=="+r.getAlias());
return null;
}
if (Log.isDebugEnabled()) Log.debug("RESOURCE="+r);
}
catch (IOException e)
{
Log.ignore(e);
}
return r;
}
/* ------------------------------------------------------------ */
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
String servletPath=null;
String pathInfo=null;
Enumeration reqRanges = null;
Boolean included =(Boolean)request.getAttribute(Dispatcher.__INCLUDE_JETTY);
if (included!=null && included.booleanValue())
{
servletPath=(String)request.getAttribute(Dispatcher.__INCLUDE_SERVLET_PATH);
pathInfo=(String)request.getAttribute(Dispatcher.__INCLUDE_PATH_INFO);
if (servletPath==null)
{
servletPath=request.getServletPath();
pathInfo=request.getPathInfo();
}
}
else
{
included=Boolean.FALSE;
servletPath=request.getServletPath();
pathInfo=request.getPathInfo();
// Is this a range request?
reqRanges = request.getHeaders(HttpHeaders.RANGE);
if (reqRanges!=null && !reqRanges.hasMoreElements())
reqRanges=null;
}
String pathInContext=URIUtil.addPaths(servletPath,pathInfo);
boolean endsWithSlash=pathInContext.endsWith(URIUtil.SLASH);
// Can we gzip this request?
String pathInContextGz=null;
boolean gzip=false;
if (!included.booleanValue() && _gzip && reqRanges==null && !endsWithSlash )
{
String accept=request.getHeader(HttpHeaders.ACCEPT_ENCODING);
if (accept!=null && accept.indexOf("gzip")>=0)
gzip=true;
}
// Find the resource and content
Resource resource=null;
HttpContent content=null;
Connector connector = HttpConnection.getCurrentConnection().getConnector();
ResourceCache cache=(connector instanceof NIOConnector) ?_nioCache:_bioCache;
try
{
// Try gzipped content first
if (gzip)
{
pathInContextGz=pathInContext+".gz";
resource=getResource(pathInContextGz);
if (resource==null || !resource.exists()|| resource.isDirectory())
{
gzip=false;
pathInContextGz=null;
}
else if (cache!=null)
{
content=cache.lookup(pathInContextGz,resource);
if (content!=null)
resource=content.getResource();
}
if (resource==null || !resource.exists()|| resource.isDirectory())
{
gzip=false;
pathInContextGz=null;
}
}
// find resource
if (!gzip)
{
if (cache==null)
resource=getResource(pathInContext);
else
{
content=cache.lookup(pathInContext,this);
if (content!=null)
resource=content.getResource();
else
resource=getResource(pathInContext);
}
}
if (Log.isDebugEnabled())
Log.debug("resource="+resource+(content!=null?" content":""));
// Handle resource
if (resource==null || !resource.exists())
response.sendError(HttpServletResponse.SC_NOT_FOUND);
else if (!resource.isDirectory())
{
// ensure we have content
if (content==null)
content=new UnCachedContent(resource);
if (included.booleanValue() || passConditionalHeaders(request,response, resource,content))
{
if (gzip)
{
response.setHeader(HttpHeaders.CONTENT_ENCODING,"gzip");
String mt=_context.getMimeType(pathInContext);
if (mt!=null)
response.setContentType(mt);
}
sendData(request,response,included.booleanValue(),resource,content,reqRanges);
}
}
else
{
String welcome=null;
if (!endsWithSlash || (pathInContext.length()==1 && request.getAttribute("org.mortbay.jetty.nullPathInfo")!=null))
{
StringBuffer buf=request.getRequestURL();
int param=buf.lastIndexOf(";");
if (param<0)
buf.append('/');
else
buf.insert(param,'/');
String q=request.getQueryString();
if (q!=null&&q.length()!=0)
{
buf.append('?');
buf.append(q);
}
response.setContentLength(0);
response.sendRedirect(response.encodeRedirectURL(buf.toString()));
}
// else look for a welcome file
else if (null!=(welcome=getWelcomeFile(resource)))
{
String ipath=URIUtil.addPaths(pathInContext,welcome);
if (_redirectWelcome)
{
// Redirect to the index
response.setContentLength(0);
String q=request.getQueryString();
if (q!=null&&q.length()!=0)
response.sendRedirect(URIUtil.addPaths( _context.getContextPath(),ipath)+"?"+q);
else
response.sendRedirect(URIUtil.addPaths( _context.getContextPath(),ipath));
}
else
{
// Forward to the index
RequestDispatcher dispatcher=request.getRequestDispatcher(ipath);
if (dispatcher!=null)
{
if (included.booleanValue())
dispatcher.include(request,response);
else
{
request.setAttribute("org.mortbay.jetty.welcome",ipath);
dispatcher.forward(request,response);
}
}
}
}
else
{
content=new UnCachedContent(resource);
if (included.booleanValue() || passConditionalHeaders(request,response, resource,content))
sendDirectory(request,response,resource,pathInContext.length()>1);
}
}
}
catch(IllegalArgumentException e)
{
Log.warn(Log.EXCEPTION,e);
}
finally
{
if (content!=null)
content.release();
else if (resource!=null)
resource.release();
}
}
/* ------------------------------------------------------------ */
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
doGet(request,response);
}
/* ------------------------------------------------------------ */
/* (non-Javadoc)
* @see javax.servlet.http.HttpServlet#doTrace(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
*/
protected void doTrace(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
{
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
}
/* ------------------------------------------------------------ */
/**
* Finds a matching welcome file for the supplied {@link Resource}. This will be the first entry in the list of
* configured {@link #_welcomes welcome files} that existing within the directory referenced by the <code>Resource.
* If the resource is not a directory, or no matching file is found, then <code>null is returned.
* The list of welcome files is read from the {@link ContextHandler} for this servlet, or
* <code>"index.jsp" , "index.html" if that is
Other Jetty examples (source code examples)Here is a short list of links related to this Jetty DefaultServlet.java source code file: |
... this post is sponsored by my books ... | |
#1 New Release! |
FP Best Seller |
Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.
A percentage of advertising revenue from
pages under the /java/jwarehouse
URI on this website is
paid back to open source projects.