Clover coverage report - Cactus 1.5 for J2EE API 1.2
Coverage timestamp: Wed Feb 18 2004 09:04:33 EST
file stats: LOC: 482   Methods: 15
NCLOC: 285   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
CactusTask.java 31.6% 33.6% 46.7% 34.4%
coverage coverage
 1   
 /*
 2   
  * ====================================================================
 3   
  *
 4   
  * The Apache Software License, Version 1.1
 5   
  *
 6   
  * Copyright (c) 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.integration.ant;
 58   
 
 59   
 import java.io.File;
 60   
 import java.net.MalformedURLException;
 61   
 import java.net.URL;
 62   
 import java.util.ArrayList;
 63   
 import java.util.Enumeration;
 64   
 import java.util.List;
 65   
 import java.util.ResourceBundle;
 66   
 
 67   
 import org.apache.cactus.integration.ant.container.Container;
 68   
 import org.apache.cactus.integration.ant.container.ContainerRunner;
 69   
 import org.apache.cactus.integration.ant.container.DeployableFile;
 70   
 import org.apache.cactus.integration.ant.container.EarParser;
 71   
 import org.apache.cactus.integration.ant.container.WarParser;
 72   
 import org.apache.cactus.integration.ant.util.AntLog;
 73   
 import org.apache.cactus.integration.ant.util.AntTaskFactory;
 74   
 import org.apache.cactus.integration.ant.util.PropertySet;
 75   
 import org.apache.tools.ant.BuildException;
 76   
 import org.apache.tools.ant.Project;
 77   
 import org.apache.tools.ant.Task;
 78   
 import org.apache.tools.ant.taskdefs.optional.junit.JUnitTask;
 79   
 import org.apache.tools.ant.taskdefs.optional.junit.JUnitTest;
 80   
 import org.apache.tools.ant.types.Environment;
 81   
 import org.apache.tools.ant.types.Environment.Variable;
 82   
 
 83   
 /**
 84   
  * An Ant task that extends the optional JUnit task to provide support for
 85   
  * in-container testing.
 86   
  * 
 87   
  * @author <a href="mailto:cmlenz@apache.org">Christopher Lenz</a>
 88   
  * @author <a href="mailto:vmassol@apache.org">Vincent Massol</a>
 89   
  *
 90   
  * @version $Id: CactusTask.java,v 1.20.2.5 2003/10/25 17:22:06 vmassol Exp $
 91   
  */
 92   
 public class CactusTask extends JUnitTask
 93   
 {
 94   
     // Instance Variables ------------------------------------------------------
 95   
 
 96   
     /**
 97   
      * The nested containerset element.
 98   
      */
 99   
     private ContainerSet containerSet;
 100   
 
 101   
     /**
 102   
      * The archive that contains the enterprise application that should be
 103   
      * tested.
 104   
      */
 105   
     private File earFile;
 106   
 
 107   
     /**
 108   
      * The archive that contains the web-app that is ready to be tested.
 109   
      */
 110   
     private File warFile;
 111   
 
 112   
     /**
 113   
      * System properties that will be set in the container JVM.
 114   
      */
 115   
     private List systemProperties = new ArrayList();
 116   
     
 117   
     /**
 118   
      * The factory for creating ant tasks that is passed to the containers.
 119   
      */
 120   
     private AntTaskFactory antTaskFactory = new AntTaskFactory()
 121   
     {
 122  0
         public Task createTask(String theName)
 123   
         {
 124  0
             Task retVal = getProject().createTask(theName);
 125  0
             if (retVal != null)
 126   
             {
 127  0
                 retVal.setTaskName(getTaskName());
 128  0
                 retVal.setLocation(getLocation());
 129  0
                 retVal.setOwningTarget(getOwningTarget());
 130   
             }
 131  0
             return retVal;
 132   
         }
 133   
     };
 134   
 
 135   
     // Constructors ------------------------------------------------------------
 136   
     
 137   
     /**
 138   
      * Constructor.
 139   
      * 
 140   
      * @throws Exception If the constructor of JUnitTask throws an exception
 141   
      */
 142  7
     public CactusTask() throws Exception
 143   
     {
 144   
         // TODO: Fix comment for this constructor as it doesn't seem quite 
 145   
         // right. Explain why we don't call the super constructor?
 146   
     }
 147   
 
 148   
     // Public Methods ----------------------------------------------------------
 149   
 
 150   
     /**
 151   
      * @see org.apache.tools.ant.Task#init()
 152   
      */
 153  7
     public void init()
 154   
     {
 155  7
         super.init();
 156   
         
 157  7
         addClasspathEntry("/org/aspectj/lang/JoinPoint.class");
 158  7
         addClasspathEntry("/org/apache/cactus/ServletTestCase.class");
 159  7
         addClasspathEntry(
 160   
             "/org/apache/cactus/integration/ant/CactusTask.class");
 161  7
         addClasspathEntry("/org/apache/commons/logging/Log.class");
 162  7
         addClasspathEntry("/org/apache/commons/httpclient/HttpClient.class");
 163   
     }
 164   
 
 165   
     /**
 166   
      * @see org.apache.tools.ant.Task#execute()
 167   
      */
 168  7
     public void execute() throws BuildException
 169   
     {
 170  7
         if ((this.warFile == null) && (this.earFile == null))
 171   
         {
 172  1
             throw new BuildException("You must specify either the [warfile] or "
 173   
                 + "the [earfile] attribute");
 174   
         }
 175   
 
 176  6
         if ((this.warFile != null) && (this.earFile != null))
 177   
         {
 178  0
             throw new BuildException("You must specify either the [warfile] or "
 179   
                 + "the [earfile] attribute but not both");
 180   
         }
 181   
 
 182   
         // Parse deployment descriptors for WAR or EAR files
 183  6
         DeployableFile deployableFile;
 184  6
         if (this.warFile != null)
 185   
         {
 186  3
             deployableFile = WarParser.parse(this.warFile);
 187   
         }
 188   
         else 
 189   
         {
 190  3
             deployableFile = EarParser.parse(this.earFile);
 191   
         } 
 192   
 
 193  3
         addRedirectorNameProperties(deployableFile);
 194   
         
 195  2
         if (this.containerSet == null)
 196   
         {
 197  2
             log("No containers specified, tests will run locally",
 198   
                 Project.MSG_VERBOSE);
 199  2
             super.execute();
 200   
         }
 201   
         else
 202   
         {
 203  0
             Container[] containers = this.containerSet.getContainers();
 204  0
             Variable contextUrl = new Variable();
 205  0
             contextUrl.setKey("cactus.contextURL");
 206  0
             addSysproperty(contextUrl);
 207  0
             for (int i = 0; i < containers.length; i++)
 208   
             {
 209  0
                 containers[i].setAntTaskFactory(this.antTaskFactory);
 210  0
                 containers[i].setLog(new AntLog(this));
 211  0
                 containers[i].setDeployableFile(deployableFile);
 212  0
                 containers[i].setSystemProperties(
 213   
                     (Variable[]) this.systemProperties.toArray(
 214   
                         new Variable[0]));
 215  0
                 if (containers[i].isEnabled())
 216   
                 {
 217  0
                     containers[i].init();
 218  0
                     log("--------------------------------------------------"
 219   
                         + "---------------",
 220   
                         Project.MSG_INFO);
 221  0
                     log("Running tests against " + containers[i].getName(),
 222   
                         Project.MSG_INFO);
 223  0
                     log("--------------------------------------------------"
 224   
                         + "---------------",
 225   
                         Project.MSG_INFO);
 226  0
                     contextUrl.setValue(
 227   
                         "http://localhost:" + containers[i].getPort() + "/"
 228   
                         + deployableFile.getTestContext());
 229  0
                     executeInContainer(containers[i], deployableFile); 
 230   
                 }
 231   
             }
 232   
         }
 233   
     }
 234   
 
 235   
     /**
 236   
      * Adds the nested containers element (only one is permitted).
 237   
      * 
 238   
      * @param theContainerSet The nested element to add
 239   
      */
 240  0
     public final void addContainerSet(ContainerSet theContainerSet)
 241   
     {
 242  0
         if (this.containerSet != null)
 243   
         {
 244  0
             throw new BuildException(
 245   
                 "Only one nested containerset element supported");
 246   
         }
 247  0
         this.containerSet = theContainerSet;
 248   
     }
 249   
 
 250   
     /**
 251   
      * Sets the enterprise application archive that will be tested. It must
 252   
      * already contain the test-cases and the required libraries as a web
 253   
      * module.
 254   
      * 
 255   
      * @param theEarFile The EAR file to set  
 256   
      */
 257  3
     public final void setEarFile(File theEarFile)
 258   
     {
 259  3
         if (this.warFile != null)
 260   
         {
 261  0
             throw new BuildException(
 262   
                 "You may only specify one of [earfile] and [warfile]");
 263   
         }
 264  3
         this.earFile = theEarFile;
 265   
     }
 266   
 
 267   
     /**
 268   
      * Sets the web application archive that will be tested. It must already 
 269   
      * contain the test-cases and the required libraries.
 270   
      * 
 271   
      * @param theWarFile The WAR file to set  
 272   
      */
 273  3
     public final void setWarFile(File theWarFile)
 274   
     {
 275  3
         if (this.earFile != null)
 276   
         {
 277  0
             throw new BuildException(
 278   
                 "You may only specify one of [earfile] and [warfile]");
 279   
         }
 280  3
         this.warFile = theWarFile;
 281   
     }
 282   
 
 283   
     /**
 284   
      * Adds a system property. Note that we can't reuse the JUnitTask
 285   
      * sysproperty element as there is no getter to get them.
 286   
      * 
 287   
      * @see JUnitTask#addSysproperty(Environment.Variable) 
 288   
      */
 289  0
     public void addSysproperty(Environment.Variable theProperty)
 290   
     {
 291  0
         addCactusServerProperty(theProperty);
 292  0
         super.addSysproperty(theProperty);
 293   
     }
 294   
 
 295   
     /**
 296   
      * Called by Ant when the Variable object has been properly initialized.
 297   
      * 
 298   
      * @param theProperty the system property to set 
 299   
      */
 300  0
     public void addConfiguredSysproperty(Environment.Variable theProperty)
 301   
     {
 302  0
         addSysproperty(theProperty);
 303   
     }
 304   
 
 305   
     /**
 306   
      * Adds a set of properties that will be used as system properties
 307   
      * either on the client side or on the server side.
 308   
      *
 309   
      * @param thePropertySet the set of properties to be added
 310   
      */
 311  0
     public void addConfiguredCactusproperty(PropertySet thePropertySet)
 312   
     {
 313   
         // Add all properties from the properties file
 314  0
         ResourceBundle bundle = thePropertySet.readProperties();
 315  0
         Enumeration keys = bundle.getKeys();
 316  0
         while (keys.hasMoreElements())
 317   
         {
 318  0
             String key = (String) keys.nextElement();
 319  0
             Variable var = new Variable();
 320  0
             var.setKey(key);
 321  0
             var.setValue(bundle.getString(key));
 322  0
             if (thePropertySet.isServer())
 323   
             {
 324  0
                 addCactusServerProperty(var);
 325   
             }
 326   
             else
 327   
             {
 328  0
                 super.addSysproperty(var);
 329   
             }
 330   
         }
 331   
     }
 332   
 
 333   
     // Private Methods ---------------------------------------------------------
 334   
 
 335   
     /**
 336   
      * Adds a Cactus system property for the client side JVM.
 337   
      * 
 338   
      * @param theKey The property name
 339   
      * @param theValue The property value
 340   
      */
 341  2
     private void addCactusClientProperty(String theKey, String theValue)
 342   
     {
 343  2
         log("Adding Cactus client system property [" + theKey 
 344   
             + "] with value [" + theValue + "]", Project.MSG_VERBOSE);
 345  2
         Variable sysProperty = new Variable();
 346  2
         sysProperty.setKey(theKey);
 347  2
         sysProperty.setValue(theValue);
 348  2
         super.addSysproperty(sysProperty);
 349   
     }
 350   
 
 351   
     /**
 352   
      * Adds a Cactus system property for the server side JVM.
 353   
      * 
 354   
      * @param theProperty The system property to set in the container JVM
 355   
      */
 356  0
     private void addCactusServerProperty(Variable theProperty)
 357   
     {
 358  0
         log("Adding Cactus server system property [cactus." 
 359   
             + theProperty.getKey() + "] with value [" 
 360   
             + theProperty.getValue() + "]", Project.MSG_VERBOSE);
 361  0
         this.systemProperties.add(theProperty);
 362   
     }
 363   
 
 364   
     /**
 365   
      * Adds a Cactus system property for the server side JVM.
 366   
      * 
 367   
      * @param theKey The property name
 368   
      * @param theValue The property value
 369   
      */
 370  0
     private void addCactusServerProperty(String theKey, String theValue)
 371   
     {
 372  0
         Variable property = new Variable();
 373  0
         property.setKey(theKey);
 374  0
         property.setValue(theValue);
 375  0
         addCactusServerProperty(property);
 376   
     }
 377   
     
 378   
     /**
 379   
      * Extracts the redirector mappings from the deployment descriptor and sets 
 380   
      * the corresponding system properties.
 381   
      * 
 382   
      * @param theFile The file to deploy in the container
 383   
      */
 384  3
     private void addRedirectorNameProperties(DeployableFile theFile)
 385   
     {
 386  3
         String filterRedirectorMapping = 
 387   
             theFile.getFilterRedirectorMapping();
 388  3
         if (filterRedirectorMapping != null)
 389   
         {
 390  0
             addCactusClientProperty("cactus.filterRedirectorName",
 391   
                 filterRedirectorMapping.substring(1));
 392   
         }
 393   
         else
 394   
         {
 395  3
             log("No mapping of the filter redirector found",
 396   
                 Project.MSG_VERBOSE);
 397   
         }
 398   
 
 399  3
         String jspRedirectorMapping = 
 400   
             theFile.getJspRedirectorMapping();
 401  3
         if (jspRedirectorMapping != null)
 402   
         {
 403  0
             addCactusClientProperty("cactus.jspRedirectorName",
 404   
                 jspRedirectorMapping.substring(1));
 405   
         }
 406   
         else
 407   
         {
 408  3
             log("No mapping of the JSP redirector found",
 409   
                 Project.MSG_VERBOSE);
 410   
         }
 411   
 
 412  3
         String servletRedirectorMapping = 
 413   
             theFile.getServletRedirectorMapping();
 414  3
         if (servletRedirectorMapping != null)
 415   
         {
 416  2
             addCactusClientProperty("cactus.servletRedirectorName",
 417   
                 servletRedirectorMapping.substring(1));
 418   
         }
 419   
         else
 420   
         {
 421  1
             throw new BuildException("The WAR has not been cactified");
 422   
         }
 423   
     }
 424   
 
 425   
     /**
 426   
      * Executes the unit tests in the given container.
 427   
      * 
 428   
      * @param theContainer The container to run the tests against
 429   
      * @param theFile the file to deploy in the container
 430   
      */
 431  0
     private void executeInContainer(Container theContainer, 
 432   
         DeployableFile theFile)
 433   
     {
 434  0
         log("Starting up container", Project.MSG_VERBOSE);
 435  0
         ContainerRunner runner = new ContainerRunner(theContainer);
 436  0
         runner.setLog(new AntLog(this));
 437  0
         try
 438   
         {
 439  0
             URL url =
 440   
                 new URL("http", "localhost", theContainer.getPort(), "/"
 441   
                 + theFile.getTestContext() 
 442   
                 + theFile.getServletRedirectorMapping()
 443   
                 + "?Cactus_Service=RUN_TEST");
 444  0
             runner.setUrl(url);
 445  0
             if (this.containerSet.getTimeout() > 0)
 446   
             {
 447  0
                 runner.setTimeout(this.containerSet.getTimeout());
 448   
             }
 449  0
             runner.startUpContainer();
 450  0
             log("Container responding to HTTP requests as "
 451   
                 + runner.getServerName(), Project.MSG_VERBOSE);
 452  0
             try
 453   
             {
 454  0
                 Enumeration tests = getIndividualTests();
 455  0
                 while (tests.hasMoreElements())
 456   
                 {
 457  0
                     JUnitTest test = (JUnitTest) tests.nextElement();
 458  0
                     if (test.shouldRun(getProject())
 459   
                      && !theContainer.isExcluded(test.getName()))
 460   
                     {
 461  0
                         if (theContainer.getToDir() != null)
 462   
                         {
 463  0
                             test.setTodir(theContainer.getToDir());
 464   
                         }
 465  0
                         execute(test);
 466   
                     }
 467   
                 }
 468   
             }
 469   
             finally
 470   
             {
 471  0
                 log("Shutting down container", Project.MSG_VERBOSE);
 472  0
                 runner.shutDownContainer();
 473  0
                 log("Container shut down", Project.MSG_VERBOSE);
 474   
             }
 475   
         }
 476   
         catch (MalformedURLException mue)
 477   
         {
 478  0
             throw new BuildException("Malformed test URL", mue);
 479   
         }
 480   
     }
 481   
 }
 482