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.portlet.handler;
018:
019: import java.util.ArrayList;
020: import java.util.Arrays;
021: import java.util.List;
022:
023: import javax.portlet.PortletRequest;
024:
025: import org.springframework.beans.BeansException;
026: import org.springframework.context.support.ApplicationObjectSupport;
027: import org.springframework.core.Ordered;
028: import org.springframework.web.context.request.WebRequestInterceptor;
029: import org.springframework.web.portlet.HandlerExecutionChain;
030: import org.springframework.web.portlet.HandlerInterceptor;
031: import org.springframework.web.portlet.HandlerMapping;
032:
033: /**
034: * Abstract base class for {@link org.springframework.web.portlet.HandlerMapping}
035: * implementations. Supports ordering, a default handler, and handler interceptors.
036: *
037: * @author Juergen Hoeller
038: * @author John A. Lewis
039: * @since 2.0
040: * @see #getHandlerInternal
041: * @see #setDefaultHandler
042: * @see #setInterceptors
043: * @see org.springframework.web.portlet.HandlerInterceptor
044: */
045: public abstract class AbstractHandlerMapping extends
046: ApplicationObjectSupport implements HandlerMapping, Ordered {
047:
048: private int order = Integer.MAX_VALUE; // default: same as non-Ordered
049:
050: private Object defaultHandler;
051:
052: private final List interceptors = new ArrayList();
053:
054: private boolean applyWebRequestInterceptorsToRenderPhaseOnly = true;
055:
056: private HandlerInterceptor[] adaptedInterceptors;
057:
058: /**
059: * Specify the order value for this HandlerMapping bean.
060: * <p>Default value is <code>Integer.MAX_VALUE</code>, meaning that it's non-ordered.
061: * @see org.springframework.core.Ordered#getOrder()
062: */
063: public final void setOrder(int order) {
064: this .order = order;
065: }
066:
067: public final int getOrder() {
068: return this .order;
069: }
070:
071: /**
072: * Set the default handler for this handler mapping.
073: * This handler will be returned if no specific mapping was found.
074: * <p>Default is <code>null</code>, indicating no default handler.
075: */
076: public void setDefaultHandler(Object defaultHandler) {
077: this .defaultHandler = defaultHandler;
078: }
079:
080: /**
081: * Return the default handler for this handler mapping,
082: * or <code>null</code> if none.
083: */
084: public Object getDefaultHandler() {
085: return this .defaultHandler;
086: }
087:
088: /**
089: * Set the interceptors to apply for all handlers mapped by this handler mapping.
090: * <p>Supported interceptor types are HandlerInterceptor and WebRequestInterceptor.
091: * Each given WebRequestInterceptor will be wrapped in a WebRequestHandlerInterceptorAdapter.
092: * @param interceptors array of handler interceptors, or <code>null</code> if none
093: * @see #adaptInterceptor
094: * @see org.springframework.web.portlet.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: * Specify whether to apply WebRequestInterceptors to the Portlet render phase
103: * only ("true", or whether to apply them to the Portlet action phase as well
104: * ("false").
105: * <p>Default is "true", since WebRequestInterceptors are usually built for
106: * MVC-style handler execution plus rendering process (which is, for example,
107: * the primary target scenario for "Open Session in View" interceptors,
108: * offering lazy loading of persistent objects during view rendering).
109: * Set this to "false" to have WebRequestInterceptors apply to the action
110: * phase as well (for example, in case of an "Open Session in View" interceptor,
111: * to allow for lazy loading outside of a transaction during the action phase).
112: * @see #setInterceptors
113: * @see org.springframework.web.context.request.WebRequestInterceptor
114: * @see WebRequestHandlerInterceptorAdapter#WebRequestHandlerInterceptorAdapter(WebRequestInterceptor, boolean)
115: * @see org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor
116: */
117: public void setApplyWebRequestInterceptorsToRenderPhaseOnly(
118: boolean applyWebRequestInterceptorsToRenderPhaseOnly) {
119: this .applyWebRequestInterceptorsToRenderPhaseOnly = applyWebRequestInterceptorsToRenderPhaseOnly;
120: }
121:
122: /**
123: * Initializes the interceptors.
124: * @see #extendInterceptors(java.util.List)
125: * @see #initInterceptors()
126: */
127: protected void initApplicationContext() throws BeansException {
128: extendInterceptors(this .interceptors);
129: initInterceptors();
130: }
131:
132: /**
133: * Extension hook that subclasses can override to register additional interceptors,
134: * given the configured interceptors (see {@link #setInterceptors}).
135: * <p>Will be invoked before {@link #initInterceptors()} adapts the specified
136: * interceptors into {@link HandlerInterceptor} instances.
137: * <p>The default implementation is empty.
138: * @param interceptors the configured interceptor List (never <code>null</code>),
139: * allowing to add further interceptors before as well as after the existing
140: * interceptors
141: */
142: protected void extendInterceptors(List interceptors) {
143: }
144:
145: /**
146: * Initialize the specified interceptors, adapting them where necessary.
147: * @see #setInterceptors
148: * @see #adaptInterceptor
149: */
150: protected void initInterceptors() {
151: if (!this .interceptors.isEmpty()) {
152: this .adaptedInterceptors = new HandlerInterceptor[this .interceptors
153: .size()];
154: for (int i = 0; i < this .interceptors.size(); i++) {
155: Object interceptor = this .interceptors.get(i);
156: if (interceptor == null) {
157: throw new IllegalArgumentException("Entry number "
158: + i + " in interceptors array is null");
159: }
160: this .adaptedInterceptors[i] = adaptInterceptor(interceptor);
161: }
162: }
163: }
164:
165: /**
166: * Adapt the given interceptor object to the HandlerInterceptor interface.
167: * <p>Supported interceptor types are HandlerInterceptor and WebRequestInterceptor.
168: * Each given WebRequestInterceptor will be wrapped in a WebRequestHandlerInterceptorAdapter.
169: * Can be overridden in subclasses.
170: * @param interceptor the specified interceptor object
171: * @return the interceptor wrapped as HandlerInterceptor
172: * @see #setApplyWebRequestInterceptorsToRenderPhaseOnly
173: * @see org.springframework.web.portlet.HandlerInterceptor
174: * @see org.springframework.web.context.request.WebRequestInterceptor
175: * @see WebRequestHandlerInterceptorAdapter
176: */
177: protected HandlerInterceptor adaptInterceptor(Object interceptor) {
178: if (interceptor instanceof HandlerInterceptor) {
179: return (HandlerInterceptor) interceptor;
180: } else if (interceptor instanceof WebRequestInterceptor) {
181: return new WebRequestHandlerInterceptorAdapter(
182: (WebRequestInterceptor) interceptor,
183: this .applyWebRequestInterceptorsToRenderPhaseOnly);
184: } else {
185: throw new IllegalArgumentException(
186: "Interceptor type not supported: "
187: + interceptor.getClass().getName());
188: }
189: }
190:
191: /**
192: * Return the adapted interceptors as HandlerInterceptor array.
193: * @return the array of HandlerInterceptors, or <code>null</code> if none
194: */
195: protected final HandlerInterceptor[] getAdaptedInterceptors() {
196: return this .adaptedInterceptors;
197: }
198:
199: /**
200: * Look up a handler for the given request, falling back to the default
201: * handler if no specific one is found.
202: * @param request current portlet request
203: * @return the corresponding handler instance, or the default handler
204: * @see #getHandlerInternal
205: */
206: public final HandlerExecutionChain getHandler(PortletRequest request)
207: throws Exception {
208: Object handler = getHandlerInternal(request);
209: if (handler == null) {
210: handler = getDefaultHandler();
211: }
212: if (handler == null) {
213: return null;
214: }
215: // Bean name or resolved handler?
216: if (handler instanceof String) {
217: String handlerName = (String) handler;
218: handler = getApplicationContext().getBean(handlerName);
219: }
220: return getHandlerExecutionChain(handler, request);
221: }
222:
223: /**
224: * Look up a handler for the given request, returning <code>null</code> if no
225: * specific one is found. This method is called by <code>getHandler<code>;
226: * a <code>null</code> return value will lead to the default handler, if one is set.
227: * @param request current portlet request
228: * @return the corresponding handler instance, or <code>null</code> if none found
229: * @throws Exception if there is an internal error
230: * @see #getHandler
231: */
232: protected abstract Object getHandlerInternal(PortletRequest request)
233: throws Exception;
234:
235: /**
236: * Build a HandlerExecutionChain for the given handler, including applicable interceptors.
237: * <p>The default implementation simply builds a standard HandlerExecutionChain with
238: * the given handler and this handler mapping's common interceptors. Subclasses may
239: * override this in order to extend/rearrange the list of interceptors.
240: * @param handler the resolved handler instance (never <code>null</code>)
241: * @param request current portlet request
242: * @return the HandlerExecutionChain (never <code>null</code>)
243: * @see #getAdaptedInterceptors()
244: */
245: protected HandlerExecutionChain getHandlerExecutionChain(
246: Object handler, PortletRequest request) {
247: return new HandlerExecutionChain(handler,
248: getAdaptedInterceptors());
249: }
250:
251: }
|