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 LOG.debug("Adding servlet mapping for named servlet:"+servlet+":"+URIUtil.addPaths(servlet_path,servlet)+"/*");
144 ServletMapping mapping = new ServletMapping();
145 mapping.setServletName(servlet);
146 mapping.setPathSpec(URIUtil.addPaths(servlet_path,servlet)+"/*");
147 _servletHandler.setServletMappings((ServletMapping[])LazyList.addToArray(_servletHandler.getServletMappings(), mapping, ServletMapping.class));
148 }
149 else
150 {
151
152 if (servlet.endsWith(".class"))
153 servlet=servlet.substring(0,servlet.length()-6);
154 if (servlet==null || servlet.length()==0)
155 {
156 response.sendError(404);
157 return;
158 }
159
160 synchronized(_servletHandler)
161 {
162
163 _invokerEntry=_servletHandler.getHolderEntry(servlet_path);
164
165
166 String path=URIUtil.addPaths(servlet_path,servlet);
167 Map.Entry entry = _servletHandler.getHolderEntry(path);
168
169 if (entry!=null && !entry.equals(_invokerEntry))
170 {
171
172 holder=(ServletHolder)entry.getValue();
173 }
174 else
175 {
176
177 LOG.debug("Making new servlet="+servlet+" with path="+path+"/*");
178 holder=_servletHandler.addServletWithMapping(servlet, path+"/*");
179
180 if (_parameters!=null)
181 holder.setInitParameters(_parameters);
182
183 try {holder.start();}
184 catch (Exception e)
185 {
186 LOG.debug(e);
187 throw new UnavailableException(e.toString());
188 }
189
190
191 if (!_nonContextServlets)
192 {
193 Object s=holder.getServlet();
194
195 if (_contextHandler.getClassLoader()!=
196 s.getClass().getClassLoader())
197 {
198 try
199 {
200 holder.stop();
201 }
202 catch (Exception e)
203 {
204 LOG.ignore(e);
205 }
206
207 LOG.warn("Dynamic servlet "+s+
208 " not loaded from context "+
209 request.getContextPath());
210 throw new UnavailableException("Not in context");
211 }
212 }
213
214 if (_verbose)
215 LOG.debug("Dynamic load '"+servlet+"' at "+path);
216 }
217 }
218 }
219
220 if (holder!=null)
221 {
222 final Request baseRequest=(request instanceof Request)?((Request)request):HttpConnection.getCurrentConnection().getRequest();
223 holder.handle(baseRequest,
224 new InvokedRequest(request,included,servlet,servlet_path,path_info),
225 response);
226 }
227 else
228 {
229 LOG.info("Can't find holder for servlet: "+servlet);
230 response.sendError(404);
231 }
232
233
234 }
235
236
237 class InvokedRequest extends HttpServletRequestWrapper
238 {
239 String _servletPath;
240 String _pathInfo;
241 boolean _included;
242
243
244 InvokedRequest(HttpServletRequest request,
245 boolean included,
246 String name,
247 String servletPath,
248 String pathInfo)
249 {
250 super(request);
251 _included=included;
252 _servletPath=URIUtil.addPaths(servletPath,name);
253 _pathInfo=pathInfo.substring(name.length()+1);
254 if (_pathInfo.length()==0)
255 _pathInfo=null;
256 }
257
258
259 public String getServletPath()
260 {
261 if (_included)
262 return super.getServletPath();
263 return _servletPath;
264 }
265
266
267 public String getPathInfo()
268 {
269 if (_included)
270 return super.getPathInfo();
271 return _pathInfo;
272 }
273
274
275 public Object getAttribute(String name)
276 {
277 if (_included)
278 {
279 if (name.equals(Dispatcher.INCLUDE_REQUEST_URI))
280 return URIUtil.addPaths(URIUtil.addPaths(getContextPath(),_servletPath),_pathInfo);
281 if (name.equals(Dispatcher.INCLUDE_PATH_INFO))
282 return _pathInfo;
283 if (name.equals(Dispatcher.INCLUDE_SERVLET_PATH))
284 return _servletPath;
285 }
286 return super.getAttribute(name);
287 }
288 }
289
290
291 private ServletHolder getHolder(ServletHolder[] holders, String servlet)
292 {
293 if (holders == null)
294 return null;
295
296 ServletHolder holder = null;
297 for (int i=0; holder==null && i<holders.length; i++)
298 {
299 if (holders[i].getName().equals(servlet))
300 {
301 holder = holders[i];
302 }
303 }
304 return holder;
305 }
306 }