001: /*
002: * Copyright 2002-2007 the original author or authors.
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: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.springframework.web.servlet.handler;
018:
019: import java.util.ArrayList;
020: import java.util.Arrays;
021: import java.util.List;
022:
023: import javax.servlet.http.HttpServletRequest;
024:
025: import org.springframework.beans.BeansException;
026: import org.springframework.core.Ordered;
027: import org.springframework.web.context.request.WebRequestInterceptor;
028: import org.springframework.web.context.support.WebApplicationObjectSupport;
029: import org.springframework.web.servlet.HandlerExecutionChain;
030: import org.springframework.web.servlet.HandlerInterceptor;
031: import org.springframework.web.servlet.HandlerMapping;
032:
033: /**
034: * Abstract base class for {@link org.springframework.web.servlet.HandlerMapping}
035: * implementations. Supports ordering, a default handler, and handler interceptors.
036: *
037: * <p>Note: This base class does <i>not</i> support exposure of the
038: * {@link #PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE}. Support for this attribute
039: * is up to concrete subclasses, typically based on request URL mappings.
040: *
041: * @author Juergen Hoeller
042: * @since 07.04.2003
043: * @see #getHandlerInternal
044: * @see #setDefaultHandler
045: * @see #setInterceptors
046: * @see org.springframework.web.servlet.HandlerInterceptor
047: */
048: public abstract class AbstractHandlerMapping extends
049: WebApplicationObjectSupport implements HandlerMapping, Ordered {
050:
051: private int order = Integer.MAX_VALUE; // default: same as non-Ordered
052:
053: private Object defaultHandler;
054:
055: private final List interceptors = new ArrayList();
056:
057: private HandlerInterceptor[] adaptedInterceptors;
058:
059: /**
060: * Specify the order value for this HandlerMapping bean.
061: * <p>Default value is <code>Integer.MAX_VALUE</code>, meaning that it's non-ordered.
062: * @see org.springframework.core.Ordered#getOrder()
063: */
064: public final void setOrder(int order) {
065: this .order = order;
066: }
067:
068: public final int getOrder() {
069: return this .order;
070: }
071:
072: /**
073: * Set the default handler for this handler mapping.
074: * This handler will be returned if no specific mapping was found.
075: * <p>Default is <code>null</code>, indicating no default handler.
076: */
077: public void setDefaultHandler(Object defaultHandler) {
078: this .defaultHandler = defaultHandler;
079: }
080:
081: /**
082: * Return the default handler for this handler mapping,
083: * or <code>null</code> if none.
084: */
085: public Object getDefaultHandler() {
086: return this .defaultHandler;
087: }
088:
089: /**
090: * Set the interceptors to apply for all handlers mapped by this handler mapping.
091: * <p>Supported interceptor types are HandlerInterceptor and WebRequestInterceptor.
092: * @param interceptors array of handler interceptors, or <code>null</code> if none
093: * @see #adaptInterceptor
094: * @see org.springframework.web.servlet.HandlerInterceptor
095: * @see org.springframework.web.context.request.WebRequestInterceptor
096: */
097: public void setInterceptors(Object[] interceptors) {
098: this .interceptors.addAll(Arrays.asList(interceptors));
099: }
100:
101: /**
102: * Initializes the interceptors.
103: * @see #extendInterceptors(java.util.List)
104: * @see #initInterceptors()
105: */
106: protected void initApplicationContext() throws BeansException {
107: extendInterceptors(this .interceptors);
108: initInterceptors();
109: }
110:
111: /**
112: * Extension hook that subclasses can override to register additional interceptors,
113: * given the configured interceptors (see {@link #setInterceptors}).
114: * <p>Will be invoked before {@link #initInterceptors()} adapts the specified
115: * interceptors into {@link HandlerInterceptor} instances.
116: * <p>The default implementation is empty.
117: * @param interceptors the configured interceptor List (never <code>null</code>),
118: * allowing to add further interceptors before as well as after the existing
119: * interceptors
120: */
121: protected void extendInterceptors(List interceptors) {
122: }
123:
124: /**
125: * Initialize the specified interceptors, adapting them where necessary.
126: * @see #setInterceptors
127: * @see #adaptInterceptor
128: */
129: protected void initInterceptors() {
130: if (!this .interceptors.isEmpty()) {
131: this .adaptedInterceptors = new HandlerInterceptor[this .interceptors
132: .size()];
133: for (int i = 0; i < this .interceptors.size(); i++) {
134: Object interceptor = this .interceptors.get(i);
135: if (interceptor == null) {
136: throw new IllegalArgumentException("Entry number "
137: + i + " in interceptors array is null");
138: }
139: this .adaptedInterceptors[i] = adaptInterceptor(interceptor);
140: }
141: }
142: }
143:
144: /**
145: * Adapt the given interceptor object to the HandlerInterceptor interface.
146: * <p>Supported interceptor types are HandlerInterceptor and WebRequestInterceptor.
147: * Each given WebRequestInterceptor will be wrapped in a WebRequestHandlerInterceptorAdapter.
148: * Can be overridden in subclasses.
149: * @param interceptor the specified interceptor object
150: * @return the interceptor wrapped as HandlerInterceptor
151: * @see org.springframework.web.servlet.HandlerInterceptor
152: * @see org.springframework.web.context.request.WebRequestInterceptor
153: * @see WebRequestHandlerInterceptorAdapter
154: */
155: protected HandlerInterceptor adaptInterceptor(Object interceptor) {
156: if (interceptor instanceof HandlerInterceptor) {
157: return (HandlerInterceptor) interceptor;
158: } else if (interceptor instanceof WebRequestInterceptor) {
159: return new WebRequestHandlerInterceptorAdapter(
160: (WebRequestInterceptor) interceptor);
161: } else {
162: throw new IllegalArgumentException(
163: "Interceptor type not supported: "
164: + interceptor.getClass().getName());
165: }
166: }
167:
168: /**
169: * Return the adapted interceptors as HandlerInterceptor array.
170: * @return the array of HandlerInterceptors, or <code>null</code> if none
171: */
172: protected final HandlerInterceptor[] getAdaptedInterceptors() {
173: return this .adaptedInterceptors;
174: }
175:
176: /**
177: * Look up a handler for the given request, falling back to the default
178: * handler if no specific one is found.
179: * @param request current HTTP request
180: * @return the corresponding handler instance, or the default handler
181: * @see #getHandlerInternal
182: */
183: public final HandlerExecutionChain getHandler(
184: HttpServletRequest request) throws Exception {
185: Object handler = getHandlerInternal(request);
186: if (handler == null) {
187: handler = getDefaultHandler();
188: }
189: if (handler == null) {
190: return null;
191: }
192: // Bean name or resolved handler?
193: if (handler instanceof String) {
194: String handlerName = (String) handler;
195: handler = getApplicationContext().getBean(handlerName);
196: }
197: return getHandlerExecutionChain(handler, request);
198: }
199:
200: /**
201: * Look up a handler for the given request, returning <code>null</code> if no
202: * specific one is found. This method is called by <code>getHandler<code>;
203: * a <code>null</code> return value will lead to the default handler, if one is set.
204: * @param request current HTTP request
205: * @return the corresponding handler instance, or <code>null</code> if none found
206: * @throws Exception if there is an internal error
207: */
208: protected abstract Object getHandlerInternal(
209: HttpServletRequest request) throws Exception;
210:
211: /**
212: * Build a HandlerExecutionChain for the given handler, including applicable interceptors.
213: * <p>The default implementation simply builds a standard HandlerExecutionChain with
214: * the given handler and this handler mapping's common interceptors. Subclasses may
215: * override this in order to extend/rearrange the list of interceptors.
216: * @param handler the resolved handler instance (never <code>null</code>)
217: * @param request current HTTP request
218: * @return the HandlerExecutionChain (never <code>null</code>)
219: * @see #getAdaptedInterceptors()
220: */
221: protected HandlerExecutionChain getHandlerExecutionChain(
222: Object handler, HttpServletRequest request) {
223: return new HandlerExecutionChain(handler,
224: getAdaptedInterceptors());
225: }
226:
227: }
|