Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/mortbay/jetty/servlet/Invoker.java


1   // ===========================================================================
2   // Copyright (c) 1996-2002 Mort Bay Consulting Pty. Ltd. All rights reserved.
3   // $Id: Invoker.java,v 1.10 2003/09/18 13:29:24 gregwilkins Exp $
4   // ---------------------------------------------------------------------------
5   
6   package org.mortbay.jetty.servlet;
7   
8   
9   import java.io.IOException;
10  import java.util.Enumeration;
11  import java.util.HashMap;
12  import java.util.Map;
13  
14  import javax.servlet.ServletContext;
15  import javax.servlet.ServletException;
16  import javax.servlet.UnavailableException;
17  import javax.servlet.http.HttpServlet;
18  import javax.servlet.http.HttpServletRequest;
19  import javax.servlet.http.HttpServletRequestWrapper;
20  import javax.servlet.http.HttpServletResponse;
21  
22  import org.apache.commons.logging.Log;
23  import org.apache.commons.logging.LogFactory;
24  import org.mortbay.util.LogSupport;
25  import org.mortbay.util.URI;
26  
27  /* ------------------------------------------------------------ */
28  /**  Dynamic Servlet Invoker.  
29   * This servlet invokes anonymous servlets that have not been defined   
30   * in the web.xml or by other means. The first element of the pathInfo  
31   * of a request passed to the envoker is treated as a servlet name for  
32   * an existing servlet, or as a class name of a new servlet.            
33   * This servlet is normally mapped to /servlet/*                        
34   * This servlet support the following initParams:                       
35   * <PRE>                                                                     
36   *  nonContextServlets       If false, the invoker can only load        
37   *                           servlets from the contexts classloader.    
38   *                           This is false by default and setting this  
39   *                           to true may have security implications.    
40   *                                                                      
41   *  verbose                  If true, log dynamic loads                 
42   *                                                                      
43   *  *                        All other parameters are copied to the     
44   *                           each dynamic servlet as init parameters    
45   * </PRE>
46   * @version $Id: Invoker.java,v 1.10 2003/09/18 13:29:24 gregwilkins Exp $
47   * @author Greg Wilkins (gregw)
48   */
49  public class Invoker extends HttpServlet
50  {
51      private static Log log = LogFactory.getLog(Invoker.class);
52  
53      private ServletHandler _servletHandler;
54      private Map.Entry _invokerEntry;
55      private Map _parameters;
56      private boolean _nonContextServlets;
57      private boolean _verbose;
58          
59      /* ------------------------------------------------------------ */
60      public void init()
61      {
62          ServletContext config=getServletContext();
63          _servletHandler=((ServletHandler.Context)config).getServletHandler();
64  
65          Enumeration e = getInitParameterNames();
66          while(e.hasMoreElements())
67          {
68              String param=(String)e.nextElement();
69              String value=getInitParameter(param);
70              String lvalue=value.toLowerCase();
71              if ("nonContextServlets".equals(param))
72              {
73                  _nonContextServlets=value.length()>0 && lvalue.startsWith("t");
74              }
75              if ("verbose".equals(param))
76              {
77                  _verbose=value.length()>0 && lvalue.startsWith("t");
78              }
79              else
80              {
81                  if (_parameters==null)
82                      _parameters=new HashMap();
83                  _parameters.put(param,value);
84              }
85          }
86      }
87      
88      /* ------------------------------------------------------------ */
89      protected void service(HttpServletRequest request, HttpServletResponse response)
90    throws ServletException, IOException
91      {
92          // Get the requested path and info
93          boolean included=false;
94          String servlet_path=(String)request.getAttribute(Dispatcher.__INCLUDE_SERVLET_PATH);
95          if (servlet_path==null)
96              servlet_path=request.getServletPath();
97          else
98              included=true;
99          String path_info = (String)request.getAttribute(Dispatcher.__INCLUDE_PATH_INFO);
100         if (path_info==null)
101             path_info=request.getPathInfo();
102         
103         // Get the servlet class
104         String servlet = path_info;
105         if (servlet==null || servlet.length()<=1 )
106         {
107             response.sendError(404);
108             return;
109         }
110         
111         int i0=servlet.charAt(0)=='/'?1:0;
112         int i1=servlet.indexOf('/',i0);
113         servlet=i1<0?servlet.substring(i0):servlet.substring(i0,i1);
114 
115         // look for a named holder
116         ServletHolder holder=_servletHandler.getServletHolder(servlet);
117         if (holder!=null)
118         {
119             // Add named servlet mapping
120             _servletHandler.addServletHolder(URI.addPaths(servlet_path,servlet)+"/*",holder);
121         }
122         else
123         {
124             // look for a class mapping
125             if (servlet.endsWith(".class"))
126                 servlet=servlet.substring(0,servlet.length()-6);
127             if (servlet==null || servlet.length()==0)
128             {
129                 response.sendError(404);
130                 return;
131             }   
132         
133             synchronized(_servletHandler)
134             {
135                 // find the entry for the invoker
136                 if (_invokerEntry==null)
137                     _invokerEntry=_servletHandler.getHolderEntry(servlet_path);
138             
139                 // Check for existing mapping (avoid threaded race).
140                 String path=URI.addPaths(servlet_path,servlet);
141                 Map.Entry entry = _servletHandler.getHolderEntry(path);
142 
143                 if (entry!=null && entry!=_invokerEntry)
144                 {
145                     // Use the holder
146                     holder=(ServletHolder)entry.getValue();       
147                 }
148                 else
149                 {
150                     // Make a holder
151                     holder=new ServletHolder(_servletHandler,servlet,servlet);
152                     
153                     if (_parameters!=null)
154                         holder.putAll(_parameters);
155                     
156                     try {holder.start();}
157                     catch (Exception e)
158                     {
159                         log.debug(LogSupport.EXCEPTION,e);
160                         throw new UnavailableException(e.toString());
161                     }
162                     
163                     // Check it is from an allowable classloader
164                     if (!_nonContextServlets)
165                     {
166                         Object s=holder.getServlet();
167                         
168                         if (_servletHandler.getClassLoader()!=
169                             s.getClass().getClassLoader())
170                         {
171                             holder.stop();
172                             log.warn("Dynamic servlet "+s+
173                                          " not loaded from context "+
174                                          request.getContextPath());
175                             throw new UnavailableException("Not in context");
176                         }
177                     }
178 
179                     // Add the holder for all the possible paths
180                     if (_verbose)
181                         log("Dynamic load '"+servlet+"' at "+path);
182                     _servletHandler.addServletHolder(path+"/*",holder);
183                     _servletHandler.addServletHolder(path+".class/*",holder);
184                 }
185             }
186             
187         }
188         
189         if (holder!=null)
190             holder.handle(new Request(request,included,servlet,servlet_path,path_info),
191                           response);
192         else
193             response.sendError(404);
194         
195     }
196 
197     /* ------------------------------------------------------------ */
198     class Request extends HttpServletRequestWrapper
199     {
200         String _servletPath;
201         String _pathInfo;
202         boolean _included;
203         
204         /* ------------------------------------------------------------ */
205         Request(HttpServletRequest request,
206                 boolean included,
207                 String name,
208                 String servletPath,
209                 String pathInfo)
210         {
211             super(request);
212             _included=included;
213             _servletPath=URI.addPaths(servletPath,name);
214             _pathInfo=pathInfo.substring(name.length()+1);
215             if (_pathInfo.length()==0)
216                 _pathInfo=null;
217         }
218         
219         /* ------------------------------------------------------------ */
220         public String getServletPath()
221         {
222             if (_included)
223                 return super.getServletPath();
224             return _servletPath;
225         }
226         
227         /* ------------------------------------------------------------ */
228         public String getPathInfo()
229         {
230             if (_included)
231                 return super.getPathInfo();
232             return _pathInfo;
233         }
234         
235         /* ------------------------------------------------------------ */
236         public Object getAttribute(String name)
237         {
238             if (_included)
239             {
240                 if (name.equals(Dispatcher.__INCLUDE_REQUEST_URI))
241                     return URI.addPaths(URI.addPaths(getContextPath(),_servletPath),_pathInfo);
242                 if (name.equals(Dispatcher.__INCLUDE_PATH_INFO))
243                     return _pathInfo;
244                 if (name.equals(Dispatcher.__INCLUDE_SERVLET_PATH))
245                     return _servletPath;
246             }
247             return super.getAttribute(name);
248         }
249     }
250 }