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