KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > web > portlet > handler > PortletModeParameterHandlerMapping


1 /*
2  * Copyright 2002-2006 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.portlet.handler;
18
19 import java.util.HashMap JavaDoc;
20 import java.util.HashSet JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.Map JavaDoc;
23 import java.util.Set JavaDoc;
24
25 import javax.portlet.PortletMode;
26 import javax.portlet.PortletRequest;
27
28 import org.springframework.beans.BeansException;
29 import org.springframework.util.Assert;
30 import org.springframework.util.CollectionUtils;
31 import org.springframework.util.ObjectUtils;
32
33 /**
34  * <p>Implementation of the HandlerMapping interface to map from
35  * the current PortletMode and a request parameter to request handler beans.
36  * The mapping consists of two levels: first the PortletMode and then the
37  * parameter value. In order to be mapped, both elements must
38  * match the mapping definition.</p>
39  *
40  * <p>This is a combination of the methods used in {@link PortletModeHandlerMapping PortletModeHandlerMapping}
41  * and {@link ParameterHandlerMapping ParameterHandlerMapping}. Unlike
42  * those two classes, this mapping cannot be initialized with properties since it
43  * requires a two-level map.</p>
44  *
45  * <p>The default name of the parameter is "action", but can be changed using
46  * {@link #setParameterName setParameterName()}.</p>
47  *
48  * <p>By default, the same parameter value may not be used in two different portlet
49  * modes. This is so that if the portal itself changes the portlet mode, the request
50  * will no longer be valid in the mapping. This behavior can be changed with
51  * {@link #setAllowDuplicateParameters setAllowDupParameters()}.</p>
52  *
53  * <p>The bean configuration for this mapping will look somthing like this:</p>
54  * <pre>
55  * &lt;bean id="portletModeParameterHandlerMapping" class="org.springframework.web.portlet.handler.PortletModeParameterHandlerMapping"&gt;
56  * &lt;property name="portletModeParameterMap"&gt;
57  * &lt;map&gt;
58  * &lt;entry key="view"&gt; &lt;!-- portlet mode: view --&gt;
59  * &lt;map&gt;
60  * &lt;entry key="add"&gt;&lt;ref bean="addItemHandler"/&gt;&lt;/entry&gt;
61  * &lt;entry key="edit"&gt;&lt;ref bean="editItemHandler"/&gt;&lt;/entry&gt;
62  * &lt;entry key="delete"&gt;&lt;ref bean="deleteItemHandler"/&gt;&lt;/entry&gt;
63  * &lt;/map&gt;
64  * &lt;/entry&gt;
65  * &lt;entry key="edit"&gt; &lt;!-- portlet mode: edit --&gt;
66  * &lt;map&gt;
67  * &lt;entry key="prefs"&gt;&lt;ref bean="preferencesHandler"/&gt;&lt;/entry&gt;
68  * &lt;entry key="resetPrefs"&gt;&lt;ref bean="resetPreferencesHandler"/&gt;&lt;/entry&gt;
69  * &lt;/map&gt;
70  * &lt;/entry&gt;
71  * &lt;/map&gt;
72  * &lt;/property&gt;
73  * &lt;/bean&gt;
74  * </pre>
75  *
76  * <p>This mapping can be chained ahead of a {@link PortletModeHandlerMapping PortletModeHandlerMapping},
77  * which can then provide defaults for each mode and an overall default as well.
78  *
79  * @author Rainer Schmitz
80  * @author Yujin Kim
81  * @author John A. Lewis
82  * @author Juergen Hoeller
83  * @since 2.0
84  * @see ParameterMappingInterceptor
85  */

