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