View Javadoc

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