1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.server.handler;
15
16 import java.io.IOException;
17 import java.io.OutputStream;
18 import java.net.MalformedURLException;
19
20 import javax.servlet.ServletException;
21 import javax.servlet.http.HttpServletRequest;
22 import javax.servlet.http.HttpServletResponse;
23
24 import org.eclipse.jetty.http.HttpFields;
25 import org.eclipse.jetty.http.HttpHeaders;
26 import org.eclipse.jetty.http.HttpMethods;
27 import org.eclipse.jetty.http.HttpStatus;
28 import org.eclipse.jetty.http.MimeTypes;
29 import org.eclipse.jetty.io.Buffer;
30 import org.eclipse.jetty.io.ByteArrayBuffer;
31 import org.eclipse.jetty.io.WriterOutputStream;
32 import org.eclipse.jetty.server.HttpConnection;
33 import org.eclipse.jetty.server.Request;
34 import org.eclipse.jetty.server.Response;
35 import org.eclipse.jetty.server.handler.ContextHandler.Context;
36 import org.eclipse.jetty.util.URIUtil;
37 import org.eclipse.jetty.util.log.Log;
38 import org.eclipse.jetty.util.resource.FileResource;
39 import org.eclipse.jetty.util.resource.Resource;
40
41
42
43
44
45
46
47
48
49
50
51
52 public class ResourceHandler extends AbstractHandler
53 {
54 ContextHandler _context;
55 Resource _baseResource;
56 Resource _defaultStylesheet;
57 Resource _stylesheet;
58 String[] _welcomeFiles={"index.html"};
59 MimeTypes _mimeTypes = new MimeTypes();
60 ByteArrayBuffer _cacheControl;
61 boolean _aliases;
62 boolean _directory;
63
64
65 public ResourceHandler()
66 {
67
68 }
69
70
71 public MimeTypes getMimeTypes()
72 {
73 return _mimeTypes;
74 }
75
76
77 public void setMimeTypes(MimeTypes mimeTypes)
78 {
79 _mimeTypes = mimeTypes;
80 }
81
82
83
84
85
86 public boolean isAliases()
87 {
88 return _aliases;
89 }
90
91
92
93
94
95
96
97
98
99 public void setAliases(boolean aliases)
100 {
101 _aliases = aliases;
102 }
103
104
105
106
107
108 public boolean isDirectoriesListed()
109 {
110 return _directory;
111 }
112
113
114
115
116
117 public void setDirectoriesListed(boolean directory)
118 {
119 _directory = directory;
120 }
121
122
123 @Override
124 public void doStart()
125 throws Exception
126 {
127 Context scontext = ContextHandler.getCurrentContext();
128 _context = (scontext==null?null:scontext.getContextHandler());
129
130 if (_context!=null)
131 _aliases=_context.isAliases();
132
133 if (!_aliases && !FileResource.getCheckAliases())
134 throw new IllegalStateException("Alias checking disabled");
135
136 super.doStart();
137 }
138
139
140
141
142
143 public Resource getBaseResource()
144 {
145 if (_baseResource==null)
146 return null;
147 return _baseResource;
148 }
149
150
151
152
153
154 public String getResourceBase()
155 {
156 if (_baseResource==null)
157 return null;
158 return _baseResource.toString();
159 }
160
161
162
163
164
165
166 public void setBaseResource(Resource base)
167 {
168 _baseResource=base;
169 }
170
171
172
173
174
175 public void setResourceBase(String resourceBase)
176 {
177 try
178 {
179 setBaseResource(Resource.newResource(resourceBase));
180 }
181 catch (Exception e)
182 {
183 Log.warn(e.toString());
184 Log.debug(e);
185 throw new IllegalArgumentException(resourceBase);
186 }
187 }
188
189
190
191
192
193 public Resource getStylesheet()
194 {
195 if(_stylesheet != null)
196 {
197 return _stylesheet;
198 }
199 else
200 {
201 if(_defaultStylesheet == null)
202 {
203 try
204 {
205 _defaultStylesheet = Resource.newResource(this.getClass().getResource("/jetty-default.css"));
206 }
207 catch(IOException e)
208 {
209 Log.warn(e.toString());
210 Log.debug(e);
211 }
212 }
213 return _defaultStylesheet;
214 }
215 }
216
217
218
219
220
221 public void setStylesheet(String stylesheet)
222 {
223 try
224 {
225 _stylesheet = Resource.newResource(stylesheet);
226 if(!_stylesheet.exists())
227 {
228 Log.warn("unable to find custom stylesheet: " + stylesheet);
229 _stylesheet = null;
230 }
231 }
232 catch(Exception e)
233 {
234 Log.warn(e.toString());
235 Log.debug(e);
236 throw new IllegalArgumentException(stylesheet.toString());
237 }
238 }
239
240
241
242
243
244 public String getCacheControl()
245 {
246 return _cacheControl.toString();
247 }
248
249
250
251
252
253 public void setCacheControl(String cacheControl)
254 {
255 _cacheControl=cacheControl==null?null:new ByteArrayBuffer(cacheControl);
256 }
257
258
259
260
261 public Resource getResource(String path) throws MalformedURLException
262 {
263 if (path==null || !path.startsWith("/"))
264 throw new MalformedURLException(path);
265
266 Resource base = _baseResource;
267 if (base==null)
268 {
269 if (_context==null)
270 return null;
271 base=_context.getBaseResource();
272 if (base==null)
273 return null;
274 }
275
276 try
277 {
278 path=URIUtil.canonicalPath(path);
279 return base.addPath(path);
280 }
281 catch(Exception e)
282 {
283 Log.ignore(e);
284 }
285
286 return null;
287 }
288
289
290 protected Resource getResource(HttpServletRequest request) throws MalformedURLException
291 {
292 String path_info=request.getPathInfo();
293 if (path_info==null)
294 return null;
295 return getResource(path_info);
296 }
297
298
299
300 public String[] getWelcomeFiles()
301 {
302 return _welcomeFiles;
303 }
304
305
306 public void setWelcomeFiles(String[] welcomeFiles)
307 {
308 _welcomeFiles=welcomeFiles;
309 }
310
311
312 protected Resource getWelcome(Resource directory) throws MalformedURLException, IOException
313 {
314 for (int i=0;i<_welcomeFiles.length;i++)
315 {
316 Resource welcome=directory.addPath(_welcomeFiles[i]);
317 if (welcome.exists() && !welcome.isDirectory())
318 return welcome;
319 }
320
321 return null;
322 }
323
324
325
326
327
328 public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
329 {
330 if (baseRequest.isHandled())
331 return;
332
333 boolean skipContentBody = false;
334 if(!HttpMethods.GET.equals(request.getMethod()))
335 {
336 if(!HttpMethods.HEAD.equals(request.getMethod()))
337 return;
338 skipContentBody = true;
339 }
340
341 Resource resource = getResource(request);
342 if (resource==null || !resource.exists())
343 {
344 if (target.endsWith("/jetty-stylesheet.css"))
345 {
346 response.setContentType("text/css");
347 resource = getStylesheet();
348 }
349 else
350 return;
351 }
352
353 if (!_aliases && resource.getAlias()!=null)
354 {
355 Log.info(resource+" aliased to "+resource.getAlias());
356 return;
357 }
358
359
360 baseRequest.setHandled(true);
361
362 if (resource.isDirectory())
363 {
364 if (!request.getPathInfo().endsWith(URIUtil.SLASH))
365 {
366 response.sendRedirect(response.encodeRedirectURL(URIUtil.addPaths(request.getRequestURI(),URIUtil.SLASH)));
367 return;
368 }
369
370 Resource welcome=getWelcome(resource);
371 if (welcome!=null && welcome.exists())
372 resource=welcome;
373 else
374 {
375 doDirectory(request,response,resource);
376 baseRequest.setHandled(true);
377 return;
378 }
379 }
380
381
382 long last_modified=resource.lastModified();
383 if (last_modified>0)
384 {
385 long if_modified=request.getDateHeader(HttpHeaders.IF_MODIFIED_SINCE);
386 if (if_modified>0 && last_modified/1000<=if_modified/1000)
387 {
388 response.setStatus(HttpStatus.NOT_MODIFIED_304);
389 return;
390 }
391 }
392
393 Buffer mime=_mimeTypes.getMimeByExtension(resource.toString());
394 if (mime==null)
395 mime=_mimeTypes.getMimeByExtension(request.getPathInfo());
396
397
398 doResponseHeaders(response,resource,mime!=null?mime.toString():null);
399 response.setDateHeader(HttpHeaders.LAST_MODIFIED,last_modified);
400 if(skipContentBody)
401 return;
402
403 OutputStream out =null;
404 try {out = response.getOutputStream();}
405 catch(IllegalStateException e) {out = new WriterOutputStream(response.getWriter());}
406
407
408 if (out instanceof HttpConnection.Output)
409 {
410
411 ((HttpConnection.Output)out).sendContent(resource.getInputStream());
412 }
413 else
414 {
415
416 resource.writeTo(out,0,resource.length());
417 }
418 }
419
420
421 protected void doDirectory(HttpServletRequest request,HttpServletResponse response, Resource resource)
422 throws IOException
423 {
424 if (_directory)
425 {
426 String listing = resource.getListHTML(request.getRequestURI(),request.getPathInfo().lastIndexOf("/") > 0);
427 response.setContentType("text/html; charset=UTF-8");
428 response.getWriter().println(listing);
429 }
430 else
431 response.sendError(HttpStatus.FORBIDDEN_403);
432 }
433
434
435
436
437
438
439
440
441
442 protected void doResponseHeaders(HttpServletResponse response, Resource resource, String mimeType)
443 {
444 if (mimeType!=null)
445 response.setContentType(mimeType);
446
447 long length=resource.length();
448
449 if (response instanceof Response)
450 {
451 HttpFields fields = ((Response)response).getHttpFields();
452
453 if (length>0)
454 fields.putLongField(HttpHeaders.CONTENT_LENGTH_BUFFER,length);
455
456 if (_cacheControl!=null)
457 fields.put(HttpHeaders.CACHE_CONTROL_BUFFER,_cacheControl);
458 }
459 else
460 {
461 if (length>0)
462 response.setHeader(HttpHeaders.CONTENT_LENGTH,Long.toString(length));
463
464 if (_cacheControl!=null)
465 response.setHeader(HttpHeaders.CACHE_CONTROL,_cacheControl.toString());
466 }
467
468 }
469 }