Coverage details for org.chwf.servlet.engine.MethodMapper

LineHitsSource
1 /*
2 Chrysalis Web Framework [http://chrysalis.sourceforge.net]
3 Copyright (c) 2002, 2003, 2004, Paul Strack
4  
5 All rights reserved.
6  
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions are met:
9  
10 1. Redistributions of source code must retain the above copyright notice, this
11 list of conditions and the following disclaimer.
12  
13 2. Redistributions in binary form must reproduce the above copyright notice,
14 this list of conditions and the following disclaimer in the documentation
15 and/or other materials provided with the distribution.
16  
17 3. Neither the name of the copyright holder nor the names of its contributors
18 may be used to endorse or promote products derived from this software without
19 specific prior written permission.
20  
21 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
22 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
25 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
28 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
30 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32  
33 package org.chwf.servlet.engine;
34  
35 import java.lang.reflect.InvocationTargetException;
36 import java.lang.reflect.Method;
37 import java.util.HashMap;
38 import java.util.Iterator;
39 import java.util.LinkedList;
40 import java.util.List;
41 import java.util.Map;
42  
43 import javax.servlet.http.HttpServletRequest;
44  
45 import org.chwf.converter.ConversionException;
46 import org.chwf.plugin.AuthenticationException;
47 import org.chwf.plugin.User;
48 import org.chwf.servlet.Controller;
49 import org.chwf.servlet.ControllerException;
50 import org.chwf.servlet.MissingParameterException;
51 import org.chwf.servlet.MultiMissingParameterException;
52 import org.chwf.servlet.MultiParameterException;
53 import org.chwf.servlet.ParameterException;
54 import org.chwf.util.MiscUtils;
55  
56 /**
57  * Mapper for methods. It stores the information necessary to invoke
58  * the method through reflection and pass it request data. Note that
59  * this method uses the term "arguments" to refer to arguments of the
60  * Java method being invoked, and reserves "parameters" to refer to
61  * request parameters.
62  *
63  * @author <a href="mailto:pfstrack@users.sourceforge.net">Paul Strack</a>
64  */
65 class MethodMapper {
66  
67   /** An empty string array. */
681  private static final String[] EMPTY_STRING_ARRAY = new String[0];
69  
70   /** The initialization method prefix. */
71   private static final String INIT_METHOD_PREFIX = "get";
72  
73   /** The controller class. */
74   private final Class controllerClass;
75  
76   /** The method being mapped. */
77   private final Method method;
78  
79   /** The method's default view. */
80   private final String defaultView;
81  
82   /** The method's default error page. */
83   private final String defaultErrorPage;
84  
85   /** Array of method roles, for security. */
86   private final String[] roles;
87  
88   /** Value indicating that the method is a bean initializer. */
89   private final boolean isInitializer;
90  
91   /** The method's argument mappers. */
92   private ArgumentMapper[] mappers;
93  
94   /** Method configuration. */
95   private final MethodConfig methodConfig;
96  
97   /** Controller mapper. */
98   private ControllerMapper controllerMapper;
99  
100   /**
101    * Get an initialization (getter) method for the given parameter. This
102    * method can only have simple (non-bean) parameters.
103    *
104    * @param parameter The request parameter.
105    * @return A MethodMapper for the init method, or null if there is none.
106    */
107   MethodMapper getInitMethod(String parameter) {
108     try {
10923      String methodName = INIT_METHOD_PREFIX + MiscUtils.capitalize(parameter);
11023      return this.controllerMapper.getMethodMapper(methodName);
111     } catch (ControllerException ex) {
11215      return null;
113     }
114   }
115  
116   /**
117    * Constructor for MethodMapper.
118    *
119    * @param methodConfig The method configuration.
120    * @param controllerMapper The controller mapper.
121    * @throws ControllerException If the method cannot be mapped.
122    */
123   MethodMapper(MethodConfig methodConfig, ControllerMapper controllerMapper)
12478    throws ControllerException {
125     try {
12678      this.controllerMapper = controllerMapper;
12778      this.methodConfig = methodConfig;
12878      this.isInitializer = methodConfig.isInitializer();
12978      this.controllerClass = methodConfig.getController();
13078      this.method = methodConfig.getMethod();
13178      this.defaultView = methodConfig.getDefaultView();
13278      this.defaultErrorPage = methodConfig.getDefaultErrorPage();
13378      this.roles = methodConfig.getRoles();
13478      createArgumentMappers(method);
13575    } catch (ControllerException ex) {
1363      throw ex;
137     } catch (Exception ex) {
1380      Object[] args =
139         { this.method.getName(), this.controllerClass.getName(), ex };
1400      throw new ControllerException(
141         ControllerMessages.MESSAGE_FAILED_METHOD_MAPPER_INIT,
142         args);
143     }
14475  }
145  
146   /**
147    * Whether the method is a bean initializer.
148    *
149    * @return Whether the method is a bean initializer.
150    */
151   boolean isInitializer() {
15228    return isInitializer;
153   }
154  
155   /**
156    * The method.
157    *
158    * @return The method.
159    */
160   Method getMethod() {
1618    return method;
162   }
163  
164   /**
165    * The method name.
166    *
167    * @return The method name.
168    */
169   String getMethodName() {
17079    return this.method.getName();
171   }
172  
173   /**
174    * The controller class.
175    *
176    * @return The controller class.
177    */
178   Class getControllerClass() {
1793    return this.controllerClass;
180   }
181  
182   /**
183    * The default view for redirection.
184    *
185    * @return The default view for redirection.
186    */
187   String getDefaultView() {
18841    return this.defaultView;
189   }
190  
191   /**
192    * The default error page for error handling.
193    *
194    * @return The default error page for error handling.
195    */
196   String getDefaultErrorPage() {
19741    return defaultErrorPage;
198   }
199  
200   /**
201    * Invoke the mapped method, passing it parameter data from the request.
202    *
203    * @param request Must contain the correct parameter data.
204    * @return The return value of the method.
205    * @throws InvocationTargetException If the underlying method invocation
206    * fails.
207    * @throws ParameterException If there is a problem with a request parameter.
208    * @throws ControllerException For general configuration problems.
209    * @throws AuthenticationException With error message for security failure.
210    */
211   Object invoke(HttpServletRequest request)
212     throws
213       InvocationTargetException,
214       ParameterException,
215       ControllerException,
216       AuthenticationException {
217     try {
21846      checkSecurity();
21944      return method.invoke(getController(), getArgumentValues(request));
220     } catch (IllegalAccessException ex) {
221       // This should not happen, but just in case ...
2220      Object[] args = { getMethodName(), getControllerClass().getName()};
2230      throw new ControllerException(
224         ControllerMessages.MESSAGE_METHOD_NOT_PUBLIC,
225         new Object[] { getMethodName(), getControllerClass().getName()});
226     }
227   }
228  
229   /**
230    * Initialize arguments for this method.
231    *
232    * @param method The method object.
233    * @throws ControllerException If argument mappers cannot be initialized.
234    * @throws ConversionException If there a conversion failures.
235    */
236   private void createArgumentMappers(Method method)
237     throws ControllerException, ConversionException {
23878    Class[] types = method.getParameterTypes();
23978    String[] arguments = methodConfig.getParameterNames();
24078    Object[] defaults = methodConfig.getParameterDefaults();
24178    this.mappers = new ArgumentMapper[types.length];
242  
243107    for (int i = 0; i < types.length; i++) {
24432      this.mappers[i] =
245         ArgumentMapper.newInstance(arguments[i], types[i], defaults[i], this);
246     }
24775  }
248  
249   /**
250    * Convert request data into objects via the argument mappers.
251    *
252    * @param request The request.
253    * @return Request data as method argument objects.
254    * @throws ParameterException With accumulated errors.
255    * @throws MissingParameterException For missing parameters.
256    */
257   private Object[] getArgumentValues(HttpServletRequest request)
258     throws ParameterException, MissingParameterException {
25944    Object[] args = new Object[this.mappers.length];
260  
26144    List missingParams = null;
26244    Map invalidParams = null;
263  
26470    for (int i = 0; i < mappers.length; i++) {
265       try {
26626        args[i] = mappers[i].format(request);
26717      } catch (MultiMissingParameterException ex) {
2683        missingParams = addMissingParams(missingParams, ex);
2693      } catch (MissingParameterException ex) {
2703        missingParams = addMissingParams(missingParams, ex.getParameter());
2713      } catch (MultiParameterException ex) {
2722        invalidParams = addInvalidParams(invalidParams, ex);
2732      } catch (ParameterException ex) {
2741        invalidParams = addInvalidParams(invalidParams, ex);
275       }
276     }
277  
27844    if (missingParams != null) {
2796      throw new MultiMissingParameterException(missingParams);
280     }
28138    if (invalidParams != null) {
2823      throw new MultiParameterException(invalidParams);
283     }
28435    return args;
285   }
286  
287   /**
288    * Accumulate missing parameters.
289    *
290    * @param missingParams Running list of missing parameters.
291    * @param ex With more missing parameters.
292    * @return The updated list.
293    */
294   private List addMissingParams(
295     List missingParams,
296     MultiMissingParameterException ex) {
297  
2983    String[] parameters = ex.getParameters();
2997    for (int j = 0; j < parameters.length; j++) {
3004      String name = parameters[j];
3014      missingParams = addMissingParams(missingParams, name);
302     }
3033    return missingParams;
304   }
305  
306   /**
307    * Accumulate missing parameters.
308    *
309    * @param missingParams Running list of missing parameters.
310    * @param name Additional missing parameter.
311    * @return The updated list.
312    */
313   private List addMissingParams(List missingParams, String name) {
3147    if (missingParams == null) {
3156      missingParams = new LinkedList();
316     }
3177    missingParams.add(name);
3187    return missingParams;
319   }
320  
321   /**
322    * Accumulate invalid parameters.
323    *
324    * @param invalidParams Running list of invalid parameters.
325    * @param ex With more invalid parameters.
326    * @return The updated list.
327    */
328   private Map addInvalidParams(Map invalidParams, MultiParameterException ex) {
3292    Iterator it = ex.getParameterNames();
3307    while (it.hasNext()) {
3313      String name = (String) it.next();
3323      String error = ex.getMessage(name);
3333      invalidParams = addInvalidParams(invalidParams, name, error);
334     }
3352    return invalidParams;
336   }
337  
338   /**
339    * Accumulate invalid parameters.
340    *
341    * @param invalidParams Running list of invalid parameters.
342    * @param ex Another invalid parameters.
343    * @return The updated list.
344    */
345   private Map addInvalidParams(Map invalidParams, ParameterException ex) {
3461    return addInvalidParams(invalidParams, ex.getParameter(), ex.getMessage());
347   }
348  
349   /**
350    * Accumulate invalid parameters.
351    *
352    * @param invalidParams Running list of invalid parameters.
353    * @param name Another invalid parameters.
354    * @param error The error message.
355    * @return The updated list.
356    */
357   private Map addInvalidParams(Map invalidParams, String name, String error) {
3584    if (invalidParams == null) {
3593      invalidParams = new HashMap();
360     }
3614    invalidParams.put(name, error);
3624    return invalidParams;
363   }
364  
365   /**
366    * Get controller singleton.
367    *
368    * @return The controller singleton.
369    * @throws ControllerException If the controller cannot be initialized.
370    */
371   private Controller getController() throws ControllerException {
37244    return Controller.getController(this.controllerClass);
373   }
374  
375   /**
376    * Check security constraints, to ensure that each user belongs to at least
377    * one of the specified roles for this method.
378    *
379    * @throws AuthenticationException With error message for security failure.
380    */
381   private void checkSecurity() throws AuthenticationException {
38246    if (this.roles.length > 0) {
3834      User.getInstance().check(roles);
384     }
38544  }
386 }

this report was generated by version 1.0.5 of jcoverage.
visit www.jcoverage.com for updates.

copyright © 2003, jcoverage ltd. all rights reserved.
Java is a trademark of Sun Microsystems, Inc. in the United States and other countries.