103928aee4356845252ac6b662d5c72c29903813eJake Slack//
203928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
303928aee4356845252ac6b662d5c72c29903813eJake Slack//  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
403928aee4356845252ac6b662d5c72c29903813eJake Slack//  ------------------------------------------------------------------------
503928aee4356845252ac6b662d5c72c29903813eJake Slack//  All rights reserved. This program and the accompanying materials
603928aee4356845252ac6b662d5c72c29903813eJake Slack//  are made available under the terms of the Eclipse Public License v1.0
703928aee4356845252ac6b662d5c72c29903813eJake Slack//  and Apache License v2.0 which accompanies this distribution.
803928aee4356845252ac6b662d5c72c29903813eJake Slack//
903928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Eclipse Public License is available at
1003928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.eclipse.org/legal/epl-v10.html
1103928aee4356845252ac6b662d5c72c29903813eJake Slack//
1203928aee4356845252ac6b662d5c72c29903813eJake Slack//      The Apache License v2.0 is available at
1303928aee4356845252ac6b662d5c72c29903813eJake Slack//      http://www.opensource.org/licenses/apache2.0.php
1403928aee4356845252ac6b662d5c72c29903813eJake Slack//
1503928aee4356845252ac6b662d5c72c29903813eJake Slack//  You may elect to redistribute this code under either of these licenses.
1603928aee4356845252ac6b662d5c72c29903813eJake Slack//  ========================================================================
1703928aee4356845252ac6b662d5c72c29903813eJake Slack//
1803928aee4356845252ac6b662d5c72c29903813eJake Slack
1903928aee4356845252ac6b662d5c72c29903813eJake Slackpackage org.eclipse.jetty.server.handler;
2003928aee4356845252ac6b662d5c72c29903813eJake Slack
2103928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.IOException;
2203928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.io.OutputStream;
2303928aee4356845252ac6b662d5c72c29903813eJake Slackimport java.net.MalformedURLException;
2403928aee4356845252ac6b662d5c72c29903813eJake Slack
2503928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.ServletException;
2603928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.http.HttpServletRequest;
2703928aee4356845252ac6b662d5c72c29903813eJake Slackimport javax.servlet.http.HttpServletResponse;
2803928aee4356845252ac6b662d5c72c29903813eJake Slack
2903928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.http.HttpFields;
3003928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.http.HttpHeaders;
3103928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.http.HttpMethods;
3203928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.http.HttpStatus;
3303928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.http.MimeTypes;
3403928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.Buffer;
3503928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.ByteArrayBuffer;
3603928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.io.WriterOutputStream;
3703928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.AbstractHttpConnection;
3803928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.Dispatcher;
3903928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.Request;
4003928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.Response;
4103928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.server.handler.ContextHandler.Context;
4203928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.URIUtil;
4303928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Log;
4403928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.log.Logger;
4503928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.resource.FileResource;
4603928aee4356845252ac6b662d5c72c29903813eJake Slackimport org.eclipse.jetty.util.resource.Resource;
4703928aee4356845252ac6b662d5c72c29903813eJake Slack
4803928aee4356845252ac6b662d5c72c29903813eJake Slack
4903928aee4356845252ac6b662d5c72c29903813eJake Slack/* ------------------------------------------------------------ */
5003928aee4356845252ac6b662d5c72c29903813eJake Slack/** Resource Handler.
5103928aee4356845252ac6b662d5c72c29903813eJake Slack *
5203928aee4356845252ac6b662d5c72c29903813eJake Slack * This handle will serve static content and handle If-Modified-Since headers.
5303928aee4356845252ac6b662d5c72c29903813eJake Slack * No caching is done.
5403928aee4356845252ac6b662d5c72c29903813eJake Slack * Requests for resources that do not exist are let pass (Eg no 404's).
5503928aee4356845252ac6b662d5c72c29903813eJake Slack *
5603928aee4356845252ac6b662d5c72c29903813eJake Slack *
5703928aee4356845252ac6b662d5c72c29903813eJake Slack * @org.apache.xbean.XBean
5803928aee4356845252ac6b662d5c72c29903813eJake Slack */
5903928aee4356845252ac6b662d5c72c29903813eJake Slackpublic class ResourceHandler extends HandlerWrapper
6003928aee4356845252ac6b662d5c72c29903813eJake Slack{
6103928aee4356845252ac6b662d5c72c29903813eJake Slack    private static final Logger LOG = Log.getLogger(ResourceHandler.class);
6203928aee4356845252ac6b662d5c72c29903813eJake Slack
6303928aee4356845252ac6b662d5c72c29903813eJake Slack    ContextHandler _context;
6403928aee4356845252ac6b662d5c72c29903813eJake Slack    Resource _baseResource;
6503928aee4356845252ac6b662d5c72c29903813eJake Slack    Resource _defaultStylesheet;
6603928aee4356845252ac6b662d5c72c29903813eJake Slack    Resource _stylesheet;
6703928aee4356845252ac6b662d5c72c29903813eJake Slack    String[] _welcomeFiles={"index.html"};
6803928aee4356845252ac6b662d5c72c29903813eJake Slack    MimeTypes _mimeTypes = new MimeTypes();
6903928aee4356845252ac6b662d5c72c29903813eJake Slack    ByteArrayBuffer _cacheControl;
7003928aee4356845252ac6b662d5c72c29903813eJake Slack    boolean _aliases;
7103928aee4356845252ac6b662d5c72c29903813eJake Slack    boolean _directory;
7203928aee4356845252ac6b662d5c72c29903813eJake Slack    boolean _etags;
7303928aee4356845252ac6b662d5c72c29903813eJake Slack
7403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
7503928aee4356845252ac6b662d5c72c29903813eJake Slack    public ResourceHandler()
7603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
7703928aee4356845252ac6b662d5c72c29903813eJake Slack
7803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
7903928aee4356845252ac6b662d5c72c29903813eJake Slack
8003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
8103928aee4356845252ac6b662d5c72c29903813eJake Slack    public MimeTypes getMimeTypes()
8203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
8303928aee4356845252ac6b662d5c72c29903813eJake Slack        return _mimeTypes;
8403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
8503928aee4356845252ac6b662d5c72c29903813eJake Slack
8603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
8703928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setMimeTypes(MimeTypes mimeTypes)
8803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
8903928aee4356845252ac6b662d5c72c29903813eJake Slack        _mimeTypes = mimeTypes;
9003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
9103928aee4356845252ac6b662d5c72c29903813eJake Slack
9203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
9303928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
9403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return True if resource aliases are allowed.
9503928aee4356845252ac6b662d5c72c29903813eJake Slack     */
9603928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isAliases()
9703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
9803928aee4356845252ac6b662d5c72c29903813eJake Slack        return _aliases;
9903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
10003928aee4356845252ac6b662d5c72c29903813eJake Slack
10103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
10203928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
10303928aee4356845252ac6b662d5c72c29903813eJake Slack     * Set if resource aliases (eg symlink, 8.3 names, case insensitivity) are allowed.
10403928aee4356845252ac6b662d5c72c29903813eJake Slack     * Allowing aliases can significantly increase security vulnerabilities.
10503928aee4356845252ac6b662d5c72c29903813eJake Slack     * If this handler is deployed inside a ContextHandler, then the
10603928aee4356845252ac6b662d5c72c29903813eJake Slack     * {@link ContextHandler#isAliases()} takes precedent.
10703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param aliases True if aliases are supported.
10803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
10903928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setAliases(boolean aliases)
11003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
11103928aee4356845252ac6b662d5c72c29903813eJake Slack        _aliases = aliases;
11203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
11303928aee4356845252ac6b662d5c72c29903813eJake Slack
11403928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
11503928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Get the directory option.
11603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return true if directories are listed.
11703928aee4356845252ac6b662d5c72c29903813eJake Slack     */
11803928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isDirectoriesListed()
11903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
12003928aee4356845252ac6b662d5c72c29903813eJake Slack        return _directory;
12103928aee4356845252ac6b662d5c72c29903813eJake Slack    }
12203928aee4356845252ac6b662d5c72c29903813eJake Slack
12303928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
12403928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Set the directory.
12503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param directory true if directories are listed.
12603928aee4356845252ac6b662d5c72c29903813eJake Slack     */
12703928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setDirectoriesListed(boolean directory)
12803928aee4356845252ac6b662d5c72c29903813eJake Slack    {
12903928aee4356845252ac6b662d5c72c29903813eJake Slack        _directory = directory;
13003928aee4356845252ac6b662d5c72c29903813eJake Slack    }
13103928aee4356845252ac6b662d5c72c29903813eJake Slack
13203928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
13303928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
13403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return True if ETag processing is done
13503928aee4356845252ac6b662d5c72c29903813eJake Slack     */
13603928aee4356845252ac6b662d5c72c29903813eJake Slack    public boolean isEtags()
13703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
13803928aee4356845252ac6b662d5c72c29903813eJake Slack        return _etags;
13903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
14003928aee4356845252ac6b662d5c72c29903813eJake Slack
14103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
14203928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
14303928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param etags True if ETag processing is done
14403928aee4356845252ac6b662d5c72c29903813eJake Slack     */
14503928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setEtags(boolean etags)
14603928aee4356845252ac6b662d5c72c29903813eJake Slack    {
14703928aee4356845252ac6b662d5c72c29903813eJake Slack        _etags = etags;
14803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
14903928aee4356845252ac6b662d5c72c29903813eJake Slack
15003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
15103928aee4356845252ac6b662d5c72c29903813eJake Slack    @Override
15203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void doStart()
15303928aee4356845252ac6b662d5c72c29903813eJake Slack    throws Exception
15403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
15503928aee4356845252ac6b662d5c72c29903813eJake Slack        Context scontext = ContextHandler.getCurrentContext();
15603928aee4356845252ac6b662d5c72c29903813eJake Slack        _context = (scontext==null?null:scontext.getContextHandler());
15703928aee4356845252ac6b662d5c72c29903813eJake Slack
15803928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_context!=null)
15903928aee4356845252ac6b662d5c72c29903813eJake Slack            _aliases=_context.isAliases();
16003928aee4356845252ac6b662d5c72c29903813eJake Slack
16103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (!_aliases && !FileResource.getCheckAliases())
16203928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new IllegalStateException("Alias checking disabled");
16303928aee4356845252ac6b662d5c72c29903813eJake Slack
16403928aee4356845252ac6b662d5c72c29903813eJake Slack        super.doStart();
16503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
16603928aee4356845252ac6b662d5c72c29903813eJake Slack
16703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
16803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
16903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Returns the resourceBase.
17003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
17103928aee4356845252ac6b662d5c72c29903813eJake Slack    public Resource getBaseResource()
17203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
17303928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_baseResource==null)
17403928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
17503928aee4356845252ac6b662d5c72c29903813eJake Slack        return _baseResource;
17603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
17703928aee4356845252ac6b662d5c72c29903813eJake Slack
17803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
17903928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
18003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Returns the base resource as a string.
18103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
18203928aee4356845252ac6b662d5c72c29903813eJake Slack    public String getResourceBase()
18303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
18403928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_baseResource==null)
18503928aee4356845252ac6b662d5c72c29903813eJake Slack            return null;
18603928aee4356845252ac6b662d5c72c29903813eJake Slack        return _baseResource.toString();
18703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
18803928aee4356845252ac6b662d5c72c29903813eJake Slack
18903928aee4356845252ac6b662d5c72c29903813eJake Slack
19003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
19103928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
19203928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param base The resourceBase to set.
19303928aee4356845252ac6b662d5c72c29903813eJake Slack     */
19403928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setBaseResource(Resource base)
19503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
19603928aee4356845252ac6b662d5c72c29903813eJake Slack        _baseResource=base;
19703928aee4356845252ac6b662d5c72c29903813eJake Slack    }
19803928aee4356845252ac6b662d5c72c29903813eJake Slack
19903928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
20003928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
20103928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param resourceBase The base resource as a string.
20203928aee4356845252ac6b662d5c72c29903813eJake Slack     */
20303928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setResourceBase(String resourceBase)
20403928aee4356845252ac6b662d5c72c29903813eJake Slack    {
20503928aee4356845252ac6b662d5c72c29903813eJake Slack        try
20603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
20703928aee4356845252ac6b662d5c72c29903813eJake Slack            setBaseResource(Resource.newResource(resourceBase));
20803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
20903928aee4356845252ac6b662d5c72c29903813eJake Slack        catch (Exception e)
21003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
21103928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.warn(e.toString());
21203928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.debug(e);
21303928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new IllegalArgumentException(resourceBase);
21403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
21503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
21603928aee4356845252ac6b662d5c72c29903813eJake Slack
21703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
21803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
21903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return Returns the stylesheet as a Resource.
22003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
22103928aee4356845252ac6b662d5c72c29903813eJake Slack    public Resource getStylesheet()
22203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
22303928aee4356845252ac6b662d5c72c29903813eJake Slack    	if(_stylesheet != null)
22403928aee4356845252ac6b662d5c72c29903813eJake Slack    	{
22503928aee4356845252ac6b662d5c72c29903813eJake Slack    	    return _stylesheet;
22603928aee4356845252ac6b662d5c72c29903813eJake Slack    	}
22703928aee4356845252ac6b662d5c72c29903813eJake Slack    	else
22803928aee4356845252ac6b662d5c72c29903813eJake Slack    	{
22903928aee4356845252ac6b662d5c72c29903813eJake Slack    	    if(_defaultStylesheet == null)
23003928aee4356845252ac6b662d5c72c29903813eJake Slack    	    {
23103928aee4356845252ac6b662d5c72c29903813eJake Slack    	        try
23203928aee4356845252ac6b662d5c72c29903813eJake Slack    	        {
23303928aee4356845252ac6b662d5c72c29903813eJake Slack    	            _defaultStylesheet =  Resource.newResource(this.getClass().getResource("/jetty-dir.css"));
23403928aee4356845252ac6b662d5c72c29903813eJake Slack    	        }
23503928aee4356845252ac6b662d5c72c29903813eJake Slack    	        catch(IOException e)
23603928aee4356845252ac6b662d5c72c29903813eJake Slack    	        {
23703928aee4356845252ac6b662d5c72c29903813eJake Slack    	            LOG.warn(e.toString());
23803928aee4356845252ac6b662d5c72c29903813eJake Slack    	            LOG.debug(e);
23903928aee4356845252ac6b662d5c72c29903813eJake Slack    	        }
24003928aee4356845252ac6b662d5c72c29903813eJake Slack    	    }
24103928aee4356845252ac6b662d5c72c29903813eJake Slack    	    return _defaultStylesheet;
24203928aee4356845252ac6b662d5c72c29903813eJake Slack    	}
24303928aee4356845252ac6b662d5c72c29903813eJake Slack    }
24403928aee4356845252ac6b662d5c72c29903813eJake Slack
24503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
24603928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
24703928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param stylesheet The location of the stylesheet to be used as a String.
24803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
24903928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setStylesheet(String stylesheet)
25003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
25103928aee4356845252ac6b662d5c72c29903813eJake Slack        try
25203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
25303928aee4356845252ac6b662d5c72c29903813eJake Slack            _stylesheet = Resource.newResource(stylesheet);
25403928aee4356845252ac6b662d5c72c29903813eJake Slack            if(!_stylesheet.exists())
25503928aee4356845252ac6b662d5c72c29903813eJake Slack            {
25603928aee4356845252ac6b662d5c72c29903813eJake Slack                LOG.warn("unable to find custom stylesheet: " + stylesheet);
25703928aee4356845252ac6b662d5c72c29903813eJake Slack                _stylesheet = null;
25803928aee4356845252ac6b662d5c72c29903813eJake Slack            }
25903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
26003928aee4356845252ac6b662d5c72c29903813eJake Slack    	catch(Exception e)
26103928aee4356845252ac6b662d5c72c29903813eJake Slack    	{
26203928aee4356845252ac6b662d5c72c29903813eJake Slack    		LOG.warn(e.toString());
26303928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.debug(e);
26403928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new IllegalArgumentException(stylesheet.toString());
26503928aee4356845252ac6b662d5c72c29903813eJake Slack    	}
26603928aee4356845252ac6b662d5c72c29903813eJake Slack    }
26703928aee4356845252ac6b662d5c72c29903813eJake Slack
26803928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
26903928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
27003928aee4356845252ac6b662d5c72c29903813eJake Slack     * @return the cacheControl header to set on all static content.
27103928aee4356845252ac6b662d5c72c29903813eJake Slack     */
27203928aee4356845252ac6b662d5c72c29903813eJake Slack    public String getCacheControl()
27303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
27403928aee4356845252ac6b662d5c72c29903813eJake Slack        return _cacheControl.toString();
27503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
27603928aee4356845252ac6b662d5c72c29903813eJake Slack
27703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
27803928aee4356845252ac6b662d5c72c29903813eJake Slack    /**
27903928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param cacheControl the cacheControl header to set on all static content.
28003928aee4356845252ac6b662d5c72c29903813eJake Slack     */
28103928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setCacheControl(String cacheControl)
28203928aee4356845252ac6b662d5c72c29903813eJake Slack    {
28303928aee4356845252ac6b662d5c72c29903813eJake Slack        _cacheControl=cacheControl==null?null:new ByteArrayBuffer(cacheControl);
28403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
28503928aee4356845252ac6b662d5c72c29903813eJake Slack
28603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
28703928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
28803928aee4356845252ac6b662d5c72c29903813eJake Slack     */
28903928aee4356845252ac6b662d5c72c29903813eJake Slack    public Resource getResource(String path) throws MalformedURLException
29003928aee4356845252ac6b662d5c72c29903813eJake Slack    {
29103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (path==null || !path.startsWith("/"))
29203928aee4356845252ac6b662d5c72c29903813eJake Slack            throw new MalformedURLException(path);
29303928aee4356845252ac6b662d5c72c29903813eJake Slack
29403928aee4356845252ac6b662d5c72c29903813eJake Slack        Resource base = _baseResource;
29503928aee4356845252ac6b662d5c72c29903813eJake Slack        if (base==null)
29603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
29703928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_context==null)
29803928aee4356845252ac6b662d5c72c29903813eJake Slack                return null;
29903928aee4356845252ac6b662d5c72c29903813eJake Slack            base=_context.getBaseResource();
30003928aee4356845252ac6b662d5c72c29903813eJake Slack            if (base==null)
30103928aee4356845252ac6b662d5c72c29903813eJake Slack                return null;
30203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
30303928aee4356845252ac6b662d5c72c29903813eJake Slack
30403928aee4356845252ac6b662d5c72c29903813eJake Slack        try
30503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
30603928aee4356845252ac6b662d5c72c29903813eJake Slack            path=URIUtil.canonicalPath(path);
30703928aee4356845252ac6b662d5c72c29903813eJake Slack            return base.addPath(path);
30803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
30903928aee4356845252ac6b662d5c72c29903813eJake Slack        catch(Exception e)
31003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
31103928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.ignore(e);
31203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
31303928aee4356845252ac6b662d5c72c29903813eJake Slack
31403928aee4356845252ac6b662d5c72c29903813eJake Slack        return null;
31503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
31603928aee4356845252ac6b662d5c72c29903813eJake Slack
31703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
31803928aee4356845252ac6b662d5c72c29903813eJake Slack    protected Resource getResource(HttpServletRequest request) throws MalformedURLException
31903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
32003928aee4356845252ac6b662d5c72c29903813eJake Slack        String servletPath;
32103928aee4356845252ac6b662d5c72c29903813eJake Slack        String pathInfo;
32203928aee4356845252ac6b662d5c72c29903813eJake Slack        Boolean included = request.getAttribute(Dispatcher.INCLUDE_REQUEST_URI) != null;
32303928aee4356845252ac6b662d5c72c29903813eJake Slack        if (included != null && included.booleanValue())
32403928aee4356845252ac6b662d5c72c29903813eJake Slack        {
32503928aee4356845252ac6b662d5c72c29903813eJake Slack            servletPath = (String)request.getAttribute(Dispatcher.INCLUDE_SERVLET_PATH);
32603928aee4356845252ac6b662d5c72c29903813eJake Slack            pathInfo = (String)request.getAttribute(Dispatcher.INCLUDE_PATH_INFO);
32703928aee4356845252ac6b662d5c72c29903813eJake Slack
32803928aee4356845252ac6b662d5c72c29903813eJake Slack            if (servletPath == null && pathInfo == null)
32903928aee4356845252ac6b662d5c72c29903813eJake Slack            {
33003928aee4356845252ac6b662d5c72c29903813eJake Slack                servletPath = request.getServletPath();
33103928aee4356845252ac6b662d5c72c29903813eJake Slack                pathInfo = request.getPathInfo();
33203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
33303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
33403928aee4356845252ac6b662d5c72c29903813eJake Slack        else
33503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
33603928aee4356845252ac6b662d5c72c29903813eJake Slack            servletPath = request.getServletPath();
33703928aee4356845252ac6b662d5c72c29903813eJake Slack            pathInfo = request.getPathInfo();
33803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
33903928aee4356845252ac6b662d5c72c29903813eJake Slack
34003928aee4356845252ac6b662d5c72c29903813eJake Slack        String pathInContext=URIUtil.addPaths(servletPath,pathInfo);
34103928aee4356845252ac6b662d5c72c29903813eJake Slack        return getResource(pathInContext);
34203928aee4356845252ac6b662d5c72c29903813eJake Slack    }
34303928aee4356845252ac6b662d5c72c29903813eJake Slack
34403928aee4356845252ac6b662d5c72c29903813eJake Slack
34503928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
34603928aee4356845252ac6b662d5c72c29903813eJake Slack    public String[] getWelcomeFiles()
34703928aee4356845252ac6b662d5c72c29903813eJake Slack    {
34803928aee4356845252ac6b662d5c72c29903813eJake Slack        return _welcomeFiles;
34903928aee4356845252ac6b662d5c72c29903813eJake Slack    }
35003928aee4356845252ac6b662d5c72c29903813eJake Slack
35103928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
35203928aee4356845252ac6b662d5c72c29903813eJake Slack    public void setWelcomeFiles(String[] welcomeFiles)
35303928aee4356845252ac6b662d5c72c29903813eJake Slack    {
35403928aee4356845252ac6b662d5c72c29903813eJake Slack        _welcomeFiles=welcomeFiles;
35503928aee4356845252ac6b662d5c72c29903813eJake Slack    }
35603928aee4356845252ac6b662d5c72c29903813eJake Slack
35703928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
35803928aee4356845252ac6b662d5c72c29903813eJake Slack    protected Resource getWelcome(Resource directory) throws MalformedURLException, IOException
35903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
36003928aee4356845252ac6b662d5c72c29903813eJake Slack        for (int i=0;i<_welcomeFiles.length;i++)
36103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
36203928aee4356845252ac6b662d5c72c29903813eJake Slack            Resource welcome=directory.addPath(_welcomeFiles[i]);
36303928aee4356845252ac6b662d5c72c29903813eJake Slack            if (welcome.exists() && !welcome.isDirectory())
36403928aee4356845252ac6b662d5c72c29903813eJake Slack                return welcome;
36503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
36603928aee4356845252ac6b662d5c72c29903813eJake Slack
36703928aee4356845252ac6b662d5c72c29903813eJake Slack        return null;
36803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
36903928aee4356845252ac6b662d5c72c29903813eJake Slack
37003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
37103928aee4356845252ac6b662d5c72c29903813eJake Slack    /*
37203928aee4356845252ac6b662d5c72c29903813eJake Slack     * @see org.eclipse.jetty.server.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int)
37303928aee4356845252ac6b662d5c72c29903813eJake Slack     */
37403928aee4356845252ac6b662d5c72c29903813eJake Slack    public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
37503928aee4356845252ac6b662d5c72c29903813eJake Slack    {
37603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (baseRequest.isHandled())
37703928aee4356845252ac6b662d5c72c29903813eJake Slack            return;
37803928aee4356845252ac6b662d5c72c29903813eJake Slack
37903928aee4356845252ac6b662d5c72c29903813eJake Slack        boolean skipContentBody = false;
38003928aee4356845252ac6b662d5c72c29903813eJake Slack
38103928aee4356845252ac6b662d5c72c29903813eJake Slack        if(!HttpMethods.GET.equals(request.getMethod()))
38203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
38303928aee4356845252ac6b662d5c72c29903813eJake Slack            if(!HttpMethods.HEAD.equals(request.getMethod()))
38403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
38503928aee4356845252ac6b662d5c72c29903813eJake Slack                //try another handler
38603928aee4356845252ac6b662d5c72c29903813eJake Slack                super.handle(target, baseRequest, request, response);
38703928aee4356845252ac6b662d5c72c29903813eJake Slack                return;
38803928aee4356845252ac6b662d5c72c29903813eJake Slack            }
38903928aee4356845252ac6b662d5c72c29903813eJake Slack            skipContentBody = true;
39003928aee4356845252ac6b662d5c72c29903813eJake Slack        }
39103928aee4356845252ac6b662d5c72c29903813eJake Slack
39203928aee4356845252ac6b662d5c72c29903813eJake Slack        Resource resource = getResource(request);
39303928aee4356845252ac6b662d5c72c29903813eJake Slack
39403928aee4356845252ac6b662d5c72c29903813eJake Slack        if (resource==null || !resource.exists())
39503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
39603928aee4356845252ac6b662d5c72c29903813eJake Slack            if (target.endsWith("/jetty-dir.css"))
39703928aee4356845252ac6b662d5c72c29903813eJake Slack            {
39803928aee4356845252ac6b662d5c72c29903813eJake Slack                resource = getStylesheet();
39903928aee4356845252ac6b662d5c72c29903813eJake Slack                if (resource==null)
40003928aee4356845252ac6b662d5c72c29903813eJake Slack                    return;
40103928aee4356845252ac6b662d5c72c29903813eJake Slack                response.setContentType("text/css");
40203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
40303928aee4356845252ac6b662d5c72c29903813eJake Slack            else
40403928aee4356845252ac6b662d5c72c29903813eJake Slack            {
40503928aee4356845252ac6b662d5c72c29903813eJake Slack                //no resource - try other handlers
40603928aee4356845252ac6b662d5c72c29903813eJake Slack                super.handle(target, baseRequest, request, response);
40703928aee4356845252ac6b662d5c72c29903813eJake Slack                return;
40803928aee4356845252ac6b662d5c72c29903813eJake Slack            }
40903928aee4356845252ac6b662d5c72c29903813eJake Slack        }
41003928aee4356845252ac6b662d5c72c29903813eJake Slack
41103928aee4356845252ac6b662d5c72c29903813eJake Slack        if (!_aliases && resource.getAlias()!=null)
41203928aee4356845252ac6b662d5c72c29903813eJake Slack        {
41303928aee4356845252ac6b662d5c72c29903813eJake Slack            LOG.info(resource+" aliased to "+resource.getAlias());
41403928aee4356845252ac6b662d5c72c29903813eJake Slack            return;
41503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
41603928aee4356845252ac6b662d5c72c29903813eJake Slack
41703928aee4356845252ac6b662d5c72c29903813eJake Slack        // We are going to serve something
41803928aee4356845252ac6b662d5c72c29903813eJake Slack        baseRequest.setHandled(true);
41903928aee4356845252ac6b662d5c72c29903813eJake Slack
42003928aee4356845252ac6b662d5c72c29903813eJake Slack        if (resource.isDirectory())
42103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
42203928aee4356845252ac6b662d5c72c29903813eJake Slack            if (!request.getPathInfo().endsWith(URIUtil.SLASH))
42303928aee4356845252ac6b662d5c72c29903813eJake Slack            {
42403928aee4356845252ac6b662d5c72c29903813eJake Slack                response.sendRedirect(response.encodeRedirectURL(URIUtil.addPaths(request.getRequestURI(),URIUtil.SLASH)));
42503928aee4356845252ac6b662d5c72c29903813eJake Slack                return;
42603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
42703928aee4356845252ac6b662d5c72c29903813eJake Slack
42803928aee4356845252ac6b662d5c72c29903813eJake Slack            Resource welcome=getWelcome(resource);
42903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (welcome!=null && welcome.exists())
43003928aee4356845252ac6b662d5c72c29903813eJake Slack                resource=welcome;
43103928aee4356845252ac6b662d5c72c29903813eJake Slack            else
43203928aee4356845252ac6b662d5c72c29903813eJake Slack            {
43303928aee4356845252ac6b662d5c72c29903813eJake Slack                doDirectory(request,response,resource);
43403928aee4356845252ac6b662d5c72c29903813eJake Slack                baseRequest.setHandled(true);
43503928aee4356845252ac6b662d5c72c29903813eJake Slack                return;
43603928aee4356845252ac6b662d5c72c29903813eJake Slack            }
43703928aee4356845252ac6b662d5c72c29903813eJake Slack        }
43803928aee4356845252ac6b662d5c72c29903813eJake Slack
43903928aee4356845252ac6b662d5c72c29903813eJake Slack        // set some headers
44003928aee4356845252ac6b662d5c72c29903813eJake Slack        long last_modified=resource.lastModified();
44103928aee4356845252ac6b662d5c72c29903813eJake Slack        String etag=null;
44203928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_etags)
44303928aee4356845252ac6b662d5c72c29903813eJake Slack        {
44403928aee4356845252ac6b662d5c72c29903813eJake Slack            // simple handling of only a single etag
44503928aee4356845252ac6b662d5c72c29903813eJake Slack            String ifnm = request.getHeader(HttpHeaders.IF_NONE_MATCH);
44603928aee4356845252ac6b662d5c72c29903813eJake Slack            etag=resource.getWeakETag();
44703928aee4356845252ac6b662d5c72c29903813eJake Slack            if (ifnm!=null && resource!=null && ifnm.equals(etag))
44803928aee4356845252ac6b662d5c72c29903813eJake Slack            {
44903928aee4356845252ac6b662d5c72c29903813eJake Slack                response.setStatus(HttpStatus.NOT_MODIFIED_304);
45003928aee4356845252ac6b662d5c72c29903813eJake Slack                baseRequest.getResponse().getHttpFields().put(HttpHeaders.ETAG_BUFFER,etag);
45103928aee4356845252ac6b662d5c72c29903813eJake Slack                return;
45203928aee4356845252ac6b662d5c72c29903813eJake Slack            }
45303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
45403928aee4356845252ac6b662d5c72c29903813eJake Slack
45503928aee4356845252ac6b662d5c72c29903813eJake Slack
45603928aee4356845252ac6b662d5c72c29903813eJake Slack        if (last_modified>0)
45703928aee4356845252ac6b662d5c72c29903813eJake Slack        {
45803928aee4356845252ac6b662d5c72c29903813eJake Slack            long if_modified=request.getDateHeader(HttpHeaders.IF_MODIFIED_SINCE);
45903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (if_modified>0 && last_modified/1000<=if_modified/1000)
46003928aee4356845252ac6b662d5c72c29903813eJake Slack            {
46103928aee4356845252ac6b662d5c72c29903813eJake Slack                response.setStatus(HttpStatus.NOT_MODIFIED_304);
46203928aee4356845252ac6b662d5c72c29903813eJake Slack                return;
46303928aee4356845252ac6b662d5c72c29903813eJake Slack            }
46403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
46503928aee4356845252ac6b662d5c72c29903813eJake Slack
46603928aee4356845252ac6b662d5c72c29903813eJake Slack        Buffer mime=_mimeTypes.getMimeByExtension(resource.toString());
46703928aee4356845252ac6b662d5c72c29903813eJake Slack        if (mime==null)
46803928aee4356845252ac6b662d5c72c29903813eJake Slack            mime=_mimeTypes.getMimeByExtension(request.getPathInfo());
46903928aee4356845252ac6b662d5c72c29903813eJake Slack
47003928aee4356845252ac6b662d5c72c29903813eJake Slack        // set the headers
47103928aee4356845252ac6b662d5c72c29903813eJake Slack        doResponseHeaders(response,resource,mime!=null?mime.toString():null);
47203928aee4356845252ac6b662d5c72c29903813eJake Slack        response.setDateHeader(HttpHeaders.LAST_MODIFIED,last_modified);
47303928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_etags)
47403928aee4356845252ac6b662d5c72c29903813eJake Slack            baseRequest.getResponse().getHttpFields().put(HttpHeaders.ETAG_BUFFER,etag);
47503928aee4356845252ac6b662d5c72c29903813eJake Slack
47603928aee4356845252ac6b662d5c72c29903813eJake Slack        if(skipContentBody)
47703928aee4356845252ac6b662d5c72c29903813eJake Slack            return;
47803928aee4356845252ac6b662d5c72c29903813eJake Slack        // Send the content
47903928aee4356845252ac6b662d5c72c29903813eJake Slack        OutputStream out =null;
48003928aee4356845252ac6b662d5c72c29903813eJake Slack        try {out = response.getOutputStream();}
48103928aee4356845252ac6b662d5c72c29903813eJake Slack        catch(IllegalStateException e) {out = new WriterOutputStream(response.getWriter());}
48203928aee4356845252ac6b662d5c72c29903813eJake Slack
48303928aee4356845252ac6b662d5c72c29903813eJake Slack        // See if a short direct method can be used?
48403928aee4356845252ac6b662d5c72c29903813eJake Slack        if (out instanceof AbstractHttpConnection.Output)
48503928aee4356845252ac6b662d5c72c29903813eJake Slack        {
48603928aee4356845252ac6b662d5c72c29903813eJake Slack            // TODO file mapped buffers
48703928aee4356845252ac6b662d5c72c29903813eJake Slack            ((AbstractHttpConnection.Output)out).sendContent(resource.getInputStream());
48803928aee4356845252ac6b662d5c72c29903813eJake Slack        }
48903928aee4356845252ac6b662d5c72c29903813eJake Slack        else
49003928aee4356845252ac6b662d5c72c29903813eJake Slack        {
49103928aee4356845252ac6b662d5c72c29903813eJake Slack            // Write content normally
49203928aee4356845252ac6b662d5c72c29903813eJake Slack            resource.writeTo(out,0,resource.length());
49303928aee4356845252ac6b662d5c72c29903813eJake Slack        }
49403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
49503928aee4356845252ac6b662d5c72c29903813eJake Slack
49603928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
49703928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void doDirectory(HttpServletRequest request,HttpServletResponse response, Resource resource)
49803928aee4356845252ac6b662d5c72c29903813eJake Slack        throws IOException
49903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
50003928aee4356845252ac6b662d5c72c29903813eJake Slack        if (_directory)
50103928aee4356845252ac6b662d5c72c29903813eJake Slack        {
50203928aee4356845252ac6b662d5c72c29903813eJake Slack            String listing = resource.getListHTML(request.getRequestURI(),request.getPathInfo().lastIndexOf("/") > 0);
50303928aee4356845252ac6b662d5c72c29903813eJake Slack            response.setContentType("text/html; charset=UTF-8");
50403928aee4356845252ac6b662d5c72c29903813eJake Slack            response.getWriter().println(listing);
50503928aee4356845252ac6b662d5c72c29903813eJake Slack        }
50603928aee4356845252ac6b662d5c72c29903813eJake Slack        else
50703928aee4356845252ac6b662d5c72c29903813eJake Slack            response.sendError(HttpStatus.FORBIDDEN_403);
50803928aee4356845252ac6b662d5c72c29903813eJake Slack    }
50903928aee4356845252ac6b662d5c72c29903813eJake Slack
51003928aee4356845252ac6b662d5c72c29903813eJake Slack    /* ------------------------------------------------------------ */
51103928aee4356845252ac6b662d5c72c29903813eJake Slack    /** Set the response headers.
51203928aee4356845252ac6b662d5c72c29903813eJake Slack     * This method is called to set the response headers such as content type and content length.
51303928aee4356845252ac6b662d5c72c29903813eJake Slack     * May be extended to add additional headers.
51403928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param response
51503928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param resource
51603928aee4356845252ac6b662d5c72c29903813eJake Slack     * @param mimeType
51703928aee4356845252ac6b662d5c72c29903813eJake Slack     */
51803928aee4356845252ac6b662d5c72c29903813eJake Slack    protected void doResponseHeaders(HttpServletResponse response, Resource resource, String mimeType)
51903928aee4356845252ac6b662d5c72c29903813eJake Slack    {
52003928aee4356845252ac6b662d5c72c29903813eJake Slack        if (mimeType!=null)
52103928aee4356845252ac6b662d5c72c29903813eJake Slack            response.setContentType(mimeType);
52203928aee4356845252ac6b662d5c72c29903813eJake Slack
52303928aee4356845252ac6b662d5c72c29903813eJake Slack        long length=resource.length();
52403928aee4356845252ac6b662d5c72c29903813eJake Slack
52503928aee4356845252ac6b662d5c72c29903813eJake Slack        if (response instanceof Response)
52603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
52703928aee4356845252ac6b662d5c72c29903813eJake Slack            HttpFields fields = ((Response)response).getHttpFields();
52803928aee4356845252ac6b662d5c72c29903813eJake Slack
52903928aee4356845252ac6b662d5c72c29903813eJake Slack            if (length>0)
53003928aee4356845252ac6b662d5c72c29903813eJake Slack                fields.putLongField(HttpHeaders.CONTENT_LENGTH_BUFFER,length);
53103928aee4356845252ac6b662d5c72c29903813eJake Slack
53203928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_cacheControl!=null)
53303928aee4356845252ac6b662d5c72c29903813eJake Slack                fields.put(HttpHeaders.CACHE_CONTROL_BUFFER,_cacheControl);
53403928aee4356845252ac6b662d5c72c29903813eJake Slack        }
53503928aee4356845252ac6b662d5c72c29903813eJake Slack        else
53603928aee4356845252ac6b662d5c72c29903813eJake Slack        {
53703928aee4356845252ac6b662d5c72c29903813eJake Slack            if (length>0)
53803928aee4356845252ac6b662d5c72c29903813eJake Slack                response.setHeader(HttpHeaders.CONTENT_LENGTH,Long.toString(length));
53903928aee4356845252ac6b662d5c72c29903813eJake Slack
54003928aee4356845252ac6b662d5c72c29903813eJake Slack            if (_cacheControl!=null)
54103928aee4356845252ac6b662d5c72c29903813eJake Slack                response.setHeader(HttpHeaders.CACHE_CONTROL,_cacheControl.toString());
54203928aee4356845252ac6b662d5c72c29903813eJake Slack        }
54303928aee4356845252ac6b662d5c72c29903813eJake Slack
54403928aee4356845252ac6b662d5c72c29903813eJake Slack    }
54503928aee4356845252ac6b662d5c72c29903813eJake Slack}
546