Clover coverage report - Code Coverage for tapestry release 4.0-beta-2
Coverage timestamp: Sat Jul 9 2005 22:02:17 EDT
file stats: LOC: 345   Methods: 11
NCLOC: 146   Classes: 1
30 day Evaluation License registered to hlship@comcast.net Your 30 day evaluation period has expired. Please visit http://www.cenqua.com 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  132 public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException,
 99    ServletException
 100    {
 101  132 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  132 protected void doService(HttpServletRequest request, HttpServletResponse response)
 139    throws IOException, ServletException
 140    {
 141  132 try
 142    {
 143  132 _registry.setupThread();
 144   
 145  132 _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  132 _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  41 public void init(ServletConfig config) throws ServletException
 202    {
 203  41 String name = config.getServletName();
 204   
 205  41 _registryKey = REGISTRY_KEY_PREFIX + name;
 206   
 207  41 long startTime = System.currentTimeMillis();
 208  41 long elapsedToRegistry = 0;
 209   
 210  41 super.init(config);
 211   
 212  41 _resolver = createClassResolver();
 213   
 214  41 try
 215    {
 216  41 _registry = constructRegistry(config);
 217   
 218  41 elapsedToRegistry = System.currentTimeMillis() - startTime;
 219   
 220  41 initializeApplication();
 221   
 222  41 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  41 long elapsedOverall = System.currentTimeMillis() - startTime;
 232   
 233  41 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  41 protected ClassResolver createClassResolver() throws ServletException
 248    {
 249  41 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  41 protected Registry constructRegistry(ServletConfig config)
 262    {
 263  41 ErrorHandler errorHandler = constructErrorHandler(config);
 264   
 265  41 RegistryBuilder builder = new RegistryBuilder(errorHandler);
 266   
 267  41 builder.addModuleDescriptorProvider(new XmlModuleDescriptorProvider(_resolver));
 268   
 269  41 String name = config.getServletName();
 270  41 ServletContext context = config.getServletContext();
 271   
 272  41 addModuleIfExists(builder, context, "/WEB-INF/" + name + "/hivemodule.xml");
 273  41 addModuleIfExists(builder, context, "/WEB-INF/hivemodule.xml");
 274   
 275  41 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  41 protected ErrorHandler constructErrorHandler(ServletConfig config)
 287    {
 288  41 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  82 protected void addModuleIfExists(RegistryBuilder builder, ServletContext context, String path)
 299    {
 300  82 Resource r = new ContextResource(context, path);
 301   
 302  82 if (r.getResourceURL() == null)
 303  82 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  41 protected void initializeApplication()
 316    {
 317  41 ApplicationInitializer ai = (ApplicationInitializer) _registry.getService(
 318    "tapestry.init.MasterInitializer",
 319    ApplicationInitializer.class);
 320   
 321  41 ai.initialize(this);
 322   
 323  41 _registry.cleanupThread();
 324   
 325  41 _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  41 public void destroy()
 336    {
 337  41 getServletContext().removeAttribute(_registryKey);
 338   
 339  41 if (_registry != null)
 340    {
 341  41 _registry.shutdown();
 342  41 _registry = null;
 343    }
 344    }
 345    }