Clover coverage report - Cactus 1.5 for J2EE API 1.3
Coverage timestamp: Wed Feb 18 2004 09:09:13 EST
file stats: LOC: 449   Methods: 14
NCLOC: 198   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
JettyTestSetup.java 0% 0% 0% 0%
coverage
 1   
 /*
 2   
  * ====================================================================
 3   
  *
 4   
  * The Apache Software License, Version 1.1
 5   
  *
 6   
  * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
 7   
  * reserved.
 8   
  *
 9   
  * Redistribution and use in source and binary forms, with or without
 10   
  * modification, are permitted provided that the following conditions
 11   
  * are met:
 12   
  *
 13   
  * 1. Redistributions of source code must retain the above copyright
 14   
  *    notice, this list of conditions and the following disclaimer.
 15   
  *
 16   
  * 2. Redistributions in binary form must reproduce the above copyright
 17   
  *    notice, this list of conditions and the following disclaimer in
 18   
  *    the documentation and/or other materials provided with the
 19   
  *    distribution.
 20   
  *
 21   
  * 3. The end-user documentation included with the redistribution, if
 22   
  *    any, must include the following acknowlegement:
 23   
  *       "This product includes software developed by the
 24   
  *        Apache Software Foundation (http://www.apache.org/)."
 25   
  *    Alternately, this acknowlegement may appear in the software itself,
 26   
  *    if and wherever such third-party acknowlegements normally appear.
 27   
  *
 28   
  * 4. The names "The Jakarta Project", "Cactus" and "Apache Software
 29   
  *    Foundation" must not be used to endorse or promote products
 30   
  *    derived from this software without prior written permission. For
 31   
  *    written permission, please contact apache@apache.org.
 32   
  *
 33   
  * 5. Products derived from this software may not be called "Apache"
 34   
  *    nor may "Apache" appear in their names without prior written
 35   
  *    permission of the Apache Group.
 36   
  *
 37   
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 38   
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 39   
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 40   
  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 41   
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 42   
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 43   
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 44   
  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 45   
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 46   
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 47   
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 48   
  * SUCH DAMAGE.
 49   
  * ====================================================================
 50   
  *
 51   
  * This software consists of voluntary contributions made by many
 52   
  * individuals on behalf of the Apache Software Foundation.  For more
 53   
  * information on the Apache Software Foundation, please see
 54   
  * <http://www.apache.org/>.
 55   
  *
 56   
  */
 57   
 package org.apache.cactus.extension.jetty;
 58   
 
 59   
 import java.io.File;
 60   
 import java.net.URL;
 61   
 
 62   
 import junit.extensions.TestSetup;
 63   
 import junit.framework.Protectable;
 64   
 import junit.framework.Test;
 65   
 import junit.framework.TestResult;
 66   
 
 67   
 import org.apache.cactus.configuration.BaseConfiguration;
 68   
 import org.apache.cactus.configuration.Configuration;
 69   
 import org.apache.cactus.configuration.FilterConfiguration;
 70   
 import org.apache.cactus.configuration.ServletConfiguration;
 71   
 import org.apache.cactus.server.FilterTestRedirector;
 72   
 import org.apache.cactus.server.ServletTestRedirector;
 73   
 import org.apache.cactus.util.ClassLoaderUtils;
 74   
 
 75   
 /**
 76   
  * Custom JUnit test setup to use to automatically start Jetty. Example:<br/>
 77   
  * <code><pre>
 78   
  * public static Test suite()
 79   
  * {
 80   
  *     TestSuite suite = new TestSuite(Myclass.class);
 81   
  *     return new JettyTestSetup(suite);
 82   
  * }
 83   
  * </pre></code>
 84   
  * 
 85   
  * @author <a href="mailto:vmassol@apache.org">Vincent Massol</a>
 86   
  *
 87   
  * @version $Id: JettyTestSetup.java,v 1.2.2.2 2003/10/28 06:59:24 vmassol Exp $
 88   
  */
 89   
 public class JettyTestSetup extends TestSetup
 90   
 {
 91   
     /**
 92   
      * Name of optional system property that points to a Jetty XML
 93   
      * configuration file.
 94   
      */
 95   
     private static final String CACTUS_JETTY_CONFIG_PROPERTY = 
 96   
         "cactus.jetty.config";
 97   
 
 98   
     /**
 99   
      * Name of optional system property that gives the directory
 100   
      * where JSPs and other resources are located. 
 101   
      */
 102   
     private static final String CACTUS_JETTY_RESOURCE_DIR_PROPERTY = 
 103   
         "cactus.jetty.resourceDir";
 104   
 
 105   
     /**
 106   
      * The configuration file to be used for initializing Jetty.
 107   
      */
 108   
     private File configFile;
 109   
 
 110   
     /**
 111   
      * The directory containing the resources of the web-application.
 112   
      */
 113   
     private File resourceDir;
 114   
 
 115   
     /**
 116   
      * The Jetty server object representing the running instance. It is
 117   
      * used to stop Jetty in {@link #tearDown()}.
 118   
      */
 119   
     private Object server; 
 120   
 
 121   
     /**
 122   
      * @param theTest the test we are decorating (usually a test suite)
 123   
      */
 124  0
     public JettyTestSetup(Test theTest)
 125   
     {
 126  0
         super(theTest);
 127   
     }
 128   
 
 129   
     /**
 130   
      * Make sure that {@link #tearDown} is called if {@link #setUp} fails
 131   
      * to start the container properly. The default 
 132   
      * {@link TestSetup#run(TestResult)} method does not provide this feature
 133   
      * unfortunately.
 134   
      *  
 135   
      * @see TestSetup#run(TestResult)
 136   
      */
 137  0
     public void run(final TestResult theResult)
 138   
     {
 139  0
         Protectable p = new Protectable()
 140   
         {
 141  0
             public void protect() throws Exception
 142   
             {
 143  0
                 try
 144   
                 {
 145  0
                     setUp();
 146  0
                     basicRun(theResult);
 147   
                 }
 148   
                 finally
 149   
                 {
 150  0
                     tearDown();
 151   
                 }
 152   
             }
 153   
         };
 154  0
         theResult.runProtected(this, p);
 155   
     }  
 156   
     
 157   
     /**
 158   
      * Start an embedded Jetty server. It is allowed to pass a Jetty XML as
 159   
      * a system property (<code>cactus.jetty.config</code>) to further 
 160   
      * configure Jetty. Example: 
 161   
      * <code>-Dcactus.jetty.config=./jetty.xml</code>.
 162   
      *
 163   
      * @exception Exception if an error happens during initialization
 164   
      */
 165  0
     protected void setUp() throws Exception
 166   
     {
 167   
         // Note: We are currently using reflection in order not to need Jetty
 168   
         // to compile Cactus. If the code becomes more complex or we need to 
 169   
         // add other initializer, it will be worth considering moving them
 170   
         // to a separate "extension" subproject which will need additional jars
 171   
         // in its classpath (using the same mechanism as the Ant project is
 172   
         // using to conditionally compile tasks).
 173   
 
 174   
         // Create configuration objects
 175  0
         BaseConfiguration baseConfig = new BaseConfiguration();
 176  0
         ServletConfiguration servletConfig = new ServletConfiguration();
 177  0
         FilterConfiguration filterConfig = new FilterConfiguration();
 178   
 
 179   
         // Create a Jetty Server object and configure a listener
 180  0
         this.server = createServer(baseConfig);
 181   
 
 182   
         // Create a Jetty context.
 183  0
         Object context = createContext(this.server, baseConfig);
 184   
         
 185   
         // Add the Cactus Servlet redirector
 186  0
         addServletRedirector(context, servletConfig);
 187   
 
 188   
         // Add the Cactus Jsp redirector
 189  0
         addJspRedirector(context);
 190   
 
 191   
         // Add the Cactus Filter redirector
 192  0
         addFilterRedirector(context, filterConfig);
 193   
 
 194   
         // Configure Jetty with an XML file if one has been specified on the
 195   
         // command line.
 196  0
         if (getConfigFile() != null)
 197   
         {
 198  0
             this.server.getClass().getMethod("configure", 
 199   
                 new Class[] {String.class}).invoke(
 200   
                     this.server, new Object[] {getConfigFile().toString()});
 201   
         }
 202   
 
 203   
         // Start the Jetty server
 204  0
         this.server.getClass().getMethod("start", null).invoke(
 205   
             this.server, null);
 206   
     }
 207   
 
 208   
     /**
 209   
      * Stop the running Jetty server.
 210   
      * 
 211   
      * @exception Exception if an error happens during the shutdown
 212   
      */
 213  0
     protected void tearDown() throws Exception
 214   
     { 
 215  0
         if (this.server != null)
 216   
         { 
 217   
             // First, verify if the server is running
 218  0
             boolean started = ((Boolean) this.server.getClass().getMethod(
 219   
                 "isStarted", null).invoke(this.server, null)).booleanValue(); 
 220   
 
 221   
             // Stop the Jetty server, if started
 222  0
             if (started)
 223   
             {
 224  0
                 this.server.getClass().getMethod("stop", null).invoke(
 225   
                     this.server, null);
 226   
             }
 227   
         } 
 228   
     }
 229   
 
 230   
     /**
 231   
      * Sets the configuration file to use for initializing Jetty.
 232   
      * 
 233   
      * @param theConfigFile The configuration file to set
 234   
      */
 235  0
     public final void setConfigFile(File theConfigFile)
 236   
     {
 237  0
         this.configFile = theConfigFile;
 238   
     }
 239   
 
 240   
     /**
 241   
      * Sets the directory in which Jetty will look for the web-application
 242   
      * resources.
 243   
      * 
 244   
      * @param theResourceDir The resource directory to set
 245   
      */
 246  0
     public final void setResourceDir(File theResourceDir)
 247   
     {
 248  0
         this.resourceDir = theResourceDir;
 249   
     }
 250   
 
 251   
     /**
 252   
      * @return The resource directory, or <code>null</code> if it has not been
 253   
      *         set
 254   
      */
 255  0
     protected final File getConfigFile()
 256   
     {
 257  0
         if (this.configFile == null)
 258   
         {
 259  0
             String configFileProperty = System.getProperty(
 260   
                 CACTUS_JETTY_CONFIG_PROPERTY);
 261  0
             if (configFileProperty != null)
 262   
             {
 263  0
                 this.configFile = new File(configFileProperty);
 264   
             }
 265   
         }
 266  0
         return this.configFile;
 267   
     }
 268   
 
 269   
     /**
 270   
      * @return The resource directory, or <code>null</code> if it has not been
 271   
      *         set
 272   
      */
 273  0
     protected final File getResourceDir()
 274   
     {
 275  0
         if (this.resourceDir == null)
 276   
         {
 277  0
             String resourceDirProperty = System.getProperty(
 278   
                 CACTUS_JETTY_RESOURCE_DIR_PROPERTY);
 279  0
             if (resourceDirProperty != null)
 280   
             {
 281  0
                 this.resourceDir = new File(resourceDirProperty);
 282   
             }
 283   
         }
 284  0
         return this.resourceDir;
 285   
     }
 286   
 
 287   
     /**
 288   
      * Create a Jetty server object and configures a listener on the
 289   
      * port defined in the Cactus context URL property.
 290   
      * 
 291   
      * @param theConfiguration the base Cactus configuration
 292   
      * @return the Jetty <code>Server</code> object
 293   
      * 
 294   
      * @exception Exception if an error happens during initialization
 295   
      */
 296  0
     private Object createServer(Configuration theConfiguration) 
 297   
         throws Exception
 298   
     {
 299   
         // Create Jetty Server object
 300  0
         Class serverClass = ClassLoaderUtils.loadClass(
 301   
             "org.mortbay.jetty.Server", this.getClass());
 302  0
         Object server = serverClass.newInstance();
 303   
 
 304  0
         URL contextURL = new URL(theConfiguration.getContextURL());
 305   
 
 306   
         // Add a listener on the port defined in the Cactus configuration
 307  0
         server.getClass().getMethod("addListener", 
 308   
             new Class[] {String.class})
 309   
             .invoke(server, new Object[] {"" + contextURL.getPort()});
 310   
 
 311  0
         return server;
 312   
     }
 313   
 
 314   
     /**
 315   
      * Create a Jetty Context. We use a <code>WebApplicationContext</code>
 316   
      * because we need to use Servlet Filters.
 317   
      * 
 318   
      * @param theServer the Jetty Server object
 319   
      * @param theConfiguration the base Cactus configuration
 320   
      * @return Object the <code>WebApplicationContext</code> object
 321   
      * 
 322   
      * @exception Exception if an error happens during initialization
 323   
      */
 324  0
     private Object createContext(Object theServer,
 325   
         Configuration theConfiguration) throws Exception
 326   
     {
 327   
         // Add a web application. This creates a WebApplicationContext.
 328   
         // Note: We do not put any WEB-INF/, lib/ nor classes/ directory
 329   
         // in the webapp.
 330  0
         URL contextURL = new URL(theConfiguration.getContextURL());
 331   
 
 332  0
         if (getResourceDir() != null)
 333   
         {
 334  0
             theServer.getClass().getMethod("addWebApplication", 
 335   
                 new Class[] {String.class, String.class})
 336   
                 .invoke(theServer, new Object[] {contextURL.getPath(), 
 337   
                     getResourceDir().toString()});
 338   
         }
 339   
         
 340   
         // Retrieves the WebApplication context created by the
 341   
         // "addWebApplication". We need it to be able to manually configure
 342   
         // other items in the context.
 343  0
         Object context = theServer.getClass().getMethod(
 344   
             "getContext", new Class[] {String.class})
 345   
             .invoke(theServer, new Object[] {contextURL.getPath()});
 346   
 
 347  0
         return context;
 348   
     }
 349   
     
 350   
     /**
 351   
      * Adds the Cactus Servlet redirector configuration
 352   
      * 
 353   
      * @param theContext the Jetty context under which to add the configuration
 354   
      * @param theConfiguration the Cactus Servlet configuration
 355   
      * 
 356   
      * @exception Exception if an error happens during initialization
 357   
      */
 358  0
     private void addServletRedirector(Object theContext,
 359   
         ServletConfiguration theConfiguration) throws Exception
 360   
     {
 361  0
         theContext.getClass().getMethod("addServlet", 
 362   
             new Class[] {String.class, String.class, String.class})
 363   
             .invoke(theContext, 
 364   
             new Object[] {theConfiguration.getDefaultRedirectorName(),
 365   
             "/" + theConfiguration.getDefaultRedirectorName(), 
 366   
             ServletTestRedirector.class.getName()});
 367   
     }
 368   
     
 369   
     /**
 370   
      * Adds the Cactus Jsp redirector configuration. We only add it if the
 371   
      * CACTUS_JETTY_RESOURCE_DIR_PROPERTY has been provided by the user. This
 372   
      * is because JSPs need to be attached to a WebApplicationHandler in Jetty.
 373   
      * 
 374   
      * @param theContext the Jetty context under which to add the configuration
 375   
      * 
 376   
      * @exception Exception if an error happens during initialization
 377   
      */
 378  0
     private void addJspRedirector(Object theContext) throws Exception
 379   
     {
 380  0
         if (getResourceDir() != null)
 381   
         {
 382  0
             theContext.getClass().getMethod("addServlet", 
 383   
                 new Class[] {String.class, String.class})
 384   
                 .invoke(theContext, 
 385   
                 new Object[] {"*.jsp", 
 386   
                 "org.apache.jasper.servlet.JspServlet"});
 387   
 
 388   
             // Get the WebApplicationHandler object in order to be able to 
 389   
             // call the addServlet() method that accpets a forced path.
 390  0
             Object handler = theContext.getClass().getMethod(
 391   
                 "getWebApplicationHandler", 
 392   
                 new Class[] {}).invoke(theContext, new Object[] {});
 393   
 
 394  0
             handler.getClass().getMethod("addServlet", 
 395   
                 new Class[] {String.class, String.class, String.class, 
 396   
                     String.class})
 397   
                 .invoke(handler, 
 398   
                 new Object[] {
 399   
                     "JspRedirector",
 400   
                     "/JspRedirector",
 401   
                     "org.apache.jasper.servlet.JspServlet",
 402   
                     "/jspRedirector.jsp"});
 403   
         }
 404   
     }
 405   
 
 406   
     /**
 407   
      * Adds the Cactus Filter redirector configuration. We only add it if the
 408   
      * CACTUS_JETTY_RESOURCE_DIR_PROPERTY has been provided by the user. This
 409   
      * is because Filters need to be attached to a WebApplicationHandler in 
 410   
      * Jetty.
 411   
      * 
 412   
      * @param theContext the Jetty context under which to add the configuration
 413   
      * @param theConfiguration the Cactus Filter configuration
 414   
      * 
 415   
      * @exception Exception if an error happens during initialization
 416   
      */
 417  0
     private void addFilterRedirector(Object theContext,
 418   
         FilterConfiguration theConfiguration) throws Exception
 419   
     {
 420  0
         if (getResourceDir() != null)
 421   
         {
 422   
             // Get the WebApplicationHandler object in order to be able to add
 423   
             // the Cactus Filter redirector
 424  0
             Object handler = theContext.getClass().getMethod(
 425   
                 "getWebApplicationHandler", 
 426   
                 new Class[] {}).invoke(theContext, new Object[] {});
 427   
     
 428  0
             Object filterHolder = handler.getClass().getMethod("defineFilter",
 429   
                 new Class[] {String.class, String.class})
 430   
                 .invoke(handler, 
 431   
                 new Object[] {theConfiguration.getDefaultRedirectorName(),
 432   
                 FilterTestRedirector.class.getName()});        
 433   
     
 434  0
             filterHolder.getClass().getMethod("addAppliesTo",
 435   
                 new Class[] {String.class})
 436   
                 .invoke(filterHolder, new Object[] {"REQUEST"});        
 437   
     
 438   
             // Map the Cactus Filter redirector to a path
 439  0
             handler.getClass().getMethod("mapPathToFilter", 
 440   
                 new Class[] {String.class, String.class})
 441   
                 .invoke(handler, 
 442   
                 new Object[] {"/" 
 443   
                 + theConfiguration.getDefaultRedirectorName(),
 444   
                 theConfiguration.getDefaultRedirectorName()});
 445   
         }
 446   
     }
 447   
 
 448   
 }
 449