KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > struts > actions > LookupDispatchAction


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

18  
19 package org.apache.struts.actions;
20
21 import java.util.HashMap JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.Locale JavaDoc;
24 import java.util.Map JavaDoc;
25
26 import javax.servlet.ServletException JavaDoc;
27 import javax.servlet.http.HttpServletRequest JavaDoc;
28 import javax.servlet.http.HttpServletResponse JavaDoc;
29
30 import org.apache.struts.Globals;
31 import org.apache.struts.action.ActionForm;
32 import org.apache.struts.action.ActionForward;
33 import org.apache.struts.action.ActionMapping;
34 import org.apache.struts.config.MessageResourcesConfig;
35 import org.apache.struts.config.ModuleConfig;
36 import org.apache.struts.util.MessageResources;
37
38 /**
39  * <p>
40  * An abstract <strong>Action</strong> that dispatches to the subclass mapped
41  * <code>execute</code> method. This is useful in
42  * cases where an HTML form has multiple submit buttons with the same name. The
43  * button name is specified by the <code>parameter</code> property of the
44  * corresponding ActionMapping. To configure the use of this action in your
45  * <code>struts-config.xml</code> file, create an entry like this:</p> <pre>
46  * &lt;action path="/test"
47  * type="org.example.MyAction"
48  * name="MyForm"
49  * scope="request"
50  * input="/test.jsp"
51  * parameter="method"/&gt;
52  * </pre> <p>
53  *
54  * which will use the value of the request parameter named "method" to locate
55  * the corresponding key in ApplicationResources. For example, you might have
56  * the following ApplicationResources.properties:</p> <pre>
57  * button.add=Add Record
58  * button.delete=Delete Record
59  * </pre><p>
60  *
61  * And your JSP would have the following format for submit buttons:</p> <pre>
62  * &lt;html:form action="/test"&gt;
63  * &lt;html:submit property="method"&gt;
64  * &lt;bean:message key="button.add"/&gt;
65  * &lt;/html:submit&gt;
66  * &lt;html:submit property="method"&gt;
67  * &lt;bean:message key="button.delete"/&gt;
68  * &lt;/html:submit&gt;
69  * &lt;/html:form&gt;
70  * </pre> <p>
71  *
72  * Your subclass must implement both getKeyMethodMap and the
73  * methods defined in the map. An example of such implementations are:</p>
74  * <pre>
75  * protected Map getKeyMethodMap() {
76  * Map map = new HashMap();
77  * map.put("button.add", "add");
78  * map.put("button.delete", "delete");
79  * return map;
80  * }
81  *
82  * public ActionForward add(ActionMapping mapping,
83  * ActionForm form,
84  * HttpServletRequest request,
85  * HttpServletResponse response)
86  * throws IOException, ServletException {
87  * // do add
88  * return mapping.findForward("success");
89  * }
90  *
91  * public ActionForward delete(ActionMapping mapping,
92  * ActionForm form,
93  * HttpServletRequest request,
94  * HttpServletResponse response)
95  * throws IOException, ServletException {
96  * // do delete
97  * return mapping.findForward("success");
98  * }
99  * <p>
100  *
101  * <strong>Notes</strong> - If duplicate values exist for the keys returned by
102  * getKeys, only the first one found will be returned. If no corresponding key
103  * is found then an exception will be thrown. You can override the
104  * method <code>unspecified</code> to provide a custom handler. If the submit
105  * was cancelled (a <code>html:cancel</code> button was pressed), the custom
106  * handler <code>cancelled</code> will be used instead.
107  *
108  */

