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