KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > beehive > netui > pageflow > ProcessPopulate


1 /*
2  * Copyright 2004 The Apache Software Foundation.
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  * $Header:$
17  */

18 package org.apache.beehive.netui.pageflow;
19
20 import org.apache.beehive.netui.util.internal.InternalStringBuilder;
21
22 import java.util.HashMap JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.Map JavaDoc;
25 import javax.servlet.ServletException JavaDoc;
26 import javax.servlet.jsp.el.VariableResolver JavaDoc;
27 import javax.servlet.http.HttpServletRequest JavaDoc;
28 import javax.servlet.http.HttpServletResponse JavaDoc;
29
30 import org.apache.beehive.netui.pageflow.internal.InternalUtils;
31 import org.apache.beehive.netui.script.Expression;
32 import org.apache.beehive.netui.script.ExpressionEvaluator;
33 import org.apache.beehive.netui.script.ExpressionEvaluatorFactory;
34 import org.apache.beehive.netui.script.ExpressionUpdateException;
35 import org.apache.beehive.netui.script.common.ImplicitObjectUtil;
36 import org.apache.beehive.netui.util.Bundle;
37 import org.apache.beehive.netui.util.logging.Logger;
38
39 import org.apache.commons.beanutils.BeanUtils;
40 import org.apache.struts.action.ActionForm;
41
42 /**
43  * Implement the processPopulate stage of the Struts / PageFlow request
44  * processing lifecycle. The {@link #populate(HttpServletRequest, HttpServletResponse, ActionForm, boolean)} method is
45  * invoked in order to take request parameters from the {@link HttpServletRequest}
46  * use the key / value pairs from the request to perform an update to the underlying
47  * JavaBean objects.
48  * <br/>
49  * <br/>
50  * Updates are performed on a key / value pair if the key is an expression; otherwise,
51  * the updates are delegated to the Struts processPopulate infrastructure.
52  *
53  */