86 public class PortletModeParameterHandlerMapping extends AbstractMapBasedHandlerMapping {
87
88     /**
89      * Default request parameter name to use for mapping to handlers: "action".
90      */

91     public final static String JavaDoc DEFAULT_PARAMETER_NAME = "action";
92
93
94     private String JavaDoc parameterName = DEFAULT_PARAMETER_NAME;
95
96     private Map JavaDoc portletModeParameterMap;
97
98     protected final Map JavaDoc modeHandlerMap = new HashMap JavaDoc();
99
100     private boolean allowDuplicateParameters = false;
101
102     private Set JavaDoc parametersUsed = new HashSet JavaDoc();
103
104
105     /**
106      * Set the name of the parameter used for mapping to handlers.
107      * <p>Default is "action".
108      */

109     public void setParameterName(String JavaDoc parameterName) {
110         Assert.hasText(parameterName, "'parameterName' must not be empty");
111         this.parameterName = parameterName;
112     }
113
114     /**
115      * Set a Map with portlet mode names as keys and another Map as values.
116      * The sub-map has parameter names as keys and handler bean or bean names as values.
117      * <p>Convenient for population with bean references.
118      * @param portletModeParameterMap two-level map of portlet modes and parameters to handler beans
119      */

120     public void setPortletModeParameterMap(Map JavaDoc portletModeParameterMap) {
121         this.portletModeParameterMap = portletModeParameterMap;
122     }
123
124     /**
125      * Set whether to allow duplicate parameter values across different portlet modes.
126      * Default is "false".
127      * <p>Doing this is dangerous because the portlet mode can be changed by the
128      * portal itself and the only way to see that is a rerender of the portlet.
129      * If the same parameter value is legal in multiple modes, then a change in
130      * mode could result in a matched mapping that is not intended and the user
131      * could end up in a strange place in the application.
132      */

133     public void setAllowDuplicateParameters(boolean allowDuplicateParameters) {
134         this.allowDuplicateParameters = allowDuplicateParameters;
135     }
136
137
138     /**
139      * Calls the <code>registerHandlers</code> method in addition
140      * to the superclass's initialization.
141      * @see #registerHandlers
142      */

143     public void initApplicationContext() throws BeansException {
144         super.initApplicationContext();
145         registerHandlers(this.portletModeParameterMap);
146     }
147
148     /**
149      * Register all handlers specified in the Portlet mode map for the corresponding modes.
150      * @param portletModeParameterMap Map with mode names as keys and parameter Maps as values
151      * @throws BeansException if the handler couldn't be registered
152      */

153     protected void registerHandlers(Map JavaDoc portletModeParameterMap) throws BeansException {
154         if (CollectionUtils.isEmpty(portletModeParameterMap)) {
155             logger.warn("'portletModeParameterMap' not set on PortletModeParameterHandlerMapping");
156         }
157         else {
158             for (Iterator JavaDoc it = portletModeParameterMap.entrySet().iterator(); it.hasNext();) {
159                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
160                 String JavaDoc modeKey = (String JavaDoc) entry.getKey();
161                 PortletMode mode = new PortletMode(modeKey);
162                 Object JavaDoc parameterMap = entry.getValue();
163                 if (!(parameterMap instanceof Map JavaDoc)) {
164                     throw new IllegalArgumentException JavaDoc(
165                             "The value for the portlet mode must be a Map of parameter Strings to handler Objects");
166                 }
167                 registerHandler(mode, (Map JavaDoc) parameterMap);
168             }
169         }
170     }
171
172     /**
173      * Register all handlers specified in the given parameter map.
174      * @param parameterMap Map with parameter names as keys and handler beans or bean names as values
175      * @throws BeansException if the handler couldn't be registered
176      */

177     protected void registerHandler(PortletMode mode, Map JavaDoc parameterMap) throws BeansException {
178         for (Iterator JavaDoc it = parameterMap.entrySet().iterator(); it.hasNext();) {
179             Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
180             String JavaDoc parameter = (String JavaDoc) entry.getKey();
181             Object JavaDoc handler = entry.getValue();
182             registerHandler(mode, parameter, handler);
183         }
184     }
185
186     /**
187      * Register the given handler instance for the given PortletMode and parameter value,
188      * under an appropriate lookup key.
189      * @param mode the PortletMode for which this mapping is valid
190      * @param parameter the parameter value to which this handler is mapped
191      * @param handler the handler instance bean
192      * @throws BeansException if the handler couldn't be registered
193      * @throws IllegalStateException if there is a conflicting handler registered
194      * @see #registerHandler(Object, Object)
195      */

196     protected void registerHandler(PortletMode mode, String JavaDoc parameter, Object JavaDoc handler)
197             throws BeansException, IllegalStateException JavaDoc {
198
199         // Check for duplicate parameter values across all portlet modes.
200
if (!this.allowDuplicateParameters && this.parametersUsed.contains(parameter)) {
201             throw new IllegalStateException JavaDoc(
202                     "Duplicate entries for parameter [" + parameter + "] in different Portlet modes");
203         }
204         this.parametersUsed.add(parameter);
205
206         registerHandler(new LookupKey(mode, parameter), handler);
207     }
208
209
210     /**
211      * Returns a lookup key that combines the current PortletMode and the current
212      * value of the specified parameter.
213      * @see javax.portlet.PortletRequest#getPortletMode()
214      * @see #setParameterName
215      */

216     protected Object JavaDoc getLookupKey(PortletRequest request) throws Exception JavaDoc {
217         PortletMode mode = request.getPortletMode();
218         String JavaDoc parameter = request.getParameter(this.parameterName);
219         return new LookupKey(mode, parameter);
220     }
221
222
223     /**
224      * Internal class used as lookup key, combining PortletMode and parameter value.
225      */

226     private static class LookupKey {
227
228         private final PortletMode mode;
229
230         private final String JavaDoc parameter;
231
232         public LookupKey(PortletMode portletMode, String JavaDoc parameter) {
233             this.mode = portletMode;
234             this.parameter = parameter;
235         }
236
237         public boolean equals(Object JavaDoc other) {
238             if (this == other) {
239                 return true;
240             }
241             if (!(other instanceof LookupKey)) {
242                 return false;
243             }
244             LookupKey otherKey = (LookupKey) other;
245             return (this.mode.equals(otherKey.mode) &&
246                     ObjectUtils.nullSafeEquals(this.parameter, otherKey.parameter));
247         }
248
249         public int hashCode() {
250             return (this.mode.hashCode() * 29 + ObjectUtils.nullSafeHashCode(this.parameter));
251         }
252
253         public String JavaDoc toString() {
254             return "Portlet mode '" + this.mode + "', parameter '" + this.parameter + "'";
255         }
256     }
257
258 }
259
Popular Tags