Clover coverage report - Ant Coverage
Coverage timestamp: Tue Apr 8 2003 20:43:55 EST
file stats: LOC: 908   Methods: 33
NCLOC: 448   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
WebsphereDeploymentTool.java 0% 0% 0% 0%
 1   
 /*
 2   
  * The Apache Software License, Version 1.1
 3   
  *
 4   
  * Copyright (c) 2001-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.FileOutputStream;
 58   
 import java.io.IOException;
 59   
 import java.io.InputStream;
 60   
 import java.util.Enumeration;
 61   
 import java.util.Hashtable;
 62   
 import java.util.Iterator;
 63   
 import java.util.jar.JarEntry;
 64   
 import java.util.jar.JarFile;
 65   
 import java.util.jar.JarOutputStream;
 66   
 import org.apache.tools.ant.AntClassLoader;
 67   
 import org.apache.tools.ant.BuildException;
 68   
 import org.apache.tools.ant.Project;
 69   
 import org.apache.tools.ant.taskdefs.Java;
 70   
 import org.apache.tools.ant.types.Commandline;
 71   
 import org.apache.tools.ant.types.EnumeratedAttribute;
 72   
 import org.apache.tools.ant.types.Environment;
 73   
 import org.apache.tools.ant.types.Path;
 74   
 
 75   
 /**
 76   
  * Websphere deployment tool that augments the ejbjar task.
 77   
  * Searches for the websphere specific deployment descriptors and
 78   
  * adds them to the final ejb jar file. Websphere has two specific descriptors for session
 79   
  * beans:
 80   
  * <ul>
 81   
  *    <li>ibm-ejb-jar-bnd.xmi</li>
 82   
  *    <li>ibm-ejb-jar-ext.xmi</li>
 83   
  * </ul>
 84   
  * and another two for container managed entity beans:
 85   
  * <ul>
 86   
  *    <li>Map.mapxmi</li>
 87   
  *    <li>Schema.dbxmi</li>
 88   
  * </ul>
 89   
  * In terms of WebSphere, the generation of container code and stubs is called <code>deployment</code>.
 90   
  * This step can be performed by the websphere element as part of the jar generation process. If the
 91   
  * switch <code>ejbdeploy</code> is on, the ejbdeploy tool from the websphere toolset is called for
 92   
  * every ejb-jar. Unfortunately, this step only works, if you use the ibm jdk. Otherwise, the rmic
 93   
  * (called by ejbdeploy) throws a ClassFormatError. Be sure to switch ejbdeploy off, if run ant with
 94   
  * sun jdk.
 95   
  *
 96   
  * @author <a href="mailto:msahu@interkeel.com">Maneesh Sahu</a>
 97   
  */
 98   
 public class WebsphereDeploymentTool extends GenericDeploymentTool {
 99   
     /**
 100   
      * Enumerated attribute with the values for the database vendor types
 101   
      *
 102   
      * @author Conor MacNeill
 103   
      */
 104   
     public static class DBVendor extends EnumeratedAttribute {
 105  0
         public String[] getValues() {
 106  0
             return new String[]{
 107   
                 "SQL92", "SQL99", "DB2UDBWIN_V71", "DB2UDBOS390_V6", "DB2UDBAS400_V4R5",
 108   
                 "ORACLE_V8", "INFORMIX_V92", "SYBASE_V1192", "MSSQLSERVER_V7", "MYSQL_V323"
 109   
                 };
 110   
         }
 111   
     }
 112   
 
 113   
 
 114   
     public static final String PUBLICID_EJB11
 115   
          = "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN";
 116   
     public static final String PUBLICID_EJB20
 117   
          = "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN";
 118   
     protected static final String SCHEMA_DIR = "Schema/";
 119   
 
 120   
     protected static final String WAS_EXT = "ibm-ejb-jar-ext.xmi";
 121   
     protected static final String WAS_BND = "ibm-ejb-jar-bnd.xmi";
 122   
     protected static final String WAS_CMP_MAP = "Map.mapxmi";
 123   
     protected static final String WAS_CMP_SCHEMA = "Schema.dbxmi";
 124   
 
 125   
     /** Instance variable that stores the suffix for the websphere jarfile. */
 126   
     private String jarSuffix = ".jar";
 127   
 
 128   
     /** Instance variable that stores the location of the ejb 1.1 DTD file. */
 129   
     private String ejb11DTD;
 130   
 
 131   
     /** Instance variable that determines whether generic ejb jars are kept. */
 132   
 
 133   
     private boolean keepGeneric = false;
 134   
 
 135   
     private boolean alwaysRebuild = true;
 136   
 
 137   
     private boolean ejbdeploy = true;
 138   
 
 139   
     /** Indicates if the old CMP location convention is to be used. */
 140   
     private boolean newCMP = false;
 141   
 
 142   
     /** The classpath to the websphere classes. */
 143   
     private Path wasClasspath = null;
 144   
 
 145   
     /** The DB Vendor name, the EJB is persisted against */
 146   
     private String dbVendor;
 147   
 
 148   
     /** The name of the database to create. (For top-down mapping only) */
 149   
     private String dbName;
 150   
 
 151   
     /** The name of the schema to create. (For top-down mappings only) */
 152   
     private String dbSchema;
 153   
 
 154   
     /** true - Only generate the deployment code, do not run RMIC or Javac */
 155   
     private boolean codegen;
 156   
 
 157   
     /** true - Only output error messages, suppress informational messages */
 158   
     private boolean quiet = true;
 159   
 
 160   
     /** true - Disable the validation steps */
 161   
     private boolean novalidate;
 162   
 
 163   
     /** true - Disable warning and informational messages */
 164   
     private boolean nowarn;
 165   
 
 166   
     /** true - Disable informational messages */
 167   
     private boolean noinform;
 168   
 
 169   
     /** true - Enable internal tracing */
 170   
     private boolean trace;
 171   
 
 172   
     /** Additional options for RMIC */
 173   
     private String rmicOptions;
 174   
 
 175   
     /** true- Use the WebSphere 3.5 compatible mapping rules */
 176   
     private boolean use35MappingRules;
 177   
 
 178   
     /** the scratchdir for the ejbdeploy operation */
 179   
     private String tempdir = "_ejbdeploy_temp";
 180   
 
 181   
     /** the home directory for websphere */
 182   
     private File websphereHome;
 183   
 
 184   
     /** Get the classpath to the websphere classpaths */
 185  0
     public Path createWASClasspath() {
 186  0
         if (wasClasspath == null) {
 187  0
             wasClasspath = new Path(getTask().getProject());
 188   
         }
 189  0
         return wasClasspath.createPath();
 190   
     }
 191   
 
 192   
 
 193  0
     public void setWASClasspath(Path wasClasspath) {
 194  0
         this.wasClasspath = wasClasspath;
 195   
     }
 196   
 
 197   
 
 198   
     /** Sets the DB Vendor for the Entity Bean mapping ; optional.
 199   
      * Valid options are for example:
 200   
      * <ul>
 201   
      * <li>SQL92</li> <li>SQL99</li> <li>DB2UDBWIN_V71</li>
 202   
      * <li>DB2UDBOS390_V6</li> <li>DB2UDBAS400_V4R5</li> <li>ORACLE_V8</li>
 203   
      * <li>INFORMIX_V92</li> <li>SYBASE_V1192</li> <li>MYSQL_V323</li>
 204   
      * </ul>
 205   
      * This is also used to determine the name of the Map.mapxmi and
 206   
      * Schema.dbxmi files, for example Account-DB2UDBWIN_V71-Map.mapxmi
 207   
      * and Account-DB2UDBWIN_V71-Schema.dbxmi.
 208   
      */
 209  0
     public void setDbvendor(DBVendor dbvendor) {
 210  0
         this.dbVendor = dbvendor.getValue();
 211   
     }
 212   
 
 213   
 
 214   
     /**
 215   
      * Sets the name of the Database to create; optional.
 216   
      *
 217   
      * @param dbName name of the database
 218   
      */
 219  0
     public void setDbname(String dbName) {
 220  0
         this.dbName = dbName;
 221   
     }
 222   
 
 223   
 
 224   
     /**
 225   
      * Sets the name of the schema to create; optional.
 226   
      *
 227   
      * @param dbSchema name of the schema
 228   
      */
 229  0
     public void setDbschema(String dbSchema) {
 230  0
         this.dbSchema = dbSchema;
 231   
     }
 232   
 
 233   
 
 234   
     /**
 235   
      * Flag, default false, to only generate the deployment
 236   
      * code, do not run RMIC or Javac
 237   
      *
 238   
      * @param codegen option
 239   
      */
 240  0
     public void setCodegen(boolean codegen) {
 241  0
         this.codegen = codegen;
 242   
     }
 243   
 
 244   
 
 245   
     /**
 246   
      * Flag, default true, to only output error messages.
 247   
      *
 248   
      * @param quiet option
 249   
      */
 250  0
     public void setQuiet(boolean quiet) {
 251  0
         this.quiet = quiet;
 252   
     }
 253   
 
 254   
 
 255   
     /**
 256   
      * Flag to disable the validation steps; optional, default false.
 257   
      *
 258   
      * @param novalidate option
 259   
      */
 260  0
     public void setNovalidate(boolean novalidate) {
 261  0
         this.novalidate = novalidate;
 262   
     }
 263   
 
 264   
 
 265   
     /**
 266   
      * Flag to disable warning and informational messages; optional, default false.
 267   
      *
 268   
      * @param nowarn option
 269   
      */
 270  0
     public void setNowarn(boolean nowarn) {
 271  0
         this.nowarn = nowarn;
 272   
     }
 273   
 
 274   
 
 275   
     /**
 276   
      * Flag to disable informational messages; optional, default false.
 277   
      *
 278   
      * @param noinfom
 279   
      */
 280  0
     public void setNoinform(boolean noinfom) {
 281  0
         this.noinform = noinform;
 282   
     }
 283   
 
 284   
 
 285   
     /**
 286   
      * Flag to enable internal tracing when set, optional, default false.
 287   
      *
 288   
      * @param trace
 289   
      */
 290  0
     public void setTrace(boolean trace) {
 291  0
         this.trace = trace;
 292   
     }
 293   
 
 294   
     /**
 295   
      * Set the rmic options.
 296   
      *
 297   
      * @param options
 298   
      */
 299  0
     public void setRmicoptions(String options) {
 300  0
         this.rmicOptions = options;
 301   
     }
 302   
 
 303   
     /**
 304   
      * Flag to use the WebSphere 3.5 compatible mapping rules ; optional, default false.
 305   
      *
 306   
      * @param attr
 307   
      */
 308  0
     public void setUse35(boolean attr) {
 309  0
         use35MappingRules = attr;
 310   
     }
 311   
 
 312   
 
 313   
     /**
 314   
      * Set the rebuild flag to false to only update changes in the jar rather
 315   
      * than rerunning ejbdeploy; optional, default true.
 316   
      */
 317  0
     public void setRebuild(boolean rebuild) {
 318  0
         this.alwaysRebuild = rebuild;
 319   
     }
 320   
 
 321   
 
 322   
     /**
 323   
      * String value appended to the basename of the deployment
 324   
      * descriptor to create the filename of the WebLogic EJB
 325   
      * jar file. Optional, default '.jar'.
 326   
      * @param inString the string to use as the suffix.
 327   
      */
 328  0
     public void setSuffix(String inString) {
 329  0
         this.jarSuffix = inString;
 330   
     }
 331   
 
 332   
 
 333   
     /**
 334   
      * This controls whether the generic file used as input to
 335   
      * ejbdeploy is retained; optional, default false.
 336   
      * @param inValue either 'true' or 'false'.
 337   
      */
 338  0
     public void setKeepgeneric(boolean inValue) {
 339  0
         this.keepGeneric = inValue;
 340   
     }
 341   
 
 342   
 
 343   
     /**
 344   
      * Decide, wether ejbdeploy should be called or not;
 345   
      * optional, default true.
 346   
      *
 347   
      * @param ejbdeploy
 348   
      */
 349  0
     public void setEjbdeploy(boolean ejbdeploy) {
 350  0
         this.ejbdeploy = ejbdeploy;
 351   
     }
 352   
 
 353   
 
 354   
     /**
 355   
      * Setter used to store the location of the Sun's Generic EJB DTD. This
 356   
      * can be a file on the system or a resource on the classpath.
 357   
      *
 358   
      * @param inString the string to use as the DTD location.
 359   
      */
 360  0
     public void setEJBdtd(String inString) {
 361  0
         this.ejb11DTD = inString;
 362   
     }
 363   
 
 364   
 
 365   
     /**
 366   
      * Set the value of the oldCMP scheme. This is an antonym for newCMP
 367   
      * @ant.attribute ignore="true"
 368   
      */
 369  0
     public void setOldCMP(boolean oldCMP) {
 370  0
         this.newCMP = !oldCMP;
 371   
     }
 372   
 
 373   
 
 374   
     /**
 375   
      * Set the value of the newCMP scheme. The old CMP scheme locates the
 376   
      * websphere CMP descriptor based on the naming convention where the
 377   
      * websphere CMP file is expected to be named with the bean name as the
 378   
      * prefix. Under this scheme the name of the CMP descriptor does not match
 379   
      * the name actually used in the main websphere EJB descriptor. Also,
 380   
      * descriptors which contain multiple CMP references could not be used.
 381   
      */
 382  0
     public void setNewCMP(boolean newCMP) {
 383  0
         this.newCMP = newCMP;
 384   
     }
 385   
 
 386   
 
 387   
     /**
 388   
      * The directory, where ejbdeploy will write temporary files;
 389   
      * optional, defaults to '_ejbdeploy_temp'.
 390   
      */
 391   
 
 392  0
     public void setTempdir(String tempdir) {
 393  0
         this.tempdir = tempdir;
 394   
     }
 395   
 
 396   
 
 397  0
     protected DescriptorHandler getDescriptorHandler(File srcDir) {
 398  0
         DescriptorHandler handler = new DescriptorHandler(getTask(), srcDir);
 399   
         // register all the DTDs, both the ones that are known and
 400   
         // any supplied by the user
 401  0
         handler.registerDTD(PUBLICID_EJB11, ejb11DTD);
 402   
 
 403  0
         for (Iterator i = getConfig().dtdLocations.iterator(); i.hasNext();) {
 404  0
             EjbJar.DTDLocation dtdLocation = (EjbJar.DTDLocation) i.next();
 405   
 
 406  0
             handler.registerDTD(dtdLocation.getPublicId(), dtdLocation.getLocation());
 407   
         }
 408   
 
 409  0
         return handler;
 410   
     }
 411   
 
 412   
 
 413  0
     protected DescriptorHandler getWebsphereDescriptorHandler(final File srcDir) {
 414  0
         DescriptorHandler handler =
 415   
             new DescriptorHandler(getTask(), srcDir) {
 416  0
                 protected void processElement() {
 417   
                 }
 418   
             };
 419   
 
 420  0
         for (Iterator i = getConfig().dtdLocations.iterator(); i.hasNext();) {
 421  0
             EjbJar.DTDLocation dtdLocation = (EjbJar.DTDLocation) i.next();
 422   
 
 423  0
             handler.registerDTD(dtdLocation.getPublicId(), dtdLocation.getLocation());
 424   
         }
 425  0
         return handler;
 426   
     }
 427   
 
 428   
 
 429   
     /**
 430   
      * Add any vendor specific files which should be included in the EJB Jar.
 431   
      */
 432  0
     protected void addVendorFiles(Hashtable ejbFiles, String baseName) {
 433   
 
 434  0
         String ddPrefix = (usingBaseJarName() ? "" : baseName);
 435  0
         String dbPrefix = (dbVendor == null) ? "" : dbVendor + "-";
 436   
 
 437   
         // Get the Extensions document
 438  0
         File websphereEXT = new File(getConfig().descriptorDir, ddPrefix + WAS_EXT);
 439   
 
 440  0
         if (websphereEXT.exists()) {
 441  0
             ejbFiles.put(META_DIR + WAS_EXT,
 442   
                 websphereEXT);
 443   
         } else {
 444  0
             log("Unable to locate websphere extensions. It was expected to be in " +
 445   
                 websphereEXT.getPath(), Project.MSG_VERBOSE);
 446   
         }
 447   
 
 448  0
         File websphereBND = new File(getConfig().descriptorDir, ddPrefix + WAS_BND);
 449   
 
 450  0
         if (websphereBND.exists()) {
 451  0
             ejbFiles.put(META_DIR + WAS_BND,
 452   
                 websphereBND);
 453   
         } else {
 454  0
             log("Unable to locate websphere bindings. It was expected to be in " +
 455   
                 websphereBND.getPath(), Project.MSG_VERBOSE);
 456   
         }
 457   
 
 458  0
         if (!newCMP) {
 459  0
             log("The old method for locating CMP files has been DEPRECATED.", Project.MSG_VERBOSE);
 460  0
             log("Please adjust your websphere descriptor and set newCMP=\"true\" " +
 461   
                 "to use the new CMP descriptor inclusion mechanism. ", Project.MSG_VERBOSE);
 462   
         } else {
 463   
             // We attempt to put in the MAP and Schema files of CMP beans
 464  0
             try {
 465   
                 // Add the Map file
 466  0
                 File websphereMAP = new File(getConfig().descriptorDir,
 467   
                     ddPrefix + dbPrefix + WAS_CMP_MAP);
 468   
 
 469  0
                 if (websphereMAP.exists()) {
 470  0
                     ejbFiles.put(META_DIR + WAS_CMP_MAP,
 471   
                         websphereMAP);
 472   
                 } else {
 473  0
                     log("Unable to locate the websphere Map: " +
 474   
                         websphereMAP.getPath(), Project.MSG_VERBOSE);
 475   
                 }
 476   
 
 477  0
                 File websphereSchema = new File(getConfig().descriptorDir,
 478   
                     ddPrefix + dbPrefix + WAS_CMP_SCHEMA);
 479   
 
 480  0
                 if (websphereSchema.exists()) {
 481  0
                     ejbFiles.put(META_DIR + SCHEMA_DIR + WAS_CMP_SCHEMA,
 482   
                         websphereSchema);
 483   
                 } else {
 484  0
                     log("Unable to locate the websphere Schema: " +
 485   
                         websphereSchema.getPath(), Project.MSG_VERBOSE);
 486   
                 }
 487   
                 // Theres nothing else to see here...keep moving sonny
 488   
             } catch (Exception e) {
 489  0
                 String msg = "Exception while adding Vendor specific files: " +
 490   
                     e.toString();
 491   
 
 492  0
                 throw new BuildException(msg, e);
 493   
             }
 494   
         }
 495   
     }
 496   
 
 497   
 
 498   
     /**
 499   
      * Get the vendor specific name of the Jar that will be output. The
 500   
      * modification date of this jar will be checked against the dependent
 501   
      * bean classes.
 502   
      */
 503  0
     File getVendorOutputJarFile(String baseName) {
 504  0
         return new File(getDestDir(), baseName + jarSuffix);
 505   
     }
 506   
 
 507   
 
 508   
     /**
 509   
      * Gets the options for the EJB Deploy operation
 510   
      *
 511   
      * @return String
 512   
      */
 513  0
     protected String getOptions() {
 514   
         // Set the options
 515  0
         StringBuffer options = new StringBuffer();
 516   
 
 517  0
         if (dbVendor != null) {
 518  0
             options.append(" -dbvendor ").append(dbVendor);
 519   
         }
 520  0
         if (dbName != null) {
 521  0
             options.append(" -dbname \"").append(dbName).append("\"");
 522   
         }
 523   
 
 524  0
         if (dbSchema != null) {
 525  0
             options.append(" -dbschema \"").append(dbSchema).append("\"");
 526   
         }
 527   
 
 528  0
         if (codegen) {
 529  0
             options.append(" -codegen");
 530   
         }
 531   
 
 532  0
         if (quiet) {
 533  0
             options.append(" -quiet");
 534   
         }
 535   
 
 536  0
         if (novalidate) {
 537  0
             options.append(" -novalidate");
 538   
         }
 539   
 
 540  0
         if (nowarn) {
 541  0
             options.append(" -nowarn");
 542   
         }
 543   
 
 544  0
         if (noinform) {
 545  0
             options.append(" -noinform");
 546   
         }
 547   
 
 548  0
         if (trace) {
 549  0
             options.append(" -trace");
 550   
         }
 551   
 
 552  0
         if (use35MappingRules) {
 553  0
             options.append(" -35");
 554   
         }
 555   
 
 556  0
         if (rmicOptions != null) {
 557  0
             options.append(" -rmic \"").append(rmicOptions).append("\"");
 558   
         }
 559   
 
 560  0
         return options.toString();
 561   
     }// end getOptions
 562   
 
 563   
 
 564   
     /**
 565   
      * Helper method invoked by execute() for each websphere jar to be built.
 566   
      * Encapsulates the logic of constructing a java task for calling
 567   
      * websphere.ejbdeploy and executing it.
 568   
      *
 569   
      * @param sourceJar java.io.File representing the source (EJB1.1) jarfile.
 570   
      * @param destJar java.io.File representing the destination, websphere
 571   
      *      jarfile.
 572   
      */
 573  0
     private void buildWebsphereJar(File sourceJar, File destJar) {
 574  0
         try {
 575  0
             if (ejbdeploy) {
 576  0
                 String args =
 577   
                     " " + sourceJar.getPath() +
 578   
                     " " + tempdir +
 579   
                     " " + destJar.getPath() +
 580   
                     " " + getOptions();
 581   
 
 582  0
                 if (getCombinedClasspath() != null && getCombinedClasspath().toString().length() > 0) {
 583  0
                     args += " -cp " + getCombinedClasspath();
 584   
                 }
 585   
 
 586   
                 // Why do my ""'s get stripped away???
 587  0
                 log("EJB Deploy Options: " + args, Project.MSG_VERBOSE);
 588   
 
 589  0
                 Java javaTask = (Java) getTask().getProject().createTask("java");
 590   
                 // Set the JvmArgs
 591  0
                 javaTask.createJvmarg().setValue("-Xms64m");
 592  0
                 javaTask.createJvmarg().setValue("-Xmx128m");
 593   
 
 594   
                 // Set the Environment variable
 595  0
                 Environment.Variable var = new Environment.Variable();
 596   
 
 597  0
                 var.setKey("websphere.lib.dir");
 598  0
                 File libdir = new File(websphereHome, "lib");
 599  0
                 var.setValue(libdir.getAbsolutePath());
 600  0
                 javaTask.addSysproperty(var);
 601   
 
 602   
                 // Set the working directory
 603  0
                 javaTask.setDir(websphereHome);
 604   
 
 605   
                 // Set the Java class name
 606  0
                 javaTask.setTaskName("ejbdeploy");
 607  0
                 javaTask.setClassname("com.ibm.etools.ejbdeploy.EJBDeploy");
 608   
 
 609  0
                 Commandline.Argument arguments = javaTask.createArg();
 610   
 
 611  0
                 arguments.setLine(args);
 612   
 
 613  0
                 Path classpath = wasClasspath;
 614   
 
 615  0
                 if (classpath == null) {
 616  0
                     classpath = getCombinedClasspath();
 617   
                 }
 618   
 
 619  0
                 if (classpath != null) {
 620  0
                     javaTask.setClasspath(classpath);
 621  0
                     javaTask.setFork(true);
 622   
                 } else {
 623  0
                     javaTask.setFork(true);
 624   
                 }
 625   
 
 626  0
                 log("Calling websphere.ejbdeploy for " + sourceJar.toString(),
 627   
                     Project.MSG_VERBOSE);
 628   
 
 629  0
                 javaTask.execute();
 630   
             }
 631   
         } catch (Exception e) {
 632   
             // Have to catch this because of the semantics of calling main()
 633  0
             String msg = "Exception while calling ejbdeploy. Details: " + e.toString();
 634   
 
 635  0
             throw new BuildException(msg, e);
 636   
         }
 637   
     }
 638   
 
 639   
 
 640   
     /**
 641   
      * Method used to encapsulate the writing of the JAR file. Iterates over
 642   
      * the filenames/java.io.Files in the Hashtable stored on the instance
 643   
      * variable ejbFiles.
 644   
      */
 645  0
     protected void writeJar(String baseName, File jarFile, Hashtable files, String publicId)
 646   
          throws BuildException {
 647  0
         if (ejbdeploy) {
 648   
             // create the -generic.jar, if required
 649  0
             File genericJarFile = super.getVendorOutputJarFile(baseName);
 650   
 
 651  0
             super.writeJar(baseName, genericJarFile, files, publicId);
 652   
 
 653   
             // create the output .jar, if required
 654  0
             if (alwaysRebuild || isRebuildRequired(genericJarFile, jarFile)) {
 655  0
                 buildWebsphereJar(genericJarFile, jarFile);
 656   
             }
 657  0
             if (!keepGeneric) {
 658  0
                 log("deleting generic jar " + genericJarFile.toString(),
 659   
                     Project.MSG_VERBOSE);
 660  0
                 genericJarFile.delete();
 661   
             }
 662   
         } else {
 663   
             // create the "undeployed" output .jar, if required
 664  0
             super.writeJar(baseName, jarFile, files, publicId);
 665   
         }
 666   
     }
 667   
 
 668   
 
 669   
     /**
 670   
      * Called to validate that the tool parameters have been configured.
 671   
      */
 672  0
     public void validateConfigured() throws BuildException {
 673  0
         super.validateConfigured();
 674  0
         if (ejbdeploy) {
 675  0
             String home = getTask().getProject().getProperty("websphere.home");
 676  0
             if (home == null) {
 677  0
                 throw new BuildException("The 'websphere.home' property must be set when 'ejbdeploy=true'");
 678   
             }
 679  0
             websphereHome = getTask().getProject().resolveFile(home);
 680   
         }
 681   
     }
 682   
 
 683   
 
 684   
     /**
 685   
      * Helper method to check to see if a websphere EBJ1.1 jar needs to be
 686   
      * rebuilt using ejbdeploy. Called from writeJar it sees if the "Bean"
 687   
      * classes are the only thing that needs to be updated and either updates
 688   
      * the Jar with the Bean classfile or returns true, saying that the whole
 689   
      * websphere jar needs to be regened with ejbdeploy. This allows faster
 690   
      * build times for working developers. <p>
 691   
      *
 692   
      * The way websphere ejbdeploy works is it creates wrappers for the
 693   
      * publicly defined methods as they are exposed in the remote interface.
 694   
      * If the actual bean changes without changing the the method signatures
 695   
      * then only the bean classfile needs to be updated and the rest of the
 696   
      * websphere jar file can remain the same. If the Interfaces, ie. the
 697   
      * method signatures change or if the xml deployment dicriptors changed,
 698   
      * the whole jar needs to be rebuilt with ejbdeploy. This is not strictly
 699   
      * true for the xml files. If the JNDI name changes then the jar doesnt
 700   
      * have to be rebuild, but if the resources references change then it
 701   
      * does. At this point the websphere jar gets rebuilt if the xml files
 702   
      * change at all.
 703   
      *
 704   
      * @param genericJarFile java.io.File The generic jar file.
 705   
      * @param websphereJarFile java.io.File The websphere jar file to check to
 706   
      *      see if it needs to be rebuilt.
 707   
      */
 708  0
     protected boolean isRebuildRequired(File genericJarFile, File websphereJarFile) {
 709  0
         boolean rebuild = false;
 710   
 
 711  0
         JarFile genericJar = null;
 712  0
         JarFile wasJar = null;
 713  0
         File newwasJarFile = null;
 714  0
         JarOutputStream newJarStream = null;
 715   
 
 716  0
         try {
 717  0
             log("Checking if websphere Jar needs to be rebuilt for jar " + websphereJarFile.getName(),
 718   
                 Project.MSG_VERBOSE);
 719   
             // Only go forward if the generic and the websphere file both exist
 720  0
             if (genericJarFile.exists() && genericJarFile.isFile()
 721   
                  && websphereJarFile.exists() && websphereJarFile.isFile()) {
 722   
                 //open jar files
 723  0
                 genericJar = new JarFile(genericJarFile);
 724  0
                 wasJar = new JarFile(websphereJarFile);
 725   
 
 726  0
                 Hashtable genericEntries = new Hashtable();
 727  0
                 Hashtable wasEntries = new Hashtable();
 728  0
                 Hashtable replaceEntries = new Hashtable();
 729   
 
 730   
                 //get the list of generic jar entries
 731  0
                 for (Enumeration e = genericJar.entries(); e.hasMoreElements();) {
 732  0
                     JarEntry je = (JarEntry) e.nextElement();
 733   
 
 734  0
                     genericEntries.put(je.getName().replace('\\', '/'), je);
 735   
                 }
 736   
                 //get the list of websphere jar entries
 737  0
                 for (Enumeration e = wasJar.entries(); e.hasMoreElements();) {
 738  0
                     JarEntry je = (JarEntry) e.nextElement();
 739   
 
 740  0
                     wasEntries.put(je.getName(), je);
 741   
                 }
 742   
 
 743   
                 //Cycle Through generic and make sure its in websphere
 744  0
                 ClassLoader genericLoader = getClassLoaderFromJar(genericJarFile);
 745   
 
 746  0
                 for (Enumeration e = genericEntries.keys(); e.hasMoreElements();) {
 747  0
                     String filepath = (String) e.nextElement();
 748   
 
 749  0
                     if (wasEntries.containsKey(filepath)) {
 750   
                         // File name/path match
 751   
                         // Check files see if same
 752  0
                         JarEntry genericEntry = (JarEntry) genericEntries.get(filepath);
 753  0
                         JarEntry wasEntry = (JarEntry) wasEntries.get(filepath);
 754   
 
 755  0
                         if ((genericEntry.getCrc() != wasEntry.getCrc()) ||
 756   
                             (genericEntry.getSize() != wasEntry.getSize())) {
 757   
 
 758  0
                             if (genericEntry.getName().endsWith(".class")) {
 759   
                                 //File are different see if its an object or an interface
 760  0
                                 String classname = genericEntry.getName().replace(File.separatorChar, '.');
 761   
 
 762  0
                                 classname = classname.substring(0, classname.lastIndexOf(".class"));
 763   
 
 764  0
                                 Class genclass = genericLoader.loadClass(classname);
 765   
 
 766  0
                                 if (genclass.isInterface()) {
 767   
                                     //Interface changed   rebuild jar.
 768  0
                                     log("Interface " + genclass.getName() + " has changed", Project.MSG_VERBOSE);
 769  0
                                     rebuild = true;
 770  0
                                     break;
 771   
                                 } else {
 772   
                                     //Object class Changed   update it.
 773  0
                                     replaceEntries.put(filepath, genericEntry);
 774   
                                 }
 775   
                             } else {
 776   
                                 // is it the manifest. If so ignore it
 777  0
                                 if (!genericEntry.getName().equals("META-INF/MANIFEST.MF")) {
 778   
                                     //File other then class changed   rebuild
 779  0
                                     log("Non class file " + genericEntry.getName() + " has changed", Project.MSG_VERBOSE);
 780  0
                                     rebuild = true;
 781   
                                 }
 782  0
                                 break;
 783   
                             }
 784   
                         }
 785   
                     } else {// a file doesnt exist rebuild
 786   
 
 787  0
                         log("File " + filepath + " not present in websphere jar", Project.MSG_VERBOSE);
 788  0
                         rebuild = true;
 789  0
                         break;
 790   
                     }
 791   
                 }
 792   
 
 793  0
                 if (!rebuild) {
 794  0
                     log("No rebuild needed - updating jar", Project.MSG_VERBOSE);
 795  0
                     newwasJarFile = new File(websphereJarFile.getAbsolutePath() + ".temp");
 796  0
                     if (newwasJarFile.exists()) {
 797  0
                         newwasJarFile.delete();
 798   
                     }
 799   
 
 800  0
                     newJarStream = new JarOutputStream(new FileOutputStream(newwasJarFile));
 801  0
                     newJarStream.setLevel(0);
 802   
 
 803   
                     //Copy files from old websphere jar
 804  0
                     for (Enumeration e = wasEntries.elements(); e.hasMoreElements();) {
 805  0
                         byte[] buffer = new byte[1024];
 806  0
                         int bytesRead;
 807  0
                         InputStream is;
 808  0
                         JarEntry je = (JarEntry) e.nextElement();
 809   
 
 810  0
                         if (je.getCompressedSize() == -1 ||
 811   
                             je.getCompressedSize() == je.getSize()) {
 812  0
                             newJarStream.setLevel(0);
 813   
                         } else {
 814  0
                             newJarStream.setLevel(9);
 815   
                         }
 816   
 
 817   
                         // Update with changed Bean class
 818  0
                         if (replaceEntries.containsKey(je.getName())) {
 819  0
                             log("Updating Bean class from generic Jar " + je.getName(),
 820   
                                 Project.MSG_VERBOSE);
 821   
                             // Use the entry from the generic jar
 822  0
                             je = (JarEntry) replaceEntries.get(je.getName());
 823  0
                             is = genericJar.getInputStream(je);
 824   
                         } else {//use fle from original websphere jar
 825   
 
 826  0
                             is = wasJar.getInputStream(je);
 827   
                         }
 828  0
                         newJarStream.putNextEntry(new JarEntry(je.getName()));
 829   
 
 830  0
                         while ((bytesRead = is.read(buffer)) != -1) {
 831  0
                             newJarStream.write(buffer, 0, bytesRead);
 832   
                         }
 833  0
                         is.close();
 834   
                     }
 835   
                 } else {
 836  0
                     log("websphere Jar rebuild needed due to changed interface or XML", Project.MSG_VERBOSE);
 837   
                 }
 838   
             } else {
 839  0
                 rebuild = true;
 840   
             }
 841   
         } catch (ClassNotFoundException cnfe) {
 842  0
             String cnfmsg = "ClassNotFoundException while processing ejb-jar file"
 843   
                  + ". Details: "
 844   
                  + cnfe.getMessage();
 845   
 
 846  0
             throw new BuildException(cnfmsg, cnfe);
 847   
         } catch (IOException ioe) {
 848  0
             String msg = "IOException while processing ejb-jar file "
 849   
                  + ". Details: "
 850   
                  + ioe.getMessage();
 851   
 
 852  0
             throw new BuildException(msg, ioe);
 853   
         } finally {
 854   
             // need to close files and perhaps rename output
 855  0
             if (genericJar != null) {
 856  0
                 try {
 857  0
                     genericJar.close();
 858   
                 } catch (IOException closeException) {
 859   
                 }
 860   
             }
 861   
 
 862  0
             if (wasJar != null) {
 863  0
                 try {
 864  0
                     wasJar.close();
 865   
                 } catch (IOException closeException) {
 866   
                 }
 867   
             }
 868   
 
 869  0
             if (newJarStream != null) {
 870  0
                 try {
 871  0
                     newJarStream.close();
 872   
                 } catch (IOException closeException) {
 873   
                 }
 874   
 
 875  0
                 websphereJarFile.delete();
 876  0
                 newwasJarFile.renameTo(websphereJarFile);
 877  0
                 if (!websphereJarFile.exists()) {
 878  0
                     rebuild = true;
 879   
                 }
 880   
             }
 881   
         }
 882   
 
 883  0
         return rebuild;
 884   
     }
 885   
 
 886   
 
 887   
     /**
 888   
      * Helper method invoked by isRebuildRequired to get a ClassLoader for a
 889   
      * Jar File passed to it.
 890   
      *
 891   
      * @param classjar java.io.File representing jar file to get classes from.
 892   
      */
 893  0
     protected ClassLoader getClassLoaderFromJar(File classjar) throws IOException {
 894  0
         Path lookupPath = new Path(getTask().getProject());
 895   
 
 896  0
         lookupPath.setLocation(classjar);
 897   
 
 898  0
         Path classpath = getCombinedClasspath();
 899   
 
 900  0
         if (classpath != null) {
 901  0
             lookupPath.append(classpath);
 902   
         }
 903   
 
 904  0
         return getTask().getProject().createClassLoader(lookupPath);
 905   
     }
 906   
 }
 907   
 
 908