Mercurial Hosting > luan
comparison src/org/eclipse/jetty/server/handler/ContextHandler.java @ 802:3428c60d7cfc
replace jetty jars with source
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Wed, 07 Sep 2016 21:15:48 -0600 |
parents | |
children | 8e9db0bbf4f9 |
comparison
equal
deleted
inserted
replaced
801:6a21393191c1 | 802:3428c60d7cfc |
---|---|
1 // | |
2 // ======================================================================== | |
3 // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. | |
4 // ------------------------------------------------------------------------ | |
5 // All rights reserved. This program and the accompanying materials | |
6 // are made available under the terms of the Eclipse Public License v1.0 | |
7 // and Apache License v2.0 which accompanies this distribution. | |
8 // | |
9 // The Eclipse Public License is available at | |
10 // http://www.eclipse.org/legal/epl-v10.html | |
11 // | |
12 // The Apache License v2.0 is available at | |
13 // http://www.opensource.org/licenses/apache2.0.php | |
14 // | |
15 // You may elect to redistribute this code under either of these licenses. | |
16 // ======================================================================== | |
17 // | |
18 | |
19 package org.eclipse.jetty.server.handler; | |
20 | |
21 import java.io.File; | |
22 import java.io.IOException; | |
23 import java.io.InputStream; | |
24 import java.net.MalformedURLException; | |
25 import java.net.URL; | |
26 import java.net.URLClassLoader; | |
27 import java.security.AccessController; | |
28 import java.util.ArrayList; | |
29 import java.util.Arrays; | |
30 import java.util.Collections; | |
31 import java.util.Enumeration; | |
32 import java.util.EventListener; | |
33 import java.util.HashMap; | |
34 import java.util.HashSet; | |
35 import java.util.Iterator; | |
36 import java.util.List; | |
37 import java.util.Locale; | |
38 import java.util.Map; | |
39 import java.util.Set; | |
40 import java.util.concurrent.CopyOnWriteArrayList; | |
41 | |
42 import javax.servlet.DispatcherType; | |
43 import javax.servlet.RequestDispatcher; | |
44 import javax.servlet.Servlet; | |
45 import javax.servlet.ServletContext; | |
46 import javax.servlet.ServletContextAttributeEvent; | |
47 import javax.servlet.ServletContextAttributeListener; | |
48 import javax.servlet.ServletContextEvent; | |
49 import javax.servlet.ServletContextListener; | |
50 import javax.servlet.ServletException; | |
51 import javax.servlet.ServletRegistration; | |
52 import javax.servlet.ServletRequestAttributeListener; | |
53 import javax.servlet.ServletRequestEvent; | |
54 import javax.servlet.ServletRequestListener; | |
55 import javax.servlet.SessionCookieConfig; | |
56 import javax.servlet.SessionTrackingMode; | |
57 import javax.servlet.Filter; | |
58 import javax.servlet.FilterRegistration; | |
59 import javax.servlet.FilterRegistration.Dynamic; | |
60 import javax.servlet.descriptor.JspConfigDescriptor; | |
61 import javax.servlet.http.HttpServletRequest; | |
62 import javax.servlet.http.HttpServletResponse; | |
63 | |
64 import org.eclipse.jetty.http.HttpException; | |
65 import org.eclipse.jetty.http.MimeTypes; | |
66 import org.eclipse.jetty.io.Buffer; | |
67 import org.eclipse.jetty.server.AbstractHttpConnection; | |
68 import org.eclipse.jetty.server.Dispatcher; | |
69 import org.eclipse.jetty.server.Handler; | |
70 import org.eclipse.jetty.server.HandlerContainer; | |
71 import org.eclipse.jetty.server.Request; | |
72 import org.eclipse.jetty.server.Server; | |
73 import org.eclipse.jetty.util.Attributes; | |
74 import org.eclipse.jetty.util.AttributesMap; | |
75 import org.eclipse.jetty.util.LazyList; | |
76 import org.eclipse.jetty.util.Loader; | |
77 import org.eclipse.jetty.util.StringUtil; | |
78 import org.eclipse.jetty.util.TypeUtil; | |
79 import org.eclipse.jetty.util.URIUtil; | |
80 import org.eclipse.jetty.util.component.AggregateLifeCycle; | |
81 import org.eclipse.jetty.util.component.Dumpable; | |
82 import org.eclipse.jetty.util.log.Log; | |
83 import org.eclipse.jetty.util.log.Logger; | |
84 import org.eclipse.jetty.util.resource.Resource; | |
85 | |
86 /* ------------------------------------------------------------ */ | |
87 /** | |
88 * ContextHandler. | |
89 * | |
90 * This handler wraps a call to handle by setting the context and servlet path, plus setting the context classloader. | |
91 * | |
92 * <p> | |
93 * If the context init parameter "org.eclipse.jetty.server.context.ManagedAttributes" is set to a comma separated list of names, then they are treated as | |
94 * context attribute names, which if set as attributes are passed to the servers Container so that they may be managed with JMX. | |
95 * <p> | |
96 * The maximum size of a form that can be processed by this context is controlled by the system properties org.eclipse.jetty.server.Request.maxFormKeys | |
97 * and org.eclipse.jetty.server.Request.maxFormContentSize. These can also be configured with {@link #setMaxFormContentSize(int)} and {@link #setMaxFormKeys(int)} | |
98 * | |
99 * @org.apache.xbean.XBean description="Creates a basic HTTP context" | |
100 */ | |
101 public class ContextHandler extends ScopedHandler implements Attributes, Server.Graceful | |
102 { | |
103 private static final Logger LOG = Log.getLogger(ContextHandler.class); | |
104 | |
105 private static final ThreadLocal<Context> __context = new ThreadLocal<Context>(); | |
106 | |
107 /** | |
108 * If a context attribute with this name is set, it is interpreted as a comma separated list of attribute name. Any other context attributes that are set | |
109 * with a name from this list will result in a call to {@link #setManagedAttribute(String, Object)}, which typically initiates the creation of a JMX MBean | |
110 * for the attribute value. | |
111 */ | |
112 public static final String MANAGED_ATTRIBUTES = "org.eclipse.jetty.server.context.ManagedAttributes"; | |
113 | |
114 /* ------------------------------------------------------------ */ | |
115 /** | |
116 * Get the current ServletContext implementation. | |
117 * | |
118 * @return ServletContext implementation | |
119 */ | |
120 public static Context getCurrentContext() | |
121 { | |
122 return __context.get(); | |
123 } | |
124 | |
125 protected Context _scontext; | |
126 | |
127 private final AttributesMap _attributes; | |
128 private final AttributesMap _contextAttributes; | |
129 private final Map<String, String> _initParams; | |
130 private ClassLoader _classLoader; | |
131 private String _contextPath = "/"; | |
132 private String _displayName; | |
133 private Resource _baseResource; | |
134 private MimeTypes _mimeTypes; | |
135 private Map<String, String> _localeEncodingMap; | |
136 private String[] _welcomeFiles; | |
137 private ErrorHandler _errorHandler; | |
138 private String[] _vhosts; | |
139 private Set<String> _connectors; | |
140 private EventListener[] _eventListeners; | |
141 private Logger _logger; | |
142 private boolean _allowNullPathInfo; | |
143 private int _maxFormKeys = Integer.getInteger("org.eclipse.jetty.server.Request.maxFormKeys",-1).intValue(); | |
144 private int _maxFormContentSize = Integer.getInteger("org.eclipse.jetty.server.Request.maxFormContentSize",-1).intValue(); | |
145 private boolean _compactPath = false; | |
146 private boolean _aliasesAllowed = false; | |
147 | |
148 private Object _contextListeners; | |
149 private Object _contextAttributeListeners; | |
150 private Object _requestListeners; | |
151 private Object _requestAttributeListeners; | |
152 private Object _durableListeners; | |
153 private Map<String, Object> _managedAttributes; | |
154 private String[] _protectedTargets; | |
155 private final CopyOnWriteArrayList<AliasCheck> _aliasChecks = new CopyOnWriteArrayList<ContextHandler.AliasCheck>(); | |
156 | |
157 private boolean _shutdown = false; | |
158 private boolean _available = true; | |
159 private volatile int _availability; // 0=STOPPED, 1=AVAILABLE, 2=SHUTDOWN, 3=UNAVAILABLE | |
160 | |
161 private final static int __STOPPED = 0, __AVAILABLE = 1, __SHUTDOWN = 2, __UNAVAILABLE = 3; | |
162 | |
163 /* ------------------------------------------------------------ */ | |
164 /** | |
165 * | |
166 */ | |
167 public ContextHandler() | |
168 { | |
169 super(); | |
170 _scontext = new Context(); | |
171 _attributes = new AttributesMap(); | |
172 _contextAttributes = new AttributesMap(); | |
173 _initParams = new HashMap<String, String>(); | |
174 addAliasCheck(new ApproveNonExistentDirectoryAliases()); | |
175 } | |
176 | |
177 /* ------------------------------------------------------------ */ | |
178 /** | |
179 * | |
180 */ | |
181 protected ContextHandler(Context context) | |
182 { | |
183 super(); | |
184 _scontext = context; | |
185 _attributes = new AttributesMap(); | |
186 _contextAttributes = new AttributesMap(); | |
187 _initParams = new HashMap<String, String>(); | |
188 addAliasCheck(new ApproveNonExistentDirectoryAliases()); | |
189 } | |
190 | |
191 /* ------------------------------------------------------------ */ | |
192 /** | |
193 * | |
194 */ | |
195 public ContextHandler(String contextPath) | |
196 { | |
197 this(); | |
198 setContextPath(contextPath); | |
199 } | |
200 | |
201 /* ------------------------------------------------------------ */ | |
202 /** | |
203 * | |
204 */ | |
205 public ContextHandler(HandlerContainer parent, String contextPath) | |
206 { | |
207 this(); | |
208 setContextPath(contextPath); | |
209 if (parent instanceof HandlerWrapper) | |
210 ((HandlerWrapper)parent).setHandler(this); | |
211 else if (parent instanceof HandlerCollection) | |
212 ((HandlerCollection)parent).addHandler(this); | |
213 } | |
214 | |
215 /* ------------------------------------------------------------ */ | |
216 @Override | |
217 public void dump(Appendable out, String indent) throws IOException | |
218 { | |
219 dumpThis(out); | |
220 dump(out,indent,Collections.singletonList(new CLDump(getClassLoader())),TypeUtil.asList(getHandlers()),getBeans(),_initParams.entrySet(), | |
221 _attributes.getAttributeEntrySet(),_contextAttributes.getAttributeEntrySet()); | |
222 } | |
223 | |
224 /* ------------------------------------------------------------ */ | |
225 public Context getServletContext() | |
226 { | |
227 return _scontext; | |
228 } | |
229 | |
230 /* ------------------------------------------------------------ */ | |
231 /** | |
232 * @return the allowNullPathInfo true if /context is not redirected to /context/ | |
233 */ | |
234 public boolean getAllowNullPathInfo() | |
235 { | |
236 return _allowNullPathInfo; | |
237 } | |
238 | |
239 /* ------------------------------------------------------------ */ | |
240 /** | |
241 * @param allowNullPathInfo | |
242 * true if /context is not redirected to /context/ | |
243 */ | |
244 public void setAllowNullPathInfo(boolean allowNullPathInfo) | |
245 { | |
246 _allowNullPathInfo = allowNullPathInfo; | |
247 } | |
248 | |
249 /* ------------------------------------------------------------ */ | |
250 @Override | |
251 public void setServer(Server server) | |
252 { | |
253 if (_errorHandler != null) | |
254 { | |
255 Server old_server = getServer(); | |
256 if (old_server != null && old_server != server) | |
257 old_server.getContainer().update(this,_errorHandler,null,"error",true); | |
258 super.setServer(server); | |
259 if (server != null && server != old_server) | |
260 server.getContainer().update(this,null,_errorHandler,"error",true); | |
261 _errorHandler.setServer(server); | |
262 } | |
263 else | |
264 super.setServer(server); | |
265 } | |
266 | |
267 /* ------------------------------------------------------------ */ | |
268 /** | |
269 * Set the virtual hosts for the context. Only requests that have a matching host header or fully qualified URL will be passed to that context with a | |
270 * virtual host name. A context with no virtual host names or a null virtual host name is available to all requests that are not served by a context with a | |
271 * matching virtual host name. | |
272 * | |
273 * @param vhosts | |
274 * Array of virtual hosts that this context responds to. A null host name or null/empty array means any hostname is acceptable. Host names may be | |
275 * String representation of IP addresses. Host names may start with '*.' to wildcard one level of names. | |
276 */ | |
277 public void setVirtualHosts(String[] vhosts) | |
278 { | |
279 if (vhosts == null) | |
280 { | |
281 _vhosts = vhosts; | |
282 } | |
283 else | |
284 { | |
285 _vhosts = new String[vhosts.length]; | |
286 for (int i = 0; i < vhosts.length; i++) | |
287 _vhosts[i] = normalizeHostname(vhosts[i]); | |
288 } | |
289 } | |
290 | |
291 /* ------------------------------------------------------------ */ | |
292 /** Either set virtual hosts or add to an existing set of virtual hosts. | |
293 * | |
294 * @param virtualHosts | |
295 * Array of virtual hosts that this context responds to. A null host name or null/empty array means any hostname is acceptable. Host names may be | |
296 * String representation of IP addresses. Host names may start with '*.' to wildcard one level of names. | |
297 */ | |
298 public void addVirtualHosts(String[] virtualHosts) | |
299 { | |
300 if (virtualHosts == null) // since this is add, we don't null the old ones | |
301 { | |
302 return; | |
303 } | |
304 else | |
305 { | |
306 List<String> currentVirtualHosts = null; | |
307 if (_vhosts != null) | |
308 { | |
309 currentVirtualHosts = new ArrayList<String>(Arrays.asList(_vhosts)); | |
310 } | |
311 else | |
312 { | |
313 currentVirtualHosts = new ArrayList<String>(); | |
314 } | |
315 | |
316 for (int i = 0; i < virtualHosts.length; i++) | |
317 { | |
318 String normVhost = normalizeHostname(virtualHosts[i]); | |
319 if (!currentVirtualHosts.contains(normVhost)) | |
320 { | |
321 currentVirtualHosts.add(normVhost); | |
322 } | |
323 } | |
324 _vhosts = currentVirtualHosts.toArray(new String[0]); | |
325 } | |
326 } | |
327 | |
328 /* ------------------------------------------------------------ */ | |
329 /** | |
330 * Removes an array of virtual host entries, if this removes all entries the _vhosts will be set to null | |
331 * | |
332 * @param virtualHosts | |
333 * Array of virtual hosts that this context responds to. A null host name or null/empty array means any hostname is acceptable. Host names may be | |
334 * String representation of IP addresses. Host names may start with '*.' to wildcard one level of names. | |
335 */ | |
336 public void removeVirtualHosts(String[] virtualHosts) | |
337 { | |
338 if (virtualHosts == null) | |
339 { | |
340 return; // do nothing | |
341 } | |
342 else if ( _vhosts == null || _vhosts.length == 0) | |
343 { | |
344 return; // do nothing | |
345 } | |
346 else | |
347 { | |
348 List<String> existingVirtualHosts = new ArrayList<String>(Arrays.asList(_vhosts)); | |
349 | |
350 for (int i = 0; i < virtualHosts.length; i++) | |
351 { | |
352 String toRemoveVirtualHost = normalizeHostname(virtualHosts[i]); | |
353 if (existingVirtualHosts.contains(toRemoveVirtualHost)) | |
354 { | |
355 existingVirtualHosts.remove(toRemoveVirtualHost); | |
356 } | |
357 } | |
358 | |
359 if (existingVirtualHosts.isEmpty()) | |
360 { | |
361 _vhosts = null; // if we ended up removing them all, just null out _vhosts | |
362 } | |
363 else | |
364 { | |
365 _vhosts = existingVirtualHosts.toArray(new String[0]); | |
366 } | |
367 } | |
368 } | |
369 | |
370 /* ------------------------------------------------------------ */ | |
371 /** | |
372 * Get the virtual hosts for the context. Only requests that have a matching host header or fully qualified URL will be passed to that context with a | |
373 * virtual host name. A context with no virtual host names or a null virtual host name is available to all requests that are not served by a context with a | |
374 * matching virtual host name. | |
375 * | |
376 * @return Array of virtual hosts that this context responds to. A null host name or empty array means any hostname is acceptable. Host names may be String | |
377 * representation of IP addresses. Host names may start with '*.' to wildcard one level of names. | |
378 */ | |
379 public String[] getVirtualHosts() | |
380 { | |
381 return _vhosts; | |
382 } | |
383 | |
384 /* ------------------------------------------------------------ */ | |
385 /** | |
386 * @return an array of connector names that this context will accept a request from. | |
387 */ | |
388 public String[] getConnectorNames() | |
389 { | |
390 if (_connectors == null || _connectors.size() == 0) | |
391 return null; | |
392 | |
393 return _connectors.toArray(new String[_connectors.size()]); | |
394 } | |
395 | |
396 /* ------------------------------------------------------------ */ | |
397 /** | |
398 * Set the names of accepted connectors. | |
399 * | |
400 * Names are either "host:port" or a specific configured name for a connector. | |
401 * | |
402 * @param connectors | |
403 * If non null, an array of connector names that this context will accept a request from. | |
404 */ | |
405 public void setConnectorNames(String[] connectors) | |
406 { | |
407 if (connectors == null || connectors.length == 0) | |
408 _connectors = null; | |
409 else | |
410 _connectors = new HashSet<String>(Arrays.asList(connectors)); | |
411 } | |
412 | |
413 /* ------------------------------------------------------------ */ | |
414 /* | |
415 * @see javax.servlet.ServletContext#getAttribute(java.lang.String) | |
416 */ | |
417 public Object getAttribute(String name) | |
418 { | |
419 return _attributes.getAttribute(name); | |
420 } | |
421 | |
422 /* ------------------------------------------------------------ */ | |
423 /* | |
424 * @see javax.servlet.ServletContext#getAttributeNames() | |
425 */ | |
426 @SuppressWarnings("unchecked") | |
427 public Enumeration getAttributeNames() | |
428 { | |
429 return AttributesMap.getAttributeNamesCopy(_attributes); | |
430 } | |
431 | |
432 /* ------------------------------------------------------------ */ | |
433 /** | |
434 * @return Returns the attributes. | |
435 */ | |
436 public Attributes getAttributes() | |
437 { | |
438 return _attributes; | |
439 } | |
440 | |
441 /* ------------------------------------------------------------ */ | |
442 /** | |
443 * @return Returns the classLoader. | |
444 */ | |
445 public ClassLoader getClassLoader() | |
446 { | |
447 return _classLoader; | |
448 } | |
449 | |
450 /* ------------------------------------------------------------ */ | |
451 /** | |
452 * Make best effort to extract a file classpath from the context classloader | |
453 * | |
454 * @return Returns the classLoader. | |
455 */ | |
456 public String getClassPath() | |
457 { | |
458 if (_classLoader == null || !(_classLoader instanceof URLClassLoader)) | |
459 return null; | |
460 URLClassLoader loader = (URLClassLoader)_classLoader; | |
461 URL[] urls = loader.getURLs(); | |
462 StringBuilder classpath = new StringBuilder(); | |
463 for (int i = 0; i < urls.length; i++) | |
464 { | |
465 try | |
466 { | |
467 Resource resource = newResource(urls[i]); | |
468 File file = resource.getFile(); | |
469 if (file != null && file.exists()) | |
470 { | |
471 if (classpath.length() > 0) | |
472 classpath.append(File.pathSeparatorChar); | |
473 classpath.append(file.getAbsolutePath()); | |
474 } | |
475 } | |
476 catch (IOException e) | |
477 { | |
478 LOG.debug(e); | |
479 } | |
480 } | |
481 if (classpath.length() == 0) | |
482 return null; | |
483 return classpath.toString(); | |
484 } | |
485 | |
486 /* ------------------------------------------------------------ */ | |
487 /** | |
488 * @return Returns the _contextPath. | |
489 */ | |
490 public String getContextPath() | |
491 { | |
492 return _contextPath; | |
493 } | |
494 | |
495 /* ------------------------------------------------------------ */ | |
496 /* | |
497 * @see javax.servlet.ServletContext#getInitParameter(java.lang.String) | |
498 */ | |
499 public String getInitParameter(String name) | |
500 { | |
501 return _initParams.get(name); | |
502 } | |
503 | |
504 /* ------------------------------------------------------------ */ | |
505 /* | |
506 */ | |
507 public String setInitParameter(String name, String value) | |
508 { | |
509 return _initParams.put(name,value); | |
510 } | |
511 | |
512 /* ------------------------------------------------------------ */ | |
513 /* | |
514 * @see javax.servlet.ServletContext#getInitParameterNames() | |
515 */ | |
516 @SuppressWarnings("rawtypes") | |
517 public Enumeration getInitParameterNames() | |
518 { | |
519 return Collections.enumeration(_initParams.keySet()); | |
520 } | |
521 | |
522 /* ------------------------------------------------------------ */ | |
523 /** | |
524 * @return Returns the initParams. | |
525 */ | |
526 public Map<String, String> getInitParams() | |
527 { | |
528 return _initParams; | |
529 } | |
530 | |
531 /* ------------------------------------------------------------ */ | |
532 /* | |
533 * @see javax.servlet.ServletContext#getServletContextName() | |
534 */ | |
535 public String getDisplayName() | |
536 { | |
537 return _displayName; | |
538 } | |
539 | |
540 /* ------------------------------------------------------------ */ | |
541 public EventListener[] getEventListeners() | |
542 { | |
543 return _eventListeners; | |
544 } | |
545 | |
546 /* ------------------------------------------------------------ */ | |
547 /** | |
548 * Set the context event listeners. | |
549 * | |
550 * @param eventListeners | |
551 * the event listeners | |
552 * @see ServletContextListener | |
553 * @see ServletContextAttributeListener | |
554 * @see ServletRequestListener | |
555 * @see ServletRequestAttributeListener | |
556 */ | |
557 public void setEventListeners(EventListener[] eventListeners) | |
558 { | |
559 _contextListeners = null; | |
560 _contextAttributeListeners = null; | |
561 _requestListeners = null; | |
562 _requestAttributeListeners = null; | |
563 | |
564 _eventListeners = eventListeners; | |
565 | |
566 for (int i = 0; eventListeners != null && i < eventListeners.length; i++) | |
567 { | |
568 EventListener listener = _eventListeners[i]; | |
569 | |
570 if (listener instanceof ServletContextListener) | |
571 _contextListeners = LazyList.add(_contextListeners,listener); | |
572 | |
573 if (listener instanceof ServletContextAttributeListener) | |
574 _contextAttributeListeners = LazyList.add(_contextAttributeListeners,listener); | |
575 | |
576 if (listener instanceof ServletRequestListener) | |
577 _requestListeners = LazyList.add(_requestListeners,listener); | |
578 | |
579 if (listener instanceof ServletRequestAttributeListener) | |
580 _requestAttributeListeners = LazyList.add(_requestAttributeListeners,listener); | |
581 } | |
582 } | |
583 | |
584 /* ------------------------------------------------------------ */ | |
585 /** | |
586 * Add a context event listeners. | |
587 * | |
588 * @see ServletContextListener | |
589 * @see ServletContextAttributeListener | |
590 * @see ServletRequestListener | |
591 * @see ServletRequestAttributeListener | |
592 */ | |
593 public void addEventListener(EventListener listener) | |
594 { | |
595 //Only listeners added before the context starts last through a stop/start cycle | |
596 if (!(isStarted() || isStarting())) | |
597 _durableListeners = LazyList.add(_durableListeners, listener); | |
598 | |
599 setEventListeners((EventListener[])LazyList.addToArray(getEventListeners(),listener,EventListener.class)); | |
600 } | |
601 | |
602 | |
603 /** | |
604 * Apply any necessary restrictions on a programmatically added | |
605 * listener. | |
606 * | |
607 * Superclasses should implement. | |
608 * | |
609 * @param listener | |
610 */ | |
611 public void restrictEventListener (EventListener listener) | |
612 { | |
613 } | |
614 | |
615 | |
616 | |
617 /* ------------------------------------------------------------ */ | |
618 /** | |
619 * @return true if this context is accepting new requests | |
620 */ | |
621 public boolean isShutdown() | |
622 { | |
623 synchronized (this) | |
624 { | |
625 return !_shutdown; | |
626 } | |
627 } | |
628 | |
629 /* ------------------------------------------------------------ */ | |
630 /** | |
631 * Set shutdown status. This field allows for graceful shutdown of a context. A started context may be put into non accepting state so that existing | |
632 * requests can complete, but no new requests are accepted. | |
633 * | |
634 * @param shutdown | |
635 * true if this context is (not?) accepting new requests | |
636 */ | |
637 public void setShutdown(boolean shutdown) | |
638 { | |
639 synchronized (this) | |
640 { | |
641 _shutdown = shutdown; | |
642 _availability = isRunning()?(_shutdown?__SHUTDOWN:_available?__AVAILABLE:__UNAVAILABLE):__STOPPED; | |
643 } | |
644 } | |
645 | |
646 /* ------------------------------------------------------------ */ | |
647 /** | |
648 * @return false if this context is unavailable (sends 503) | |
649 */ | |
650 public boolean isAvailable() | |
651 { | |
652 synchronized (this) | |
653 { | |
654 return _available; | |
655 } | |
656 } | |
657 | |
658 /* ------------------------------------------------------------ */ | |
659 /** | |
660 * Set Available status. | |
661 */ | |
662 public void setAvailable(boolean available) | |
663 { | |
664 synchronized (this) | |
665 { | |
666 _available = available; | |
667 _availability = isRunning()?(_shutdown?__SHUTDOWN:_available?__AVAILABLE:__UNAVAILABLE):__STOPPED; | |
668 } | |
669 } | |
670 | |
671 /* ------------------------------------------------------------ */ | |
672 public Logger getLogger() | |
673 { | |
674 return _logger; | |
675 } | |
676 | |
677 /* ------------------------------------------------------------ */ | |
678 public void setLogger(Logger logger) | |
679 { | |
680 _logger = logger; | |
681 } | |
682 | |
683 /* ------------------------------------------------------------ */ | |
684 /* | |
685 * @see org.eclipse.thread.AbstractLifeCycle#doStart() | |
686 */ | |
687 @Override | |
688 protected void doStart() throws Exception | |
689 { | |
690 _availability = __STOPPED; | |
691 | |
692 if (_contextPath == null) | |
693 throw new IllegalStateException("Null contextPath"); | |
694 | |
695 _logger = Log.getLogger(getDisplayName() == null?getContextPath():getDisplayName()); | |
696 ClassLoader old_classloader = null; | |
697 Thread current_thread = null; | |
698 Context old_context = null; | |
699 | |
700 try | |
701 { | |
702 // Set the classloader | |
703 if (_classLoader != null) | |
704 { | |
705 current_thread = Thread.currentThread(); | |
706 old_classloader = current_thread.getContextClassLoader(); | |
707 current_thread.setContextClassLoader(_classLoader); | |
708 } | |
709 | |
710 if (_mimeTypes == null) | |
711 _mimeTypes = new MimeTypes(); | |
712 | |
713 old_context = __context.get(); | |
714 __context.set(_scontext); | |
715 | |
716 // defers the calling of super.doStart() | |
717 startContext(); | |
718 | |
719 synchronized(this) | |
720 { | |
721 _availability = _shutdown?__SHUTDOWN:_available?__AVAILABLE:__UNAVAILABLE; | |
722 } | |
723 } | |
724 finally | |
725 { | |
726 __context.set(old_context); | |
727 | |
728 // reset the classloader | |
729 if (_classLoader != null) | |
730 { | |
731 current_thread.setContextClassLoader(old_classloader); | |
732 } | |
733 | |
734 } | |
735 } | |
736 | |
737 /* ------------------------------------------------------------ */ | |
738 /** | |
739 * Extensible startContext. this method is called from {@link ContextHandler#doStart()} instead of a call to super.doStart(). This allows derived classes to | |
740 * insert additional handling (Eg configuration) before the call to super.doStart by this method will start contained handlers. | |
741 * | |
742 * @see org.eclipse.jetty.server.handler.ContextHandler.Context | |
743 */ | |
744 protected void startContext() throws Exception | |
745 { | |
746 String managedAttributes = _initParams.get(MANAGED_ATTRIBUTES); | |
747 if (managedAttributes != null) | |
748 { | |
749 _managedAttributes = new HashMap<String, Object>(); | |
750 String[] attributes = managedAttributes.split(","); | |
751 for (String attribute : attributes) | |
752 _managedAttributes.put(attribute,null); | |
753 | |
754 Enumeration e = _scontext.getAttributeNames(); | |
755 while (e.hasMoreElements()) | |
756 { | |
757 String name = (String)e.nextElement(); | |
758 Object value = _scontext.getAttribute(name); | |
759 checkManagedAttribute(name,value); | |
760 } | |
761 } | |
762 | |
763 super.doStart(); | |
764 | |
765 if (_errorHandler != null) | |
766 _errorHandler.start(); | |
767 | |
768 // Context listeners | |
769 if (_contextListeners != null) | |
770 { | |
771 ServletContextEvent event = new ServletContextEvent(_scontext); | |
772 for (int i = 0; i < LazyList.size(_contextListeners); i++) | |
773 { | |
774 callContextInitialized(((ServletContextListener)LazyList.get(_contextListeners, i)), event); | |
775 } | |
776 } | |
777 } | |
778 | |
779 /* ------------------------------------------------------------ */ | |
780 public void callContextInitialized (ServletContextListener l, ServletContextEvent e) | |
781 { | |
782 l.contextInitialized(e); | |
783 } | |
784 | |
785 /* ------------------------------------------------------------ */ | |
786 public void callContextDestroyed (ServletContextListener l, ServletContextEvent e) | |
787 { | |
788 l.contextDestroyed(e); | |
789 } | |
790 | |
791 /* ------------------------------------------------------------ */ | |
792 /* | |
793 * @see org.eclipse.thread.AbstractLifeCycle#doStop() | |
794 */ | |
795 @Override | |
796 protected void doStop() throws Exception | |
797 { | |
798 _availability = __STOPPED; | |
799 | |
800 ClassLoader old_classloader = null; | |
801 Thread current_thread = null; | |
802 | |
803 Context old_context = __context.get(); | |
804 __context.set(_scontext); | |
805 try | |
806 { | |
807 // Set the classloader | |
808 if (_classLoader != null) | |
809 { | |
810 current_thread = Thread.currentThread(); | |
811 old_classloader = current_thread.getContextClassLoader(); | |
812 current_thread.setContextClassLoader(_classLoader); | |
813 } | |
814 | |
815 super.doStop(); | |
816 | |
817 // Context listeners | |
818 if (_contextListeners != null) | |
819 { | |
820 ServletContextEvent event = new ServletContextEvent(_scontext); | |
821 for (int i = LazyList.size(_contextListeners); i-- > 0;) | |
822 { | |
823 ((ServletContextListener)LazyList.get(_contextListeners,i)).contextDestroyed(event); | |
824 } | |
825 } | |
826 | |
827 //remove all non-durable listeners | |
828 setEventListeners((EventListener[])LazyList.toArray(_durableListeners, EventListener.class)); | |
829 _durableListeners = null; | |
830 | |
831 if (_errorHandler != null) | |
832 _errorHandler.stop(); | |
833 | |
834 Enumeration e = _scontext.getAttributeNames(); | |
835 while (e.hasMoreElements()) | |
836 { | |
837 String name = (String)e.nextElement(); | |
838 checkManagedAttribute(name,null); | |
839 } | |
840 } | |
841 finally | |
842 { | |
843 LOG.info("stopped {}",this); | |
844 __context.set(old_context); | |
845 // reset the classloader | |
846 if (_classLoader != null) | |
847 current_thread.setContextClassLoader(old_classloader); | |
848 } | |
849 | |
850 _contextAttributes.clearAttributes(); | |
851 } | |
852 | |
853 /* ------------------------------------------------------------ */ | |
854 /* | |
855 * @see org.eclipse.jetty.server.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse) | |
856 */ | |
857 public boolean checkContext(final String target, final Request baseRequest, final HttpServletResponse response) throws IOException, ServletException | |
858 { | |
859 DispatcherType dispatch = baseRequest.getDispatcherType(); | |
860 | |
861 switch (_availability) | |
862 { | |
863 case __STOPPED: | |
864 case __SHUTDOWN: | |
865 return false; | |
866 case __UNAVAILABLE: | |
867 baseRequest.setHandled(true); | |
868 response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE); | |
869 return false; | |
870 default: | |
871 if ((DispatcherType.REQUEST.equals(dispatch) && baseRequest.isHandled())) | |
872 return false; | |
873 } | |
874 | |
875 // Check the vhosts | |
876 if (_vhosts != null && _vhosts.length > 0) | |
877 { | |
878 String vhost = normalizeHostname(baseRequest.getServerName()); | |
879 | |
880 boolean match = false; | |
881 | |
882 // TODO non-linear lookup | |
883 for (int i = 0; !match && i < _vhosts.length; i++) | |
884 { | |
885 String contextVhost = _vhosts[i]; | |
886 if (contextVhost == null) | |
887 continue; | |
888 if (contextVhost.startsWith("*.")) | |
889 { | |
890 // wildcard only at the beginning, and only for one additional subdomain level | |
891 match = contextVhost.regionMatches(true,2,vhost,vhost.indexOf(".") + 1,contextVhost.length() - 2); | |
892 } | |
893 else | |
894 match = contextVhost.equalsIgnoreCase(vhost); | |
895 } | |
896 if (!match) | |
897 return false; | |
898 } | |
899 | |
900 // Check the connector | |
901 if (_connectors != null && _connectors.size() > 0) | |
902 { | |
903 String connector = AbstractHttpConnection.getCurrentConnection().getConnector().getName(); | |
904 if (connector == null || !_connectors.contains(connector)) | |
905 return false; | |
906 } | |
907 | |
908 // Are we not the root context? | |
909 if (_contextPath.length() > 1) | |
910 { | |
911 // reject requests that are not for us | |
912 if (!target.startsWith(_contextPath)) | |
913 return false; | |
914 if (target.length() > _contextPath.length() && target.charAt(_contextPath.length()) != '/') | |
915 return false; | |
916 | |
917 // redirect null path infos | |
918 if (!_allowNullPathInfo && _contextPath.length() == target.length()) | |
919 { | |
920 // context request must end with / | |
921 baseRequest.setHandled(true); | |
922 if (baseRequest.getQueryString() != null) | |
923 response.sendRedirect(URIUtil.addPaths(baseRequest.getRequestURI(),URIUtil.SLASH) + "?" + baseRequest.getQueryString()); | |
924 else | |
925 response.sendRedirect(URIUtil.addPaths(baseRequest.getRequestURI(),URIUtil.SLASH)); | |
926 return false; | |
927 } | |
928 } | |
929 | |
930 return true; | |
931 } | |
932 | |
933 /* ------------------------------------------------------------ */ | |
934 /** | |
935 * @see org.eclipse.jetty.server.handler.ScopedHandler#doScope(java.lang.String, org.eclipse.jetty.server.Request, javax.servlet.http.HttpServletRequest, | |
936 * javax.servlet.http.HttpServletResponse) | |
937 */ | |
938 @Override | |
939 public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException | |
940 { | |
941 if (LOG.isDebugEnabled()) | |
942 LOG.debug("scope {}|{}|{} @ {}",baseRequest.getContextPath(),baseRequest.getServletPath(),baseRequest.getPathInfo(),this); | |
943 | |
944 Context old_context = null; | |
945 String old_context_path = null; | |
946 String old_servlet_path = null; | |
947 String old_path_info = null; | |
948 ClassLoader old_classloader = null; | |
949 Thread current_thread = null; | |
950 String pathInfo = target; | |
951 | |
952 DispatcherType dispatch = baseRequest.getDispatcherType(); | |
953 | |
954 old_context = baseRequest.getContext(); | |
955 | |
956 // Are we already in this context? | |
957 if (old_context != _scontext) | |
958 { | |
959 // check the target. | |
960 if (DispatcherType.REQUEST.equals(dispatch) || DispatcherType.ASYNC.equals(dispatch) || (DispatcherType.ERROR.equals(dispatch) && baseRequest.getAsyncContinuation().isExpired())) | |
961 { | |
962 if (_compactPath) | |
963 target = URIUtil.compactPath(target); | |
964 if (!checkContext(target,baseRequest,response)) | |
965 return; | |
966 | |
967 if (target.length() > _contextPath.length()) | |
968 { | |
969 if (_contextPath.length() > 1) | |
970 target = target.substring(_contextPath.length()); | |
971 pathInfo = target; | |
972 } | |
973 else if (_contextPath.length() == 1) | |
974 { | |
975 target = URIUtil.SLASH; | |
976 pathInfo = URIUtil.SLASH; | |
977 } | |
978 else | |
979 { | |
980 target = URIUtil.SLASH; | |
981 pathInfo = null; | |
982 } | |
983 } | |
984 | |
985 // Set the classloader | |
986 if (_classLoader != null) | |
987 { | |
988 current_thread = Thread.currentThread(); | |
989 old_classloader = current_thread.getContextClassLoader(); | |
990 current_thread.setContextClassLoader(_classLoader); | |
991 } | |
992 } | |
993 | |
994 try | |
995 { | |
996 old_context_path = baseRequest.getContextPath(); | |
997 old_servlet_path = baseRequest.getServletPath(); | |
998 old_path_info = baseRequest.getPathInfo(); | |
999 | |
1000 // Update the paths | |
1001 baseRequest.setContext(_scontext); | |
1002 __context.set(_scontext); | |
1003 if (!DispatcherType.INCLUDE.equals(dispatch) && target.startsWith("/")) | |
1004 { | |
1005 if (_contextPath.length() == 1) | |
1006 baseRequest.setContextPath(""); | |
1007 else | |
1008 baseRequest.setContextPath(_contextPath); | |
1009 baseRequest.setServletPath(null); | |
1010 baseRequest.setPathInfo(pathInfo); | |
1011 } | |
1012 | |
1013 if (LOG.isDebugEnabled()) | |
1014 LOG.debug("context={}|{}|{} @ {}",baseRequest.getContextPath(),baseRequest.getServletPath(), baseRequest.getPathInfo(),this); | |
1015 | |
1016 // start manual inline of nextScope(target,baseRequest,request,response); | |
1017 if (never()) | |
1018 nextScope(target,baseRequest,request,response); | |
1019 else if (_nextScope != null) | |
1020 _nextScope.doScope(target,baseRequest,request,response); | |
1021 else if (_outerScope != null) | |
1022 _outerScope.doHandle(target,baseRequest,request,response); | |
1023 else | |
1024 doHandle(target,baseRequest,request,response); | |
1025 // end manual inline (pathentic attempt to reduce stack depth) | |
1026 } | |
1027 finally | |
1028 { | |
1029 if (old_context != _scontext) | |
1030 { | |
1031 // reset the classloader | |
1032 if (_classLoader != null) | |
1033 { | |
1034 current_thread.setContextClassLoader(old_classloader); | |
1035 } | |
1036 | |
1037 // reset the context and servlet path. | |
1038 baseRequest.setContext(old_context); | |
1039 __context.set(old_context); | |
1040 baseRequest.setContextPath(old_context_path); | |
1041 baseRequest.setServletPath(old_servlet_path); | |
1042 baseRequest.setPathInfo(old_path_info); | |
1043 } | |
1044 } | |
1045 } | |
1046 | |
1047 /* ------------------------------------------------------------ */ | |
1048 /** | |
1049 * @see org.eclipse.jetty.server.handler.ScopedHandler#doHandle(java.lang.String, org.eclipse.jetty.server.Request, javax.servlet.http.HttpServletRequest, | |
1050 * javax.servlet.http.HttpServletResponse) | |
1051 */ | |
1052 @Override | |
1053 public void doHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException | |
1054 { | |
1055 final DispatcherType dispatch = baseRequest.getDispatcherType(); | |
1056 final boolean new_context = baseRequest.takeNewContext(); | |
1057 try | |
1058 { | |
1059 if (new_context) | |
1060 { | |
1061 // Handle the REALLY SILLY request events! | |
1062 if (_requestAttributeListeners != null) | |
1063 { | |
1064 final int s = LazyList.size(_requestAttributeListeners); | |
1065 for (int i = 0; i < s; i++) | |
1066 baseRequest.addEventListener(((EventListener)LazyList.get(_requestAttributeListeners,i))); | |
1067 } | |
1068 | |
1069 if (_requestListeners != null) | |
1070 { | |
1071 final int s = LazyList.size(_requestListeners); | |
1072 final ServletRequestEvent sre = new ServletRequestEvent(_scontext,request); | |
1073 for (int i = 0; i < s; i++) | |
1074 ((ServletRequestListener)LazyList.get(_requestListeners,i)).requestInitialized(sre); | |
1075 } | |
1076 } | |
1077 | |
1078 if (DispatcherType.REQUEST.equals(dispatch) && isProtectedTarget(target)) | |
1079 throw new HttpException(HttpServletResponse.SC_NOT_FOUND); | |
1080 | |
1081 // start manual inline of nextHandle(target,baseRequest,request,response); | |
1082 // noinspection ConstantIfStatement | |
1083 if (never()) | |
1084 nextHandle(target,baseRequest,request,response); | |
1085 else if (_nextScope != null && _nextScope == _handler) | |
1086 _nextScope.doHandle(target,baseRequest,request,response); | |
1087 else if (_handler != null) | |
1088 _handler.handle(target,baseRequest,request,response); | |
1089 // end manual inline | |
1090 } | |
1091 catch (HttpException e) | |
1092 { | |
1093 LOG.debug(e); | |
1094 baseRequest.setHandled(true); | |
1095 response.sendError(e.getStatus(),e.getReason()); | |
1096 } | |
1097 finally | |
1098 { | |
1099 // Handle more REALLY SILLY request events! | |
1100 if (new_context) | |
1101 { | |
1102 if (_requestListeners != null) | |
1103 { | |
1104 final ServletRequestEvent sre = new ServletRequestEvent(_scontext,request); | |
1105 for (int i = LazyList.size(_requestListeners); i-- > 0;) | |
1106 ((ServletRequestListener)LazyList.get(_requestListeners,i)).requestDestroyed(sre); | |
1107 } | |
1108 | |
1109 if (_requestAttributeListeners != null) | |
1110 { | |
1111 for (int i = LazyList.size(_requestAttributeListeners); i-- > 0;) | |
1112 baseRequest.removeEventListener(((EventListener)LazyList.get(_requestAttributeListeners,i))); | |
1113 } | |
1114 } | |
1115 } | |
1116 } | |
1117 | |
1118 /* ------------------------------------------------------------ */ | |
1119 /* | |
1120 * Handle a runnable in this context | |
1121 */ | |
1122 public void handle(Runnable runnable) | |
1123 { | |
1124 ClassLoader old_classloader = null; | |
1125 Thread current_thread = null; | |
1126 Context old_context = null; | |
1127 try | |
1128 { | |
1129 old_context = __context.get(); | |
1130 __context.set(_scontext); | |
1131 | |
1132 // Set the classloader | |
1133 if (_classLoader != null) | |
1134 { | |
1135 current_thread = Thread.currentThread(); | |
1136 old_classloader = current_thread.getContextClassLoader(); | |
1137 current_thread.setContextClassLoader(_classLoader); | |
1138 } | |
1139 | |
1140 runnable.run(); | |
1141 } | |
1142 finally | |
1143 { | |
1144 __context.set(old_context); | |
1145 if (old_classloader != null) | |
1146 { | |
1147 current_thread.setContextClassLoader(old_classloader); | |
1148 } | |
1149 } | |
1150 } | |
1151 | |
1152 /* ------------------------------------------------------------ */ | |
1153 /** | |
1154 * Check the target. Called by {@link #handle(String, Request, HttpServletRequest, HttpServletResponse)} when a target within a context is determined. If | |
1155 * the target is protected, 404 is returned. | |
1156 */ | |
1157 /* ------------------------------------------------------------ */ | |
1158 public boolean isProtectedTarget(String target) | |
1159 { | |
1160 if (target == null || _protectedTargets == null) | |
1161 return false; | |
1162 | |
1163 while (target.startsWith("//")) | |
1164 target=URIUtil.compactPath(target); | |
1165 | |
1166 boolean isProtected = false; | |
1167 int i=0; | |
1168 while (!isProtected && i<_protectedTargets.length) | |
1169 { | |
1170 isProtected = StringUtil.startsWithIgnoreCase(target, _protectedTargets[i++]); | |
1171 } | |
1172 return isProtected; | |
1173 } | |
1174 | |
1175 | |
1176 public void setProtectedTargets (String[] targets) | |
1177 { | |
1178 if (targets == null) | |
1179 { | |
1180 _protectedTargets = null; | |
1181 return; | |
1182 } | |
1183 | |
1184 _protectedTargets = new String[targets.length]; | |
1185 System.arraycopy(targets, 0, _protectedTargets, 0, targets.length); | |
1186 } | |
1187 | |
1188 public String[] getProtectedTargets () | |
1189 { | |
1190 if (_protectedTargets == null) | |
1191 return null; | |
1192 | |
1193 String[] tmp = new String[_protectedTargets.length]; | |
1194 System.arraycopy(_protectedTargets, 0, tmp, 0, _protectedTargets.length); | |
1195 return tmp; | |
1196 } | |
1197 | |
1198 | |
1199 /* ------------------------------------------------------------ */ | |
1200 /* | |
1201 * @see javax.servlet.ServletContext#removeAttribute(java.lang.String) | |
1202 */ | |
1203 public void removeAttribute(String name) | |
1204 { | |
1205 checkManagedAttribute(name,null); | |
1206 _attributes.removeAttribute(name); | |
1207 } | |
1208 | |
1209 /* ------------------------------------------------------------ */ | |
1210 /* | |
1211 * Set a context attribute. Attributes set via this API cannot be overriden by the ServletContext.setAttribute API. Their lifecycle spans the stop/start of | |
1212 * a context. No attribute listener events are triggered by this API. | |
1213 * | |
1214 * @see javax.servlet.ServletContext#setAttribute(java.lang.String, java.lang.Object) | |
1215 */ | |
1216 public void setAttribute(String name, Object value) | |
1217 { | |
1218 checkManagedAttribute(name,value); | |
1219 _attributes.setAttribute(name,value); | |
1220 } | |
1221 | |
1222 /* ------------------------------------------------------------ */ | |
1223 /** | |
1224 * @param attributes | |
1225 * The attributes to set. | |
1226 */ | |
1227 public void setAttributes(Attributes attributes) | |
1228 { | |
1229 _attributes.clearAttributes(); | |
1230 _attributes.addAll(attributes); | |
1231 Enumeration e = _attributes.getAttributeNames(); | |
1232 while (e.hasMoreElements()) | |
1233 { | |
1234 String name = (String)e.nextElement(); | |
1235 checkManagedAttribute(name,attributes.getAttribute(name)); | |
1236 } | |
1237 } | |
1238 | |
1239 /* ------------------------------------------------------------ */ | |
1240 public void clearAttributes() | |
1241 { | |
1242 Enumeration e = _attributes.getAttributeNames(); | |
1243 while (e.hasMoreElements()) | |
1244 { | |
1245 String name = (String)e.nextElement(); | |
1246 checkManagedAttribute(name,null); | |
1247 } | |
1248 _attributes.clearAttributes(); | |
1249 } | |
1250 | |
1251 /* ------------------------------------------------------------ */ | |
1252 public void checkManagedAttribute(String name, Object value) | |
1253 { | |
1254 if (_managedAttributes != null && _managedAttributes.containsKey(name)) | |
1255 { | |
1256 setManagedAttribute(name,value); | |
1257 } | |
1258 } | |
1259 | |
1260 /* ------------------------------------------------------------ */ | |
1261 public void setManagedAttribute(String name, Object value) | |
1262 { | |
1263 Object old = _managedAttributes.put(name,value); | |
1264 getServer().getContainer().update(this,old,value,name,true); | |
1265 } | |
1266 | |
1267 /* ------------------------------------------------------------ */ | |
1268 /** | |
1269 * @param classLoader | |
1270 * The classLoader to set. | |
1271 */ | |
1272 public void setClassLoader(ClassLoader classLoader) | |
1273 { | |
1274 _classLoader = classLoader; | |
1275 } | |
1276 | |
1277 /* ------------------------------------------------------------ */ | |
1278 /** | |
1279 * @param contextPath | |
1280 * The _contextPath to set. | |
1281 */ | |
1282 public void setContextPath(String contextPath) | |
1283 { | |
1284 if (contextPath != null && contextPath.length() > 1 && contextPath.endsWith("/")) | |
1285 throw new IllegalArgumentException("ends with /"); | |
1286 _contextPath = contextPath; | |
1287 | |
1288 if (getServer() != null && (getServer().isStarting() || getServer().isStarted())) | |
1289 { | |
1290 Handler[] contextCollections = getServer().getChildHandlersByClass(ContextHandlerCollection.class); | |
1291 for (int h = 0; contextCollections != null && h < contextCollections.length; h++) | |
1292 ((ContextHandlerCollection)contextCollections[h]).mapContexts(); | |
1293 } | |
1294 } | |
1295 | |
1296 /* ------------------------------------------------------------ */ | |
1297 /** | |
1298 * @param servletContextName | |
1299 * The servletContextName to set. | |
1300 */ | |
1301 public void setDisplayName(String servletContextName) | |
1302 { | |
1303 _displayName = servletContextName; | |
1304 } | |
1305 | |
1306 /* ------------------------------------------------------------ */ | |
1307 /** | |
1308 * @return Returns the resourceBase. | |
1309 */ | |
1310 public Resource getBaseResource() | |
1311 { | |
1312 if (_baseResource == null) | |
1313 return null; | |
1314 return _baseResource; | |
1315 } | |
1316 | |
1317 /* ------------------------------------------------------------ */ | |
1318 /** | |
1319 * @return Returns the base resource as a string. | |
1320 */ | |
1321 public String getResourceBase() | |
1322 { | |
1323 if (_baseResource == null) | |
1324 return null; | |
1325 return _baseResource.toString(); | |
1326 } | |
1327 | |
1328 /* ------------------------------------------------------------ */ | |
1329 /** | |
1330 * @param base | |
1331 * The resourceBase to set. | |
1332 */ | |
1333 public void setBaseResource(Resource base) | |
1334 { | |
1335 _baseResource = base; | |
1336 } | |
1337 | |
1338 /* ------------------------------------------------------------ */ | |
1339 /** | |
1340 * @param resourceBase | |
1341 * The base resource as a string. | |
1342 */ | |
1343 public void setResourceBase(String resourceBase) | |
1344 { | |
1345 try | |
1346 { | |
1347 setBaseResource(newResource(resourceBase)); | |
1348 } | |
1349 catch (Exception e) | |
1350 { | |
1351 LOG.warn(e.toString()); | |
1352 LOG.debug(e); | |
1353 throw new IllegalArgumentException(resourceBase); | |
1354 } | |
1355 } | |
1356 | |
1357 /* ------------------------------------------------------------ */ | |
1358 /** | |
1359 * @return True if aliases are allowed | |
1360 */ | |
1361 public boolean isAliases() | |
1362 { | |
1363 return _aliasesAllowed; | |
1364 } | |
1365 | |
1366 /* ------------------------------------------------------------ */ | |
1367 /** | |
1368 * @param aliases | |
1369 * aliases are allowed | |
1370 */ | |
1371 public void setAliases(boolean aliases) | |
1372 { | |
1373 _aliasesAllowed = aliases; | |
1374 } | |
1375 | |
1376 /* ------------------------------------------------------------ */ | |
1377 /** | |
1378 * @return Returns the mimeTypes. | |
1379 */ | |
1380 public MimeTypes getMimeTypes() | |
1381 { | |
1382 if (_mimeTypes == null) | |
1383 _mimeTypes = new MimeTypes(); | |
1384 return _mimeTypes; | |
1385 } | |
1386 | |
1387 /* ------------------------------------------------------------ */ | |
1388 /** | |
1389 * @param mimeTypes | |
1390 * The mimeTypes to set. | |
1391 */ | |
1392 public void setMimeTypes(MimeTypes mimeTypes) | |
1393 { | |
1394 _mimeTypes = mimeTypes; | |
1395 } | |
1396 | |
1397 /* ------------------------------------------------------------ */ | |
1398 /** | |
1399 */ | |
1400 public void setWelcomeFiles(String[] files) | |
1401 { | |
1402 _welcomeFiles = files; | |
1403 } | |
1404 | |
1405 /* ------------------------------------------------------------ */ | |
1406 /** | |
1407 * @return The names of the files which the server should consider to be welcome files in this context. | |
1408 * @see <a href="http://jcp.org/aboutJava/communityprocess/final/jsr154/index.html">The Servlet Specification</a> | |
1409 * @see #setWelcomeFiles | |
1410 */ | |
1411 public String[] getWelcomeFiles() | |
1412 { | |
1413 return _welcomeFiles; | |
1414 } | |
1415 | |
1416 /* ------------------------------------------------------------ */ | |
1417 /** | |
1418 * @return Returns the errorHandler. | |
1419 */ | |
1420 public ErrorHandler getErrorHandler() | |
1421 { | |
1422 return _errorHandler; | |
1423 } | |
1424 | |
1425 /* ------------------------------------------------------------ */ | |
1426 /** | |
1427 * @param errorHandler | |
1428 * The errorHandler to set. | |
1429 */ | |
1430 public void setErrorHandler(ErrorHandler errorHandler) | |
1431 { | |
1432 if (errorHandler != null) | |
1433 errorHandler.setServer(getServer()); | |
1434 if (getServer() != null) | |
1435 getServer().getContainer().update(this,_errorHandler,errorHandler,"errorHandler",true); | |
1436 _errorHandler = errorHandler; | |
1437 } | |
1438 | |
1439 /* ------------------------------------------------------------ */ | |
1440 public int getMaxFormContentSize() | |
1441 { | |
1442 return _maxFormContentSize; | |
1443 } | |
1444 | |
1445 /* ------------------------------------------------------------ */ | |
1446 /** | |
1447 * Set the maximum size of a form post, to protect against DOS attacks from large forms. | |
1448 * @param maxSize | |
1449 */ | |
1450 public void setMaxFormContentSize(int maxSize) | |
1451 { | |
1452 _maxFormContentSize = maxSize; | |
1453 } | |
1454 | |
1455 /* ------------------------------------------------------------ */ | |
1456 public int getMaxFormKeys() | |
1457 { | |
1458 return _maxFormKeys; | |
1459 } | |
1460 | |
1461 /* ------------------------------------------------------------ */ | |
1462 /** | |
1463 * Set the maximum number of form Keys to protect against DOS attack from crafted hash keys. | |
1464 * @param max | |
1465 */ | |
1466 public void setMaxFormKeys(int max) | |
1467 { | |
1468 _maxFormKeys = max; | |
1469 } | |
1470 | |
1471 /* ------------------------------------------------------------ */ | |
1472 /** | |
1473 * @return True if URLs are compacted to replace multiple '/'s with a single '/' | |
1474 */ | |
1475 public boolean isCompactPath() | |
1476 { | |
1477 return _compactPath; | |
1478 } | |
1479 | |
1480 /* ------------------------------------------------------------ */ | |
1481 /** | |
1482 * @param compactPath | |
1483 * True if URLs are compacted to replace multiple '/'s with a single '/' | |
1484 */ | |
1485 public void setCompactPath(boolean compactPath) | |
1486 { | |
1487 _compactPath = compactPath; | |
1488 } | |
1489 | |
1490 /* ------------------------------------------------------------ */ | |
1491 @Override | |
1492 public String toString() | |
1493 { | |
1494 String[] vhosts = getVirtualHosts(); | |
1495 | |
1496 StringBuilder b = new StringBuilder(); | |
1497 | |
1498 Package pkg = getClass().getPackage(); | |
1499 if (pkg != null) | |
1500 { | |
1501 String p = pkg.getName(); | |
1502 if (p != null && p.length() > 0) | |
1503 { | |
1504 String[] ss = p.split("\\."); | |
1505 for (String s : ss) | |
1506 b.append(s.charAt(0)).append('.'); | |
1507 } | |
1508 } | |
1509 b.append(getClass().getSimpleName()); | |
1510 b.append('{').append(getContextPath()).append(',').append(getBaseResource()); | |
1511 | |
1512 if (vhosts != null && vhosts.length > 0) | |
1513 b.append(',').append(vhosts[0]); | |
1514 b.append('}'); | |
1515 | |
1516 return b.toString(); | |
1517 } | |
1518 | |
1519 /* ------------------------------------------------------------ */ | |
1520 public synchronized Class<?> loadClass(String className) throws ClassNotFoundException | |
1521 { | |
1522 if (className == null) | |
1523 return null; | |
1524 | |
1525 if (_classLoader == null) | |
1526 return Loader.loadClass(this.getClass(),className); | |
1527 | |
1528 return _classLoader.loadClass(className); | |
1529 } | |
1530 | |
1531 /* ------------------------------------------------------------ */ | |
1532 public void addLocaleEncoding(String locale, String encoding) | |
1533 { | |
1534 if (_localeEncodingMap == null) | |
1535 _localeEncodingMap = new HashMap<String, String>(); | |
1536 _localeEncodingMap.put(locale,encoding); | |
1537 } | |
1538 | |
1539 /* ------------------------------------------------------------ */ | |
1540 public String getLocaleEncoding(String locale) | |
1541 { | |
1542 if (_localeEncodingMap == null) | |
1543 return null; | |
1544 String encoding = _localeEncodingMap.get(locale); | |
1545 return encoding; | |
1546 } | |
1547 | |
1548 /* ------------------------------------------------------------ */ | |
1549 /** | |
1550 * Get the character encoding for a locale. The full locale name is first looked up in the map of encodings. If no encoding is found, then the locale | |
1551 * language is looked up. | |
1552 * | |
1553 * @param locale | |
1554 * a <code>Locale</code> value | |
1555 * @return a <code>String</code> representing the character encoding for the locale or null if none found. | |
1556 */ | |
1557 public String getLocaleEncoding(Locale locale) | |
1558 { | |
1559 if (_localeEncodingMap == null) | |
1560 return null; | |
1561 String encoding = _localeEncodingMap.get(locale.toString()); | |
1562 if (encoding == null) | |
1563 encoding = _localeEncodingMap.get(locale.getLanguage()); | |
1564 return encoding; | |
1565 } | |
1566 | |
1567 /* ------------------------------------------------------------ */ | |
1568 /* | |
1569 */ | |
1570 public Resource getResource(String path) throws MalformedURLException | |
1571 { | |
1572 if (path == null || !path.startsWith(URIUtil.SLASH)) | |
1573 throw new MalformedURLException(path); | |
1574 | |
1575 if (_baseResource == null) | |
1576 return null; | |
1577 | |
1578 try | |
1579 { | |
1580 path = URIUtil.canonicalPath(path); | |
1581 Resource resource = _baseResource.addPath(path); | |
1582 | |
1583 if (checkAlias(path,resource)) | |
1584 return resource; | |
1585 return null; | |
1586 } | |
1587 catch (Exception e) | |
1588 { | |
1589 LOG.ignore(e); | |
1590 } | |
1591 | |
1592 return null; | |
1593 } | |
1594 | |
1595 /* ------------------------------------------------------------ */ | |
1596 public boolean checkAlias(String path, Resource resource) | |
1597 { | |
1598 // Is the resource aliased? | |
1599 if (!_aliasesAllowed && resource.getAlias() != null) | |
1600 { | |
1601 if (LOG.isDebugEnabled()) | |
1602 LOG.debug("Aliased resource: " + resource + "~=" + resource.getAlias()); | |
1603 | |
1604 // alias checks | |
1605 for (Iterator<AliasCheck> i=_aliasChecks.iterator();i.hasNext();) | |
1606 { | |
1607 AliasCheck check = i.next(); | |
1608 if (check.check(path,resource)) | |
1609 { | |
1610 if (LOG.isDebugEnabled()) | |
1611 LOG.debug("Aliased resource: " + resource + " approved by " + check); | |
1612 return true; | |
1613 } | |
1614 } | |
1615 return false; | |
1616 } | |
1617 return true; | |
1618 } | |
1619 | |
1620 /* ------------------------------------------------------------ */ | |
1621 /** | |
1622 * Convert URL to Resource wrapper for {@link Resource#newResource(URL)} enables extensions to provide alternate resource implementations. | |
1623 */ | |
1624 public Resource newResource(URL url) throws IOException | |
1625 { | |
1626 return Resource.newResource(url); | |
1627 } | |
1628 | |
1629 /* ------------------------------------------------------------ */ | |
1630 /** | |
1631 * Convert a URL or path to a Resource. The default implementation is a wrapper for {@link Resource#newResource(String)}. | |
1632 * | |
1633 * @param urlOrPath | |
1634 * The URL or path to convert | |
1635 * @return The Resource for the URL/path | |
1636 * @throws IOException | |
1637 * The Resource could not be created. | |
1638 */ | |
1639 public Resource newResource(String urlOrPath) throws IOException | |
1640 { | |
1641 return Resource.newResource(urlOrPath); | |
1642 } | |
1643 | |
1644 /* ------------------------------------------------------------ */ | |
1645 /* | |
1646 */ | |
1647 public Set<String> getResourcePaths(String path) | |
1648 { | |
1649 try | |
1650 { | |
1651 path = URIUtil.canonicalPath(path); | |
1652 Resource resource = getResource(path); | |
1653 | |
1654 if (resource != null && resource.exists()) | |
1655 { | |
1656 if (!path.endsWith(URIUtil.SLASH)) | |
1657 path = path + URIUtil.SLASH; | |
1658 | |
1659 String[] l = resource.list(); | |
1660 if (l != null) | |
1661 { | |
1662 HashSet<String> set = new HashSet<String>(); | |
1663 for (int i = 0; i < l.length; i++) | |
1664 set.add(path + l[i]); | |
1665 return set; | |
1666 } | |
1667 } | |
1668 } | |
1669 catch (Exception e) | |
1670 { | |
1671 LOG.ignore(e); | |
1672 } | |
1673 return Collections.emptySet(); | |
1674 } | |
1675 | |
1676 /* ------------------------------------------------------------ */ | |
1677 private String normalizeHostname(String host) | |
1678 { | |
1679 if (host == null) | |
1680 return null; | |
1681 | |
1682 if (host.endsWith(".")) | |
1683 return host.substring(0,host.length() - 1); | |
1684 | |
1685 return host; | |
1686 } | |
1687 | |
1688 /* ------------------------------------------------------------ */ | |
1689 /** | |
1690 * Add an AliasCheck instance to possibly permit aliased resources | |
1691 * @param check The alias checker | |
1692 */ | |
1693 public void addAliasCheck(AliasCheck check) | |
1694 { | |
1695 _aliasChecks.add(check); | |
1696 } | |
1697 | |
1698 /* ------------------------------------------------------------ */ | |
1699 /** | |
1700 * @return Mutable list of Alias checks | |
1701 */ | |
1702 public List<AliasCheck> getAliasChecks() | |
1703 { | |
1704 return _aliasChecks; | |
1705 } | |
1706 | |
1707 /* ------------------------------------------------------------ */ | |
1708 /** | |
1709 * Context. | |
1710 * <p> | |
1711 * A partial implementation of {@link javax.servlet.ServletContext}. A complete implementation is provided by the derived {@link ContextHandler}. | |
1712 * </p> | |
1713 * | |
1714 * | |
1715 */ | |
1716 public class Context implements ServletContext | |
1717 { | |
1718 protected int _majorVersion = 3; | |
1719 protected int _minorVersion = 0; | |
1720 protected boolean _enabled = true; //whether or not the dynamic API is enabled for callers | |
1721 | |
1722 /* ------------------------------------------------------------ */ | |
1723 protected Context() | |
1724 { | |
1725 } | |
1726 | |
1727 /* ------------------------------------------------------------ */ | |
1728 public ContextHandler getContextHandler() | |
1729 { | |
1730 // TODO reduce visibility of this method | |
1731 return ContextHandler.this; | |
1732 } | |
1733 | |
1734 /* ------------------------------------------------------------ */ | |
1735 /* | |
1736 * @see javax.servlet.ServletContext#getContext(java.lang.String) | |
1737 */ | |
1738 @Override | |
1739 public ServletContext getContext(String uripath) | |
1740 { | |
1741 List<ContextHandler> contexts = new ArrayList<ContextHandler>(); | |
1742 Handler[] handlers = getServer().getChildHandlersByClass(ContextHandler.class); | |
1743 String matched_path = null; | |
1744 | |
1745 for (Handler handler : handlers) | |
1746 { | |
1747 if (handler == null) | |
1748 continue; | |
1749 ContextHandler ch = (ContextHandler)handler; | |
1750 String context_path = ch.getContextPath(); | |
1751 | |
1752 if (uripath.equals(context_path) || (uripath.startsWith(context_path) && uripath.charAt(context_path.length()) == '/') | |
1753 || "/".equals(context_path)) | |
1754 { | |
1755 // look first for vhost matching context only | |
1756 if (getVirtualHosts() != null && getVirtualHosts().length > 0) | |
1757 { | |
1758 if (ch.getVirtualHosts() != null && ch.getVirtualHosts().length > 0) | |
1759 { | |
1760 for (String h1 : getVirtualHosts()) | |
1761 for (String h2 : ch.getVirtualHosts()) | |
1762 if (h1.equals(h2)) | |
1763 { | |
1764 if (matched_path == null || context_path.length() > matched_path.length()) | |
1765 { | |
1766 contexts.clear(); | |
1767 matched_path = context_path; | |
1768 } | |
1769 | |
1770 if (matched_path.equals(context_path)) | |
1771 contexts.add(ch); | |
1772 } | |
1773 } | |
1774 } | |
1775 else | |
1776 { | |
1777 if (matched_path == null || context_path.length() > matched_path.length()) | |
1778 { | |
1779 contexts.clear(); | |
1780 matched_path = context_path; | |
1781 } | |
1782 | |
1783 if (matched_path.equals(context_path)) | |
1784 contexts.add(ch); | |
1785 } | |
1786 } | |
1787 } | |
1788 | |
1789 if (contexts.size() > 0) | |
1790 return contexts.get(0)._scontext; | |
1791 | |
1792 // try again ignoring virtual hosts | |
1793 matched_path = null; | |
1794 for (Handler handler : handlers) | |
1795 { | |
1796 if (handler == null) | |
1797 continue; | |
1798 ContextHandler ch = (ContextHandler)handler; | |
1799 String context_path = ch.getContextPath(); | |
1800 | |
1801 if (uripath.equals(context_path) || (uripath.startsWith(context_path) && uripath.charAt(context_path.length()) == '/') | |
1802 || "/".equals(context_path)) | |
1803 { | |
1804 if (matched_path == null || context_path.length() > matched_path.length()) | |
1805 { | |
1806 contexts.clear(); | |
1807 matched_path = context_path; | |
1808 } | |
1809 | |
1810 if (matched_path.equals(context_path)) | |
1811 contexts.add(ch); | |
1812 } | |
1813 } | |
1814 | |
1815 if (contexts.size() > 0) | |
1816 return contexts.get(0)._scontext; | |
1817 return null; | |
1818 } | |
1819 | |
1820 /* ------------------------------------------------------------ */ | |
1821 /* | |
1822 * @see javax.servlet.ServletContext#getMajorVersion() | |
1823 */ | |
1824 @Override | |
1825 public int getMajorVersion() | |
1826 { | |
1827 return 3; | |
1828 } | |
1829 | |
1830 | |
1831 /* ------------------------------------------------------------ */ | |
1832 /* | |
1833 * @see javax.servlet.ServletContext#getMimeType(java.lang.String) | |
1834 */ | |
1835 @Override | |
1836 public String getMimeType(String file) | |
1837 { | |
1838 if (_mimeTypes == null) | |
1839 return null; | |
1840 Buffer mime = _mimeTypes.getMimeByExtension(file); | |
1841 if (mime != null) | |
1842 return mime.toString(); | |
1843 return null; | |
1844 } | |
1845 | |
1846 /* ------------------------------------------------------------ */ | |
1847 /* | |
1848 * @see javax.servlet.ServletContext#getMinorVersion() | |
1849 */ | |
1850 @Override | |
1851 public int getMinorVersion() | |
1852 { | |
1853 return 0; | |
1854 } | |
1855 | |
1856 /* ------------------------------------------------------------ */ | |
1857 /* | |
1858 * @see javax.servlet.ServletContext#getNamedDispatcher(java.lang.String) | |
1859 */ | |
1860 @Override | |
1861 public RequestDispatcher getNamedDispatcher(String name) | |
1862 { | |
1863 return null; | |
1864 } | |
1865 | |
1866 /* ------------------------------------------------------------ */ | |
1867 /* | |
1868 * @see javax.servlet.ServletContext#getRequestDispatcher(java.lang.String) | |
1869 */ | |
1870 @Override | |
1871 public RequestDispatcher getRequestDispatcher(String uriInContext) | |
1872 { | |
1873 if (uriInContext == null) | |
1874 return null; | |
1875 | |
1876 if (!uriInContext.startsWith("/")) | |
1877 return null; | |
1878 | |
1879 try | |
1880 { | |
1881 String query = null; | |
1882 int q = 0; | |
1883 if ((q = uriInContext.indexOf('?')) > 0) | |
1884 { | |
1885 query = uriInContext.substring(q + 1); | |
1886 uriInContext = uriInContext.substring(0,q); | |
1887 } | |
1888 | |
1889 String pathInContext = URIUtil.canonicalPath(URIUtil.decodePath(uriInContext)); | |
1890 if (pathInContext!=null) | |
1891 { | |
1892 String uri = URIUtil.addPaths(getContextPath(),uriInContext); | |
1893 ContextHandler context = ContextHandler.this; | |
1894 return new Dispatcher(context,uri,pathInContext,query); | |
1895 } | |
1896 } | |
1897 catch (Exception e) | |
1898 { | |
1899 LOG.ignore(e); | |
1900 } | |
1901 return null; | |
1902 } | |
1903 | |
1904 /* ------------------------------------------------------------ */ | |
1905 /* | |
1906 * @see javax.servlet.ServletContext#getRealPath(java.lang.String) | |
1907 */ | |
1908 @Override | |
1909 public String getRealPath(String path) | |
1910 { | |
1911 if (path == null) | |
1912 return null; | |
1913 if (path.length() == 0) | |
1914 path = URIUtil.SLASH; | |
1915 else if (path.charAt(0) != '/') | |
1916 path = URIUtil.SLASH + path; | |
1917 | |
1918 try | |
1919 { | |
1920 Resource resource = ContextHandler.this.getResource(path); | |
1921 if (resource != null) | |
1922 { | |
1923 File file = resource.getFile(); | |
1924 if (file != null) | |
1925 return file.getCanonicalPath(); | |
1926 } | |
1927 } | |
1928 catch (Exception e) | |
1929 { | |
1930 LOG.ignore(e); | |
1931 } | |
1932 | |
1933 return null; | |
1934 } | |
1935 | |
1936 /* ------------------------------------------------------------ */ | |
1937 @Override | |
1938 public URL getResource(String path) throws MalformedURLException | |
1939 { | |
1940 Resource resource = ContextHandler.this.getResource(path); | |
1941 if (resource != null && resource.exists()) | |
1942 return resource.getURL(); | |
1943 return null; | |
1944 } | |
1945 | |
1946 /* ------------------------------------------------------------ */ | |
1947 /* | |
1948 * @see javax.servlet.ServletContext#getResourceAsStream(java.lang.String) | |
1949 */ | |
1950 @Override | |
1951 public InputStream getResourceAsStream(String path) | |
1952 { | |
1953 try | |
1954 { | |
1955 URL url = getResource(path); | |
1956 if (url == null) | |
1957 return null; | |
1958 Resource r = Resource.newResource(url); | |
1959 return r.getInputStream(); | |
1960 } | |
1961 catch (Exception e) | |
1962 { | |
1963 LOG.ignore(e); | |
1964 return null; | |
1965 } | |
1966 } | |
1967 | |
1968 /* ------------------------------------------------------------ */ | |
1969 /* | |
1970 * @see javax.servlet.ServletContext#getResourcePaths(java.lang.String) | |
1971 */ | |
1972 @Override | |
1973 public Set getResourcePaths(String path) | |
1974 { | |
1975 return ContextHandler.this.getResourcePaths(path); | |
1976 } | |
1977 | |
1978 /* ------------------------------------------------------------ */ | |
1979 /* | |
1980 * @see javax.servlet.ServletContext#getServerInfo() | |
1981 */ | |
1982 @Override | |
1983 public String getServerInfo() | |
1984 { | |
1985 return "jetty/" + Server.getVersion(); | |
1986 } | |
1987 | |
1988 /* ------------------------------------------------------------ */ | |
1989 /* | |
1990 * @see javax.servlet.ServletContext#getServlet(java.lang.String) | |
1991 */ | |
1992 @Override | |
1993 @Deprecated | |
1994 public Servlet getServlet(String name) throws ServletException | |
1995 { | |
1996 return null; | |
1997 } | |
1998 | |
1999 /* ------------------------------------------------------------ */ | |
2000 /* | |
2001 * @see javax.servlet.ServletContext#getServletNames() | |
2002 */ | |
2003 @SuppressWarnings("unchecked") | |
2004 @Override | |
2005 @Deprecated | |
2006 public Enumeration getServletNames() | |
2007 { | |
2008 return Collections.enumeration(Collections.EMPTY_LIST); | |
2009 } | |
2010 | |
2011 /* ------------------------------------------------------------ */ | |
2012 /* | |
2013 * @see javax.servlet.ServletContext#getServlets() | |
2014 */ | |
2015 @SuppressWarnings("unchecked") | |
2016 @Override | |
2017 @Deprecated | |
2018 public Enumeration getServlets() | |
2019 { | |
2020 return Collections.enumeration(Collections.EMPTY_LIST); | |
2021 } | |
2022 | |
2023 /* ------------------------------------------------------------ */ | |
2024 /* | |
2025 * @see javax.servlet.ServletContext#log(java.lang.Exception, java.lang.String) | |
2026 */ | |
2027 @Override | |
2028 public void log(Exception exception, String msg) | |
2029 { | |
2030 _logger.warn(msg,exception); | |
2031 } | |
2032 | |
2033 /* ------------------------------------------------------------ */ | |
2034 /* | |
2035 * @see javax.servlet.ServletContext#log(java.lang.String) | |
2036 */ | |
2037 @Override | |
2038 public void log(String msg) | |
2039 { | |
2040 _logger.info(msg); | |
2041 } | |
2042 | |
2043 /* ------------------------------------------------------------ */ | |
2044 /* | |
2045 * @see javax.servlet.ServletContext#log(java.lang.String, java.lang.Throwable) | |
2046 */ | |
2047 @Override | |
2048 public void log(String message, Throwable throwable) | |
2049 { | |
2050 _logger.warn(message,throwable); | |
2051 } | |
2052 | |
2053 /* ------------------------------------------------------------ */ | |
2054 /* | |
2055 * @see javax.servlet.ServletContext#getInitParameter(java.lang.String) | |
2056 */ | |
2057 @Override | |
2058 public String getInitParameter(String name) | |
2059 { | |
2060 return ContextHandler.this.getInitParameter(name); | |
2061 } | |
2062 | |
2063 /* ------------------------------------------------------------ */ | |
2064 /* | |
2065 * @see javax.servlet.ServletContext#getInitParameterNames() | |
2066 */ | |
2067 @SuppressWarnings("unchecked") | |
2068 @Override | |
2069 public Enumeration getInitParameterNames() | |
2070 { | |
2071 return ContextHandler.this.getInitParameterNames(); | |
2072 } | |
2073 | |
2074 /* ------------------------------------------------------------ */ | |
2075 /* | |
2076 * @see javax.servlet.ServletContext#getAttribute(java.lang.String) | |
2077 */ | |
2078 @Override | |
2079 public synchronized Object getAttribute(String name) | |
2080 { | |
2081 Object o = ContextHandler.this.getAttribute(name); | |
2082 if (o == null && _contextAttributes != null) | |
2083 o = _contextAttributes.getAttribute(name); | |
2084 return o; | |
2085 } | |
2086 | |
2087 /* ------------------------------------------------------------ */ | |
2088 /* | |
2089 * @see javax.servlet.ServletContext#getAttributeNames() | |
2090 */ | |
2091 @SuppressWarnings("unchecked") | |
2092 @Override | |
2093 public synchronized Enumeration getAttributeNames() | |
2094 { | |
2095 HashSet<String> set = new HashSet<String>(); | |
2096 if (_contextAttributes != null) | |
2097 { | |
2098 Enumeration<String> e = _contextAttributes.getAttributeNames(); | |
2099 while (e.hasMoreElements()) | |
2100 set.add(e.nextElement()); | |
2101 } | |
2102 Enumeration<String> e = _attributes.getAttributeNames(); | |
2103 while (e.hasMoreElements()) | |
2104 set.add(e.nextElement()); | |
2105 | |
2106 return Collections.enumeration(set); | |
2107 } | |
2108 | |
2109 /* ------------------------------------------------------------ */ | |
2110 /* | |
2111 * @see javax.servlet.ServletContext#setAttribute(java.lang.String, java.lang.Object) | |
2112 */ | |
2113 @Override | |
2114 public synchronized void setAttribute(String name, Object value) | |
2115 { | |
2116 checkManagedAttribute(name,value); | |
2117 Object old_value = _contextAttributes.getAttribute(name); | |
2118 | |
2119 if (value == null) | |
2120 _contextAttributes.removeAttribute(name); | |
2121 else | |
2122 _contextAttributes.setAttribute(name,value); | |
2123 | |
2124 if (_contextAttributeListeners != null) | |
2125 { | |
2126 ServletContextAttributeEvent event = new ServletContextAttributeEvent(_scontext,name,old_value == null?value:old_value); | |
2127 | |
2128 for (int i = 0; i < LazyList.size(_contextAttributeListeners); i++) | |
2129 { | |
2130 ServletContextAttributeListener l = (ServletContextAttributeListener)LazyList.get(_contextAttributeListeners,i); | |
2131 | |
2132 if (old_value == null) | |
2133 l.attributeAdded(event); | |
2134 else if (value == null) | |
2135 l.attributeRemoved(event); | |
2136 else | |
2137 l.attributeReplaced(event); | |
2138 } | |
2139 } | |
2140 } | |
2141 | |
2142 /* ------------------------------------------------------------ */ | |
2143 /* | |
2144 * @see javax.servlet.ServletContext#removeAttribute(java.lang.String) | |
2145 */ | |
2146 @Override | |
2147 public synchronized void removeAttribute(String name) | |
2148 { | |
2149 checkManagedAttribute(name,null); | |
2150 | |
2151 if (_contextAttributes == null) | |
2152 { | |
2153 // Set it on the handler | |
2154 _attributes.removeAttribute(name); | |
2155 return; | |
2156 } | |
2157 | |
2158 Object old_value = _contextAttributes.getAttribute(name); | |
2159 _contextAttributes.removeAttribute(name); | |
2160 if (old_value != null) | |
2161 { | |
2162 if (_contextAttributeListeners != null) | |
2163 { | |
2164 ServletContextAttributeEvent event = new ServletContextAttributeEvent(_scontext,name,old_value); | |
2165 | |
2166 for (int i = 0; i < LazyList.size(_contextAttributeListeners); i++) | |
2167 ((ServletContextAttributeListener)LazyList.get(_contextAttributeListeners,i)).attributeRemoved(event); | |
2168 } | |
2169 } | |
2170 } | |
2171 | |
2172 /* ------------------------------------------------------------ */ | |
2173 /* | |
2174 * @see javax.servlet.ServletContext#getServletContextName() | |
2175 */ | |
2176 @Override | |
2177 public String getServletContextName() | |
2178 { | |
2179 String name = ContextHandler.this.getDisplayName(); | |
2180 if (name == null) | |
2181 name = ContextHandler.this.getContextPath(); | |
2182 return name; | |
2183 } | |
2184 | |
2185 /* ------------------------------------------------------------ */ | |
2186 @Override | |
2187 public String getContextPath() | |
2188 { | |
2189 if ((_contextPath != null) && _contextPath.equals(URIUtil.SLASH)) | |
2190 return ""; | |
2191 | |
2192 return _contextPath; | |
2193 } | |
2194 | |
2195 /* ------------------------------------------------------------ */ | |
2196 @Override | |
2197 public String toString() | |
2198 { | |
2199 return "ServletContext@" + ContextHandler.this.toString(); | |
2200 } | |
2201 | |
2202 /* ------------------------------------------------------------ */ | |
2203 @Override | |
2204 public boolean setInitParameter(String name, String value) | |
2205 { | |
2206 if (ContextHandler.this.getInitParameter(name) != null) | |
2207 return false; | |
2208 ContextHandler.this.getInitParams().put(name,value); | |
2209 return true; | |
2210 } | |
2211 | |
2212 /* ------------------------------------------------------------ */ | |
2213 final private static String __unimplmented="Unimplemented - use org.eclipse.jetty.servlet.ServletContextHandler"; | |
2214 | |
2215 @Override | |
2216 public Dynamic addFilter(String filterName, Class<? extends Filter> filterClass) | |
2217 { | |
2218 LOG.warn(__unimplmented); | |
2219 return null; | |
2220 } | |
2221 | |
2222 @Override | |
2223 public Dynamic addFilter(String filterName, Filter filter) | |
2224 { | |
2225 LOG.warn(__unimplmented); | |
2226 return null; | |
2227 } | |
2228 | |
2229 @Override | |
2230 public Dynamic addFilter(String filterName, String className) | |
2231 { | |
2232 LOG.warn(__unimplmented); | |
2233 return null; | |
2234 } | |
2235 | |
2236 @Override | |
2237 public javax.servlet.ServletRegistration.Dynamic addServlet(String servletName, Class<? extends Servlet> servletClass) | |
2238 { | |
2239 LOG.warn(__unimplmented); | |
2240 return null; | |
2241 } | |
2242 | |
2243 @Override | |
2244 public javax.servlet.ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet) | |
2245 { | |
2246 LOG.warn(__unimplmented); | |
2247 return null; | |
2248 } | |
2249 | |
2250 @Override | |
2251 public javax.servlet.ServletRegistration.Dynamic addServlet(String servletName, String className) | |
2252 { | |
2253 LOG.warn(__unimplmented); | |
2254 return null; | |
2255 } | |
2256 | |
2257 @Override | |
2258 public <T extends Filter> T createFilter(Class<T> c) throws ServletException | |
2259 { | |
2260 LOG.warn(__unimplmented); | |
2261 return null; | |
2262 } | |
2263 | |
2264 @Override | |
2265 public <T extends Servlet> T createServlet(Class<T> c) throws ServletException | |
2266 { | |
2267 LOG.warn(__unimplmented); | |
2268 return null; | |
2269 } | |
2270 | |
2271 @Override | |
2272 public Set<SessionTrackingMode> getDefaultSessionTrackingModes() | |
2273 { | |
2274 LOG.warn(__unimplmented); | |
2275 return null; | |
2276 } | |
2277 | |
2278 @Override | |
2279 public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() | |
2280 { | |
2281 LOG.warn(__unimplmented); | |
2282 return null; | |
2283 } | |
2284 | |
2285 @Override | |
2286 public FilterRegistration getFilterRegistration(String filterName) | |
2287 { | |
2288 LOG.warn(__unimplmented); | |
2289 return null; | |
2290 } | |
2291 | |
2292 @Override | |
2293 public Map<String, ? extends FilterRegistration> getFilterRegistrations() | |
2294 { | |
2295 LOG.warn(__unimplmented); | |
2296 return null; | |
2297 } | |
2298 | |
2299 @Override | |
2300 public ServletRegistration getServletRegistration(String servletName) | |
2301 { | |
2302 LOG.warn(__unimplmented); | |
2303 return null; | |
2304 } | |
2305 | |
2306 @Override | |
2307 public Map<String, ? extends ServletRegistration> getServletRegistrations() | |
2308 { | |
2309 LOG.warn(__unimplmented); | |
2310 return null; | |
2311 } | |
2312 | |
2313 @Override | |
2314 public SessionCookieConfig getSessionCookieConfig() | |
2315 { | |
2316 LOG.warn(__unimplmented); | |
2317 return null; | |
2318 } | |
2319 | |
2320 @Override | |
2321 public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes) | |
2322 { | |
2323 LOG.warn(__unimplmented); | |
2324 } | |
2325 | |
2326 @Override | |
2327 public void addListener(String className) | |
2328 { | |
2329 if (!_enabled) | |
2330 throw new UnsupportedOperationException(); | |
2331 | |
2332 try | |
2333 { | |
2334 // Class<? extends EventListener> clazz = _classLoader==null?Loader.loadClass(ContextHandler.class,className):_classLoader.loadClass(className); | |
2335 Class clazz = _classLoader==null?Loader.loadClass(ContextHandler.class,className):_classLoader.loadClass(className); | |
2336 addListener(clazz); | |
2337 } | |
2338 catch (ClassNotFoundException e) | |
2339 { | |
2340 throw new IllegalArgumentException(e); | |
2341 } | |
2342 } | |
2343 | |
2344 @Override | |
2345 public <T extends EventListener> void addListener(T t) | |
2346 { | |
2347 if (!_enabled) | |
2348 throw new UnsupportedOperationException(); | |
2349 ContextHandler.this.addEventListener(t); | |
2350 ContextHandler.this.restrictEventListener(t); | |
2351 } | |
2352 | |
2353 @Override | |
2354 public void addListener(Class<? extends EventListener> listenerClass) | |
2355 { | |
2356 if (!_enabled) | |
2357 throw new UnsupportedOperationException(); | |
2358 | |
2359 try | |
2360 { | |
2361 EventListener e = createListener(listenerClass); | |
2362 ContextHandler.this.addEventListener(e); | |
2363 ContextHandler.this.restrictEventListener(e); | |
2364 } | |
2365 catch (ServletException e) | |
2366 { | |
2367 throw new IllegalArgumentException(e); | |
2368 } | |
2369 } | |
2370 | |
2371 @Override | |
2372 public <T extends EventListener> T createListener(Class<T> clazz) throws ServletException | |
2373 { | |
2374 try | |
2375 { | |
2376 return clazz.newInstance(); | |
2377 } | |
2378 catch (InstantiationException e) | |
2379 { | |
2380 throw new ServletException(e); | |
2381 } | |
2382 catch (IllegalAccessException e) | |
2383 { | |
2384 throw new ServletException(e); | |
2385 } | |
2386 } | |
2387 | |
2388 @Override | |
2389 public ClassLoader getClassLoader() | |
2390 { | |
2391 AccessController.checkPermission(new RuntimePermission("getClassLoader")); | |
2392 return _classLoader; | |
2393 } | |
2394 | |
2395 @Override | |
2396 public int getEffectiveMajorVersion() | |
2397 { | |
2398 return _majorVersion; | |
2399 } | |
2400 | |
2401 @Override | |
2402 public int getEffectiveMinorVersion() | |
2403 { | |
2404 return _minorVersion; | |
2405 } | |
2406 | |
2407 public void setEffectiveMajorVersion (int v) | |
2408 { | |
2409 _majorVersion = v; | |
2410 } | |
2411 | |
2412 public void setEffectiveMinorVersion (int v) | |
2413 { | |
2414 _minorVersion = v; | |
2415 } | |
2416 | |
2417 @Override | |
2418 public JspConfigDescriptor getJspConfigDescriptor() | |
2419 { | |
2420 LOG.warn(__unimplmented); | |
2421 return null; | |
2422 } | |
2423 | |
2424 public void setJspConfigDescriptor(JspConfigDescriptor d) | |
2425 { | |
2426 | |
2427 } | |
2428 | |
2429 @Override | |
2430 public void declareRoles(String... roleNames) | |
2431 { | |
2432 if (!isStarting()) | |
2433 throw new IllegalStateException (); | |
2434 if (!_enabled) | |
2435 throw new UnsupportedOperationException(); | |
2436 | |
2437 // TODO Auto-generated method stub | |
2438 | |
2439 } | |
2440 | |
2441 public void setEnabled(boolean enabled) | |
2442 { | |
2443 _enabled = enabled; | |
2444 } | |
2445 | |
2446 public boolean isEnabled() | |
2447 { | |
2448 return _enabled; | |
2449 } | |
2450 } | |
2451 | |
2452 private static class CLDump implements Dumpable | |
2453 { | |
2454 final ClassLoader _loader; | |
2455 | |
2456 CLDump(ClassLoader loader) | |
2457 { | |
2458 _loader = loader; | |
2459 } | |
2460 | |
2461 public String dump() | |
2462 { | |
2463 return AggregateLifeCycle.dump(this); | |
2464 } | |
2465 | |
2466 public void dump(Appendable out, String indent) throws IOException | |
2467 { | |
2468 out.append(String.valueOf(_loader)).append("\n"); | |
2469 | |
2470 if (_loader != null) | |
2471 { | |
2472 Object parent = _loader.getParent(); | |
2473 if (parent != null) | |
2474 { | |
2475 if (!(parent instanceof Dumpable)) | |
2476 parent = new CLDump((ClassLoader)parent); | |
2477 | |
2478 if (_loader instanceof URLClassLoader) | |
2479 AggregateLifeCycle.dump(out,indent,TypeUtil.asList(((URLClassLoader)_loader).getURLs()),Collections.singleton(parent)); | |
2480 else | |
2481 AggregateLifeCycle.dump(out,indent,Collections.singleton(parent)); | |
2482 } | |
2483 } | |
2484 } | |
2485 } | |
2486 | |
2487 | |
2488 /* ------------------------------------------------------------ */ | |
2489 /** Interface to check aliases | |
2490 */ | |
2491 public interface AliasCheck | |
2492 { | |
2493 /* ------------------------------------------------------------ */ | |
2494 /** Check an alias | |
2495 * @param path The path the aliased resource was created for | |
2496 * @param resource The aliased resourced | |
2497 * @return True if the resource is OK to be served. | |
2498 */ | |
2499 boolean check(String path, Resource resource); | |
2500 } | |
2501 | |
2502 | |
2503 /* ------------------------------------------------------------ */ | |
2504 /** Approve Aliases with same suffix. | |
2505 * Eg. a symbolic link from /foobar.html to /somewhere/wibble.html would be | |
2506 * approved because both the resource and alias end with ".html". | |
2507 */ | |
2508 @Deprecated | |
2509 public static class ApproveSameSuffixAliases implements AliasCheck | |
2510 { | |
2511 { | |
2512 LOG.warn("ApproveSameSuffixAlias is not safe for production"); | |
2513 } | |
2514 | |
2515 public boolean check(String path, Resource resource) | |
2516 { | |
2517 int dot = path.lastIndexOf('.'); | |
2518 if (dot<0) | |
2519 return false; | |
2520 String suffix=path.substring(dot); | |
2521 return resource.toString().endsWith(suffix); | |
2522 } | |
2523 } | |
2524 | |
2525 | |
2526 /* ------------------------------------------------------------ */ | |
2527 /** Approve Aliases with a path prefix. | |
2528 * Eg. a symbolic link from /dirA/foobar.html to /dirB/foobar.html would be | |
2529 * approved because both the resource and alias end with "/foobar.html". | |
2530 */ | |
2531 @Deprecated | |
2532 public static class ApprovePathPrefixAliases implements AliasCheck | |
2533 { | |
2534 { | |
2535 LOG.warn("ApprovePathPrefixAliases is not safe for production"); | |
2536 } | |
2537 | |
2538 public boolean check(String path, Resource resource) | |
2539 { | |
2540 int slash = path.lastIndexOf('/'); | |
2541 if (slash<0 || slash==path.length()-1) | |
2542 return false; | |
2543 String suffix=path.substring(slash); | |
2544 return resource.toString().endsWith(suffix); | |
2545 } | |
2546 } | |
2547 | |
2548 /* ------------------------------------------------------------ */ | |
2549 /** Approve Aliases of a non existent directory. | |
2550 * If a directory "/foobar/" does not exist, then the resource is | |
2551 * aliased to "/foobar". Accept such aliases. | |
2552 */ | |
2553 public static class ApproveNonExistentDirectoryAliases implements AliasCheck | |
2554 { | |
2555 public boolean check(String path, Resource resource) | |
2556 { | |
2557 if (resource.exists()) | |
2558 return false; | |
2559 | |
2560 String a=resource.getAlias().toString(); | |
2561 String r=resource.getURL().toString(); | |
2562 | |
2563 if (a.length()>r.length()) | |
2564 return a.startsWith(r) && a.length()==r.length()+1 && a.endsWith("/"); | |
2565 else | |
2566 return r.startsWith(a) && r.length()==a.length()+1 && r.endsWith("/"); | |
2567 } | |
2568 } | |
2569 | |
2570 } |