View Javadoc

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