KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > web > servlet > handler > AbstractUrlHandlerMapping


1 /*
2  * Copyright 2002-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.web.servlet.handler;
18
19 import java.util.Collections JavaDoc;
20 import java.util.HashMap JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.Map JavaDoc;
23
24 import javax.servlet.http.HttpServletRequest JavaDoc;
25
26 import org.springframework.beans.BeansException;
27 import org.springframework.util.AntPathMatcher;
28 import org.springframework.util.Assert;
29 import org.springframework.util.PathMatcher;
30 import org.springframework.web.servlet.HandlerMapping;
31 import org.springframework.web.util.UrlPathHelper;
32
33 /**
34  * Abstract base class for URL-mapped {@link org.springframework.web.servlet.HandlerMapping}
35  * implementations. Provides infrastructure for mapping handlers to URLs and configurable
36  * URL lookup. For information on the latter, see "alwaysUseFullPath" property.
37  *
38  * <p>Supports direct matches, e.g. a registered "/test" matches "/test", and
39  * various Ant-style pattern matches, e.g. a registered "/t*" pattern matches
40  * both "/test" and "/team", "/test/*" matches all paths in the "/test" directory,
41  * "/test/**" matches all paths below "/test". For details, see the
42  * {@link org.springframework.util.AntPathMatcher AntPathMatcher} javadoc.
43  *
44  * <p>Will search all path patterns to find the most exact match for the
45  * current request path. The most exact match is defined as the longest
46  * path pattern that matches the current request path.
47  *
48  * @author Juergen Hoeller
49  * @since 16.04.2003
50  * @see #setAlwaysUseFullPath
51  * @see #setUrlDecode
52  * @see org.springframework.util.AntPathMatcher
53  */

