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