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