001: //========================================================================
002: //Copyright 2006 Mort Bay Consulting Pty. Ltd.
003: //------------------------------------------------------------------------
004: //Licensed under the Apache License, Version 2.0 (the "License");
005: //you may not use this file except in compliance with the License.
006: //You may obtain a copy of the License at
007: //http://www.apache.org/licenses/LICENSE-2.0
008: //Unless required by applicable law or agreed to in writing, software
009: //distributed under the License is distributed on an "AS IS" BASIS,
010: //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011: //See the License for the specific language governing permissions and
012: //limitations under the License.
013: //========================================================================
014:
015: package org.mortbay.jetty.handler;
016:
017: import java.io.IOException;
018: import java.util.ArrayList;
019: import java.util.Iterator;
020: import java.util.List;
021: import java.util.Map;
022:
023: import javax.servlet.ServletException;
024: import javax.servlet.http.HttpServletRequest;
025: import javax.servlet.http.HttpServletResponse;
026:
027: import org.mortbay.jetty.Handler;
028: import org.mortbay.jetty.HttpConnection;
029: import org.mortbay.jetty.Request;
030: import org.mortbay.jetty.servlet.PathMap;
031: import org.mortbay.log.Log;
032: import org.mortbay.util.LazyList;
033:
034: /* ------------------------------------------------------------ */
035: /** ContextHandlerCollection.
036: *
037: * This {@link org.mortbay.jetty.handler.HandlerCollection} is creates a
038: * {@link org.mortbay.jetty.servlet.PathMap} to it's contained handlers based
039: * on the context path of any contained {@link org.mortbay.jetty.handler.ContextHandler}s.
040: * The contexts do not need to be directly contained, only children of the contained handlers.
041: * Multiple contexts may have the same context path and they are called in order until one
042: * handles the request.
043: *
044: * @org.apache.xbean.XBean element="contexts"
045: */
046: public class ContextHandlerCollection extends HandlerCollection {
047: private PathMap _contextMap;
048: private Class _contextClass = ContextHandler.class;
049:
050: /* ------------------------------------------------------------ */
051: /**
052: * Remap the context paths.
053: * TODO make this private
054: */
055: public void mapContexts() {
056: _contextMap = null;
057: Handler[] handlers = getHandlers();
058: if (handlers != null && handlers.length > 0) {
059: PathMap contextMap = new PathMap();
060: List list = new ArrayList();
061: for (int i = 0; i < handlers.length; i++) {
062: list.clear();
063:
064: expandHandler(handlers[i], list, ContextHandler.class);
065:
066: Iterator iter = list.iterator();
067: while (iter.hasNext()) {
068: Handler handler = (Handler) iter.next();
069:
070: String contextPath = ((ContextHandler) handler)
071: .getContextPath();
072:
073: if (contextPath == null
074: || contextPath.indexOf(',') >= 0
075: || contextPath.startsWith("*"))
076: throw new IllegalArgumentException(
077: "Illegal context spec:" + contextPath);
078:
079: if (!contextPath.startsWith("/"))
080: contextPath = '/' + contextPath;
081:
082: if (contextPath.length() > 1) {
083: if (contextPath.endsWith("/"))
084: contextPath += "*";
085: else if (!contextPath.endsWith("/*"))
086: contextPath += "/*";
087: }
088:
089: Object contexts = contextMap.get(contextPath);
090: contexts = LazyList.add(contexts, handlers[i]);
091: contextMap.put(contextPath, contexts);
092: }
093: }
094: _contextMap = contextMap;
095: }
096: }
097:
098: /* ------------------------------------------------------------ */
099: /*
100: * @see org.mortbay.jetty.handler.HandlerCollection#setHandlers(org.mortbay.jetty.Handler[])
101: */
102: public void setHandlers(Handler[] handlers) {
103: _contextMap = null;
104: super .setHandlers(handlers);
105: if (isStarted())
106: mapContexts();
107: }
108:
109: /* ------------------------------------------------------------ */
110: protected void doStart() throws Exception {
111: mapContexts();
112: super .doStart();
113: }
114:
115: /* ------------------------------------------------------------ */
116: /*
117: * @see org.mortbay.jetty.Handler#handle(java.lang.String, javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse, int)
118: */
119: public void handle(String target, HttpServletRequest request,
120: HttpServletResponse response, int dispatch)
121: throws IOException, ServletException {
122: Handler[] handlers = getHandlers();
123: if (handlers == null || handlers.length == 0)
124: return;
125:
126: Request base_request = HttpConnection.getCurrentConnection()
127: .getRequest();
128: PathMap map = _contextMap;
129: if (map != null && target != null && target.startsWith("/")) {
130: Object contexts = map.getLazyMatches(target);
131: for (int i = 0; i < LazyList.size(contexts); i++) {
132: Map.Entry entry = (Map.Entry) LazyList.get(contexts, i);
133: Object list = entry.getValue();
134: for (int j = 0; j < LazyList.size(list); j++) {
135: Handler handler = (Handler) LazyList.get(list, j);
136: handler.handle(target, request, response, dispatch);
137:
138: if (base_request.isHandled())
139: return;
140: }
141: }
142: } else {
143: for (int i = 0; i < handlers.length; i++) {
144: handlers[i].handle(target, request, response, dispatch);
145: if (base_request.isHandled())
146: return;
147: }
148: }
149: }
150:
151: /* ------------------------------------------------------------ */
152: /** Add a context handler.
153: * @param contextPath The context path to add
154: * @return
155: * @throws IllegalAccessException
156: * @throws InstantiationException
157: */
158: public ContextHandler addContext(String contextPath,
159: String resourceBase) {
160: try {
161: ContextHandler context = (ContextHandler) _contextClass
162: .newInstance();
163: context.setContextPath(contextPath);
164: context.setResourceBase(resourceBase);
165: addHandler(context);
166: return context;
167: } catch (Exception e) {
168: Log.warn(e);
169: throw new Error(e);
170: }
171: }
172:
173: /* ------------------------------------------------------------ */
174: /**
175: * @return The class to use to add new Contexts
176: */
177: public Class getContextClass() {
178: return _contextClass;
179: }
180:
181: /* ------------------------------------------------------------ */
182: /**
183: * @param contextClass The class to use to add new Contexts
184: */
185: public void setContextClass(Class contextClass) {
186: if (contextClass == null
187: || !(ContextHandler.class
188: .isAssignableFrom(contextClass)))
189: throw new IllegalArgumentException();
190: _contextClass = contextClass;
191: }
192:
193: }
|