109 public abstract class LookupDispatchAction extends DispatchAction {
110
111     /**
112      * Reverse lookup map from resource value to resource key.
113      */

114     protected Map JavaDoc localeMap = new HashMap JavaDoc();
115
116     /**
117      * Resource key to method name lookup.
118      */

119     protected Map JavaDoc keyMethodMap = null;
120
121     // ---------------------------------------------------------- Public Methods
122

123     /**
124      * Process the specified HTTP request, and create the corresponding HTTP
125      * response (or forward to another web component that will create it).
126      * Return an <code>ActionForward</code> instance describing where and how
127      * control should be forwarded, or <code>null</code> if the response has
128      * already been completed.
129      *
130      * @param mapping The ActionMapping used to select this instance
131      * @param request The HTTP request we are processing
132      * @param response The HTTP response we are creating
133      * @param form The optional ActionForm bean for this request (if any)
134      * @return Describes where and how control should be forwarded.
135      * @exception Exception if an error occurs
136      */

137     public ActionForward execute(
138         ActionMapping mapping,
139         ActionForm form,
140         HttpServletRequest JavaDoc request,
141         HttpServletResponse JavaDoc response)
142         throws Exception JavaDoc {
143
144         if (isCancelled(request)) {
145             ActionForward af = cancelled(mapping, form, request, response);
146             if (af != null) {
147                 return af;
148             }
149         }
150         // Identify the request parameter containing the method name
151
String JavaDoc parameter = mapping.getParameter();
152         if (parameter == null) {
153             String JavaDoc message = messages.getMessage("dispatch.handler", mapping.getPath());
154             throw new ServletException JavaDoc(message);
155         }
156
157         // Identify the string to lookup
158
String JavaDoc methodName = getMethodName(mapping, form, request, response, parameter);
159
160         return dispatchMethod(mapping, form, request, response, methodName);
161
162     }
163
164     /**
165      * This is the first time this Locale is used so build the reverse lookup Map.
166      * Search for message keys in all configured MessageResources for
167      * the current module.
168      */

169     private Map JavaDoc initLookupMap(HttpServletRequest JavaDoc request, Locale JavaDoc userLocale) {
170         Map JavaDoc lookupMap = new HashMap JavaDoc();
171         this.keyMethodMap = this.getKeyMethodMap();
172
173         ModuleConfig moduleConfig =
174                 (ModuleConfig) request.getAttribute(Globals.MODULE_KEY);
175
176         MessageResourcesConfig[] mrc = moduleConfig.findMessageResourcesConfigs();
177
178         // Look through all module's MessageResources
179
for (int i = 0; i < mrc.length; i++) {
180             MessageResources resources = this.getResources(request, mrc[i].getKey());
181
182             // Look for key in MessageResources
183
Iterator JavaDoc iter = this.keyMethodMap.keySet().iterator();
184             while (iter.hasNext()) {
185                 String JavaDoc key = (String JavaDoc) iter.next();
186                 String JavaDoc text = resources.getMessage(userLocale, key);
187
188                 // Found key and haven't added to Map yet, so add the text
189
if ((text != null) && !lookupMap.containsKey(text)) {
190                     lookupMap.put(text, key);
191                 }
192             }
193         }
194
195         return lookupMap;
196     }
197
198     /**
199      * Provides the mapping from resource key to method name.
200      *
201      * @return Resource key / method name map.
202      */

203     protected abstract Map JavaDoc getKeyMethodMap();
204
205     /**
206      * Lookup the method name corresponding to the client request's locale.
207      *
208      * @param request The HTTP request we are processing
209      * @param keyName The parameter name to use as the properties key
210      * @param mapping The ActionMapping used to select this instance
211      *
212      * @return The method's localized name.
213      * @throws ServletException if keyName cannot be resolved
214      * @since Struts 1.2.0
215      */

216     protected String JavaDoc getLookupMapName(
217         HttpServletRequest JavaDoc request,
218         String JavaDoc keyName,
219         ActionMapping mapping)
220         throws ServletException JavaDoc {
221
222         // Based on this request's Locale get the lookupMap
223
Map JavaDoc lookupMap = null;
224
225         synchronized(localeMap) {
226             Locale JavaDoc userLocale = this.getLocale(request);
227             lookupMap = (Map JavaDoc) this.localeMap.get(userLocale);
228
229             if (lookupMap == null) {
230                 lookupMap = this.initLookupMap(request, userLocale);
231                 this.localeMap.put(userLocale, lookupMap);
232             }
233         }
234
235         // Find the key for the resource
236
String JavaDoc key = (String JavaDoc) lookupMap.get(keyName);
237         if (key == null) {
238             String JavaDoc message = messages.getMessage(
239                     "dispatch.resource", mapping.getPath(), keyName);
240             throw new ServletException JavaDoc(message);
241         }
242
243         // Find the method name
244
String JavaDoc methodName = (String JavaDoc) keyMethodMap.get(key);
245         if (methodName == null) {
246             String JavaDoc message = messages.getMessage(
247                     "dispatch.lookup", mapping.getPath(), key);
248             throw new ServletException JavaDoc(message);
249         }
250
251         return methodName;
252     }
253
254     /**
255      * Returns the method name, given a parameter's value.
256      *
257      * @param mapping The ActionMapping used to select this instance
258      * @param form The optional ActionForm bean for this request (if any)
259      * @param request The HTTP request we are processing
260      * @param response The HTTP response we are creating
261      * @param parameter The <code>ActionMapping</code> parameter's name
262      *
263      * @return The method's name.
264      * @since Struts 1.2.0
265      */

266     protected String JavaDoc getMethodName(
267         ActionMapping mapping,
268         ActionForm form,
269         HttpServletRequest JavaDoc request,
270         HttpServletResponse JavaDoc response,
271         String JavaDoc parameter)
272         throws Exception JavaDoc {
273
274         // Identify the method name to be dispatched to.
275
// dispatchMethod() will call unspecified() if name is null
276
String JavaDoc keyName = request.getParameter(parameter);
277         if (keyName == null || keyName.length() == 0) {
278             return null;
279         }
280
281         String JavaDoc methodName = getLookupMapName(request, keyName, mapping);
282
283         return methodName;
284     }
285
286
287 }
288
Popular Tags