1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.servlet;
15
16 import java.io.IOException;
17 import java.util.Enumeration;
18 import java.util.HashMap;
19 import java.util.Map;
20
21 import javax.servlet.ServletContext;
22 import javax.servlet.ServletException;
23 import javax.servlet.UnavailableException;
24 import javax.servlet.http.HttpServlet;
25 import javax.servlet.http.HttpServletRequest;
26 import javax.servlet.http.HttpServletRequestWrapper;
27 import javax.servlet.http.HttpServletResponse;
28
29 import org.eclipse.jetty.server.Dispatcher;
30 import org.eclipse.jetty.server.Handler;
31 import org.eclipse.jetty.server.HttpConnection;
32 import org.eclipse.jetty.server.Request;
33 import org.eclipse.jetty.server.handler.ContextHandler;
34 import org.eclipse.jetty.server.handler.HandlerWrapper;
35 import org.eclipse.jetty.util.LazyList;
36 import org.eclipse.jetty.util.URIUtil;
37 import org.eclipse.jetty.util.log.Log;
38 import org.eclipse.jetty.util.log.Logger;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62 public class Invoker extends HttpServlet
63 {
64 private static final Logger LOG = Log.getLogger(Invoker.class);
65
66
67 private ContextHandler _contextHandler;
68 private ServletHandler _servletHandler;
69 private Map.Entry _invokerEntry;
70 private Map _parameters;
71 private boolean _nonContextServlets;
72 private boolean _verbose;
73
74
75 public void init()
76 {
77 ServletContext config=getServletContext();
78 _contextHandler=((ContextHandler.Context)config).getContextHandler();
79
80 Handler handler=_contextHandler.getHandler();
81 while (handler!=null && !(handler instanceof ServletHandler) && (handler instanceof HandlerWrapper))
82 handler=((HandlerWrapper)handler).getHandler();
83 _servletHandler = (ServletHandler)handler;
84 Enumeration e = getInitParameterNames();
85 while(e.hasMoreElements())
86 {
87 String param=(String)e.nextElement();
88 String value=getInitParameter(param);
89 String lvalue=value.toLowerCase();
90 if ("nonContextServlets".equals(param))
91 {
92 _nonContextServlets=value.length()>0 && lvalue.startsWith("t");
93 }
94 if ("verbose".equals(param))
95 {
96 _verbose=value.length()>0 && lvalue.startsWith("t");
97 }
98 else
99 {
100 if (_parameters==null)
101 _parameters=new HashMap();
102 _parameters.put(param,value);
103 }
104 }
105 }
106
107
108 protected void service(HttpServletRequest request, HttpServletResponse response)
109 throws ServletException, IOException
110 {
111
112 boolean included=false;
113 String servlet_path=(String)request.getAttribute(Dispatcher.INCLUDE_SERVLET_PATH);
114 if (servlet_path==null)
115 servlet_path=request.getServletPath();
116 else
117 included=true;
118 String path_info = (String)request.getAttribute(Dispatcher.INCLUDE_PATH_INFO);
119 if (path_info==null)
120 path_info=request.getPathInfo();
121
122
123 String servlet = path_info;
124 if (servlet==null || servlet.length()<=1 )
125 {
126 response.sendError(404);
127 return;
128 }
129
130
131 int i0=servlet.charAt(0)=='/'?1:0;
132 int i1=servlet.indexOf('/',i0);
133 servlet=i1<0?servlet.substring(i0):servlet.substring(i0,i1);
134
135
136 ServletHolder[] holders = _servletHandler.getServlets();
137 ServletHolder holder = getHolder (holders, servlet);
138
139 if (holder!=null)
140 {
141
142
143 if (LOG.isDebugEnabled())
144 LOG.debug("Adding servlet mapping for named servlet:"+servlet+":"+URIUtil.addPaths(servlet_path,servlet)+"/*");
145 ServletMapping mapping = new ServletMapping();
146 mapping.setServletName(servlet);
147 mapping.setPathSpec(URIUtil.addPaths(servlet_path,servlet)+"/*");
148 _servletHandler.setServletMappings((ServletMapping[])LazyList.addToArray(_servletHandler.getServletMappings(), mapping, ServletMapping.class));
149 }
150 else
151 {
152
153 if (servlet.endsWith(".class"))
154 servlet=servlet.substring(0,servlet.length()-6);
155 if (servlet==null || servlet.length()==0)
156 {
157 response.sendError(404);
158 return;
159 }
160
161 synchronized(_servletHandler)
162 {
163
164 _invokerEntry=_servletHandler.getHolderEntry(servlet_path);
165
166
167 String path=URIUtil.addPaths(servlet_path,servlet);
168 Map.Entry entry = _servletHandler.getHolderEntry(path);
169
170 if (entry!=null && !entry.equals(_invokerEntry))
171 {
172
173 holder=(ServletHolder)entry.getValue();
174 }
175 else
176 {
177
178 if (LOG.isDebugEnabled())
179 LOG.debug("Making new servlet="+servlet+" with path="+path+"/*");
180 holder=_servletHandler.addServletWithMapping(servlet, path+"/*");
181
182 if (_parameters!=null)
183 holder.setInitParameters(_parameters);
184
185 try {holder.start();}
186 catch (Exception e)
187 {
188 LOG.debug(e);
189 throw new UnavailableException(e.toString());
190 }
191
192
193 if (!_nonContextServlets)
194 {
195 Object s=holder.getServlet();
196
197 if (_contextHandler.getClassLoader()!=
198 s.getClass().getClassLoader())
199 {
200 try
201 {
202 holder.stop();
203 }
204 catch (Exception e)
205 {
206 LOG.ignore(e);
207 }
208
209 LOG.warn("Dynamic servlet "+s+
210 " not loaded from context "+
211 request.getContextPath());
212 throw new UnavailableException("Not in context");
213 }
214 }
215
216 if (_verbose && LOG.isDebugEnabled())
217 LOG.debug("Dynamic load '"+servlet+"' at "+path);
218 }
219 }
220 }
221
222 if (holder!=null)
223 {
224 final Request baseRequest=(request instanceof Request)?((Request)request):HttpConnection.getCurrentConnection().getRequest();
225 holder.handle(baseRequest,
226 new InvokedRequest(request,included,servlet,servlet_path,path_info),
227 response);
228 }
229 else
230 {
231 LOG.info("Can't find holder for servlet: "+servlet);
232 response.sendError(404);
233 }
234
235
236 }
237
238
239 class InvokedRequest extends HttpServletRequestWrapper
240 {
241 String _servletPath;
242 String _pathInfo;
243 boolean _included;
244
245
246 InvokedRequest(HttpServletRequest request,
247 boolean included,
248 String name,
249 String servletPath,
250 String pathInfo)
251 {
252 super(request);
253 _included=included;
254 _servletPath=URIUtil.addPaths(servletPath,name);
255 _pathInfo=pathInfo.substring(name.length()+1);
256 if (_pathInfo.length()==0)
257 _pathInfo=null;
258 }
259
260
261 public String getServletPath()
262 {
263 if (_included)
264 return super.getServletPath();
265 return _servletPath;
266 }
267
268
269 public String getPathInfo()
270 {
271 if (_included)
272 return super.getPathInfo();
273 return _pathInfo;
274 }
275
276
277 public Object getAttribute(String name)
278 {
279 if (_included)
280 {
281 if (name.equals(Dispatcher.INCLUDE_REQUEST_URI))
282 return URIUtil.addPaths(URIUtil.addPaths(getContextPath(),_servletPath),_pathInfo);
283 if (name.equals(Dispatcher.INCLUDE_PATH_INFO))
284 return _pathInfo;
285 if (name.equals(Dispatcher.INCLUDE_SERVLET_PATH))
286 return _servletPath;
287 }
288 return super.getAttribute(name);
289 }
290 }
291
292
293 private ServletHolder getHolder(ServletHolder[] holders, String servlet)
294 {
295 if (holders == null)
296 return null;
297
298 ServletHolder holder = null;
299 for (int i=0; holder==null && i<holders.length; i++)
300 {
301 if (holders[i].getName().equals(servlet))
302 {
303 holder = holders[i];
304 }
305 }
306 return holder;
307 }
308 }