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