Clover coverage report - Code Coverage for tapestry release 4.0-beta-8
Coverage timestamp: Sat Sep 24 2005 11:50:34 EDT
file stats: LOC: 341   Methods: 11
NCLOC: 142   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
ApplicationServlet.java 50% 75% 81.8% 74.6%
coverage coverage
 1    // Copyright 2004, 2005 The Apache Software Foundation
 2    //
 3    // Licensed under the Apache License, Version 2.0 (the "License");
 4    // you may not use this file except in compliance with the License.
 5    // You may obtain a copy of the License at
 6    //
 7    // http://www.apache.org/licenses/LICENSE-2.0
 8    //
 9    // Unless required by applicable law or agreed to in writing, software
 10    // distributed under the License is distributed on an "AS IS" BASIS,
 11    // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 12    // See the License for the specific language governing permissions and
 13    // limitations under the License.
 14   
 15    package org.apache.tapestry;
 16   
 17    import java.io.IOException;
 18    import java.util.Locale;
 19   
 20    import javax.servlet.ServletConfig;
 21    import javax.servlet.ServletContext;
 22    import javax.servlet.ServletException;
 23    import javax.servlet.http.HttpServlet;
 24    import javax.servlet.http.HttpServletRequest;
 25    import javax.servlet.http.HttpServletResponse;
 26   
 27    import org.apache.commons.logging.Log;
 28    import org.apache.commons.logging.LogFactory;
 29    import org.apache.hivemind.ClassResolver;
 30    import org.apache.hivemind.ErrorHandler;
 31    import org.apache.hivemind.Registry;
 32    import org.apache.hivemind.Resource;
 33    import org.apache.hivemind.impl.DefaultClassResolver;
 34    import org.apache.hivemind.impl.RegistryBuilder;
 35    import org.apache.hivemind.impl.StrictErrorHandler;
 36    import org.apache.hivemind.impl.XmlModuleDescriptorProvider;
 37    import org.apache.hivemind.util.ContextResource;
 38    import org.apache.tapestry.services.ApplicationInitializer;
 39    import org.apache.tapestry.services.ServletRequestServicer;
 40    import org.apache.tapestry.util.exception.ExceptionAnalyzer;
 41   
 42    /**
 43    * Links a servlet container with a Tapestry application. The servlet has some responsibilities
 44    * related to bootstrapping the application (in terms of logging, reading the
 45    * {@link ApplicationSpecification specification}, etc.). It is also responsible for creating or
 46    * locating the {@link IEngine}and delegating incoming requests to it.
 47    * <p>
 48    * The servlet init parameter <code>org.apache.tapestry.specification-path</code> should be set to
 49    * the complete resource path (within the classpath) to the application specification, i.e.,
 50    * <code>/com/foo/bar/MyApp.application</code>.
 51    * <p>
 52    * In some servlet containers (notably <a href="www.bea.com"/>WebLogic </a>) it is necessary to
 53    * invoke {@link HttpSession#setAttribute(String,Object)}in order to force a persistent value to be
 54    * replicated to the other servers in the cluster. Tapestry applications usually only have a single
 55    * persistent value, the {@link IEngine engine}. For persistence to work in such an environment,
 56    * the JVM system property <code>org.apache.tapestry.store-engine</code> must be set to
 57    * <code>true</code>. This will force the application servlet to restore the engine into the
 58    * {@link HttpSession}at the end of each request cycle.
 59    * <p>
 60    * As of release 1.0.1, it is no longer necessary for a {@link HttpSession}to be created on the
 61    * first request cycle. Instead, the HttpSession is created as needed by the {@link IEngine}...
 62    * that is, when a visit object is created, or when persistent page state is required. Otherwise,
 63    * for sessionless requests, an {@link IEngine}from a {@link Pool}is used. Additional work must be
 64    * done so that the {@link IEngine}can change locale <em>without</em> forcing the creation of a
 65    * session; this involves the servlet and the engine storing locale information in a {@link Cookie}.
 66    * <p>
 67    * As of release 4.0, this servlet will also create a HiveMind Registry and manage it.
 68    *
 69    * @author Howard Lewis Ship
 70    */
 71   
 72    public class ApplicationServlet extends HttpServlet
 73    {
 74    private static final long serialVersionUID = -8046042689991538059L;
 75   
 76    /**
 77    * Prefix used to store the HiveMind Registry into the ServletContext. This string is suffixed
 78    * with the servlet name (in case multiple Tapestry applications are executing within a single
 79    * web application).
 80    *
 81    * @since 4.0
 82    */
 83   
 84    private static final String REGISTRY_KEY_PREFIX = "org.apache.tapestry.Registry:";
 85   
 86    private static final Log LOG = LogFactory.getLog(ApplicationServlet.class);
 87   
 88    /**
 89    * Invokes {@link #doService(HttpServletRequest, HttpServletResponse)}.
 90    *
 91    * @since 1.0.6
 92    */
 93   
 94  133 public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException,
 95    ServletException
 96    {
 97  133 doService(request, response);
 98    }
 99   
 100    /**
 101    * @since 2.3
 102    */
 103   
 104    private ClassResolver _resolver;
 105   
 106    /**
 107    * The key used to store the registry into the ServletContext.
 108    *
 109    * @since 4.0
 110    */
 111   
 112    private String _registryKey;
 113   
 114    /**
 115    * @since 4.0
 116    */
 117   
 118    private Registry _registry;
 119   
 120    /**
 121    * @since 4.0
 122    */
 123    private ServletRequestServicer _requestServicer;
 124   
 125    /**
 126    * Handles the GET and POST requests. Performs the following:
 127    * <ul>
 128    * <li>Construct a {@link RequestContext}
 129    * <li>Invoke {@link #getEngine(RequestContext)}to get or create the {@link IEngine}
 130    * <li>Invoke {@link IEngine#service(RequestContext)}on the application
 131    * </ul>
 132    */
 133   
 134  133 protected void doService(HttpServletRequest request, HttpServletResponse response)
 135    throws IOException, ServletException
 136    {
 137  133 try
 138    {
 139  133 _registry.setupThread();
 140   
 141  133 _requestServicer.service(request, response);
 142    }
 143    catch (ServletException ex)
 144    {
 145  0 log("ServletException", ex);
 146   
 147  0 show(ex);
 148   
 149    // Rethrow it.
 150   
 151  0 throw ex;
 152    }
 153    catch (IOException ex)
 154    {
 155  0 log("IOException", ex);
 156   
 157  0 show(ex);
 158   
 159    // Rethrow it.
 160   
 161  0 throw ex;
 162    }
 163    finally
 164    {
 165  133 _registry.cleanupThread();
 166    }
 167    }
 168   
 169  0 protected void show(Exception ex)
 170    {
 171  0 System.err.println("\n\n**********************************************************\n\n");
 172   
 173  0 new ExceptionAnalyzer().reportException(ex, System.err);
 174   
 175  0 System.err.println("\n**********************************************************\n");
 176   
 177    }
 178   
 179    /**
 180    * Invokes {@link #doService(HttpServletRequest, HttpServletResponse)}.
 181    */
 182   
 183  0 public void doPost(HttpServletRequest request, HttpServletResponse response)
 184    throws IOException, ServletException
 185    {
 186  0 doService(request, response);
 187    }
 188   
 189    /**
 190    * Reads the application specification when the servlet is first initialized. All
 191    * {@link IEngine engine instances}will have access to the specification via the servlet.
 192    *
 193    * @see #constructApplicationSpecification()
 194    * @see #createResourceResolver()
 195    */
 196   
 197  41 public void init(ServletConfig config) throws ServletException
 198    {
 199  41 String name = config.getServletName();
 200   
 201  41 _registryKey = REGISTRY_KEY_PREFIX + name;
 202   
 203  41 long startTime = System.currentTimeMillis();
 204  41 long elapsedToRegistry = 0;
 205   
 206  41 super.init(config);
 207   
 208  41 _resolver = createClassResolver();
 209   
 210  41 try
 211    {
 212  41 _registry = constructRegistry(config);
 213   
 214  41 elapsedToRegistry = System.currentTimeMillis() - startTime;
 215   
 216  41 initializeApplication();
 217   
 218  41 config.getServletContext().setAttribute(_registryKey, _registry);
 219    }
 220    catch (Exception ex)
 221    {
 222  0 show(ex);
 223   
 224  0 throw new ServletException(TapestryMessages.servletInitFailure(ex), ex);
 225    }
 226   
 227  41 long elapsedOverall = System.currentTimeMillis() - startTime;
 228   
 229  41 LOG.info(TapestryMessages.servletInit(name, elapsedToRegistry, elapsedOverall));
 230    }
 231   
 232    /**
 233    * Invoked from {@link #init(ServletConfig)}to create a resource resolver for the servlet
 234    * (which will utlimately be shared and used through the application).
 235    * <p>
 236    * This implementation constructs a {@link DefaultResourceResolver}, subclasses may provide a
 237    * different implementation.
 238    *
 239    * @see #getResourceResolver()
 240    * @since 2.3
 241    */
 242   
 243  41 protected ClassResolver createClassResolver()
 244    {
 245  41 return new DefaultClassResolver();
 246    }
 247   
 248    /**
 249    * Invoked from {@link #init(ServletConfig)}to construct the Registry to be used by the
 250    * application.
 251    * <p>
 252    * This looks in the standard places (on the classpath), but also in the WEB-INF/name and
 253    * WEB-INF folders (where name is the name of the servlet).
 254    *
 255    * @since 4.0
 256    */
 257  41 protected Registry constructRegistry(ServletConfig config)
 258    {
 259  41 ErrorHandler errorHandler = constructErrorHandler(config);
 260   
 261  41 RegistryBuilder builder = new RegistryBuilder(errorHandler);
 262   
 263  41 builder.addModuleDescriptorProvider(new XmlModuleDescriptorProvider(_resolver));
 264   
 265  41 String name = config.getServletName();
 266  41 ServletContext context = config.getServletContext();
 267   
 268  41 addModuleIfExists(builder, context, "/WEB-INF/" + name + "/hivemodule.xml");
 269  41 addModuleIfExists(builder, context, "/WEB-INF/hivemodule.xml");
 270   
 271  41 return builder.constructRegistry(Locale.getDefault());
 272    }
 273   
 274    /**
 275    * Invoked by {@link #constructRegistry(ServletConfig)} to create and return an
 276    * {@link ErrorHandler} instance to be used when constructing the Registry (and then to handle
 277    * any runtime exceptions). This implementation returns a new instance of
 278    * {@link org.apache.hivemind.impl.StrictErrorHandler}.
 279    *
 280    * @since 4.0
 281    */
 282  41 protected ErrorHandler constructErrorHandler(ServletConfig config)
 283    {
 284  41 return new StrictErrorHandler();
 285    }
 286   
 287    /**
 288    * Looks for a file in the servlet context; if it exists, it is expected to be a HiveMind module
 289    * descriptor, and is added to the builder.
 290    *
 291    * @since 4.0
 292    */
 293   
 294  82 protected void addModuleIfExists(RegistryBuilder builder, ServletContext context, String path)
 295    {
 296  82 Resource r = new ContextResource(context, path);
 297   
 298  82 if (r.getResourceURL() == null)
 299  82 return;
 300   
 301  0 builder.addModuleDescriptorProvider(new XmlModuleDescriptorProvider(_resolver, r));
 302    }
 303   
 304    /**
 305    * Invoked from {@link #init(ServletConfig)}, after the registry has been constructed, to
 306    * bootstrap the application via the <code>tapestry.MasterApplicationInitializer</code>
 307    * service.
 308    *
 309    * @since 4.0
 310    */
 311  41 protected void initializeApplication()
 312    {
 313  41 ApplicationInitializer ai = (ApplicationInitializer) _registry.getService(
 314    "tapestry.init.MasterInitializer",
 315    ApplicationInitializer.class);
 316   
 317  41 ai.initialize(this);
 318   
 319  41 _registry.cleanupThread();
 320   
 321  41 _requestServicer = (ServletRequestServicer) _registry.getService(
 322    "tapestry.request.ServletRequestServicer",
 323    ServletRequestServicer.class);
 324    }
 325   
 326    /**
 327    * Shuts down the registry (if it exists).
 328    *
 329    * @since 4.0
 330    */
 331  41 public void destroy()
 332    {
 333  41 getServletContext().removeAttribute(_registryKey);
 334   
 335  41 if (_registry != null)
 336    {
 337  41 _registry.shutdown();
 338  41 _registry = null;
 339    }
 340    }
 341    }