2011/08/05 - Jakarta Cactus has been retired.

For more information, please explore the Attic.

Clover coverage report - Cactus 1.8dev for J2EE API 1.3
Coverage timestamp: Sun Mar 26 2006 18:50:18 BRT
file stats: LOC: 474   Methods: 19
NCLOC: 249   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
JBoss3xContainer.java 0% 0% 0% 0%
coverage
 1   
 /* 
 2   
  * ========================================================================
 3   
  * 
 4   
  * Copyright 2003-2004 The Apache Software Foundation.
 5   
  *
 6   
  * Licensed under the Apache License, Version 2.0 (the "License");
 7   
  * you may not use this file except in compliance with the License.
 8   
  * You may obtain a copy of the License at
 9   
  * 
 10   
  *   http://www.apache.org/licenses/LICENSE-2.0
 11   
  * 
 12   
  * Unless required by applicable law or agreed to in writing, software
 13   
  * distributed under the License is distributed on an "AS IS" BASIS,
 14   
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15   
  * See the License for the specific language governing permissions and
 16   
  * limitations under the License.
 17   
  * 
 18   
  * ========================================================================
 19   
  */
 20   
 package org.apache.cactus.integration.ant.container.jboss;
 21   
 
 22   
 import java.io.File;
 23   
 import java.io.IOException;
 24   
 import java.io.StringReader;
 25   
 import java.util.jar.Attributes;
 26   
 import java.util.jar.JarFile;
 27   
 import java.util.jar.Manifest;
 28   
 import java.util.zip.ZipEntry;
 29   
 
 30   
 import javax.xml.parsers.DocumentBuilder;
 31   
 import javax.xml.parsers.DocumentBuilderFactory;
 32   
 import javax.xml.parsers.ParserConfigurationException;
 33   
 
 34   
 import org.apache.cactus.integration.ant.container.AbstractJavaContainer;
 35   
 import org.apache.tools.ant.BuildException;
 36   
 import org.apache.tools.ant.taskdefs.Copy;
 37   
 import org.apache.tools.ant.taskdefs.Java;
 38   
 import org.apache.tools.ant.types.FileSet;
 39   
 import org.apache.tools.ant.types.Path;
 40   
 import org.apache.tools.ant.util.FileUtils;
 41   
 import org.w3c.dom.Document;
 42   
 import org.w3c.dom.Element;
 43   
 import org.w3c.dom.Node;
 44   
 import org.xml.sax.EntityResolver;
 45   
 import org.xml.sax.InputSource;
 46   
 import org.xml.sax.SAXException;
 47   
 
 48   
 /**
 49   
  * Special container support for the JBoss application server.
 50   
  * 
 51   
  * @version $Id: JBoss3xContainer.java 239130 2005-01-29 15:49:18Z vmassol $
 52   
  */
 53   
 public class JBoss3xContainer extends AbstractJavaContainer
 54   
 {
 55   
     // Instance Variables ------------------------------------------------------
 56   
 
 57   
     /**
 58   
      * The JBoss 3.x installation directory.
 59   
      */
 60   
     private File dir;
 61   
 
 62   
     /**
 63   
      * The name of the server configuration to use for running the tests.
 64   
      */
 65   
     private String config = "default";
 66   
 
 67   
     /**
 68   
      * The location of a directory where to find the JBoss server 
 69   
      * configurations.
 70   
      */
 71   
     private File configDir;
 72   
     
 73   
     /**
 74   
      * The port to which the container should be bound.
 75   
      */
 76   
     private int port = 8080;
 77   
 
 78   
     /**
 79   
      * The server JNDI Port (used during shutdown)
 80   
      */
 81   
     private int jndiPort = 1099;
 82   
     
 83   
     /**
 84   
      * The JBoss version detected by reading the Manifest file in the
 85   
      * installation directory.
 86   
      */
 87   
     private String version;
 88   
 
 89   
     /**
 90   
      * The context root of the tested application.
 91   
      */
 92   
     private String testContextRoot;
 93   
 
 94   
     /**
 95   
      * The temporary directory from which the container will be started.
 96   
      */
 97   
     private File tmpDir;
 98   
     
 99   
     // Public Methods ----------------------------------------------------------
 100   
 
 101   
     /**
 102   
      * Sets the JBoss installation directory.
 103   
      * 
 104   
      * @param theDir The directory to set
 105   
      * @throws BuildException If the specified directory doesn't contain a valid
 106   
      *         JBoss 3.x installation
 107   
      */
 108  0
     public final void setDir(File theDir) throws BuildException
 109   
     {
 110  0
         this.dir = theDir;
 111   
     }
 112   
 
 113   
     /**
 114   
      * Sets the name of the server configuration to use for running the tests.
 115   
      * 
 116   
      * @param theConfig The configuration name
 117   
      */
 118  0
     public final void setConfig(String theConfig)
 119   
     {
 120  0
         this.config = theConfig;
 121   
     }
 122   
 
 123   
     /**
 124   
      * Sets the location of the server configuration directory.
 125   
      * 
 126   
      * @param theConfigDir The configuration directory
 127   
      */
 128  0
     public final void setConfigDir(File theConfigDir)
 129   
     {
 130  0
         this.configDir = theConfigDir;
 131   
     }
 132   
     
 133   
     /**
 134   
      * Sets the port that will be used to poll the server to verify if
 135   
      * it is started. This is needed for the use case where the user
 136   
      * has defined his own JBoss configuration by using the
 137   
      * {@link #setConfig(String)} call and has defined a port other
 138   
      * than the default one. 
 139   
      * 
 140   
      * Note: This value is not yet used to set the port
 141   
      * to which the container will listen to. The reason is that this is
 142   
      * hard to implement with JBoss and nobody had the courage to implement
 143   
      * it yet...
 144   
      * 
 145   
      * @param thePort The port to set
 146   
      */
 147  0
     public final void setPort(int thePort)
 148   
     {
 149  0
         this.port = thePort;
 150   
     }
 151   
 
 152   
     /**
 153   
      * Specify the JNDI port to use.
 154   
      *
 155   
      * @param theJndiPort The JNDI port
 156   
      */
 157  0
     public final void setJndiPort(int theJndiPort)
 158   
     {
 159  0
         this.jndiPort = theJndiPort;
 160   
     }
 161   
 
 162   
     /**
 163   
      * Sets the temporary directory from which the container is run.
 164   
      * 
 165   
      * @param theTmpDir The temporary directory to set
 166   
      */
 167  0
     public final void setTmpDir(File theTmpDir)
 168   
     {
 169  0
         this.tmpDir = theTmpDir;
 170   
     }
 171   
     
 172   
     // Container Implementation ------------------------------------------------
 173   
 
 174   
     /**
 175   
      * @see AbstractJavaContainer#getTestContext()
 176   
      */
 177  0
     public String getTestContext()
 178   
     {
 179  0
         return this.testContextRoot;
 180   
     }
 181   
     
 182   
     /**
 183   
      * @see AbstractJavaContainer#getName()
 184   
      */
 185  0
     public final String getName()
 186   
     {
 187  0
         return "JBoss " + this.version;
 188   
     }
 189   
 
 190   
     /**
 191   
      * @see AbstractJavaContainer#getPort() 
 192   
      */
 193  0
     public final int getPort()
 194   
     {
 195  0
         return this.port;
 196   
     }
 197   
 
 198   
     /**
 199   
      * Returns the server JNDI port.
 200   
      *
 201   
      * @return The JNDI port
 202   
      */
 203  0
     public final int getJndiPort()
 204   
     {
 205  0
         return this.jndiPort;
 206   
     }
 207   
 
 208   
     /**
 209   
      * @return The temporary directory from which the container will be 
 210   
      *         started.
 211   
      */
 212  0
     protected final File getTmpDir()
 213   
     {
 214  0
         return this.tmpDir;
 215   
     }
 216   
 
 217   
     /**
 218   
      * @see AbstractJavaContainer#init()
 219   
      */
 220  0
     public final void init()
 221   
     {
 222   
         // Verify the installation directory
 223  0
         this.version = getVersion(this.dir);
 224  0
         if (this.version == null)
 225   
         {
 226  0
             throw new BuildException(this.dir
 227   
                 + " not recognized as a JBoss 3.x installation");
 228   
         }
 229  0
         if (!this.version.startsWith("3"))
 230   
         {
 231  0
             throw new BuildException(
 232   
                 "This element doesn't support version " + this.version
 233   
                 + " of JBoss");
 234   
         }
 235   
 
 236   
         // Try to infer the test root context from the JBoss specific
 237   
         // <code>jboss-web.xml</code> file.
 238  0
         this.testContextRoot = getTestContextFromJBossWebXml();
 239   
         
 240   
         // TODO: as long as we don't have a way to set the port on the JBoss 
 241   
         // instance, we'll at least need to extract the port from a config file
 242   
         // in the installation directory
 243   
     }
 244   
 
 245   
     /**
 246   
      * @see AbstractJavaContainer#startUp()
 247   
      */
 248  0
     public final void startUp()
 249   
     {
 250  0
         try
 251   
         {
 252   
             // TODO: It seems JBoss 3.2.x does not support server 
 253   
             // configurations located in directories with spaces in their name.
 254   
             // Thus we define the default tmp dir to default to where default
 255   
             // JBoss server configurations are located. This should be removed
 256   
             // once we find out how to make JBoss work when using the default
 257   
             // tmp dir of System.getProperty("java.io.tmpdir")
 258  0
             if (getTmpDir() == null)
 259   
             {
 260  0
                 setTmpDir(new File(this.dir, "server/cactus"));
 261   
             }            
 262   
             
 263  0
             File customServerDir = setupTempDirectory(getTmpDir(), 
 264   
                 "cactus/jboss3x");
 265  0
             cleanTempDirectory(customServerDir);
 266   
             
 267  0
             prepare("cactus/jboss3x", customServerDir);
 268   
             
 269  0
             File binDir = new File(this.dir, "bin");
 270   
             
 271  0
             Java java = createJavaForStartUp();
 272  0
             java.setDir(binDir);
 273   
             
 274  0
             java.addSysproperty(
 275   
                 createSysProperty("program.name",
 276   
                     new File(binDir, "run.bat")));
 277  0
             java.addSysproperty(
 278   
                 createSysProperty("jboss.server.home.dir", customServerDir));
 279  0
             java.addSysproperty(
 280   
                 createSysProperty("jboss.server.home.url",
 281   
                     customServerDir.toURL().toString()));
 282   
 
 283  0
             Path classpath = java.createClasspath();
 284  0
             classpath.createPathElement().setLocation(
 285   
                 new File(binDir, "run.jar"));
 286  0
             addToolsJarToClasspath(classpath);
 287  0
             java.setClassname("org.jboss.Main");
 288  0
             java.createArg().setValue("-c");
 289  0
             java.createArg().setValue(this.config);
 290  0
             java.execute();
 291   
         }
 292   
         catch (IOException ioe)
 293   
         {
 294  0
             getLog().error("Failed to startup the container", ioe);
 295  0
             throw new BuildException(ioe);
 296   
         }
 297   
     }
 298   
 
 299   
     /**
 300   
      * @see AbstractJavaContainer#shutDown()
 301   
      */
 302  0
     public final void shutDown()
 303   
     {
 304  0
         File binDir = new File(this.dir, "bin");
 305   
             
 306  0
         Java java = createJavaForShutDown();
 307  0
         java.setFork(true);
 308   
 
 309  0
         Path classPath = java.createClasspath();
 310  0
         classPath.createPathElement().setLocation(
 311   
             new File(binDir, "shutdown.jar"));
 312   
 
 313  0
         java.setClassname("org.jboss.Shutdown");
 314   
         
 315  0
         if (this.version.startsWith("3.2"))
 316   
         {
 317  0
             java.createArg().setValue("--server=" + this.getServer() + ":"
 318   
                 + this.getJndiPort());
 319  0
             java.createArg().setValue("--shutdown");
 320   
         }
 321   
         else
 322   
         {
 323  0
             java.createArg().setValue(this.getServer());
 324  0
             java.createArg().setValue(String.valueOf(getPort()));
 325   
         }
 326  0
         java.execute();
 327   
     }
 328   
 
 329   
     // Private Methods ---------------------------------------------------------
 330   
 
 331   
     /**
 332   
      * @return the test context from JBoss's <code>jboss-web.xml</code> or null
 333   
      *         if none has been defined or if the file doesn't exist
 334   
      */
 335  0
     private String getTestContextFromJBossWebXml()
 336   
     {
 337  0
         String testContext = null;
 338   
         
 339  0
         try
 340   
         {
 341  0
             Document doc = getJBossWebXML();
 342  0
             Element root = doc.getDocumentElement();
 343  0
             Node context = root.getElementsByTagName("context-root").item(0);
 344  0
             testContext = context.getFirstChild().getNodeValue();
 345   
         }
 346   
         catch (Exception e)
 347   
         {
 348   
             // no worries if we can't find what we are looking for (for now).
 349   
         }
 350   
 
 351  0
         return testContext;
 352   
     }
 353   
     
 354   
     /**
 355   
      * Prepares a temporary installation of the container and deploys the 
 356   
      * web-application.
 357   
      * 
 358   
      * @param theDirName The name of the temporary container installation
 359   
      *        directory
 360   
      * @param theCustomServerDir the directory where the JBoss server 
 361   
      *        configuration is to be deployed
 362   
      * @throws IOException If an I/O error occurs
 363   
      */
 364  0
     private void prepare(String theDirName, File theCustomServerDir) 
 365   
         throws IOException
 366   
     {
 367  0
         FileUtils fileUtils = FileUtils.newFileUtils();
 368   
 
 369   
         // If the configDir property has not been set, let's default it to
 370   
         // the default JBoss server configuration directory.
 371  0
         File computedConfigDir;
 372  0
         if (this.configDir == null)
 373   
         {
 374  0
             computedConfigDir = new File(this.dir, "server");
 375   
         }
 376   
         else
 377   
         {
 378  0
             computedConfigDir = this.configDir;
 379   
         }
 380   
         
 381   
         // Copy the default JBoss server config directory into our custom
 382   
         // server directory.
 383  0
         Copy copy = new Copy();
 384  0
         copy.setTaskName("cactus");
 385  0
         copy.setProject(getProject());
 386  0
         copy.setTodir(theCustomServerDir);
 387  0
         FileSet srcFiles = new FileSet();
 388  0
         srcFiles.setDir(new File(computedConfigDir, this.config));
 389  0
         copy.addFileset(srcFiles);
 390  0
         copy.execute();
 391   
             
 392   
         // Deploy the web-app by copying the WAR file into the webapps
 393   
         // directory
 394  0
         File deployDir = new File(theCustomServerDir, "/deploy");
 395  0
         fileUtils.copyFile(getDeployableFile().getFile(),
 396   
             new File(deployDir, getDeployableFile().getFile().getName()), 
 397   
             null, true);
 398   
     }
 399   
 
 400   
     /**
 401   
      * Returns the version of the JBoss installation.
 402   
      * 
 403   
      * @param theDir The JBoss installation directory 
 404   
      * @return The JBoss version, or <code>null</code> if the verion number
 405   
      *         could not be retrieved
 406   
      */
 407  0
     private String getVersion(File theDir)
 408   
     {
 409   
         // Extract version information from the manifest in run.jar
 410  0
         String retVal = null;
 411  0
         try
 412   
         {
 413  0
             JarFile runJar = new JarFile(new File(theDir, "bin/run.jar"));
 414  0
             Manifest mf = runJar.getManifest();
 415  0
             if (mf != null)
 416   
             {
 417  0
                 Attributes attrs = mf.getMainAttributes();
 418  0
                 retVal = attrs.getValue(Attributes.Name.SPECIFICATION_VERSION);
 419   
             }
 420   
             else
 421   
             {
 422  0
                 getLog().warn("Couldn't find MANIFEST.MF in " + runJar);
 423   
             }
 424   
         }
 425   
         catch (IOException ioe)
 426   
         {
 427  0
             getLog().warn("Couldn't retrieve JBoss version information", ioe);
 428   
         }
 429  0
         return retVal;
 430   
     }
 431   
 
 432   
     /**
 433   
      * Get a Document object for the <code>jboss-web.xml</code> file.
 434   
      * 
 435   
      * @return The parsed XML Document object or null if not found
 436   
      * @throws IOException If there is a problem reading files
 437   
      * @throws ParserConfigurationException If there is a problem w/ parser
 438   
      * @throws SAXException If there is a problem with parsing
 439   
      */
 440  0
     private Document getJBossWebXML() throws
 441   
         IOException, ParserConfigurationException, SAXException
 442   
     {
 443  0
         Document doc = null;
 444  0
         File configDir = new File(this.dir, "server");
 445  0
         File deployDir = new File(configDir, this.config + "/deploy");
 446  0
         File warFile = new File(deployDir,
 447   
             getDeployableFile().getFile().getName());
 448   
  
 449  0
         JarFile war = new JarFile(warFile);
 450  0
         ZipEntry entry = war.getEntry("WEB-INF/jboss-web.xml");
 451  0
         if (entry != null)
 452   
         {
 453  0
             DocumentBuilderFactory factory =
 454   
                 DocumentBuilderFactory.newInstance();
 455  0
             factory.setValidating(false);
 456  0
             factory.setNamespaceAware(false);
 457   
             
 458  0
             DocumentBuilder builder = factory.newDocumentBuilder();
 459  0
             builder.setEntityResolver(new EntityResolver()
 460   
             {
 461  0
                 public InputSource resolveEntity(String thePublicId, 
 462   
                     String theSystemId) throws SAXException
 463   
                 {
 464  0
                     return new InputSource(new StringReader(""));
 465   
                 }
 466   
             });
 467  0
             doc = builder.parse(war.getInputStream(entry));
 468   
         }
 469  0
         war.close();
 470  0
         return doc;
 471   
     }
 472   
     
 473   
 }
 474