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

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.util.HashMap;
37 import java.util.Iterator;
38 import java.util.Map;
39  
40 import javax.servlet.ServletRequest;
41 import javax.servlet.http.HttpServletRequest;
42  
43 import org.chwf.servlet.Controller;
44 import org.chwf.servlet.ControllerException;
45 import org.chwf.servlet.InvocationContext;
46  
47 /**
48  * Class that maps a particular controller. It has utility methods to
49  * invoke the controller reflexively using request data. The mapper for
50  * a particular controller class is a singleton.
51  *
52  * @author <a href="mailto:pfstrack@users.sourceforge.net">Paul Strack</a>
53  */
54 public class ControllerMapper {
55  
56   /** A cache of all mappers. */
571  private static final Map MAPPERS = new HashMap();
58  
59   /**
60    * Invoke the controller for the servlet request. This method is intended to
61    * be the primary entry point for controller invocations. It returns the
62    * {@link InvocationContext} which can be used to determine the view page
63    * and whether any errors were generated.
64    *
65    * <pre>InvocationContext context = ControllerMapper.invoke(request);</pre>
66    *
67    * @param request The request.
68    * @return The controller context.
69    * @throws ControllerException For system errors.
70    */
71   public static InvocationContext invoke(ServletRequest request)
72     throws ControllerException {
7314    HttpServletRequest httpRequest = (HttpServletRequest) request;
7414    String uri = httpRequest.getRequestURI();
7514    Class controllerClass = URIMapper.getControllerClass(uri);
7612    String methodName = URIMapper.getControllerMethod(uri);
7712    ControllerMapper mapper = getMapper(controllerClass);
7812    return mapper.invoke(httpRequest, methodName);
79   }
80  
81   /**
82    * Retrieve the mapper for the controller (a per-class singleton).
83    *
84    * @param controllerClass The controller class.
85    * @return The mapper.
86    * @throws ControllerException If the mapper cannot be initialized.
87    */
88   public static ControllerMapper getMapper(Class controllerClass)
89     throws ControllerException {
9018    synchronized (MAPPERS) {
9118      ControllerMapper mapper = (ControllerMapper) MAPPERS.get(controllerClass);
9218      if (mapper == null) {
939        mapper = new ControllerMapper(controllerClass);
949        MAPPERS.put(controllerClass, mapper);
95       }
9618      return mapper;
970    }
98   }
99  
100   /** The controller class being mapped. */
101   private final Class controllerClass;
102  
103   /** The mapped methods of the controller class. */
10441  private final Map methodMappers = new HashMap();
105  
106   /** The mapped methods of the controller class. */
107   private final ControllerConfig controllerConfig;
108  
109   /**
110    * Constructor for ControllerMapper.
111    *
112    * @param controllerClass The controller being mapped.
113    * @throws ControllerException If the mapper cannot be initialized.
114    */
11541  public ControllerMapper(Class controllerClass) throws ControllerException {
11641    assertIsController(controllerClass);
11741    this.controllerClass = controllerClass;
11841    this.controllerConfig = new ControllerConfig(controllerClass);
11941    addMethodMappers(true);
12041    addMethodMappers(false);
12138  }
122  
123   /**
124    * Invoke the given method of the controller for the given request. The
125    * {@link #invoke(ServletRequest request)} method delegates to this one.
126    *
127    * @param request The request.
128    * @param methodName The name of the method invoked.
129    * @return The invocation context.
130    * @throws ControllerException For system errors.
131    */
132   public InvocationContext invoke(
133     HttpServletRequest request,
134     String methodName)
135     throws ControllerException {
136  
13743    MethodMapper mapper = getMethodMapper(methodName);
13841    Controller controller = Controller.getController(this.controllerClass);
13941    InvocationContext context = controller.initContext();
140  
14141    context.setDefaultView(mapper.getDefaultView());
14241    context.setDefaultErrorPage(mapper.getDefaultErrorPage());
143  
144     try {
14541      invokeStart(controller, context);
14641      invokeControllerMethod(request, mapper, context);
14735    } finally {
1486      invokeStop(controller, context);
149     }
150  
15135    return context;
152   }
153  
154   /**
155    * Invokes controller's start method. Errors are stored in the invocation
156    * context.
157    *
158    * @param controller The controller.
159    * @param context The invocation context.
160    */
161   private void invokeStart(Controller controller, InvocationContext context) {
162     try {
16341      controller.start();
16440    } catch (Exception ex) {
1651      context.handleError(ex);
166     }
16741  }
168  
169   /**
170    * Invokes main controller method, if there are no errors in the invocation
171    * context.
172    *
173    * @param request The servlet request.
174    * @param mapper The method mapper.
175    * @param context The invocation context.
176    * @throws ControllerException For controller exceptions.
177    */
178   private void invokeControllerMethod(
179     HttpServletRequest request,
180     MethodMapper mapper,
181     InvocationContext context)
182     throws ControllerException {
183     try {
18441      if (!context.hasError()) {
18540        context.setResult(mapper.invoke(request));
186       }
18728    } catch (InvocationTargetException ex) {
1882      context.handleError(ex.getTargetException());
1892    } catch (ControllerException ex) {
1906      context.handleError(ex);
1916      throw ex;
192     } catch (Exception ex) {
1935      context.handleError(ex);
194     }
19535  }
196  
197   /**
198    * Invokes controller's stop method. Errors are stored in the invocation
199    * context.
200    *
201    * @param controller The controller.
202    * @param context The invocation context.
203    */
204   private void invokeStop(Controller controller, InvocationContext context) {
205     try {
20641      controller.stop();
20741    } catch (Exception ex) {
2080      context.handleError(ex);
209     }
21041  }
211  
212   /**
213    * Add a set of method mappers. Has a control flag allowing initializer
214    * methods to be added before non-initializers.
215    *
216    * @param initializers True if only initializers should be added. False
217    * if other controller methods are to be added.
218    * @throws ControllerException If the method mappers cannot be initialized.
219    */
220   private void addMethodMappers(boolean initializers)
221     throws ControllerException {
22282    Iterator methodNames = controllerConfig.getMethodNames();
223317    while (methodNames.hasNext()) {
224156      String methodName = methodNames.next().toString();
225156      MethodConfig methodConfig = controllerConfig.getMethodConfig(methodName);
226156      if (!initializers ^ methodConfig.isInitializer()) {
22778        MethodMapper methodMapper = new MethodMapper(methodConfig, this);
22875        methodMappers.put(methodMapper.getMethodName(), methodMapper);
229       }
230     }
23179  }
232  
233   /**
234    * Retrieve a method mapper by method name.
235    *
236    * @param methodName The method name.
237    * @return The method mapper.
238    * @throws ControllerException If the method is not found.
239    */
240   MethodMapper getMethodMapper(String methodName)
241     throws ControllerException {
24266    MethodMapper mapper = (MethodMapper) methodMappers.get(methodName);
24366    if (mapper == null) {
24417      throw new ControllerException(
245         ControllerMessages.MESSAGE_UNKNOWN_METHOD,
246         new Object[] { methodName, this.controllerClass.getName()});
247     } else {
24849      return mapper;
249     }
250   }
251  
252   /**
253    * True if the class is a valid controller. This method tests to ensure
254    * that the controller is subclass of <code>Controller</code> and has a
255    * public no-parameter constructor that can be invoked with exceptions.
256    *
257    * @param controllerClass The class being tested.
258    * @return true if it is a valid controller.
259    * @throws ControllerException If not a valid Controller.
260    */
261   private static boolean assertIsController(Class controllerClass)
262     throws ControllerException {
263  
264     try {
26541      Controller controller = (Controller) controllerClass.newInstance();
26641      return true;
267     } catch (Exception ex) {
2680      Object[] arguments = { controllerClass.getName(), ex };
2690      throw new ControllerException(
270         ControllerMessages.MESSAGE_INVALID_CONTROLLER,
271         arguments);
272     }
273   }
274 }

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.