54 public class ProcessPopulate
55 {
56     /**
57      * This defines the name of the parameter that will contain the NetUI ID map..
58      */

59     public static final String JavaDoc IDMAP_PARAMETER_NAME = "netuiIdMap";
60
61     private static final Logger _logger = Logger.getInstance(ProcessPopulate.class);
62
63     // these must be kept in sync with the context names specified in the scripting languages
64
private static final String JavaDoc PAGE_FLOW_CONTEXT = "pageFlow";
65     private static final String JavaDoc GLOBAL_APP_CONTEXT = "globalApp";
66
67     private static final String JavaDoc WLW_TAG_HANDLER_PREFIX = "wlw-";
68     private static final String JavaDoc WLW_TAG_HANDLER_SUFFIX = ":";
69
70     private static final Map JavaDoc handlerMap = new HashMap JavaDoc();
71
72     /**
73      * An inner class that represnts the data that will be used to
74      * perform an update. If a key has a prefix handler, this
75      * node is constructed and passed to the prefix handler
76      * so that the prefix handler can change the expression or
77      * values that will be used to execute the expression update.
78      */

79     public final static class ExpressionUpdateNode
80     {
81         public String JavaDoc expression = null;
82         public String JavaDoc[] values = null;
83
84         // can't be constructed outside of this class
85
private ExpressionUpdateNode() {}
86
87         public String JavaDoc toString()
88         {
89             InternalStringBuilder buf = new InternalStringBuilder();
90             buf.append("expression: " + expression + "\n");
91             if(values != null)
92                 for(int i = 0; i < values.length; i++)
93                     buf.append("value[" + i + "]: " + values[i]);
94             else buf.append("values are null");
95
96             return buf.toString();
97         }
98     }
99
100     /**
101      * Register a {@link org.apache.beehive.netui.pageflow.RequestParameterHandler} that is added to handle a
102      * particular prefix which be present as a prefix to a request parameter
103      * key. For keys that match the prefix, the key / value from the request
104      * are put in an {@link ExpressionUpdateNode} struct and handed to the
105      * {@link org.apache.beehive.netui.pageflow.RequestParameterHandler} for processing. The returned {@link ExpressionUpdateNode}
106      * is used to perform an expression update.
107      *
108      * @param prefix the String prefix that will be appended to request paramters that
109      * should pass through the {@link RequestParameterHandler} before being updated.
110      * @param handler the handler that should handle all request paramters with
111      * the given <code>prefix</code>
112      */

113     public static void registerPrefixHandler(String JavaDoc prefix, RequestParameterHandler handler)
114     {
115         // should happen very infrequently
116
synchronized(handlerMap)
117         {
118             String JavaDoc msg = "Register RequestParameterHandler with\n\tprefix: " + prefix + "\n\thandler: " + (handler != null ? handler.getClass().getName(): null);
119
120             if(_logger.isInfoEnabled()) _logger.info(msg);
121
122             if (handlerMap.get(prefix) == null)
123                 handlerMap.put(prefix, handler);
124         }
125     }
126
127     /**
128      * Write the handler name specified onto the given expression.
129      */

130     public static String JavaDoc writeHandlerName(String JavaDoc handler, String JavaDoc expression)
131     {
132         if(!ExpressionEvaluatorFactory.getInstance().isExpression(expression))
133             throw new IllegalArgumentException JavaDoc(Bundle.getErrorString("ProcessPopulate_handler_nonAtomicExpression", new Object JavaDoc[] {expression}));
134
135         if(!handlerMap.containsKey(handler))
136             throw new IllegalStateException JavaDoc(Bundle.getErrorString("ProcessPopulate_handler_notRegistered", new Object JavaDoc[] {handler}));
137
138         InternalStringBuilder buf = new InternalStringBuilder();
139         buf.append(WLW_TAG_HANDLER_PREFIX);
140         buf.append(handler);
141         buf.append(WLW_TAG_HANDLER_SUFFIX);
142         buf.append(expression);
143
144         return buf.toString();
145     }
146
147     /**
148      * Use the request parameters to populate all properties that have expression keys into
149      * the underlying JavaBeans.
150      * Creates a <code>java.util.Map</code> of objects that will be consumed by
151      * Struts processPopulate. This includes all request attributes that
152      * were not expressions
153      *
154      * @param request the current <code>HttpServletRequest</code>
155      * @param form if this request references an action and it has an <code>ActionForm</code>
156      * associated with it, then the <code>form</code> parameter is non-null.
157      * @throws ServletException when an error occurs in populating data after
158      * the request; failure here can be caused by failures in creating
159      * or executing update expressions.
160      */

161     public static void populate(HttpServletRequest JavaDoc request, HttpServletResponse JavaDoc response, ActionForm form, boolean requestHasPopulated)
162         throws ServletException JavaDoc
163     {
164         String JavaDoc key = null;
165         Map JavaDoc strutsProperties = null;
166         ExpressionEvaluator ee = ExpressionEvaluatorFactory.getInstance();
167
168         // a boolean so that we can avoid an instanceof below...
169
boolean isMultipart = false;
170
171         // if this returns null, it's not a mulitpart request
172
Map JavaDoc params = MultipartRequestUtils.handleMultipartRequest(request, form);
173
174         // make adjustments
175
if(params != null)
176             isMultipart = true;
177         else params = request.getParameterMap();
178
179         if(params == null)
180         {
181             if(_logger.isWarnEnabled()) _logger.warn("An error occurred checking a request for multipart status. No model values were updated.");
182             return;
183         }
184
185         /* explicitly build a variable resolver that is used to provide objects that may be updated to the expression engine */
186         VariableResolver JavaDoc variableResolver = ImplicitObjectUtil.getUpdateVariableResolver(form, request, response, true);
187
188         /* todo: are there any ordering issues with using an Iterator vs. an Enumeration here? */
189         Iterator JavaDoc iterator = params.keySet().iterator();
190         while (iterator.hasNext())
191         {
192             key = (String JavaDoc) iterator.next();
193             String JavaDoc expr = null;
194
195             // if there is an expression map, lookup the real expression from the name
196
expr = key;
197             if (_logger.isDebugEnabled())
198                 _logger.debug("key: " + key + " value type: " + params.get(key).getClass().getName() + " value: " + params.get(key));
199
200             try
201             {
202                 Object JavaDoc paramsValue = params.get(key);
203                 if (ee.containsExpression(expr))
204                 {
205                     Object JavaDoc updateValue = null;
206                     if (!isMultipart || paramsValue instanceof String JavaDoc[])
207                     {
208                         String JavaDoc[] values = (String JavaDoc[]) paramsValue;
209
210                         // the only "contains" case that is accepted
211
if (expr.startsWith(WLW_TAG_HANDLER_PREFIX))
212                         {
213                             if (_logger.isDebugEnabled()) _logger.debug("Found an expression requiring a TAG HANDLER");
214
215                             ExpressionUpdateNode node = doTagHandler(key, expr, values, request);
216
217                             expr = node.expression;
218                             values = node.values;
219                         }
220
221                         if (values != null && values.length == 1)
222                             updateValue = values[0];
223                         else
224                             updateValue = values;
225                     }
226                     // handle funky types that Struts returns for a file upload request handler
227
else
228                     {
229                         updateValue = params.get(key);
230                     }
231
232                     try
233                     {
234                         // trap any bad expressions here
235
if (ee.isExpression(expr))
236                         {
237                             // common case, make this fast
238
if (!requestHasPopulated)
239                                 ee.update(expr, updateValue, variableResolver, true);
240                             // must check the expression to make sure pageFlow. and globalApp. don't get executed more than once
241
else
242                             {
243                                 Expression pe = ee.parseExpression(expr);
244                                 String JavaDoc contextName = pe.getContext();
245                                 if (!contextName.equals(PAGE_FLOW_CONTEXT) && !contextName.equals(GLOBAL_APP_CONTEXT))
246                                     ee.update(expr, updateValue, variableResolver, true);
247                             }
248                         }
249                     }
250                             // catch any errors, particularly expression parse failures
251
catch (ExpressionUpdateException e)
252                     {
253                         String JavaDoc s = Bundle.getString("ExprUpdateError", new Object JavaDoc[]{expr, e});
254
255                         // this is the hairy NetUI Warning that gets printed to the console
256
System.err.println(s);
257                         if (_logger.isErrorEnabled()) _logger.error(s);
258
259                         // add binding errors via PageFlowUtils
260
InternalUtils.addBindingUpdateError(request, expr, s, e);
261                     }
262                 }
263                 else
264                 {
265                     if (_logger.isDebugEnabled()) _logger.debug("HTTP request parameter key \"" + key + "\" is not an expression, handle with Struts");
266
267                     if (strutsProperties == null)
268                         strutsProperties = new HashMap JavaDoc();
269
270                     strutsProperties.put(key, paramsValue);
271                 }
272             }
273                     // catch any unexpected exception
274
catch (Exception JavaDoc e)
275             {
276                 String JavaDoc s = Bundle.getString("ProcessPopulate_exprUpdateError", new Object JavaDoc[]{expr, e});
277                 //e.printStackTrace();
278

279                 System.err.println(s);
280
281                 if (_logger.isWarnEnabled()) _logger.warn(s, e);
282
283                 // add binding errors via PageFlowUtils
284
InternalUtils.addBindingUpdateError(request, expr, s, e);
285             }
286         }
287
288         handleStrutsProperties(strutsProperties, form);
289     }
290
291     /**
292      * Process a single key.
293      *
294      * @param key the request key that is being processed
295      * @param request the ServletRequest object representing this request
296      */

297     static final ExpressionUpdateNode doTagHandler(String JavaDoc key, String JavaDoc expression, String JavaDoc[] values, HttpServletRequest JavaDoc request)
298     {
299         // not sure if this array will be mutable. don't want to find out at this point.
300
String JavaDoc[] _values = values;
301
302         // key might be mangled here; make a copy
303
String JavaDoc expr = expression;
304
305         if(_logger.isDebugEnabled()) _logger.debug("Found prefixed tag; handlerName: " + key.substring(WLW_TAG_HANDLER_PREFIX.length(), key.indexOf(WLW_TAG_HANDLER_SUFFIX)));
306             
307         String JavaDoc handlerName = expression.substring(WLW_TAG_HANDLER_PREFIX.length(), expression.indexOf(WLW_TAG_HANDLER_SUFFIX));
308         
309         // execute callback to parameter handler. Generally, these are tags.
310
RequestParameterHandler handler = (RequestParameterHandler)handlerMap.get(handlerName);
311         
312         if(handler != null)
313         {
314             expr = expression.substring(expression.indexOf(WLW_TAG_HANDLER_SUFFIX)+1);
315             
316             if(_logger.isDebugEnabled()) _logger.debug("found handler for prefix \"" + handlerName + "\" type: " +
317                                    (handler != null ? handler.getClass().getName() : null) + "\n\t" +
318                                    "key: \"" + key + "\" expr: \"" + expr + "\"");
319             
320             ExpressionUpdateNode node = new ExpressionUpdateNode();
321             node.expression = expr;
322             node.values = _values;
323             
324             // request, request key, the standalone expression (may have other stuff bracketing the expression
325
handler.process(request, key, expression, node);
326             
327             return node;
328         }
329         else throw new IllegalStateException JavaDoc("Request parameter references a tag handler prefix \"" +
330                                              handlerName + "\" that is not registered for expression \"" + key + "\"");
331     }
332
333     // @struts: org.apache.struts.util.RequestUtils.populate
334
private static final void handleStrutsProperties(Map JavaDoc strutsProperties, ActionForm form)
335     {
336         if(strutsProperties != null)
337         {
338             if(_logger.isDebugEnabled()) _logger.debug("Handle Struts request parameters.");
339
340             // default to Struts for non-expression keys
341
try
342             {
343                 BeanUtils.populate(form, strutsProperties);
344             }
345             catch(Exception JavaDoc e)
346             {
347                 throw new RuntimeException JavaDoc("Exception processing bean and request parameters: ", e);
348             }
349         }
350     }
351 }
352
Popular Tags