View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2012 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.servlets;
20  
21  import java.io.IOException;
22  import javax.servlet.RequestDispatcher;
23  import javax.servlet.ServletContext;
24  import javax.servlet.ServletException;
25  import javax.servlet.http.HttpServlet;
26  import javax.servlet.http.HttpServletRequest;
27  import javax.servlet.http.HttpServletResponse;
28  
29  /* ------------------------------------------------------------ */
30  /** Concatenation Servlet
31   * This servlet may be used to concatenate multiple resources into
32   * a single response.  It is intended to be used to load multiple
33   * javascript or css files, but may be used for any content of the
34   * same mime type that can be meaningfully concatenated.
35   * <p>
36   * The servlet uses {@link RequestDispatcher#include(javax.servlet.ServletRequest, javax.servlet.ServletResponse)}
37   * to combine the requested content, so dynamically generated content
38   * may be combined (Eg engine.js for DWR).
39   * <p>
40   * The servlet uses parameter names of the query string as resource names
41   * relative to the context root.  So these script tags:
42   * <pre>
43   *  &lt;script type="text/javascript" src="../js/behaviour.js"&gt;&lt;/script&gt;
44   *  &lt;script type="text/javascript" src="../js/ajax.js&/chat/chat.js"&gt;&lt;/script&gt;
45   *  &lt;script type="text/javascript" src="../chat/chat.js"&gt;&lt;/script&gt;
46   * </pre> can be replaced with the single tag (with the ConcatServlet mapped to /concat):
47   * <pre>
48   *  &lt;script type="text/javascript" src="../concat?/js/behaviour.js&/js/ajax.js&/chat/chat.js"&gt;&lt;/script&gt;
49   * </pre>
50   * The {@link ServletContext#getMimeType(String)} method is used to determine the
51   * mime type of each resource.  If the types of all resources do not match, then a 415
52   * UNSUPPORTED_MEDIA_TYPE error is returned.
53   * <p>
54   * If the init parameter "development" is set to "true" then the servlet will run in
55   * development mode and the content will be concatenated on every request. Otherwise
56   * the init time of the servlet is used as the lastModifiedTime of the combined content
57   * and If-Modified-Since requests are handled with 206 NOT Modified responses if
58   * appropriate. This means that when not in development mode, the servlet must be
59   * restarted before changed content will be served.
60   *
61   *
62   *
63   */
64  public class ConcatServlet extends HttpServlet
65  {
66      boolean _development;
67      long _lastModified;
68      ServletContext _context;
69  
70      /* ------------------------------------------------------------ */
71      public void init() throws ServletException
72      {
73          _lastModified=System.currentTimeMillis();
74          _context=getServletContext();
75          _development="true".equals(getInitParameter("development"));
76      }
77  
78      /* ------------------------------------------------------------ */
79      /*
80       * @return The start time of the servlet unless in development mode, in which case -1 is returned.
81       */
82      protected long getLastModified(HttpServletRequest req)
83      {
84          return _development?-1:_lastModified;
85      }
86  
87      /* ------------------------------------------------------------ */
88      protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException
89      {
90          String q=req.getQueryString();
91          if (q==null)
92          {
93              resp.sendError(HttpServletResponse.SC_NO_CONTENT);
94              return;
95          }
96  
97          String[] parts = q.split("\\&");
98          String type=null;
99          for (int i=0;i<parts.length;i++)
100         {
101             String t = _context.getMimeType(parts[i]);
102             if (t!=null)
103             {
104                 if (type==null)
105                     type=t;
106                 else if (!type.equals(t))
107                 {
108                     resp.sendError(HttpServletResponse.SC_UNSUPPORTED_MEDIA_TYPE);
109                     return;
110                 }
111             }
112         }
113 
114         if (type!=null)
115             resp.setContentType(type);
116 
117         for (int i=0;i<parts.length;i++)
118         {
119             RequestDispatcher dispatcher=_context.getRequestDispatcher(parts[i]);
120             if (dispatcher!=null)
121                 dispatcher.include(req,resp);
122         }
123     }
124 }