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