View Javadoc

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