54 public abstract class AbstractUrlHandlerMapping extends AbstractHandlerMapping {
55
56     private UrlPathHelper urlPathHelper = new UrlPathHelper();
57
58     private PathMatcher pathMatcher = new AntPathMatcher();
59
60     private Object JavaDoc rootHandler;
61
62     private boolean lazyInitHandlers = false;
63
64     private final Map JavaDoc handlerMap = new HashMap JavaDoc();
65
66
67     /**
68      * Set if URL lookup should always use the full path within the current servlet
69      * context. Else, the path within the current servlet mapping is used if applicable
70      * (that is, in the case of a ".../*" servlet mapping in web.xml).
71      * <p>Default is "false".
72      * @see org.springframework.web.util.UrlPathHelper#setAlwaysUseFullPath
73      */

74     public void setAlwaysUseFullPath(boolean alwaysUseFullPath) {
75         this.urlPathHelper.setAlwaysUseFullPath(alwaysUseFullPath);
76     }
77
78     /**
79      * Set if context path and request URI should be URL-decoded. Both are returned
80      * <i>undecoded</i> by the Servlet API, in contrast to the servlet path.
81      * <p>Uses either the request encoding or the default encoding according
82      * to the Servlet spec (ISO-8859-1).
83      * <p>Note: Setting this to "true" requires JDK 1.4 if the encoding differs
84      * from the VM's platform default encoding, as JDK 1.3's URLDecoder class
85      * does not offer a way to specify the encoding.
86      * @see org.springframework.web.util.UrlPathHelper#setUrlDecode
87      */

88     public void setUrlDecode(boolean urlDecode) {
89         this.urlPathHelper.setUrlDecode(urlDecode);
90     }
91
92     /**
93      * Set the UrlPathHelper to use for resolution of lookup paths.
94      * <p>Use this to override the default UrlPathHelper with a custom subclass,
95      * or to share common UrlPathHelper settings across multiple HandlerMappings
96      * and MethodNameResolvers.
97      * @see org.springframework.web.servlet.mvc.multiaction.AbstractUrlMethodNameResolver#setUrlPathHelper
98      */

99     public void setUrlPathHelper(UrlPathHelper urlPathHelper) {
100         this.urlPathHelper = urlPathHelper;
101     }
102
103     /**
104      * Set the PathMatcher implementation to use for matching URL paths
105      * against registered URL patterns. Default is AntPathMatcher.
106      * @see org.springframework.util.AntPathMatcher
107      */

108     public void setPathMatcher(PathMatcher pathMatcher) {
109         Assert.notNull(pathMatcher, "PathMatcher must not be null");
110         this.pathMatcher = pathMatcher;
111     }
112
113     /**
114      * Set the root handler for this handler mapping, that is,
115      * the handler to be registered for the root path ("/").
116      * <p>Default is <code>null</code>, indicating no root handler.
117      */

118     public void setRootHandler(Object JavaDoc rootHandler) {
119         this.rootHandler = rootHandler;
120     }
121
122     /**
123      * Return the root handler for this handler mapping (registered for "/"),
124      * or <code>null</code> if none.
125      */

126     public Object JavaDoc getRootHandler() {
127         return this.rootHandler;
128     }
129
130     /**
131      * Set whether to lazily initialize handlers. Only applicable to
132      * singleton handlers, as prototypes are always lazily initialized.
133      * Default is "false", as eager initialization allows for more efficiency
134      * through referencing the controller objects directly.
135      * <p>If you want to allow your controllers to be lazily initialized,
136      * make them "lazy-init" and set this flag to true. Just making them
137      * "lazy-init" will not work, as they are initialized through the
138      * references from the handler mapping in this case.
139      */

140     public void setLazyInitHandlers(boolean lazyInitHandlers) {
141         this.lazyInitHandlers = lazyInitHandlers;
142     }
143
144
145     /**
146      * Look up a handler for the URL path of the given request.
147      * @param request current HTTP request
148      * @return the handler instance, or <code>null</code> if none found
149      */

150     protected Object JavaDoc getHandlerInternal(HttpServletRequest JavaDoc request) throws Exception JavaDoc {
151         String JavaDoc lookupPath = this.urlPathHelper.getLookupPathForRequest(request);
152         if (logger.isDebugEnabled()) {
153             logger.debug("Looking up handler for [" + lookupPath + "]");
154         }
155         Object JavaDoc handler = lookupHandler(lookupPath, request);
156         if (handler == null) {
157             // We need to care for the default handler directly, since we need to
158
// expose the PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE for it as well.
159
if ("/".equals(lookupPath)) {
160                 handler = getRootHandler();
161             }
162             if (handler == null) {
163                 handler = getDefaultHandler();
164             }
165             if (handler != null) {
166                 exposePathWithinMapping(lookupPath, request);
167             }
168         }
169         return handler;
170     }
171
172     /**
173      * Look up a handler instance for the given URL path.
174      * <p>Supports direct matches, e.g. a registered "/test" matches "/test",
175      * and various Ant-style pattern matches, e.g. a registered "/t*" matches
176      * both "/test" and "/team". For details, see the AntPathMatcher class.
177      * <p>Looks for the most exact pattern, where most exact is defined as
178      * the longest path pattern.
179      * @param urlPath URL the bean is mapped to
180      * @param request current HTTP request (to expose the path within the mapping to)
181      * @return the associated handler instance, or <code>null</code> if not found
182      * @see #exposePathWithinMapping
183      * @see org.springframework.util.AntPathMatcher
184      */

185     protected Object JavaDoc lookupHandler(String JavaDoc urlPath, HttpServletRequest JavaDoc request) {
186         // Direct match?
187
Object JavaDoc handler = this.handlerMap.get(urlPath);
188         if (handler != null) {
189             exposePathWithinMapping(urlPath, request);
190             return handler;
191         }
192         // Pattern match?
193
String JavaDoc bestPathMatch = null;
194         for (Iterator JavaDoc it = this.handlerMap.keySet().iterator(); it.hasNext();) {
195             String JavaDoc registeredPath = (String JavaDoc) it.next();
196             if (this.pathMatcher.match(registeredPath, urlPath) &&
197                     (bestPathMatch == null || bestPathMatch.length() <= registeredPath.length())) {
198                 bestPathMatch = registeredPath;
199             }
200         }
201         if (bestPathMatch != null) {
202             handler = this.handlerMap.get(bestPathMatch);
203             exposePathWithinMapping(this.pathMatcher.extractPathWithinPattern(bestPathMatch, urlPath), request);
204         }
205         return handler;
206     }
207
208     /**
209      * Expose the path within the current mapping as request attribute.
210      * @param pathWithinMapping the path within the current mapping
211      * @param request the request to expose the path to
212      * @see #PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE
213      */

214     protected void exposePathWithinMapping(String JavaDoc pathWithinMapping, HttpServletRequest JavaDoc request) {
215         request.setAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE, pathWithinMapping);
216     }
217
218
219     /**
220      * Register the specified handler for the given URL paths.
221      * @param urlPaths the URLs that the bean should be mapped to
222      * @param beanName the name of the handler bean
223      * @throws BeansException if the handler couldn't be registered
224      * @throws IllegalStateException if there is a conflicting handler registered
225      */

