Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 900   Methods: 31
NCLOC: 463   Classes: 1
 
 Source file Conditionals Statements Methods TOTAL
WeblogicDeploymentTool.java 0% 0% 0% 0%
 1   
 /*
 2   
  * The Apache Software License, Version 1.1
 3   
  *
 4   
  * Copyright (c) 2000-2003 The Apache Software Foundation.  All rights
 5   
  * reserved.
 6   
  *
 7   
  * Redistribution and use in source and binary forms, with or without
 8   
  * modification, are permitted provided that the following conditions
 9   
  * are met:
 10   
  *
 11   
  * 1. Redistributions of source code must retain the above copyright
 12   
  *    notice, this list of conditions and the following disclaimer.
 13   
  *
 14   
  * 2. Redistributions in binary form must reproduce the above copyright
 15   
  *    notice, this list of conditions and the following disclaimer in
 16   
  *    the documentation and/or other materials provided with the
 17   
  *    distribution.
 18   
  *
 19   
  * 3. The end-user documentation included with the redistribution, if
 20   
  *    any, must include the following acknowlegement:
 21   
  *       "This product includes software developed by the
 22   
  *        Apache Software Foundation (http://www.apache.org/)."
 23   
  *    Alternately, this acknowlegement may appear in the software itself,
 24   
  *    if and wherever such third-party acknowlegements normally appear.
 25   
  *
 26   
  * 4. The names "Ant" and "Apache Software
 27   
  *    Foundation" must not be used to endorse or promote products derived
 28   
  *    from this software without prior written permission. For written
 29   
  *    permission, please contact apache@apache.org.
 30   
  *
 31   
  * 5. Products derived from this software may not be called "Apache"
 32   
  *    nor may "Apache" appear in their names without prior written
 33   
  *    permission of the Apache Group.
 34   
  *
 35   
  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 36   
  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 37   
  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 38   
  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 39   
  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 40   
  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 41   
  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 42   
  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 43   
  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 44   
  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 45   
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 46   
  * SUCH DAMAGE.
 47   
  * ====================================================================
 48   
  *
 49   
  * This software consists of voluntary contributions made by many
 50   
  * individuals on behalf of the Apache Software Foundation.  For more
 51   
  * information on the Apache Software Foundation, please see
 52   
  * <http://www.apache.org/>.
 53   
  */
 54   
 package org.apache.tools.ant.taskdefs.optional.ejb;
 55   
 
 56   
 import java.io.File;
 57   
 import java.io.FileInputStream;
 58   
 import java.io.FileOutputStream;
 59   
 import java.io.IOException;
 60   
 import java.io.InputStream;
 61   
 import java.util.Enumeration;
 62   
 import java.util.Hashtable;
 63   
 import java.util.Iterator;
 64   
 import java.util.Vector;
 65   
 import java.util.jar.JarEntry;
 66   
 import java.util.jar.JarFile;
 67   
 import java.util.jar.JarOutputStream;
 68   
 import javax.xml.parsers.SAXParser;
 69   
 import javax.xml.parsers.SAXParserFactory;
 70   
 import org.apache.tools.ant.AntClassLoader;
 71   
 import org.apache.tools.ant.BuildException;
 72   
 import org.apache.tools.ant.Project;
 73   
 import org.apache.tools.ant.taskdefs.Java;
 74   
 import org.apache.tools.ant.types.Environment;
 75   
 import org.apache.tools.ant.types.Path;
 76   
 import org.apache.tools.ant.util.FileUtils;
 77   
 import org.xml.sax.InputSource;
 78   
 
 79   
 /**
 80   
     The weblogic element is used to control the weblogic.ejbc compiler for
 81   
     generating weblogic EJB jars. Prior to Ant 1.3, the method of locating CMP
 82   
     descriptors was to use the ejbjar naming convention. So if your ejb-jar was
 83   
     called, Customer-ejb-jar.xml, your weblogic descriptor was called Customer-
 84   
     weblogic-ejb-jar.xml and your CMP descriptor had to be Customer-weblogic-cmp-
 85   
     rdbms-jar.xml. In addition, the &lt;type-storage&gt; element in the weblogic
 86   
     descriptor had to be set to the standard name META-INF/weblogic-cmp-rdbms-
 87   
     jar.xml, as that is where the CMP descriptor was mapped to in the generated
 88   
     jar.
 89   
 */
 90   
 public class WeblogicDeploymentTool extends GenericDeploymentTool {
 91   
     public static final String PUBLICID_EJB11
 92   
          = "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN";
 93   
     public static final String PUBLICID_EJB20
 94   
          = "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN";
 95   
     public static final String PUBLICID_WEBLOGIC_EJB510
 96   
          = "-//BEA Systems, Inc.//DTD WebLogic 5.1.0 EJB//EN";
 97   
     public static final String PUBLICID_WEBLOGIC_EJB600
 98   
          = "-//BEA Systems, Inc.//DTD WebLogic 6.0.0 EJB//EN";
 99   
     public static final String PUBLICID_WEBLOGIC_EJB700
 100   
          = "-//BEA Systems, Inc.//DTD WebLogic 7.0.0 EJB//EN";
 101   
 
 102   
     protected static final String DEFAULT_WL51_EJB11_DTD_LOCATION
 103   
          = "/weblogic/ejb/deployment/xml/ejb-jar.dtd";
 104   
     protected static final String DEFAULT_WL60_EJB11_DTD_LOCATION
 105   
          = "/weblogic/ejb20/dd/xml/ejb11-jar.dtd";
 106   
     protected static final String DEFAULT_WL60_EJB20_DTD_LOCATION
 107   
          = "/weblogic/ejb20/dd/xml/ejb20-jar.dtd";
 108   
 
 109   
     protected static final String DEFAULT_WL51_DTD_LOCATION
 110   
          = "/weblogic/ejb/deployment/xml/weblogic-ejb-jar.dtd";
 111   
     protected static final String DEFAULT_WL60_51_DTD_LOCATION
 112   
          = "/weblogic/ejb20/dd/xml/weblogic510-ejb-jar.dtd";
 113   
     protected static final String DEFAULT_WL60_DTD_LOCATION
 114   
          = "/weblogic/ejb20/dd/xml/weblogic600-ejb-jar.dtd";
 115   
     protected static final String DEFAULT_WL70_DTD_LOCATION
 116   
          = "/weblogic/ejb20/dd/xml/weblogic700-ejb-jar.dtd";
 117   
 
 118   
     protected static final String DEFAULT_COMPILER = "default";
 119   
 
 120   
     protected static final String WL_DD = "weblogic-ejb-jar.xml";
 121   
     protected static final String WL_CMP_DD = "weblogic-cmp-rdbms-jar.xml";
 122   
 
 123   
     protected static final String COMPILER_EJB11 = "weblogic.ejbc";
 124   
     protected static final String COMPILER_EJB20 = "weblogic.ejbc20";
 125   
 
 126   
     /** Instance variable that stores the suffix for the weblogic jarfile. */
 127   
     private String jarSuffix = ".jar";
 128   
 
 129   
     /** Instance variable that stores the location of the weblogic DTD file. */
 130   
     private String weblogicDTD;
 131   
 
 132   
     /** Instance variable that stores the location of the ejb 1.1 DTD file. */
 133   
     private String ejb11DTD;
 134   
 
 135   
     /** Instance variable that determines whether generic ejb jars are kept. */
 136   
     private boolean keepgenerated = false;
 137   
 
 138   
     /**
 139   
      * Instance variable that stores the fully qualified classname of the
 140   
      * weblogic EJBC compiler
 141   
      */
 142   
     private String ejbcClass = null;
 143   
 
 144   
     private String additionalArgs = "";
 145   
 
 146   
     /**
 147   
      * additional args to pass to the spawned jvm
 148   
      */
 149   
     private String additionalJvmArgs = "";
 150   
 
 151   
     private boolean keepGeneric = false;
 152   
 
 153   
     private String compiler = null;
 154   
 
 155   
     private boolean alwaysRebuild = true;
 156   
 
 157   
     /** controls whether ejbc is run on the generated jar */
 158   
     private boolean noEJBC = false;
 159   
 
 160   
     /** Indicates if the old CMP location convention is to be used.  */
 161   
     private boolean newCMP = false;
 162   
 
 163   
     /** The classpath to the weblogic classes. */
 164   
     private Path wlClasspath = null;
 165   
 
 166   
     /** System properties for the JVM. */
 167   
     private Vector sysprops = new Vector();
 168   
 
 169   
     /**
 170   
      * The weblogic.StdoutSeverityLevel to use when running the JVM that
 171   
      * executes ejbc. Set to 16 to avoid the warnings about EJB Home and
 172   
      * Remotes being in the classpath
 173   
      */
 174   
     private Integer jvmDebugLevel = null;
 175   
 
 176   
     /** File utilities instance for copying jars */
 177   
     private FileUtils fileUtils = FileUtils.newFileUtils();
 178   
 
 179   
     private File outputDir;
 180   
 
 181   
     /**
 182   
      * Add a nested sysproperty element.
 183   
      */
 184  0
     public void addSysproperty(Environment.Variable sysp) {
 185  0
         sysprops.add(sysp);
 186   
     }
 187   
 
 188   
 
 189   
     /** Get the classpath to the weblogic classpaths  */
 190  0
     public Path createWLClasspath() {
 191  0
         if (wlClasspath == null) {
 192  0
             wlClasspath = new Path(getTask().getProject());
 193   
         }
 194  0
         return wlClasspath.createPath();
 195   
     }
 196   
 
 197   
     /**
 198   
      * If set ejbc will use this directory as the output
 199   
      * destination rather than a jar file. This allows for the
 200   
      * generation of &quot;exploded&quot; jars.
 201   
      */
 202  0
     public void setOutputDir(File outputDir) {
 203  0
         this.outputDir = outputDir;
 204   
     }
 205   
 
 206   
 
 207   
     /**
 208   
      * Optional classpath to WL6.0.
 209   
      * Weblogic 6.0 will give a warning if the home and remote interfaces
 210   
      * of a bean are on the system classpath used to run weblogic.ejbc.
 211   
      * In that case, the standard weblogic classes should be set with
 212   
      * this attribute (or equivalent nested element) and the
 213   
      * home and remote interfaces located with the standard classpath
 214   
      * attribute
 215   
      */
 216  0
     public void setWLClasspath(Path wlClasspath) {
 217  0
         this.wlClasspath = wlClasspath;
 218   
     }
 219   
 
 220   
 
 221   
     /**
 222   
      * The compiler (switch <code>-compiler</code>) to use; optional.
 223   
      * This allows for the selection of a different compiler
 224   
      * to be used for the compilation of the generated Java
 225   
      * files. This could be set, for example, to Jikes to
 226   
      * compile with the Jikes compiler. If this is not set
 227   
      * and the <code>build.compiler</code> property is set
 228   
      * to jikes, the Jikes compiler will be used. If this
 229   
      * is not desired, the value &quot;<code>default</code>&quot;
 230   
      * may be given to use the default compiler
 231   
      */
 232  0
     public void setCompiler(String compiler) {
 233  0
         this.compiler = compiler;
 234   
     }
 235   
 
 236   
 
 237   
     /**
 238   
      * Set the rebuild flag to false to only update changes in the jar rather
 239   
      * than rerunning ejbc; optional, default true.
 240   
      * This flag controls whether weblogic.ejbc is always
 241   
      * invoked to build the jar file. In certain circumstances,
 242   
      * such as when only a bean class has been changed, the jar
 243   
      * can be generated by merely replacing the changed classes
 244   
      * and not rerunning ejbc. Setting this to false will reduce
 245   
      * the time to run ejbjar.
 246   
      */
 247  0
     public void setRebuild(boolean rebuild) {
 248  0
         this.alwaysRebuild = rebuild;
 249   
     }
 250   
 
 251   
 
 252   
     /**
 253   
      * Sets the weblogic.StdoutSeverityLevel to use when running the JVM that
 254   
      * executes ejbc; optional. Set to 16 to avoid the warnings about EJB Home and
 255   
      * Remotes being in the classpath
 256   
      */
 257  0
     public void setJvmDebugLevel(Integer jvmDebugLevel) {
 258  0
         this.jvmDebugLevel = jvmDebugLevel;
 259   
     }
 260   
 
 261   
 
 262  0
     public Integer getJvmDebugLevel() {
 263  0
         return jvmDebugLevel;
 264   
     }
 265   
 
 266   
 
 267   
 
 268   
     /**
 269   
      * Setter used to store the suffix for the generated weblogic jar file.
 270   
      *
 271   
      * @param inString the string to use as the suffix.
 272   
      */
 273  0
     public void setSuffix(String inString) {
 274  0
         this.jarSuffix = inString;
 275   
     }
 276   
 
 277   
 
 278   
     /**
 279   
      * controls whether the generic file used as input to
 280   
      * ejbc is retained; defaults to false
 281   
      *
 282   
      * @param inValue true for keep generic
 283   
      */
 284  0
     public void setKeepgeneric(boolean inValue) {
 285  0
         this.keepGeneric = inValue;
 286   
     }
 287   
 
 288   
 
 289   
     /**
 290   
      * Controls whether weblogic will keep the generated Java
 291   
      * files used to build the class files added to the
 292   
      * jar. This can be useful when debugging; default is false.
 293   
      *
 294   
      * @param inValue either 'true' or 'false'
 295   
      */
 296  0
     public void setKeepgenerated(String inValue) {
 297  0
         this.keepgenerated = Boolean.valueOf(inValue).booleanValue();
 298   
     }
 299   
 
 300   
 
 301   
     /**
 302   
      * Any optional extra arguments pass to the weblogic.ejbc
 303   
      * tool.
 304   
      */
 305  0
     public void setArgs(String args) {
 306  0
         this.additionalArgs = args;
 307   
     }
 308   
 
 309   
 
 310   
     /**
 311   
      * Set any additional arguments to pass to the weblogic JVM; optional.
 312   
      * @param args the arguments to be passed to the JVM
 313   
      */
 314  0
     public void setJvmargs(String args) {
 315  0
         this.additionalJvmArgs = args;
 316   
     }
 317   
 
 318   
     /**
 319   
      * Set the classname of the ejbc compiler;  optional
 320   
      * Normally ejbjar determines
 321   
      * the appropriate class based on the DTD used for the EJB. The EJB 2.0 compiler
 322   
      * featured in weblogic 6 has, however, been deprecated in version 7. When
 323   
      * using with version 7 this attribute should be set to
 324   
      * &quot;weblogic.ejbc&quot; to avoid the deprecation warning.
 325   
      */
 326  0
     public void setEjbcClass(String ejbcClass) {
 327  0
         this.ejbcClass = ejbcClass;
 328   
     }
 329   
 
 330   
 
 331   
     /** Get the ejbc compiler class  */
 332  0
     public String getEjbcClass() {
 333  0
         return ejbcClass;
 334   
     }
 335   
 
 336   
 
 337   
     /**
 338   
      * <b>Deprecated</b>. Defines the location of the ejb-jar DTD in
 339   
      *  the weblogic class hierarchy. Should not be needed, and the
 340   
      * nested &lt;dtd&gt; element is recommended when it is.
 341   
      *
 342   
      * @param inString the string to use as the DTD location.
 343   
      */
 344  0
     public void setWeblogicdtd(String inString) {
 345  0
         setEJBdtd(inString);
 346   
     }
 347   
 
 348   
 
 349   
     /**
 350   
      * <b>Deprecated</b>. Defines the location of weblogic DTD in
 351   
      *  the weblogic class hierarchy. Should not be needed, and the
 352   
      * nested &lt;dtd&gt; element is recommended when it is.
 353   
      *
 354   
      * @param inString the string to use as the DTD location.
 355   
      */
 356  0
     public void setWLdtd(String inString) {
 357  0
         this.weblogicDTD = inString;
 358   
     }
 359   
 
 360   
 
 361   
     /**
 362   
      * <b>Deprecated</b>. Defines the location of Sun's EJB DTD in
 363   
      *  the weblogic class hierarchy. Should not be needed, and the
 364   
      * nested &lt;dtd&gt; element is recommended when it is.
 365   
      *
 366   
      * @param inString the string to use as the DTD location.
 367   
      */
 368  0
     public void setEJBdtd(String inString) {
 369  0
         this.ejb11DTD = inString;
 370   
     }
 371   
 
 372   
 
 373   
     /**
 374   
      * Set the value of the oldCMP scheme. This is an antonym for newCMP
 375   
      * @ant.attribute ignore="true'
 376   
      */
 377  0
     public void setOldCMP(boolean oldCMP) {
 378  0
         this.newCMP = !oldCMP;
 379   
     }
 380   
 
 381   
 
 382   
     /**
 383   
      * If this is set to true, the new method for locating
 384   
      * CMP descriptors will be used; optional, default false.
 385   
      * <P>
 386   
      * The old CMP scheme locates the
 387   
      * weblogic CMP descriptor based on the naming convention where the
 388   
      * weblogic CMP file is expected to be named with the bean name as the
 389   
      * prefix. Under this scheme the name of the CMP descriptor does not match
 390   
      * the name actually used in the main weblogic EJB descriptor. Also,
 391   
      * descriptors which contain multiple CMP references could not be used.
 392   
      */
 393  0
     public void setNewCMP(boolean newCMP) {
 394  0
         this.newCMP = newCMP;
 395   
     }
 396   
 
 397   
 
 398   
     /**
 399   
      * Do not EJBC the jar after it has been put together;
 400   
      * optional, default false
 401   
      */
 402  0
     public void setNoEJBC(boolean noEJBC) {
 403  0
         this.noEJBC = noEJBC;
 404   
     }
 405   
 
 406   
 
 407  0
     protected void registerKnownDTDs(DescriptorHandler handler) {
 408   
         // register all the known DTDs
 409  0
         handler.registerDTD(PUBLICID_EJB11, DEFAULT_WL51_EJB11_DTD_LOCATION);
 410  0
         handler.registerDTD(PUBLICID_EJB11, DEFAULT_WL60_EJB11_DTD_LOCATION);
 411  0
         handler.registerDTD(PUBLICID_EJB11, ejb11DTD);
 412  0
         handler.registerDTD(PUBLICID_EJB20, DEFAULT_WL60_EJB20_DTD_LOCATION);
 413   
     }
 414   
 
 415   
 
 416  0
     protected DescriptorHandler getWeblogicDescriptorHandler(final File srcDir) {
 417  0
         DescriptorHandler handler =
 418   
             new DescriptorHandler(getTask(), srcDir) {
 419  0
                 protected void processElement() {
 420  0
                     if (currentElement.equals("type-storage")) {
 421   
                         // Get the filename of vendor specific descriptor
 422  0
                         String fileNameWithMETA = currentText;
 423   
                         //trim the META_INF\ off of the file name
 424  0
                         String fileName
 425   
                              = fileNameWithMETA.substring(META_DIR.length(),
 426   
                             fileNameWithMETA.length());
 427  0
                         File descriptorFile = new File(srcDir, fileName);
 428   
 
 429  0
                         ejbFiles.put(fileNameWithMETA, descriptorFile);
 430   
                     }
 431   
                 }
 432   
             };
 433   
 
 434  0
         handler.registerDTD(PUBLICID_WEBLOGIC_EJB510, DEFAULT_WL51_DTD_LOCATION);
 435  0
         handler.registerDTD(PUBLICID_WEBLOGIC_EJB510, DEFAULT_WL60_51_DTD_LOCATION);
 436  0
         handler.registerDTD(PUBLICID_WEBLOGIC_EJB600, DEFAULT_WL60_DTD_LOCATION);
 437  0
         handler.registerDTD(PUBLICID_WEBLOGIC_EJB700, DEFAULT_WL70_DTD_LOCATION);
 438  0
         handler.registerDTD(PUBLICID_WEBLOGIC_EJB510, weblogicDTD);
 439  0
         handler.registerDTD(PUBLICID_WEBLOGIC_EJB600, weblogicDTD);
 440   
 
 441  0
         for (Iterator i = getConfig().dtdLocations.iterator(); i.hasNext();) {
 442  0
             EjbJar.DTDLocation dtdLocation = (EjbJar.DTDLocation) i.next();
 443   
 
 444  0
             handler.registerDTD(dtdLocation.getPublicId(), dtdLocation.getLocation());
 445   
         }
 446  0
         return handler;
 447   
     }
 448   
 
 449   
 
 450   
     /**
 451   
      * Add any vendor specific files which should be included in the EJB Jar.
 452   
      */
 453  0
     protected void addVendorFiles(Hashtable ejbFiles, String ddPrefix) {
 454  0
         File weblogicDD = new File(getConfig().descriptorDir, ddPrefix + WL_DD);
 455   
 
 456  0
         if (weblogicDD.exists()) {
 457  0
             ejbFiles.put(META_DIR + WL_DD,
 458   
                 weblogicDD);
 459   
         } else {
 460  0
             log("Unable to locate weblogic deployment descriptor. It was expected to be in " +
 461   
                 weblogicDD.getPath(), Project.MSG_WARN);
 462  0
             return;
 463   
         }
 464   
 
 465  0
         if (!newCMP) {
 466  0
             log("The old method for locating CMP files has been DEPRECATED.", Project.MSG_VERBOSE);
 467  0
             log("Please adjust your weblogic descriptor and set newCMP=\"true\" " +
 468   
                 "to use the new CMP descriptor inclusion mechanism. ", Project.MSG_VERBOSE);
 469   
             // The the weblogic cmp deployment descriptor
 470  0
             File weblogicCMPDD = new File(getConfig().descriptorDir, ddPrefix + WL_CMP_DD);
 471   
 
 472  0
             if (weblogicCMPDD.exists()) {
 473  0
                 ejbFiles.put(META_DIR + WL_CMP_DD,
 474   
                     weblogicCMPDD);
 475   
             }
 476   
         } else {
 477   
             // now that we have the weblogic descriptor, we parse the file
 478   
             // to find other descriptors needed to deploy the bean.
 479   
             // this could be the weblogic-cmp-rdbms.xml or any other O/R
 480   
             // mapping tool descriptors.
 481  0
             try {
 482  0
                 File ejbDescriptor = (File) ejbFiles.get(META_DIR + EJB_DD);
 483  0
                 SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
 484   
 
 485  0
                 saxParserFactory.setValidating(true);
 486   
 
 487  0
                 SAXParser saxParser = saxParserFactory.newSAXParser();
 488  0
                 DescriptorHandler handler = getWeblogicDescriptorHandler(ejbDescriptor.getParentFile());
 489   
 
 490  0
                 saxParser.parse(new InputSource
 491   
                     (new FileInputStream(weblogicDD)),
 492   
                         handler);
 493   
 
 494  0
                 Hashtable ht = handler.getFiles();
 495  0
                 Enumeration e = ht.keys();
 496   
 
 497  0
                 while (e.hasMoreElements()) {
 498  0
                     String key = (String) e.nextElement();
 499   
 
 500  0
                     ejbFiles.put(key, ht.get(key));
 501   
                 }
 502   
             } catch (Exception e) {
 503  0
                 String msg = "Exception while adding Vendor specific files: " + e.toString();
 504   
 
 505  0
                 throw new BuildException(msg, e);
 506   
             }
 507   
         }
 508   
     }
 509   
 
 510   
 
 511   
     /**
 512   
      * Get the vendor specific name of the Jar that will be output. The
 513   
      * modification date of this jar will be checked against the dependent
 514   
      * bean classes.
 515   
      */
 516  0
     File getVendorOutputJarFile(String baseName) {
 517  0
         return new File(getDestDir(), baseName + jarSuffix);
 518   
     }
 519   
 
 520   
 
 521   
     /**
 522   
      * Helper method invoked by execute() for each WebLogic jar to be built.
 523   
      * Encapsulates the logic of constructing a java task for calling
 524   
      * weblogic.ejbc and executing it.
 525   
      *
 526   
      * @param sourceJar java.io.File representing the source (EJB1.1) jarfile.
 527   
      * @param destJar java.io.File representing the destination, WebLogic
 528   
      *      jarfile.
 529   
      */
 530  0
     private void buildWeblogicJar(File sourceJar, File destJar, String publicId) {
 531  0
         Java javaTask = null;
 532   
 
 533  0
         if (noEJBC) {
 534  0
             try {
 535  0
                 fileUtils.copyFile(sourceJar, destJar);
 536  0
                 if (!keepgenerated) {
 537  0
                     sourceJar.delete();
 538   
                 }
 539  0
                 return;
 540   
             } catch (IOException e) {
 541  0
                 throw new BuildException("Unable to write EJB jar", e);
 542   
             }
 543   
         }
 544   
 
 545  0
         String ejbcClassName = ejbcClass;
 546   
 
 547  0
         try {
 548  0
             javaTask = (Java) getTask().getProject().createTask("java");
 549  0
             javaTask.setTaskName("ejbc");
 550   
 
 551  0
             javaTask.createJvmarg().setLine(additionalJvmArgs);
 552  0
             if (!(sysprops.isEmpty())) {
 553  0
                 for (Enumeration en = sysprops.elements() ; en.hasMoreElements();) {
 554  0
                     Environment.Variable entry
 555   
                         = (Environment.Variable) en.nextElement();
 556  0
                     javaTask.addSysproperty(entry);
 557   
                 }
 558   
             }
 559   
 
 560  0
             if (getJvmDebugLevel() != null) {
 561  0
                 javaTask.createJvmarg().setLine(" -Dweblogic.StdoutSeverityLevel=" + jvmDebugLevel);
 562   
             }
 563   
 
 564  0
             if (ejbcClassName == null) {
 565   
                 // try to determine it from publicId
 566  0
                 if (PUBLICID_EJB11.equals(publicId)) {
 567  0
                     ejbcClassName = COMPILER_EJB11;
 568  0
                 } else if (PUBLICID_EJB20.equals(publicId)) {
 569  0
                     ejbcClassName = COMPILER_EJB20;
 570   
                 } else {
 571  0
                     log("Unrecognized publicId " + publicId + " - using EJB 1.1 compiler", Project.MSG_WARN);
 572  0
                     ejbcClassName = COMPILER_EJB11;
 573   
                 }
 574   
             }
 575   
 
 576  0
             javaTask.setClassname(ejbcClassName);
 577  0
             javaTask.createArg().setLine(additionalArgs);
 578  0
             if (keepgenerated) {
 579  0
                 javaTask.createArg().setValue("-keepgenerated");
 580   
             }
 581  0
             if (compiler == null) {
 582   
                 // try to use the compiler specified by build.compiler. 
 583   
                 // Right now we are just going to allow Jikes
 584  0
                 String buildCompiler 
 585   
                     = getTask().getProject().getProperty("build.compiler");
 586   
 
 587  0
                 if (buildCompiler != null && buildCompiler.equals("jikes")) {
 588  0
                     javaTask.createArg().setValue("-compiler");
 589  0
                     javaTask.createArg().setValue("jikes");
 590   
                 }
 591   
             } else {
 592  0
                 if (!compiler.equals(DEFAULT_COMPILER)) {
 593  0
                     javaTask.createArg().setValue("-compiler");
 594  0
                     javaTask.createArg().setLine(compiler);
 595   
                 }
 596   
             }
 597   
 
 598  0
             Path combinedClasspath = getCombinedClasspath();
 599  0
             if (wlClasspath != null && combinedClasspath != null
 600   
                  && combinedClasspath.toString().trim().length() > 0) {
 601  0
                 javaTask.createArg().setValue("-classpath");
 602  0
                 javaTask.createArg().setPath(combinedClasspath);
 603   
             }
 604   
 
 605  0
             javaTask.createArg().setValue(sourceJar.getPath());
 606  0
             if (outputDir == null) {
 607  0
                 javaTask.createArg().setValue(destJar.getPath());
 608   
             } else {
 609  0
                 javaTask.createArg().setValue(outputDir.getPath());
 610   
             }
 611   
 
 612  0
             Path classpath = wlClasspath;
 613   
 
 614  0
             if (classpath == null) {
 615  0
                 classpath = getCombinedClasspath();
 616   
             }
 617   
 
 618  0
             javaTask.setFork(true);
 619  0
             if (classpath != null) {
 620  0
                 javaTask.setClasspath(classpath);
 621   
             }
 622   
 
 623  0
             log("Calling " + ejbcClassName + " for " + sourceJar.toString(),
 624   
                 Project.MSG_VERBOSE);
 625   
 
 626  0
             if (javaTask.executeJava() != 0) {
 627  0
                 throw new BuildException("Ejbc reported an error");
 628   
             }
 629   
         } catch (Exception e) {
 630   
             // Have to catch this because of the semantics of calling main()
 631  0
             String msg = "Exception while calling " + ejbcClassName 
 632   
                 + ". Details: " + e.toString();
 633   
 
 634  0
             throw new BuildException(msg, e);
 635   
         }
 636   
     }
 637   
 
 638   
 
 639   
     /**
 640   
      * Method used to encapsulate the writing of the JAR file. Iterates over
 641   
      * the filenames/java.io.Files in the Hashtable stored on the instance
 642   
      * variable ejbFiles.
 643   
      */
 644  0
     protected void writeJar(String baseName, File jarFile, Hashtable files,
 645   
                             String publicId) throws BuildException {
 646   
         // need to create a generic jar first.
 647  0
         File genericJarFile = super.getVendorOutputJarFile(baseName);
 648   
 
 649  0
         super.writeJar(baseName, genericJarFile, files, publicId);
 650   
 
 651  0
         if (alwaysRebuild || isRebuildRequired(genericJarFile, jarFile)) {
 652  0
             buildWeblogicJar(genericJarFile, jarFile, publicId);
 653   
         }
 654  0
         if (!keepGeneric) {
 655  0
             log("deleting generic jar " + genericJarFile.toString(),
 656   
                 Project.MSG_VERBOSE);
 657  0
             genericJarFile.delete();
 658   
         }
 659   
     }
 660   
 
 661   
 
 662   
     /**
 663   
      * Called to validate that the tool parameters have been configured.
 664   
      */
 665  0
     public void validateConfigured() throws BuildException {
 666  0
         super.validateConfigured();
 667   
     }
 668   
 
 669   
 
 670   
     /**
 671   
      * Helper method to check to see if a weblogic EBJ1.1 jar needs to be
 672   
      * rebuilt using ejbc. Called from writeJar it sees if the "Bean" classes
 673   
      * are the only thing that needs to be updated and either updates the Jar
 674   
      * with the Bean classfile or returns true, saying that the whole weblogic
 675   
      * jar needs to be regened with ejbc. This allows faster build times for
 676   
      * working developers. <p>
 677   
      *
 678   
      * The way weblogic ejbc works is it creates wrappers for the publicly
 679   
      * defined methods as they are exposed in the remote interface. If the
 680   
      * actual bean changes without changing the the method signatures then
 681   
      * only the bean classfile needs to be updated and the rest of the
 682   
      * weblogic jar file can remain the same. If the Interfaces, ie. the
 683   
      * method signatures change or if the xml deployment dicriptors changed,
 684   
      * the whole jar needs to be rebuilt with ejbc. This is not strictly true
 685   
      * for the xml files. If the JNDI name changes then the jar doesnt have to
 686   
      * be rebuild, but if the resources references change then it does. At
 687   
      * this point the weblogic jar gets rebuilt if the xml files change at
 688   
      * all.
 689   
      *
 690   
      * @param genericJarFile java.io.File The generic jar file.
 691   
      * @param weblogicJarFile java.io.File The weblogic jar file to check to
 692   
      *      see if it needs to be rebuilt.
 693   
      */
 694  0
     protected boolean isRebuildRequired(File genericJarFile, File weblogicJarFile) {
 695  0
         boolean rebuild = false;
 696   
 
 697  0
         JarFile genericJar = null;
 698  0
         JarFile wlJar = null;
 699  0
         File newWLJarFile = null;
 700  0
         JarOutputStream newJarStream = null;
 701   
 
 702  0
         try {
 703  0
             log("Checking if weblogic Jar needs to be rebuilt for jar " + weblogicJarFile.getName(),
 704   
                 Project.MSG_VERBOSE);
 705   
             // Only go forward if the generic and the weblogic file both exist
 706  0
             if (genericJarFile.exists() && genericJarFile.isFile()
 707   
                  && weblogicJarFile.exists() && weblogicJarFile.isFile()) {
 708   
                 //open jar files
 709  0
                 genericJar = new JarFile(genericJarFile);
 710  0
                 wlJar = new JarFile(weblogicJarFile);
 711   
 
 712  0
                 Hashtable genericEntries = new Hashtable();
 713  0
                 Hashtable wlEntries = new Hashtable();
 714  0
                 Hashtable replaceEntries = new Hashtable();
 715   
 
 716   
                 //get the list of generic jar entries
 717  0
                 for (Enumeration e = genericJar.entries(); e.hasMoreElements();) {
 718  0
                     JarEntry je = (JarEntry) e.nextElement();
 719   
 
 720  0
                     genericEntries.put(je.getName().replace('\\', '/'), je);
 721   
                 }
 722   
                 //get the list of weblogic jar entries
 723  0
                 for (Enumeration e = wlJar.entries(); e.hasMoreElements();) {
 724  0
                     JarEntry je = (JarEntry) e.nextElement();
 725   
 
 726  0
                     wlEntries.put(je.getName(), je);
 727   
                 }
 728   
 
 729   
                 //Cycle Through generic and make sure its in weblogic
 730  0
                 ClassLoader genericLoader
 731   
                     = getClassLoaderFromJar(genericJarFile);
 732   
 
 733  0
                 for (Enumeration e = genericEntries.keys(); e.hasMoreElements();) {
 734  0
                     String filepath = (String) e.nextElement();
 735   
 
 736  0
                     if (wlEntries.containsKey(filepath)) {// File name/path match
 737   
 
 738   
                         // Check files see if same
 739  0
                         JarEntry genericEntry = (JarEntry) genericEntries.get(filepath);
 740  0
                         JarEntry wlEntry = (JarEntry) wlEntries.get(filepath);
 741   
 
 742  0
                         if ((genericEntry.getCrc() != wlEntry.getCrc()) || // Crc's Match
 743   
                         (genericEntry.getSize() != wlEntry.getSize())) {// Size Match
 744   
 
 745  0
                             if (genericEntry.getName().endsWith(".class")) {
 746   
                                 //File are different see if its an object or an interface
 747  0
                                 String classname = genericEntry.getName().replace(File.separatorChar, '.');
 748   
 
 749  0
                                 classname = classname.substring(0, classname.lastIndexOf(".class"));
 750   
 
 751  0
                                 Class genclass = genericLoader.loadClass(classname);
 752   
 
 753  0
                                 if (genclass.isInterface()) {
 754   
                                     //Interface changed   rebuild jar.
 755  0
                                     log("Interface " + genclass.getName() + " has changed", Project.MSG_VERBOSE);
 756  0
                                     rebuild = true;
 757  0
                                     break;
 758   
                                 } else {
 759   
                                     //Object class Changed   update it.
 760  0
                                     replaceEntries.put(filepath, genericEntry);
 761   
                                 }
 762   
                             } else {
 763   
                                 // is it the manifest. If so ignore it
 764  0
                                 if (!genericEntry.getName().equals("META-INF/MANIFEST.MF")) {
 765   
                                     //File other then class changed   rebuild
 766  0
                                     log("Non class file " + genericEntry.getName() + " has changed", Project.MSG_VERBOSE);
 767  0
                                     rebuild = true;
 768  0
                                     break;
 769   
                                 }
 770   
                             }
 771   
                         }
 772   
                     } else {// a file doesnt exist rebuild
 773   
 
 774  0
                         log("File " + filepath + " not present in weblogic jar", Project.MSG_VERBOSE);
 775  0
                         rebuild = true;
 776  0
                         break;
 777   
                     }
 778   
                 }
 779   
 
 780  0
                 if (!rebuild) {
 781  0
                     log("No rebuild needed - updating jar", Project.MSG_VERBOSE);
 782  0
                     newWLJarFile = new File(weblogicJarFile.getAbsolutePath() + ".temp");
 783  0
                     if (newWLJarFile.exists()) {
 784  0
                         newWLJarFile.delete();
 785   
                     }
 786   
 
 787  0
                     newJarStream = new JarOutputStream(new FileOutputStream(newWLJarFile));
 788  0
                     newJarStream.setLevel(0);
 789   
 
 790   
                     //Copy files from old weblogic jar
 791  0
                     for (Enumeration e = wlEntries.elements(); e.hasMoreElements();) {
 792  0
                         byte[] buffer = new byte[1024];
 793  0
                         int bytesRead;
 794  0
                         InputStream is;
 795  0
                         JarEntry je = (JarEntry) e.nextElement();
 796   
 
 797  0
                         if (je.getCompressedSize() == -1 ||
 798   
                             je.getCompressedSize() == je.getSize()) {
 799  0
                             newJarStream.setLevel(0);
 800   
                         } else {
 801  0
                             newJarStream.setLevel(9);
 802   
                         }
 803   
 
 804   
                         // Update with changed Bean class
 805  0
                         if (replaceEntries.containsKey(je.getName())) {
 806  0
                             log("Updating Bean class from generic Jar " + je.getName(), Project.MSG_VERBOSE);
 807   
                             // Use the entry from the generic jar
 808  0
                             je = (JarEntry) replaceEntries.get(je.getName());
 809  0
                             is = genericJar.getInputStream(je);
 810   
                         } else {//use fle from original weblogic jar
 811   
 
 812  0
                             is = wlJar.getInputStream(je);
 813   
                         }
 814  0
                         newJarStream.putNextEntry(new JarEntry(je.getName()));
 815   
 
 816  0
                         while ((bytesRead = is.read(buffer)) != -1) {
 817  0
                             newJarStream.write(buffer, 0, bytesRead);
 818   
                         }
 819  0
                         is.close();
 820   
                     }
 821   
                 } else {
 822  0
                     log("Weblogic Jar rebuild needed due to changed "
 823   
                          + "interface or XML", Project.MSG_VERBOSE);
 824   
                 }
 825   
 
 826  0
                 if (genericLoader instanceof AntClassLoader) {
 827  0
                     AntClassLoader loader = (AntClassLoader)genericLoader;
 828  0
                     loader.cleanup();
 829   
                 }
 830   
             } else {
 831  0
                 rebuild = true;
 832   
             }
 833   
         } catch (ClassNotFoundException cnfe) {
 834  0
             String cnfmsg = "ClassNotFoundException while processing ejb-jar file"
 835   
                  + ". Details: "
 836   
                  + cnfe.getMessage();
 837   
 
 838  0
             throw new BuildException(cnfmsg, cnfe);
 839   
         } catch (IOException ioe) {
 840  0
             String msg = "IOException while processing ejb-jar file "
 841   
                  + ". Details: "
 842   
                  + ioe.getMessage();
 843   
 
 844  0
             throw new BuildException(msg, ioe);
 845   
         } finally {
 846   
             // need to close files and perhaps rename output
 847  0
             if (genericJar != null) {
 848  0
                 try {
 849  0
                     genericJar.close();
 850   
                 } catch (IOException closeException) {
 851   
                 }
 852   
             }
 853   
 
 854  0
             if (wlJar != null) {
 855  0
                 try {
 856  0
                     wlJar.close();
 857   
                 } catch (IOException closeException) {
 858   
                 }
 859   
             }
 860   
 
 861  0
             if (newJarStream != null) {
 862  0
                 try {
 863  0
                     newJarStream.close();
 864   
                 } catch (IOException closeException) {
 865   
                 }
 866   
 
 867  0
                 weblogicJarFile.delete();
 868  0
                 newWLJarFile.renameTo(weblogicJarFile);
 869  0
                 if (!weblogicJarFile.exists()) {
 870  0
                     rebuild = true;
 871   
                 }
 872   
             }
 873   
         }
 874   
 
 875  0
         return rebuild;
 876   
     }
 877   
 
 878   
 
 879   
     /**
 880   
      * Helper method invoked by isRebuildRequired to get a ClassLoader for a
 881   
      * Jar File passed to it.
 882   
      *
 883   
      * @param classjar java.io.File representing jar file to get classes from.
 884   
      */
 885  0
     protected ClassLoader getClassLoaderFromJar(File classjar) throws IOException {
 886  0
         Path lookupPath = new Path(getTask().getProject());
 887   
 
 888  0
         lookupPath.setLocation(classjar);
 889   
 
 890  0
         Path classpath = getCombinedClasspath();
 891   
 
 892  0
         if (classpath != null) {
 893  0
             lookupPath.append(classpath);
 894   
         }
 895   
 
 896  0
         return getTask().getProject().createClassLoader(lookupPath);
 897   
     }
 898   
 }
 899   
 
 900