0001: //========================================================================
0002: //$Id: ContextHandler.java,v 1.16 2005/11/17 11:19:45 gregwilkins Exp $
0003: //Copyright 2004-2005 Mort Bay Consulting Pty. Ltd.
0004: //------------------------------------------------------------------------
0005: //Licensed under the Apache License, Version 2.0 (the "License");
0006: //you may not use this file except in compliance with the License.
0007: //You may obtain a copy of the License at
0008: //http://www.apache.org/licenses/LICENSE-2.0
0009: //Unless required by applicable law or agreed to in writing, software
0010: //distributed under the License is distributed on an "AS IS" BASIS,
0011: //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0012: //See the License for the specific language governing permissions and
0013: //limitations under the License.
0014: //========================================================================
0015:
0016: package org.mortbay.jetty.handler;
0017:
0018: import java.io.File;
0019: import java.io.IOException;
0020: import java.io.InputStream;
0021: import java.net.MalformedURLException;
0022: import java.net.URL;
0023: import java.net.URLClassLoader;
0024: import java.util.Arrays;
0025: import java.util.Collections;
0026: import java.util.Enumeration;
0027: import java.util.EventListener;
0028: import java.util.HashMap;
0029: import java.util.HashSet;
0030: import java.util.Locale;
0031: import java.util.Map;
0032: import java.util.Set;
0033:
0034: import javax.servlet.RequestDispatcher;
0035: import javax.servlet.Servlet;
0036: import javax.servlet.ServletContext;
0037: import javax.servlet.ServletContextAttributeEvent;
0038: import javax.servlet.ServletContextAttributeListener;
0039: import javax.servlet.ServletContextEvent;
0040: import javax.servlet.ServletContextListener;
0041: import javax.servlet.ServletException;
0042: import javax.servlet.ServletRequestAttributeListener;
0043: import javax.servlet.ServletRequestEvent;
0044: import javax.servlet.ServletRequestListener;
0045: import javax.servlet.http.HttpServletRequest;
0046: import javax.servlet.http.HttpServletResponse;
0047:
0048: import org.mortbay.io.Buffer;
0049: import org.mortbay.jetty.Handler;
0050: import org.mortbay.jetty.HandlerContainer;
0051: import org.mortbay.jetty.HttpConnection;
0052: import org.mortbay.jetty.HttpException;
0053: import org.mortbay.jetty.MimeTypes;
0054: import org.mortbay.jetty.Request;
0055: import org.mortbay.jetty.Server;
0056: import org.mortbay.log.Log;
0057: import org.mortbay.log.Logger;
0058: import org.mortbay.resource.Resource;
0059: import org.mortbay.util.Attributes;
0060: import org.mortbay.util.AttributesMap;
0061: import org.mortbay.util.LazyList;
0062: import org.mortbay.util.Loader;
0063: import org.mortbay.util.URIUtil;
0064:
0065: /* ------------------------------------------------------------ */
0066: /** ContextHandler.
0067: *
0068: * This handler wraps a call to handle by setting the context and
0069: * servlet path, plus setting the context classloader.
0070: *
0071: * Note. Because of http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4425695
0072: * directly replacing war or jar files in a context is not supported.
0073: * You should use classes instead of jars if they will change, or deploy
0074: * a packed war file that gets extracted on deployment.
0075: *
0076: *
0077: * @org.apache.xbean.XBean description="Creates a basic HTTP context"
0078: *
0079: * @author gregw
0080: *
0081: */
0082: public class ContextHandler extends HandlerWrapper implements
0083: Attributes {
0084: private static ThreadLocal __context = new ThreadLocal();
0085:
0086: /* ------------------------------------------------------------ */
0087: /** Get the current ServletContext implementation.
0088: * This call is only valid during a call to doStart and is available to
0089: * nested handlers to access the context.
0090: *
0091: * @return ServletContext implementation
0092: */
0093: public static SContext getCurrentContext() {
0094: SContext context = (SContext) __context.get();
0095: return context;
0096: }
0097:
0098: protected SContext _scontext;
0099:
0100: private Attributes _attributes;
0101: private Attributes _contextAttributes;
0102: private ClassLoader _classLoader;
0103: private String _contextPath;
0104: private Map _initParams;
0105: private String _displayName;
0106: private String _docRoot;
0107: private Resource _baseResource;
0108: private MimeTypes _mimeTypes;
0109: private Map _localeEncodingMap;
0110: private String[] _welcomeFiles;
0111: private ErrorHandler _errorHandler;
0112: private String[] _vhosts;
0113: private Set _connectors;
0114: private EventListener[] _eventListeners;
0115: private Logger _logger;
0116: private boolean _shutdown;
0117: private int _maxFormContentSize = Integer.getInteger(
0118: "org.mortbay.jetty.Request.maxFormContentSize", 200000)
0119: .intValue();;
0120:
0121: private Object _contextListeners;
0122: private Object _contextAttributeListeners;
0123: private Object _requestListeners;
0124: private Object _requestAttributeListeners;
0125:
0126: /* ------------------------------------------------------------ */
0127: /**
0128: *
0129: */
0130: public ContextHandler() {
0131: super ();
0132: _scontext = new SContext();
0133: _attributes = new AttributesMap();
0134: _initParams = new HashMap();
0135: }
0136:
0137: /* ------------------------------------------------------------ */
0138: /**
0139: *
0140: */
0141: protected ContextHandler(SContext context) {
0142: super ();
0143: _scontext = context;
0144: _attributes = new AttributesMap();
0145: _initParams = new HashMap();
0146: }
0147:
0148: /* ------------------------------------------------------------ */
0149: /**
0150: *
0151: */
0152: public ContextHandler(String contextPath) {
0153: this ();
0154: setContextPath(contextPath);
0155: }
0156:
0157: /* ------------------------------------------------------------ */
0158: /**
0159: *
0160: */
0161: public ContextHandler(HandlerContainer parent, String contextPath) {
0162: this ();
0163: setContextPath(contextPath);
0164: parent.addHandler(this );
0165: }
0166:
0167: /* ------------------------------------------------------------ */
0168: public SContext getServletContext() {
0169: return _scontext;
0170: }
0171:
0172: /* ------------------------------------------------------------ */
0173: public void setServer(Server server) {
0174: if (_errorHandler != null) {
0175: Server old_server = getServer();
0176: if (old_server != null && old_server != server)
0177: old_server.getContainer().update(this , _errorHandler,
0178: null, "error", true);
0179: super .setServer(server);
0180: if (server != null && server != old_server)
0181: server.getContainer().update(this , null, _errorHandler,
0182: "error", true);
0183: _errorHandler.setServer(server);
0184: } else
0185: super .setServer(server);
0186:
0187: }
0188:
0189: /* ------------------------------------------------------------ */
0190: /** Set the virtual hosts for the context.
0191: * Only requests that have a matching host header or fully qualified
0192: * URL will be passed to that context with a virtual host name.
0193: * A context with no virtual host names or a null virtual host name is
0194: * available to all requests that are not served by a context with a
0195: * matching virtual host name.
0196: * @param vhosts Array of virtual hosts that this context responds to. A
0197: * null host name or null/empty array means any hostname is acceptable.
0198: * Host names may String representation of IP addresses.
0199: */
0200: public void setVirtualHosts(String[] vhosts) {
0201: _vhosts = vhosts;
0202: }
0203:
0204: /* ------------------------------------------------------------ */
0205: /** Get the virtual hosts for the context.
0206: * Only requests that have a matching host header or fully qualified
0207: * URL will be passed to that context with a virtual host name.
0208: * A context with no virtual host names or a null virtual host name is
0209: * available to all requests that are not served by a context with a
0210: * matching virtual host name.
0211: * @return Array of virtual hosts that this context responds to. A
0212: * null host name or empty array means any hostname is acceptable.
0213: * Host names may be String representation of IP addresses.
0214: */
0215: public String[] getVirtualHosts() {
0216: return _vhosts;
0217: }
0218:
0219: /* ------------------------------------------------------------ */
0220: /**
0221: * @deprecated use {@link #setConnectorNames(String[])}
0222: */
0223: public void setHosts(String[] hosts) {
0224: setConnectorNames(hosts);
0225: }
0226:
0227: /* ------------------------------------------------------------ */
0228: /** Get the hosts for the context.
0229: * @deprecated
0230: */
0231: public String[] getHosts() {
0232: return getConnectorNames();
0233: }
0234:
0235: /* ------------------------------------------------------------ */
0236: /**
0237: * @return an array of connector names that this context
0238: * will accept a request from.
0239: */
0240: public String[] getConnectorNames() {
0241: if (_connectors == null || _connectors.size() == 0)
0242: return null;
0243:
0244: return (String[]) _connectors.toArray(new String[_connectors
0245: .size()]);
0246: }
0247:
0248: /* ------------------------------------------------------------ */
0249: /** Set the names of accepted connectors.
0250: *
0251: * Names are either "host:port" or a specific configured name for a connector.
0252: *
0253: * @param connectors If non null, an array of connector names that this context
0254: * will accept a request from.
0255: */
0256: public void setConnectorNames(String[] connectors) {
0257: if (connectors == null || connectors.length == 0)
0258: _connectors = null;
0259: else
0260: _connectors = new HashSet(Arrays.asList(connectors));
0261: }
0262:
0263: /* ------------------------------------------------------------ */
0264: /*
0265: * @see javax.servlet.ServletContext#getAttribute(java.lang.String)
0266: */
0267: public Object getAttribute(String name) {
0268: return _attributes.getAttribute(name);
0269: }
0270:
0271: /* ------------------------------------------------------------ */
0272: /*
0273: * @see javax.servlet.ServletContext#getAttributeNames()
0274: */
0275: public Enumeration getAttributeNames() {
0276: return _attributes.getAttributeNames();
0277: }
0278:
0279: /* ------------------------------------------------------------ */
0280: /**
0281: * @return Returns the attributes.
0282: */
0283: public Attributes getAttributes() {
0284: return _attributes;
0285: }
0286:
0287: /* ------------------------------------------------------------ */
0288: /**
0289: * @return Returns the classLoader.
0290: */
0291: public ClassLoader getClassLoader() {
0292: return _classLoader;
0293: }
0294:
0295: /* ------------------------------------------------------------ */
0296: /**
0297: * Make best effort to extract a file classpath from the context classloader
0298: * @return Returns the classLoader.
0299: */
0300: public String getClassPath() {
0301: if (_classLoader == null
0302: || !(_classLoader instanceof URLClassLoader))
0303: return null;
0304: URLClassLoader loader = (URLClassLoader) _classLoader;
0305: URL[] urls = loader.getURLs();
0306: StringBuffer classpath = new StringBuffer();
0307: for (int i = 0; i < urls.length; i++) {
0308: try {
0309: Resource resource = Resource.newResource(urls[i]);
0310: File file = resource.getFile();
0311: if (file.exists()) {
0312: if (classpath.length() > 0)
0313: classpath.append(File.pathSeparatorChar);
0314: classpath.append(file.getAbsolutePath());
0315: }
0316: } catch (IOException e) {
0317: Log.debug(e);
0318: }
0319: }
0320: if (classpath.length() == 0)
0321: return null;
0322: return classpath.toString();
0323: }
0324:
0325: /* ------------------------------------------------------------ */
0326: /**
0327: * @return Returns the _contextPath.
0328: */
0329: public String getContextPath() {
0330: return _contextPath;
0331: }
0332:
0333: /* ------------------------------------------------------------ */
0334: /*
0335: * @see javax.servlet.ServletContext#getInitParameter(java.lang.String)
0336: */
0337: public String getInitParameter(String name) {
0338: return (String) _initParams.get(name);
0339: }
0340:
0341: /* ------------------------------------------------------------ */
0342: /*
0343: * @see javax.servlet.ServletContext#getInitParameterNames()
0344: */
0345: public Enumeration getInitParameterNames() {
0346: return Collections.enumeration(_initParams.keySet());
0347: }
0348:
0349: /* ------------------------------------------------------------ */
0350: /**
0351: * @return Returns the initParams.
0352: */
0353: public Map getInitParams() {
0354: return _initParams;
0355: }
0356:
0357: /* ------------------------------------------------------------ */
0358: /*
0359: * @see javax.servlet.ServletContext#getServletContextName()
0360: */
0361: public String getDisplayName() {
0362: return _displayName;
0363: }
0364:
0365: /* ------------------------------------------------------------ */
0366: public EventListener[] getEventListeners() {
0367: return _eventListeners;
0368: }
0369:
0370: /* ------------------------------------------------------------ */
0371: public void setEventListeners(EventListener[] eventListeners) {
0372: _contextListeners = null;
0373: _contextAttributeListeners = null;
0374: _requestListeners = null;
0375: _requestAttributeListeners = null;
0376:
0377: _eventListeners = eventListeners;
0378:
0379: for (int i = 0; eventListeners != null
0380: && i < eventListeners.length; i++) {
0381: EventListener listener = _eventListeners[i];
0382:
0383: if (listener instanceof ServletContextListener)
0384: _contextListeners = LazyList.add(_contextListeners,
0385: listener);
0386:
0387: if (listener instanceof ServletContextAttributeListener)
0388: _contextAttributeListeners = LazyList.add(
0389: _contextAttributeListeners, listener);
0390:
0391: if (listener instanceof ServletRequestListener)
0392: _requestListeners = LazyList.add(_requestListeners,
0393: listener);
0394:
0395: if (listener instanceof ServletRequestAttributeListener)
0396: _requestAttributeListeners = LazyList.add(
0397: _requestAttributeListeners, listener);
0398: }
0399: }
0400:
0401: /* ------------------------------------------------------------ */
0402: public void addEventListener(EventListener listener) {
0403: setEventListeners((EventListener[]) LazyList.addToArray(
0404: getEventListeners(), listener, EventListener.class));
0405: }
0406:
0407: /* ------------------------------------------------------------ */
0408: /**
0409: * @return true if this context is accepting new requests
0410: */
0411: public boolean isShutdown() {
0412: return !_shutdown;
0413: }
0414:
0415: /* ------------------------------------------------------------ */
0416: /** Set shutdown status.
0417: * This field allows for graceful shutdown of a context. A started context may be put into non accepting state so
0418: * that existing requests can complete, but no new requests are accepted.
0419: * @param accepting true if this context is accepting new requests
0420: */
0421: public void setShutdown(boolean shutdown) {
0422: _shutdown = shutdown;
0423: }
0424:
0425: /* ------------------------------------------------------------ */
0426: /*
0427: * @see org.mortbay.thread.AbstractLifeCycle#doStart()
0428: */
0429: protected void doStart() throws Exception {
0430: _logger = Log
0431: .getLogger(getDisplayName() == null ? getContextPath()
0432: : getDisplayName());
0433: ClassLoader old_classloader = null;
0434: Thread current_thread = null;
0435: Object old_context = null;
0436: _contextAttributes = new AttributesMap();
0437: try {
0438: // Set the classloader
0439: if (_classLoader != null) {
0440: current_thread = Thread.currentThread();
0441: old_classloader = current_thread
0442: .getContextClassLoader();
0443: current_thread.setContextClassLoader(_classLoader);
0444: }
0445:
0446: if (_mimeTypes == null)
0447: _mimeTypes = new MimeTypes();
0448:
0449: old_context = __context.get();
0450: __context.set(_scontext);
0451:
0452: if (_errorHandler == null)
0453: setErrorHandler(new ErrorHandler());
0454:
0455: startContext();
0456:
0457: } finally {
0458: __context.set(old_context);
0459:
0460: // reset the classloader
0461: if (_classLoader != null) {
0462: current_thread.setContextClassLoader(old_classloader);
0463: }
0464: }
0465: }
0466:
0467: /* ------------------------------------------------------------ */
0468: protected void startContext() throws Exception {
0469: super .doStart();
0470:
0471: if (_errorHandler != null)
0472: _errorHandler.start();
0473:
0474: // Context listeners
0475: if (_contextListeners != null) {
0476: ServletContextEvent event = new ServletContextEvent(
0477: _scontext);
0478: for (int i = 0; i < LazyList.size(_contextListeners); i++) {
0479: ((ServletContextListener) LazyList.get(
0480: _contextListeners, i))
0481: .contextInitialized(event);
0482: }
0483: }
0484: }
0485:
0486: /* ------------------------------------------------------------ */
0487: /*
0488: * @see org.mortbay.thread.AbstractLifeCycle#doStop()
0489: */
0490: protected void doStop() throws Exception {
0491: ClassLoader old_classloader = null;
0492: Thread current_thread = null;
0493:
0494: Object old_context = __context.get();
0495: __context.set(_scontext);
0496: try {
0497: // Set the classloader
0498: if (_classLoader != null) {
0499: current_thread = Thread.currentThread();
0500: old_classloader = current_thread
0501: .getContextClassLoader();
0502: current_thread.setContextClassLoader(_classLoader);
0503: }
0504:
0505: super .doStop();
0506:
0507: // Context listeners
0508: if (_contextListeners != null) {
0509: ServletContextEvent event = new ServletContextEvent(
0510: _scontext);
0511: for (int i = LazyList.size(_contextListeners); i-- > 0;) {
0512: ((ServletContextListener) LazyList.get(
0513: _contextListeners, i))
0514: .contextDestroyed(event);
0515: }
0516: }
0517:
0518: if (_errorHandler != null)
0519: _errorHandler.stop();
0520: } finally {
0521: __context.set(old_context);
0522: // reset the classloader
0523: if (_classLoader != null)
0524: current_thread.setContextClassLoader(old_classloader);
0525: }
0526:
0527: if (_contextAttributes != null)
0528: _contextAttributes.clearAttributes();
0529: _contextAttributes = null;
0530: }
0531:
0532: /* ------------------------------------------------------------ */
0533: /*
0534: * @see org.mortbay.jetty.Handler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
0535: */
0536: public void handle(String target, HttpServletRequest request,
0537: HttpServletResponse response, int dispatch)
0538: throws IOException, ServletException {
0539: boolean new_context = false;
0540: SContext old_context = null;
0541: String old_context_path = null;
0542: String old_servlet_path = null;
0543: String old_path_info = null;
0544: ClassLoader old_classloader = null;
0545: Thread current_thread = null;
0546:
0547: Request base_request = (request instanceof Request) ? (Request) request
0548: : HttpConnection.getCurrentConnection().getRequest();
0549: if (!isStarted() || _shutdown
0550: || (dispatch == REQUEST && base_request.isHandled()))
0551: return;
0552:
0553: old_context = base_request.getContext();
0554:
0555: // Are we already in this context?
0556: if (old_context != _scontext) {
0557: new_context = true;
0558:
0559: // Check the vhosts
0560: if (_vhosts != null && _vhosts.length > 0) {
0561: String vhost = request.getServerName();
0562: boolean match = false;
0563:
0564: // TODO non-linear lookup
0565: for (int i = 0; !match && i < _vhosts.length; i++)
0566: match = _vhosts[i] != null
0567: && _vhosts[i].equalsIgnoreCase(vhost);
0568: if (!match)
0569: return;
0570: }
0571:
0572: // Check the connector
0573: if (_connectors != null && _connectors.size() > 0) {
0574: String connector = HttpConnection
0575: .getCurrentConnection().getConnector()
0576: .getName();
0577: if (connector == null
0578: || !_connectors.contains(connector))
0579: return;
0580: }
0581:
0582: // Nope - so check the target.
0583: if (dispatch == REQUEST) {
0584: if (target.equals(_contextPath)) {
0585: target = _contextPath;
0586: if (!target.endsWith("/")) {
0587: base_request.setHandled(true);
0588: if (request.getQueryString() != null)
0589: response.sendRedirect(target + "/?"
0590: + request.getQueryString());
0591: else
0592: response.sendRedirect(target + "/");
0593: return;
0594: }
0595: } else if (target.startsWith(_contextPath)
0596: && (_contextPath.length() == 1 || target
0597: .charAt(_contextPath.length()) == '/')) {
0598: if (_contextPath.length() > 1)
0599: target = target
0600: .substring(_contextPath.length());
0601: } else {
0602: // Not for this context!
0603: return;
0604: }
0605: }
0606: }
0607:
0608: try {
0609: old_context_path = base_request.getContextPath();
0610: old_servlet_path = base_request.getServletPath();
0611: old_path_info = base_request.getPathInfo();
0612:
0613: // Update the paths
0614: base_request.setContext(_scontext);
0615: if (dispatch != INCLUDE && target.startsWith("/")) {
0616: if (_contextPath.length() == 1)
0617: base_request.setContextPath("");
0618: else
0619: base_request.setContextPath(_contextPath);
0620: base_request.setServletPath(null);
0621: base_request.setPathInfo(target);
0622: }
0623:
0624: ServletRequestEvent event = null;
0625: if (new_context) {
0626: // Set the classloader
0627: if (_classLoader != null) {
0628: current_thread = Thread.currentThread();
0629: old_classloader = current_thread
0630: .getContextClassLoader();
0631: current_thread.setContextClassLoader(_classLoader);
0632: }
0633:
0634: // Handle the REALLY SILLY request events!
0635: if (_requestListeners != null) {
0636: event = new ServletRequestEvent(_scontext, request);
0637: for (int i = 0; i < LazyList
0638: .size(_requestListeners); i++)
0639: ((ServletRequestListener) LazyList.get(
0640: _requestListeners, i))
0641: .requestInitialized(event);
0642: }
0643: for (int i = 0; i < LazyList
0644: .size(_requestAttributeListeners); i++)
0645: base_request
0646: .addEventListener(((EventListener) LazyList
0647: .get(_requestAttributeListeners, i)));
0648: }
0649:
0650: // Handle the request
0651: try {
0652: if (dispatch == REQUEST && isProtectedTarget(target))
0653: throw new HttpException(
0654: HttpServletResponse.SC_NOT_FOUND);
0655:
0656: Handler handler = getHandler();
0657: if (handler != null)
0658: handler.handle(target, request, response, dispatch);
0659: } catch (HttpException e) {
0660: Log.debug(e);
0661: response.sendError(e.getStatus(), e.getReason());
0662: } finally {
0663: // Handle more REALLY SILLY request events!
0664: if (new_context) {
0665: for (int i = LazyList.size(_requestListeners); i-- > 0;)
0666: ((ServletRequestListener) LazyList.get(
0667: _requestListeners, i))
0668: .requestDestroyed(event);
0669:
0670: for (int i = 0; i < LazyList
0671: .size(_requestAttributeListeners); i++)
0672: base_request
0673: .removeEventListener(((EventListener) LazyList
0674: .get(
0675: _requestAttributeListeners,
0676: i)));
0677: }
0678: }
0679: } finally {
0680: if (old_context != _scontext) {
0681: // reset the classloader
0682: if (_classLoader != null) {
0683: current_thread
0684: .setContextClassLoader(old_classloader);
0685: }
0686:
0687: // reset the context and servlet path.
0688: base_request.setContext(old_context);
0689: base_request.setContextPath(old_context_path);
0690: base_request.setServletPath(old_servlet_path);
0691: base_request.setPathInfo(old_path_info);
0692: }
0693: }
0694: }
0695:
0696: /* ------------------------------------------------------------ */
0697: /** Check the target.
0698: * Called by {@link #handle(String, HttpServletRequest, HttpServletResponse, int)} when a
0699: * target within a context is determined. If the target is protected, 404 is returned.
0700: * The default implementation always returns false.
0701: * @see org.mortbay.jetty.webapp.WebAppContext#isProtectedTarget(String)
0702: */
0703: /* ------------------------------------------------------------ */
0704: protected boolean isProtectedTarget(String target) {
0705: return false;
0706: }
0707:
0708: /* ------------------------------------------------------------ */
0709: /*
0710: * @see javax.servlet.ServletContext#removeAttribute(java.lang.String)
0711: */
0712: public void removeAttribute(String name) {
0713: _attributes.removeAttribute(name);
0714: }
0715:
0716: /* ------------------------------------------------------------ */
0717: /* Set a context attribute.
0718: * Attributes set via this API cannot be overriden by the ServletContext.setAttribute API.
0719: * Their lifecycle spans the stop/start of a context. No attribute listener events are
0720: * triggered by this API.
0721: * @see javax.servlet.ServletContext#setAttribute(java.lang.String, java.lang.Object)
0722: */
0723: public void setAttribute(String name, Object value) {
0724: _attributes.setAttribute(name, value);
0725: }
0726:
0727: /* ------------------------------------------------------------ */
0728: /**
0729: * @param attributes The attributes to set.
0730: */
0731: public void setAttributes(Attributes attributes) {
0732: _attributes = attributes;
0733: }
0734:
0735: /* ------------------------------------------------------------ */
0736: public void clearAttributes() {
0737: _attributes.clearAttributes();
0738: }
0739:
0740: /* ------------------------------------------------------------ */
0741: /**
0742: * @param classLoader The classLoader to set.
0743: */
0744: public void setClassLoader(ClassLoader classLoader) {
0745: _classLoader = classLoader;
0746: }
0747:
0748: /* ------------------------------------------------------------ */
0749: /**
0750: * @param contextPath The _contextPath to set.
0751: */
0752: public void setContextPath(String contextPath) {
0753: if (contextPath != null && contextPath.length() > 1
0754: && contextPath.endsWith("/"))
0755: throw new IllegalArgumentException("ends with /");
0756: _contextPath = contextPath;
0757:
0758: if (getServer() != null
0759: && (getServer().isStarting() || getServer().isStarted())) {
0760: Handler[] contextCollections = getServer()
0761: .getChildHandlersByClass(
0762: ContextHandlerCollection.class);
0763: for (int h = 0; contextCollections != null
0764: && h < contextCollections.length; h++)
0765: ((ContextHandlerCollection) contextCollections[h])
0766: .mapContexts();
0767: }
0768: }
0769:
0770: /* ------------------------------------------------------------ */
0771: /**
0772: * @param initParams The initParams to set.
0773: */
0774: public void setInitParams(Map initParams) {
0775: if (initParams == null)
0776: return;
0777: _initParams = new HashMap(initParams);
0778: }
0779:
0780: /* ------------------------------------------------------------ */
0781: /**
0782: * @param servletContextName The servletContextName to set.
0783: */
0784: public void setDisplayName(String servletContextName) {
0785: _displayName = servletContextName;
0786: }
0787:
0788: /* ------------------------------------------------------------ */
0789: /**
0790: * @return Returns the resourceBase.
0791: */
0792: public Resource getBaseResource() {
0793: if (_baseResource == null)
0794: return null;
0795: return _baseResource;
0796: }
0797:
0798: /* ------------------------------------------------------------ */
0799: /**
0800: * @return Returns the base resource as a string.
0801: */
0802: public String getResourceBase() {
0803: if (_baseResource == null)
0804: return null;
0805: return _baseResource.toString();
0806: }
0807:
0808: /* ------------------------------------------------------------ */
0809: /**
0810: * @param base The resourceBase to set.
0811: */
0812: public void setBaseResource(Resource base) {
0813: _baseResource = base;
0814: _docRoot = null;
0815:
0816: try {
0817: File file = _baseResource.getFile();
0818: if (file != null) {
0819: _docRoot = file.getCanonicalPath();
0820: if (_docRoot.endsWith(File.pathSeparator))
0821: _docRoot = _docRoot.substring(0,
0822: _docRoot.length() - 1);
0823: }
0824: } catch (Exception e) {
0825: Log.warn(e);
0826: throw new IllegalArgumentException(base.toString());
0827: }
0828: }
0829:
0830: /* ------------------------------------------------------------ */
0831: /**
0832: * @param resourceBase The base resource as a string.
0833: */
0834: public void setResourceBase(String resourceBase) {
0835: try {
0836: setBaseResource(Resource.newResource(resourceBase));
0837: } catch (Exception e) {
0838: Log.warn(e);
0839: throw new IllegalArgumentException(resourceBase);
0840: }
0841: }
0842:
0843: /* ------------------------------------------------------------ */
0844: /**
0845: * @return Returns the mimeTypes.
0846: */
0847: public MimeTypes getMimeTypes() {
0848: return _mimeTypes;
0849: }
0850:
0851: /* ------------------------------------------------------------ */
0852: /**
0853: * @param mimeTypes The mimeTypes to set.
0854: */
0855: public void setMimeTypes(MimeTypes mimeTypes) {
0856: _mimeTypes = mimeTypes;
0857: }
0858:
0859: /* ------------------------------------------------------------ */
0860: /**
0861: */
0862: public void setWelcomeFiles(String[] files) {
0863: _welcomeFiles = files;
0864: }
0865:
0866: /* ------------------------------------------------------------ */
0867: /**
0868: * @return The names of the files which the server should consider to be welcome files in this context.
0869: * @see <a href="http://jcp.org/aboutJava/communityprocess/final/jsr154/index.html">The Servlet Specification</a>
0870: * @see #setWelcomeFiles
0871: */
0872: public String[] getWelcomeFiles() {
0873: return _welcomeFiles;
0874: }
0875:
0876: /* ------------------------------------------------------------ */
0877: /**
0878: * @return Returns the errorHandler.
0879: */
0880: public ErrorHandler getErrorHandler() {
0881: return _errorHandler;
0882: }
0883:
0884: /* ------------------------------------------------------------ */
0885: /**
0886: * @param errorHandler The errorHandler to set.
0887: */
0888: public void setErrorHandler(ErrorHandler errorHandler) {
0889: if (errorHandler != null)
0890: errorHandler.setServer(getServer());
0891: if (getServer() != null)
0892: getServer().getContainer().update(this , _errorHandler,
0893: errorHandler, "errorHandler", true);
0894: _errorHandler = errorHandler;
0895: }
0896:
0897: /* ------------------------------------------------------------ */
0898: public int getMaxFormContentSize() {
0899: return _maxFormContentSize;
0900: }
0901:
0902: /* ------------------------------------------------------------ */
0903: public void setMaxFormContentSize(int maxSize) {
0904: _maxFormContentSize = maxSize;
0905: }
0906:
0907: /* ------------------------------------------------------------ */
0908: public String toString() {
0909:
0910: return this .getClass().getName() + "@"
0911: + Integer.toHexString(hashCode()) + "{"
0912: + getContextPath() + "," + getBaseResource() + "}";
0913: }
0914:
0915: /* ------------------------------------------------------------ */
0916: public synchronized Class loadClass(String className)
0917: throws ClassNotFoundException {
0918: if (className == null)
0919: return null;
0920:
0921: if (_classLoader == null)
0922: return Loader.loadClass(this .getClass(), className);
0923:
0924: return _classLoader.loadClass(className);
0925: }
0926:
0927: /* ------------------------------------------------------------ */
0928: public void addLocaleEncoding(String locale, String encoding) {
0929: if (_localeEncodingMap == null)
0930: _localeEncodingMap = new HashMap();
0931: _localeEncodingMap.put(locale, encoding);
0932: }
0933:
0934: /* ------------------------------------------------------------ */
0935: /**
0936: * Get the character encoding for a locale. The full locale name is first
0937: * looked up in the map of encodings. If no encoding is found, then the
0938: * locale language is looked up.
0939: *
0940: * @param locale a <code>Locale</code> value
0941: * @return a <code>String</code> representing the character encoding for
0942: * the locale or null if none found.
0943: */
0944: public String getLocaleEncoding(Locale locale) {
0945: if (_localeEncodingMap == null)
0946: return null;
0947: String encoding = (String) _localeEncodingMap.get(locale
0948: .toString());
0949: if (encoding == null)
0950: encoding = (String) _localeEncodingMap.get(locale
0951: .getLanguage());
0952: return encoding;
0953: }
0954:
0955: /* ------------------------------------------------------------ */
0956: /*
0957: */
0958: public Resource getResource(String path)
0959: throws MalformedURLException {
0960: if (path == null || !path.startsWith("/"))
0961: throw new MalformedURLException(path);
0962:
0963: if (_baseResource == null)
0964: return null;
0965:
0966: try {
0967: path = URIUtil.canonicalPath(path);
0968: Resource resource = _baseResource.addPath(path);
0969: return resource;
0970: } catch (Exception e) {
0971: Log.ignore(e);
0972: }
0973:
0974: return null;
0975: }
0976:
0977: /* ------------------------------------------------------------ */
0978: /*
0979: */
0980: public Set getResourcePaths(String path) {
0981: try {
0982: path = URIUtil.canonicalPath(path);
0983: Resource resource = getResource(path);
0984:
0985: if (resource != null && resource.exists()) {
0986: if (!path.endsWith("/"))
0987: path = path + "/";
0988:
0989: String[] l = resource.list();
0990: if (l != null) {
0991: HashSet set = new HashSet();
0992: for (int i = 0; i < l.length; i++)
0993: set.add(path + l[i]);
0994: return set;
0995: }
0996: }
0997: } catch (Exception e) {
0998: Log.ignore(e);
0999: }
1000: return Collections.EMPTY_SET;
1001: }
1002:
1003: /* ------------------------------------------------------------ */
1004: /** Context.
1005: * <p>
1006: * Implements {@link javax.servlet.ServletContext} from the {@link javax.servlet} package.
1007: * </p>
1008: * @author gregw
1009: *
1010: */
1011: public class SContext implements ServletContext {
1012: /* ------------------------------------------------------------ */
1013: protected SContext() {
1014: }
1015:
1016: /* ------------------------------------------------------------ */
1017: public ContextHandler getContextHandler() {
1018: // TODO reduce visibility of this method
1019: return ContextHandler.this ;
1020: }
1021:
1022: /* ------------------------------------------------------------ */
1023: /*
1024: * @see javax.servlet.ServletContext#getContext(java.lang.String)
1025: */
1026: public ServletContext getContext(String uripath) {
1027: // TODO this is a very poor implementation!
1028: // TODO move this to Server
1029: ContextHandler context = null;
1030: Handler[] handlers = getServer().getChildHandlersByClass(
1031: ContextHandler.class);
1032: for (int i = 0; i < handlers.length; i++) {
1033: if (handlers[i] == null || !handlers[i].isStarted())
1034: continue;
1035: ContextHandler ch = (ContextHandler) handlers[i];
1036: String context_path = ch.getContextPath();
1037: if (uripath.equals(context_path)
1038: || (uripath.startsWith(context_path) && uripath
1039: .charAt(context_path.length()) == '/')) {
1040: if (context == null
1041: || context_path.length() > context
1042: .getContextPath().length())
1043: context = ch;
1044: }
1045: }
1046:
1047: if (context != null)
1048: return context._scontext;
1049: return null;
1050: }
1051:
1052: /* ------------------------------------------------------------ */
1053: /*
1054: * @see javax.servlet.ServletContext#getMajorVersion()
1055: */
1056: public int getMajorVersion() {
1057: return 2;
1058: }
1059:
1060: /* ------------------------------------------------------------ */
1061: /*
1062: * @see javax.servlet.ServletContext#getMimeType(java.lang.String)
1063: */
1064: public String getMimeType(String file) {
1065: if (_mimeTypes == null)
1066: return null;
1067: Buffer mime = _mimeTypes.getMimeByExtension(file);
1068: if (mime != null)
1069: return mime.toString();
1070: return null;
1071: }
1072:
1073: /* ------------------------------------------------------------ */
1074: /*
1075: * @see javax.servlet.ServletContext#getMinorVersion()
1076: */
1077: public int getMinorVersion() {
1078: return 5;
1079: }
1080:
1081: /* ------------------------------------------------------------ */
1082: /*
1083: * @see javax.servlet.ServletContext#getNamedDispatcher(java.lang.String)
1084: */
1085: public RequestDispatcher getNamedDispatcher(String name) {
1086: return null;
1087: }
1088:
1089: /* ------------------------------------------------------------ */
1090: /*
1091: * @see javax.servlet.ServletContext#getRealPath(java.lang.String)
1092: */
1093: public String getRealPath(String path) {
1094: if (_docRoot == null)
1095: return null;
1096:
1097: if (path == null)
1098: return null;
1099: path = URIUtil.canonicalPath(path);
1100:
1101: if (!path.startsWith("/"))
1102: path = "/" + path;
1103: if (File.separatorChar != '/')
1104: path = path.replace('/', File.separatorChar);
1105:
1106: return _docRoot + path;
1107: }
1108:
1109: /* ------------------------------------------------------------ */
1110: /*
1111: * @see javax.servlet.ServletContext#getRequestDispatcher(java.lang.String)
1112: */
1113: public RequestDispatcher getRequestDispatcher(
1114: String uriInContext) {
1115: return null;
1116: }
1117:
1118: /* ------------------------------------------------------------ */
1119: /*
1120: */
1121: public URL getResource(String path)
1122: throws MalformedURLException {
1123: Resource resource = ContextHandler.this .getResource(path);
1124: if (resource != null && resource.exists())
1125: return resource.getURL();
1126: return null;
1127: }
1128:
1129: /* ------------------------------------------------------------ */
1130: /*
1131: * @see javax.servlet.ServletContext#getResourceAsStream(java.lang.String)
1132: */
1133: public InputStream getResourceAsStream(String path) {
1134: try {
1135: URL url = getResource(path);
1136: if (url == null)
1137: return null;
1138: return url.openStream();
1139: } catch (Exception e) {
1140: Log.ignore(e);
1141: return null;
1142: }
1143: }
1144:
1145: /* ------------------------------------------------------------ */
1146: /*
1147: * @see javax.servlet.ServletContext#getResourcePaths(java.lang.String)
1148: */
1149: public Set getResourcePaths(String path) {
1150: return ContextHandler.this .getResourcePaths(path);
1151: }
1152:
1153: /* ------------------------------------------------------------ */
1154: /*
1155: * @see javax.servlet.ServletContext#getServerInfo()
1156: */
1157: public String getServerInfo() {
1158: return "jetty-" + getServer().getVersion();
1159: }
1160:
1161: /* ------------------------------------------------------------ */
1162: /*
1163: * @see javax.servlet.ServletContext#getServlet(java.lang.String)
1164: */
1165: public Servlet getServlet(String name) throws ServletException {
1166: return null;
1167: }
1168:
1169: /* ------------------------------------------------------------ */
1170: /*
1171: * @see javax.servlet.ServletContext#getServletNames()
1172: */
1173: public Enumeration getServletNames() {
1174: return Collections.enumeration(Collections.EMPTY_LIST);
1175: }
1176:
1177: /* ------------------------------------------------------------ */
1178: /*
1179: * @see javax.servlet.ServletContext#getServlets()
1180: */
1181: public Enumeration getServlets() {
1182: return Collections.enumeration(Collections.EMPTY_LIST);
1183: }
1184:
1185: /* ------------------------------------------------------------ */
1186: /*
1187: * @see javax.servlet.ServletContext#log(java.lang.Exception, java.lang.String)
1188: */
1189: public void log(Exception exception, String msg) {
1190: _logger.warn(msg, exception);
1191: }
1192:
1193: /* ------------------------------------------------------------ */
1194: /*
1195: * @see javax.servlet.ServletContext#log(java.lang.String)
1196: */
1197: public void log(String msg) {
1198: _logger.info(msg, null, null);
1199: }
1200:
1201: /* ------------------------------------------------------------ */
1202: /*
1203: * @see javax.servlet.ServletContext#log(java.lang.String, java.lang.Throwable)
1204: */
1205: public void log(String message, Throwable throwable) {
1206: _logger.warn(message, throwable);
1207: }
1208:
1209: /* ------------------------------------------------------------ */
1210: /*
1211: * @see javax.servlet.ServletContext#getInitParameter(java.lang.String)
1212: */
1213: public String getInitParameter(String name) {
1214: return ContextHandler.this .getInitParameter(name);
1215: }
1216:
1217: /* ------------------------------------------------------------ */
1218: /*
1219: * @see javax.servlet.ServletContext#getInitParameterNames()
1220: */
1221: public Enumeration getInitParameterNames() {
1222: return ContextHandler.this .getInitParameterNames();
1223: }
1224:
1225: /* ------------------------------------------------------------ */
1226: /*
1227: * @see javax.servlet.ServletContext#getAttribute(java.lang.String)
1228: */
1229: public synchronized Object getAttribute(String name) {
1230: Object o = ContextHandler.this .getAttribute(name);
1231: if (o == null)
1232: o = _contextAttributes.getAttribute(name);
1233: return o;
1234: }
1235:
1236: /* ------------------------------------------------------------ */
1237: /*
1238: * @see javax.servlet.ServletContext#getAttributeNames()
1239: */
1240: public synchronized Enumeration getAttributeNames() {
1241: HashSet set = new HashSet();
1242: Enumeration e = _contextAttributes.getAttributeNames();
1243: while (e.hasMoreElements())
1244: set.add(e.nextElement());
1245: e = ContextHandler.this .getAttributeNames();
1246: while (e.hasMoreElements())
1247: set.add(e.nextElement());
1248:
1249: return Collections.enumeration(set);
1250: }
1251:
1252: /* ------------------------------------------------------------ */
1253: /*
1254: * @see javax.servlet.ServletContext#setAttribute(java.lang.String, java.lang.Object)
1255: */
1256: public synchronized void setAttribute(String name, Object value) {
1257: if (_contextAttributes == null)
1258: return;
1259:
1260: Object old_value = _contextAttributes == null ? null
1261: : _contextAttributes.getAttribute(name);
1262:
1263: if (value == null)
1264: _contextAttributes.removeAttribute(name);
1265: else
1266: _contextAttributes.setAttribute(name, value);
1267:
1268: if (_contextAttributeListeners != null) {
1269: ServletContextAttributeEvent event = new ServletContextAttributeEvent(
1270: _scontext, name, old_value == null ? value
1271: : old_value);
1272:
1273: for (int i = 0; i < LazyList
1274: .size(_contextAttributeListeners); i++) {
1275: ServletContextAttributeListener l = (ServletContextAttributeListener) LazyList
1276: .get(_contextAttributeListeners, i);
1277:
1278: if (old_value == null)
1279: l.attributeAdded(event);
1280: else if (value == null)
1281: l.attributeRemoved(event);
1282: else
1283: l.attributeReplaced(event);
1284: }
1285: }
1286: }
1287:
1288: /* ------------------------------------------------------------ */
1289: /*
1290: * @see javax.servlet.ServletContext#removeAttribute(java.lang.String)
1291: */
1292: public synchronized void removeAttribute(String name) {
1293: Object old_value = _contextAttributes.getAttribute(name);
1294: _contextAttributes.removeAttribute(name);
1295: if (old_value != null) {
1296: if (_contextAttributeListeners != null) {
1297: ServletContextAttributeEvent event = new ServletContextAttributeEvent(
1298: _scontext, name, old_value);
1299:
1300: for (int i = 0; i < LazyList
1301: .size(_contextAttributeListeners); i++)
1302: ((ServletContextAttributeListener) LazyList
1303: .get(_contextAttributeListeners, i))
1304: .attributeRemoved(event);
1305: }
1306: }
1307: }
1308:
1309: /* ------------------------------------------------------------ */
1310: /*
1311: * @see javax.servlet.ServletContext#getServletContextName()
1312: */
1313: public String getServletContextName() {
1314: String name = ContextHandler.this .getDisplayName();
1315: if (name == null)
1316: name = ContextHandler.this .getContextPath();
1317: return name;
1318: }
1319:
1320: /* ------------------------------------------------------------ */
1321: /**
1322: * @return Returns the _contextPath.
1323: */
1324: public String getContextPath() {
1325: if ((_contextPath != null) && _contextPath.equals("/"))
1326: return "";
1327:
1328: return _contextPath;
1329: }
1330:
1331: /* ------------------------------------------------------------ */
1332: public String toString() {
1333: return "ServletContext@"
1334: + Integer.toHexString(hashCode())
1335: + "{"
1336: + (getContextPath().equals("") ? "/"
1337: : getContextPath()) + ","
1338: + getBaseResource() + "}";
1339: }
1340:
1341: }
1342:
1343: }
|