226     protected void registerHandler(String JavaDoc[] urlPaths, String JavaDoc beanName) throws BeansException, IllegalStateException JavaDoc {
227         Assert.notNull(urlPaths, "URL path array must not be null");
228         for (int j = 0; j < urlPaths.length; j++) {
229             registerHandler(urlPaths[j], beanName);
230         }
231     }
232
233     /**
234      * Register the specified handler for the given URL path.
235      * @param urlPath the URL the bean should be mapped to
236      * @param handler the handler instance or handler bean name String
237      * (a bean name will automatically be resolved into the corrresponding handler bean)
238      * @throws BeansException if the handler couldn't be registered
239      * @throws IllegalStateException if there is a conflicting handler registered
240      */

241     protected void registerHandler(String JavaDoc urlPath, Object JavaDoc handler) throws BeansException, IllegalStateException JavaDoc {
242         Assert.notNull(urlPath, "URL path must not be null");
243         Assert.notNull(handler, "Handler object must not be null");
244
245         Object JavaDoc mappedHandler = this.handlerMap.get(urlPath);
246         if (mappedHandler != null) {
247             throw new IllegalStateException JavaDoc(
248                     "Cannot map handler [" + handler + "] to URL path [" + urlPath +
249                     "]: There is already handler [" + mappedHandler + "] mapped.");
250         }
251
252         // Eagerly resolve handler if referencing singleton via name.
253
if (!this.lazyInitHandlers && handler instanceof String JavaDoc) {
254             String JavaDoc handlerName = (String JavaDoc) handler;
255             if (getApplicationContext().isSingleton(handlerName)) {
256                 handler = getApplicationContext().getBean(handlerName);
257             }
258         }
259
260         if (urlPath.equals("/")) {
261             if (logger.isDebugEnabled()) {
262                 logger.debug("Root mapping to handler [" + handler + "]");
263             }
264             setRootHandler(handler);
265         }
266         else if (urlPath.equals("/*")) {
267             if (logger.isDebugEnabled()) {
268                 logger.debug("Default mapping to handler [" + handler + "]");
269             }
270             setDefaultHandler(handler);
271         }
272         else {
273             this.handlerMap.put(urlPath, handler);
274             if (logger.isDebugEnabled()) {
275                 logger.debug("Mapped URL path [" + urlPath + "] onto handler [" + handler + "]");
276             }
277         }
278     }
279
280
281     /**
282      * Return the registered handlers as an unmodifiable Map, with the registered path
283      * as key and the handler object (or handler bean name in case of a lazy-init handler)
284      * as value.
285      * @see #getDefaultHandler()
286      */

287     public final Map JavaDoc getHandlerMap() {
288         return Collections.unmodifiableMap(this.handlerMap);
289     }
290
291 }
292
Popular Tags