You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by co...@locus.apache.org on 2000/08/02 16:30:59 UTC

cvs commit: jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/ejb DescriptorHandler.java EJBDeploymentTool.java GenericDeploymentTool.java WeblogicDeploymentTool.java EjbJar.java

conor       00/08/02 07:30:57

  Modified:    src/main/org/apache/tools/ant/taskdefs/optional/ejb
                        EjbJar.java
  Added:       src/main/org/apache/tools/ant/taskdefs/optional/ejb
                        DescriptorHandler.java EJBDeploymentTool.java
                        GenericDeploymentTool.java
                        WeblogicDeploymentTool.java
  Log:
  Change the ejbjar to separate out vendor specific processing into separate
  tool classes.
  
  Split the Descriptor handler to a separate class
  
  Allow local DTDs to be loaded to resolve the external entities
  
  Moved all Weblogic specific code into a separate deployment tool object.
  
  Usage for generic jars is now
  
  <ejbjar srcdir="${descriptor.dir}" destdir="${deploymentjar.dir}">
    <include name="**/*-ejb-jar.xml"/>
  </ejbjar>
  
  For a weblogic deployment you now add a nested element with the weblogic specific
  configs
  
  <ejbjar srcdir="${descriptor.dir}">
    <weblogic destdir="${deploymentjar.dir}"
              classpath="${descriptorbuild.classpath}"
              keepgeneric="false"
              suffix=".jar"/>
    <include name="**/*-ejb-jar.xml"/>
    <exclude name="**/*-weblogic-ejb-jar.xml"/>
  </ejbjar>
  
  Revision  Changes    Path
  1.4       +71 -484   jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/ejb/EjbJar.java
  
  Index: EjbJar.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/ejb/EjbJar.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- EjbJar.java	2000/07/31 12:09:29	1.3
  +++ EjbJar.java	2000/08/02 14:30:56	1.4
  @@ -1,7 +1,7 @@
   /*
    * The Apache Software License, Version 1.1
    *
  - * Copyright (c) 1999 The Apache Software Foundation.  All rights
  + * Copyright (c) 2000 The Apache Software Foundation.  All rights
    * reserved.
    *
    * Redistribution and use in source and binary forms, with or without
  @@ -55,37 +55,20 @@
   package org.apache.tools.ant.taskdefs.optional.ejb;
   
   // Standard java imports
  -import java.io.FileInputStream;
  -import java.io.FileOutputStream;
  -import java.io.PrintWriter;
  -import java.io.File;
  -import java.io.IOException;
  -import java.util.jar.*;
  -import java.util.zip.*;
  -import java.util.ArrayList;
  -import java.util.Hashtable;
  -import java.util.Iterator;
  +import java.io.*;
  +import java.util.*;
   
   // XML imports
   import javax.xml.parsers.SAXParser;
   import javax.xml.parsers.SAXParserFactory;
   import javax.xml.parsers.ParserConfigurationException;
  -import org.xml.sax.Parser;
  -import org.xml.sax.Locator;
  -import org.xml.sax.InputSource;
  -import org.xml.sax.AttributeList;
  -import org.xml.sax.DocumentHandler;
   import org.xml.sax.SAXException;
  -import org.xml.sax.SAXParseException;
  -import org.xml.sax.helpers.ParserFactory;
   
   // Apache/Ant imports
   import org.apache.tools.ant.BuildException;
  -import org.apache.tools.ant.Task;
   import org.apache.tools.ant.Project;
   import org.apache.tools.ant.DirectoryScanner;
   import org.apache.tools.ant.taskdefs.MatchingTask;
  -import org.apache.tools.ant.taskdefs.Java;
   
   /**
    * <p>Provides automated ejb jar file creation for ant.  Extends the MatchingTask
  @@ -104,146 +87,21 @@
    * 5.1 jars. The weblogic deployment descriptors, used in constructing the 
    * Weblogic jar, are located based on a simple naming convention. The name of the
    * standard deployment descriptor is taken upto the first instance of a String,
  - * specified by the attribute basenameterminator, and then the regular Weblogic
  - * descriptor name is appended. For example if basenameterminator is set to '-',
  + * specified by the attribute basenameTerminator, and then the regular Weblogic
  + * descriptor name is appended. For example if basenameTerminator is set to '-',
    * its default value, and a standard descriptor is called Foo-ejb-jar.xml then
    * the files Foo-weblogic-ejb-jar.xml and Foo-weblogic-cmp-rdbms-jar.xml will be
    * looked for, and if found, included in the jarfile.</p>
    *
    * <p>Attributes and setter methods are provided to support optional generation
    * of Weblogic5.1 jars, optional deletion of generic jar files, setting alternate
  - * values for basenameterminator, and setting the strings to append to the names
  + * values for basenameTerminator, and setting the strings to append to the names
    * of the generated jarfiles.</p>
    *
    * @author <a href="mailto:tfennell@sapient.com">Tim Fennell</a>
    */
   public class EjbJar extends MatchingTask {
   
  -    /**
  -     * Inner class used by EjbJar to facilitate the parsing of deployment
  -     * descriptors and the capture of appropriate information. Extends
  -     * HandlerBase so it only implements the methods needed. During parsing
  -     * creates a hashtable consisting of entries mapping the name it should be
  -     * inserted into an EJB jar as to a File representing the file on disk. This
  -     * list can then be accessed through the getFiles() method.
  -     */
  -    protected class DescriptorHandler extends org.xml.sax.HandlerBase {
  -        /**
  -         * Bunch of constants used for storing entries in a hashtable, and for
  -         * constructing the filenames of various parts of the ejb jar.
  -         */
  -        private static final String HOME_INTERFACE   = "home";
  -        private static final String REMOTE_INTERFACE = "remote";
  -        private static final String BEAN_CLASS       = "ejb-class";
  -        private static final String PK_CLASS         = "prim-key-class";
  -
  -        /**
  -         * Instance variable used to store the name of the current attribute being
  -         * processed by the SAX parser.  Accessed by the SAX parser call-back methods
  -         * startElement() and endElement().
  -         */
  -        private String currentAttribute = null;
  -
  -        /**
  -         * Instance variable that stores the names of the files as they will be
  -         * put into the jar file, mapped to File objects  Accessed by the SAX
  -         * parser call-back method characters().
  -         */
  -        private Hashtable ejbFiles = null;
  -
  -        /** Instance variable to store the source directory of the task */
  -    
  -
  -        /**
  -         * Getter method that returns the set of files to include in the EJB jar.
  -         */
  -        public Hashtable getFiles() {
  -            return (ejbFiles == null) ? new Hashtable() : ejbFiles;
  -        }
  -
  -
  -        /**
  -         * SAX parser call-back method that is used to initialize the values of some
  -         * instance variables to ensure safe operation.
  -         */
  -        public void startDocument() throws SAXException {
  -            this.ejbFiles         = new Hashtable(10, 1);
  -            this.currentAttribute = null;
  -        }
  -
  -
  -        /**
  -         * SAX parser call-back method that is invoked when a new element is entered
  -         * into.  Used to store the context (attribute name) in the currentAttribute
  -         * instance variable.
  -         * @param name The name of the element being entered.
  -         * @param attrs Attributes associated to the element.
  -         */
  -        public void startElement(String name, AttributeList attrs) 
  -            throws SAXException {
  -            this.currentAttribute = name;
  -        }
  -
  -
  -        /**
  -         * SAX parser call-back method that is invoked when an element is exited.
  -         * Used to blank out (set to the empty string, not nullify) the name of
  -         * the currentAttribute.  A better method would be to use a stack as an
  -         * instance variable, however since we are only interested in leaf-node
  -         * data this is a simpler and workable solution.
  -         * @param name The name of the attribute being exited. Ignored
  -         *        in this implementation.
  -         */
  -        public void endElement(String name) throws SAXException {
  -            this.currentAttribute = "";
  -        }
  -
  -        /**
  -         * SAX parser call-back method invoked whenever characters are located within
  -         * an element.  currentAttribute (modified by startElement and endElement)
  -         * tells us whether we are in an interesting element (one of the up to four
  -         * classes of an EJB).  If so then converts the classname from the format
  -         * org.apache.tools.ant.Parser to the convention for storing such a class,
  -         * org/apache/tools/ant/Parser.class.  This is then resolved into a file
  -         * object under the srcdir which is stored in a Hashtable.
  -         * @param ch A character array containing all the characters in
  -         *        the element, and maybe others that should be ignored.
  -         * @param start An integer marking the position in the char
  -         *        array to start reading from.
  -         * @param length An integer representing an offset into the
  -         *        char array where the current data terminates.
  -         */
  -        public void characters(char[] ch, int start, int length) 
  -            throws SAXException {
  -            if (currentAttribute.equals(DescriptorHandler.HOME_INTERFACE)   ||
  -                currentAttribute.equals(DescriptorHandler.REMOTE_INTERFACE) ||
  -                currentAttribute.equals(DescriptorHandler.BEAN_CLASS)       ||
  -                currentAttribute.equals(DescriptorHandler.PK_CLASS)) {
  -                
  -                // Get the filename into a String object
  -                File classFile = null;
  -                String className = new String(ch, start, length);
  -
  -                // If it's a primitive wrapper then we shouldn't try and put
  -                // it into the jar, so ignore it.
  -                if (!className.startsWith("java.lang")) {
  -                    // Translate periods into path separators, add .class to the
  -                    // name, create the File object and add it to the Hashtable.
  -                    className = className.replace('.', File.separatorChar);
  -                    className += ".class";
  -                    classFile = new File(srcdir, className);
  -                    ejbFiles.put(className, classFile);
  -                }
  -            }
  -        }
  -    } // End of DescriptorHandler
  -
  -    /** Private constants that are used when constructing the standard jarfile */
  -    private static final String META_DIR  = "META-INF/";
  -    private static final String EJB_DD    = "ejb-jar.xml";
  -    private static final String WL_DD     = "weblogic-ejb-jar.xml";
  -    private static final String WL_CMP_DD = "weblogic-cmp-rdbms-jar.xml";
  -
       /** Stores a handle to the directory under which to search for files */
       private File srcdir = null;
   
  @@ -255,47 +113,50 @@
        * of a flat directory as the destination for the jar files.
        */
       private boolean flatdestdir = false;
  -
  -    /** Instance variable that determines whether to generate weblogic jars. */
  -    private boolean generateweblogic = false;
  -
  -    /** Instance variable that determines whether generic ejb jars are kept. */
  -    private boolean keepgeneric = true;
       
       /** Instance variable that marks the end of the 'basename' */
  -    private String basenameterminator = "-";
  +    private String basenameTerminator = "-";
   
       /** Instance variable that stores the suffix for the generated jarfile. */
       private String genericjarsuffix = "-generic.jar";
  +
  +    /**
  +     * The list of deployment tools we are going to run.
  +     */
  +    private ArrayList deploymentTools = new ArrayList();
   
  -    /** Instance variable that stores the suffix for the weblogic jarfile. */
  -    private String weblogicjarsuffix = "-wl.jar";
  +    public EJBDeploymentTool createWeblogic() {
  +        EJBDeploymentTool tool = new WeblogicDeploymentTool();
  +        tool.setTask(this);
  +        deploymentTools.add(tool);
  +        return tool;
  +    }
   
       /**
        * Setter used to store the value of srcdir prior to execute() being called.
  -     * @param inDir The string indicating the source directory.
  +     * @param inDir the source directory.
        */
  -    public void setSrcdir(String inDir) {
  -        this.srcdir = this.project.resolveFile(inDir);
  +    public void setSrcdir(File inDir) {
  +        this.srcdir = inDir;
       }
   
       /**
        * Setter used to store the value of destination directory prior to execute()
        * being called.
  -     * @param inFile The string indicating the source directory.
  +     * @param inFile the destination directory.
        */
  -    public void setDestdir(String inDir) {
  -        this.destdir = this.project.resolveFile(inDir);
  +    public void setDestdir(File inDir) {
  +        this.destdir = inDir;
       }
   
       /**
        * Setter used to store the value of flatdestdir.
        * @param inValue a string, either 'true' or 'false'.
        */
  -    public void setFlatdestdir(String inValue) {
  -        this.flatdestdir = Boolean.valueOf(inValue).booleanValue();
  +    public void setFlatdestdir(boolean inValue) {
  +        this.flatdestdir = inValue;
       }
  -
  +     
       /**
        * Setter used to store the suffix for the generated jar file.
        * @param inString the string to use as the suffix.
  @@ -305,164 +166,13 @@
       }
   
       /**
  -     * Setter used to store the suffix for the generated weblogic jar file.
  -     * @param inString the string to use as the suffix.
  -     */
  -    public void setWeblogicjarsuffix(String inString) {
  -        this.weblogicjarsuffix = inString;
  -    }
  -
  -    /**
  -     * Setter used to store the value of generateweblogic.
  -     * @param inValue a string, either 'true' or 'false'.
  -     */
  -    public void setGenerateweblogic(String inValue) {
  -        this.generateweblogic = Boolean.valueOf(inValue).booleanValue();
  -    }
  -
  -    /**
  -     * Setter used to store the value of keepgeneric
  -     * @param inValue a string, either 'true' or 'false'.
  -     */
  -    public void setKeepgeneric(String inValue) {
  -        this.keepgeneric = Boolean.valueOf(inValue).booleanValue();
  -    }
  -    
  -    /**
  -     * Setter used to store the value of basenameterminator
  +     * Setter used to store the value of basenameTerminator
        * @param inValue a string which marks the end of the basename.
  -     */
  -    public void setBasenameterminator(String inValue) {
  -        if (inValue != null) this.basenameterminator = inValue;
  -    }
  -
  -    /**
  -     * Utility method that encapsulates the logic of adding a file entry to
  -     * a .jar file.  Used by execute() to add entries to the jar file as it is
  -     * constructed.
  -     * @param jStream A JarOutputStream into which to write the
  -     *        jar entry.
  -     * @param iStream A FileInputStream from which to read the
  -     *        contents the file being added.
  -     * @param filename A String representing the name, including
  -     *        all relevant path information, that should be stored for the entry
  -     *        being added.
  -     */
  -    protected void addFileToJar(JarOutputStream jStream,
  -                                FileInputStream iStream,
  -                                String          filename)
  -        throws BuildException {
  -        try {
  -            // Create the zip entry and add it to the jar file
  -            ZipEntry zipEntry = new ZipEntry(filename);
  -            jStream.putNextEntry(zipEntry);
  -            
  -            // Create the file input stream, and buffer everything over
  -            // to the jar output stream
  -            byte[] byteBuffer = new byte[2 * 1024];
  -            int count = 0;
  -            do {
  -                jStream.write(byteBuffer, 0, count);
  -                count = iStream.read(byteBuffer, 0, byteBuffer.length);
  -            } while (count != -1);
  -            
  -            // Close up the file input stream for the class file
  -            iStream.close();
  -        }
  -        catch (IOException ioe) {
  -            String msg = "IOException while adding entry "
  -                         + filename + "to jarfile."
  -                         + ioe.getMessage();
  -            throw new BuildException(msg, ioe);
  -        }
  -    }
  -
  -    /**
  -     * Method used to encapsulate the writing of the JAR file. Iterates over the
  -     * filenames/java.io.Files in the Hashtable stored on the instance variable
  -     * ejbFiles.
  -     */
  -    public void writeJar(File jarfile, Hashtable files) throws BuildException{
  -        JarOutputStream jarStream = null;
  -        Iterator entryIterator = null;
  -        String entryName = null;
  -        File entryFile = null;
  -
  -        try {
  -            /* If the jarfile already exists then whack it and recreate it.
  -             * Should probably think of a more elegant way to handle this
  -             * so that in case of errors we don't leave people worse off
  -             * than when we started =)
  -             */
  -            if (jarfile.exists()) jarfile.delete();
  -            jarfile.getParentFile().mkdirs();
  -            jarfile.createNewFile();
  -            
  -            // Create the streams necessary to write the jarfile
  -            jarStream = new JarOutputStream(new FileOutputStream(jarfile));
  -            jarStream.setMethod(JarOutputStream.DEFLATED);
  -            
  -            // Loop through all the class files found and add them to the jar
  -            entryIterator = files.keySet().iterator();
  -            while (entryIterator.hasNext()) {
  -                entryName = (String) entryIterator.next();
  -                entryFile = (File) files.get(entryName);
  -                
  -                this.log("adding file '" + entryName + "'",
  -                         Project.MSG_VERBOSE);
  -
  -                addFileToJar(jarStream,
  -                             new FileInputStream(entryFile),
  -                             entryName);
  -            }
  -            // All done.  Close the jar stream.
  -            jarStream.close();
  -        }
  -        catch(IOException ioe) {
  -            String msg = "IOException while processing ejb-jar file '"
  -                + jarfile.toString()
  -                + "'. Details: "
  -                + ioe.getMessage();
  -            throw new BuildException(msg, ioe);
  -        }
  -    } // end of writeJar
  -    
  -
  -    /**
  -     * Helper method invoked by execute() for each WebLogic jar to be built.
  -     * Encapsulates the logic of constructing a java task for calling
  -     * weblogic.ejbc and executing it.
  -     * @param sourceJar java.io.File representing the source (EJB1.1) jarfile.
  -     * @param destJar java.io.File representing the destination, WebLogic
  -     *        jarfile.
        */
  -    public void buildWeblogicJar(File sourceJar, File destJar) {
  -        org.apache.tools.ant.taskdefs.Java javaTask = null;
  -        
  -        try {
  -            // Unfortunately, because weblogic.ejbc calls system.exit(), we
  -            // cannot do it 'in-process'. If they ever fix this, we should
  -            // change this code - it would be much quicker!
  -            String args = "-noexit " + sourceJar + " " + destJar;
  -            
  -            javaTask = (Java) this.project.createTask("java");
  -            javaTask.setClassname("weblogic.ejbc");
  -            javaTask.setArgs(args);
  -            javaTask.setFork(false);
  -
  -            this.log("Calling weblogic.ejbc for " + sourceJar.toString(),
  -                     Project.MSG_INFO);
  -
  -            javaTask.execute();
  -        }
  -        catch (Exception e) {
  -            // Have to catch this because of the semantics of calling main()
  -            String msg = "Exception while calling ejbc. Details: " + e.toString();
  -            throw new BuildException(msg, e);
  -        }
  +    public void setBasenameTerminator(String inValue) {
  +        if (inValue != null) this.basenameTerminator = inValue;
       }
   
  -
       /**
        * Invoked by Ant after the task is prepared, when it is ready to execute
        * this task.  Parses the XML deployment descriptor to acquire the list of
  @@ -475,173 +185,51 @@
        *            that a major problem occurred within this task.
        */
       public void execute() throws BuildException {
  -        boolean          needBuild  = true;
  -        DirectoryScanner ds         = null;
  -        String[]         files      = null;
  -        int              index      = 0;
  -        File             weblogicDD = null;
  -        File             jarfile    = null;
  -        File             wlJarfile  = null;
  -        File             jarToCheck = null;
  -        DescriptorHandler handler   = null;
  -        Hashtable        ejbFiles   = null;
  -        String           baseName   = null;
  -
  -        // Lets do a little asserting to make sure we have all the
  -        // required attributes from the task processor
  -        StringBuffer sb = new StringBuffer();
  -        boolean die = false;
  -        sb.append("Processing ejbjar - the following attributes ");
  -        sb.append("must be specified: ");
  -        if (this.srcdir     == null) { sb.append("srcdir ");     die = true; }
  -        if (this.destdir    == null) { sb.append("destdir");     die = true; }
  -        if ( die ) throw new BuildException(sb.toString());
  +        if (srcdir == null) {
  +            throw new BuildException("The srcdir attribute must be specified");
  +        }
  +        
  +        if (deploymentTools.size() == 0) {
  +            GenericDeploymentTool genericTool = new GenericDeploymentTool();
  +            genericTool.setDestdir(destdir);
  +            genericTool.setTask(this);
  +            genericTool.setGenericjarsuffix(genericjarsuffix);
   
  +            deploymentTools.add(genericTool);
  +        }
  +        
  +        for (Iterator i = deploymentTools.iterator(); i.hasNext(); ) {
  +            EJBDeploymentTool tool = (EJBDeploymentTool)i.next();
  +            tool.configure(basenameTerminator, flatdestdir);
  +            tool.validateConfigured();
  +        }
  +        
           try {
               // Create the parser using whatever parser the system dictates
               SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
  -            saxParserFactory.setValidating(false);
  +            saxParserFactory.setValidating(true);
               SAXParser saxParser = saxParserFactory.newSAXParser();
  -
  -            ds = this.getDirectoryScanner(this.srcdir);
  +    
  +            DirectoryScanner ds = getDirectoryScanner(srcdir);
               ds.scan();
  -            files = ds.getIncludedFiles();
  -
  -            this.log(files.length + " deployment descriptors located.",
  -                     Project.MSG_VERBOSE);
  -
  +            String[] files = ds.getIncludedFiles();
  +    
  +            log(files.length + " deployment descriptors located.",
  +                Project.MSG_VERBOSE);
  +            
  +                            
               // Loop through the files. Each file represents one deployment
               // descriptor, and hence one bean in our model.
  -            for (index=0; index < files.length; ++index) {
  -
  -                // By default we assume we need to build.
  -                needBuild = true;
  -
  -                // Work out what the base name is
  -                int endBaseName = 
  -                    files[index].indexOf(basenameterminator,
  -                                         files[index].lastIndexOf(File.separator));
  -                baseName = files[index].substring(0, endBaseName);
  -
  -                /* Parse the ejb deployment descriptor.  While it may not
  -                 * look like much, we use a SAXParser and an inner class to
  -                 * get hold of all the classfile names for the descriptor.
  -                 */
  -                handler = new DescriptorHandler();
  -                saxParser.parse(new InputSource
  -                                (new FileInputStream
  -                                 (new File(this.srcdir, files[index]))),
  -                                handler);
  -
  -                ejbFiles = handler.getFiles();
  -        
  -                /* Now try to locate all of the deployment descriptors for the
  -                 * jar, and if they exist, add them to the list of files.
  -                 */
  -
  -                // First the regular deployment descriptor
  -                ejbFiles.put(EjbJar.META_DIR + EjbJar.EJB_DD,
  -                             new File(this.srcdir, files[index]));
  -
  -                // Then the weblogic deployment descriptor
  -                weblogicDD = new File(this.srcdir,
  -                                      baseName 
  -                                      + this.basenameterminator
  -                                      + EjbJar.WL_DD);
  -
  -                if (weblogicDD.exists()) {
  -                    ejbFiles.put(EjbJar.META_DIR + EjbJar.WL_DD,
  -                                 weblogicDD);
  +            for (int index = 0; index < files.length; ++index) {
  +                // process the deployment descriptor in each tool
  +                for (Iterator i = deploymentTools.iterator(); i.hasNext(); ) {
  +                    EJBDeploymentTool tool = (EJBDeploymentTool)i.next();
  +                    processDescriptor(files[index], saxParser, tool);
                   }
  -
  -                // The the weblogic cmp deployment descriptor
  -                weblogicDD = new File(this.srcdir,
  -                                      baseName
  -                                      + this.basenameterminator 
  -                                      + EjbJar.WL_CMP_DD);
  -
  -                if (weblogicDD.exists()) {
  -                    ejbFiles.put(EjbJar.META_DIR + EjbJar.WL_CMP_DD,
  -                                 weblogicDD);
  -                }
  -
  -                // Lastly create File object for the Jar files. If we are using
  -                // a flat destination dir, then we need to redefine baseName!
  -                if (this.flatdestdir) {
  -                    int startName = baseName.lastIndexOf(File.separator);
  -                    int endName   = baseName.length();
  -                    baseName = baseName.substring(startName, endName);
  -                }
  -
  -                jarfile = new File(this.destdir,
  -                                   baseName
  -                                   + this.genericjarsuffix);
  -                
  -                wlJarfile = new File(this.destdir,
  -                                     baseName
  -                                     + this.weblogicjarsuffix);
  -                
  -                /* Check to see if the jar file is already up to date. 
  -                 * Unfortunately we have to parse the descriptor just to do
  -                 * that, but it's still a saving over re-constructing the jar
  -                 * file each time. Tertiary is used to determine which jarfile
  -                 * we should check times against...think about it.
  -                 */
  -                jarToCheck = this.generateweblogic ? wlJarfile : jarfile;
  -                
  -                if (jarToCheck.exists()) {
  -                    long    lastBuild = jarToCheck.lastModified();
  -                    Iterator fileIter = ejbFiles.values().iterator();
  -                    File currentFile  = null;
  -                    
  -                    // Set the need build to false until we find out otherwise.
  -                    needBuild = false;
  -
  -                    // Loop through the files seeing if any has been touched
  -                    // more recently than the destination jar.
  -                    while( (needBuild == false) && (fileIter.hasNext()) ) {
  -                        currentFile = (File) fileIter.next();
  -                        needBuild = ( lastBuild < currentFile.lastModified() );
  -                    }
  -                }
  -                
  -                // Check to see if we need a build and start
  -                // doing the work!
  -                if (needBuild) {
  -                    // Log that we are going to build...
  -                    this.log( "building "
  -                              + jarfile.getName()
  -                              + " with "
  -                              + String.valueOf(ejbFiles.size())
  -                              + " total files",
  -                              Project.MSG_INFO);
  -
  -                    // Use helper method to write the jarfile
  -                    this.writeJar(jarfile, ejbFiles);
  -
  -                    // Generate weblogic jar if requested
  -                    if (this.generateweblogic) {
  -                        this.buildWeblogicJar(jarfile, wlJarfile);
  -                    }
  -
  -                    // Delete the original jar if we weren't asked to keep it.
  -                    if (!this.keepgeneric) {
  -                        this.log("deleting jar " + jarfile.toString(),
  -                                 Project.MSG_INFO);
  -                        jarfile.delete();
  -                    }
  -                }
  -                else {
  -                    // Log that the file is up to date...
  -                    this.log(jarfile.toString() + " is up to date.",
  -                             Project.MSG_INFO);
  -                }
  -            }
  +            }    
           }
           catch (SAXException se) {
  -            String msg = "SAXException while parsing '"
  -                + files[index].toString()
  -                + "'. This probably indicates badly-formed XML."
  +            String msg = "SAXException while creating parser."
                   + "  Details: "
                   + se.getMessage();
               throw new BuildException(msg, se);
  @@ -651,15 +239,14 @@
                          + "Details: " + pce.getMessage();
               throw new BuildException(msg, pce);
           }
  -        catch (IOException ioe) {
  -            String msg = "IOException while parsing'"
  -                + files[index].toString()
  -                + "'.  This probably indicates that the descriptor"
  -                + " doesn't exist. Details:"
  -                + ioe.getMessage();
  -            throw new BuildException(msg, ioe);
  -        }
       } // end of execute()
  +
  +    
  +    private void processDescriptor(String descriptorFilename, SAXParser saxParser,
  +                                   EJBDeploymentTool tool) {
  +
  +        tool.processDescriptor(srcdir, descriptorFilename, saxParser);
  +    }
   }
   
   
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/ejb/DescriptorHandler.java
  
  Index: DescriptorHandler.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.taskdefs.optional.ejb;
  
  import java.util.*;
  import java.io.*;
  
  import org.xml.sax.InputSource;
  import org.xml.sax.SAXException;
  import org.xml.sax.AttributeList;
  
  /**
   * Inner class used by EjbJar to facilitate the parsing of deployment
   * descriptors and the capture of appropriate information. Extends
   * HandlerBase so it only implements the methods needed. During parsing
   * creates a hashtable consisting of entries mapping the name it should be
   * inserted into an EJB jar as to a File representing the file on disk. This
   * list can then be accessed through the getFiles() method.
   */
  public class DescriptorHandler extends org.xml.sax.HandlerBase {
      /**
       * Bunch of constants used for storing entries in a hashtable, and for
       * constructing the filenames of various parts of the ejb jar.
       */
      private static final String HOME_INTERFACE   = "home";
      private static final String REMOTE_INTERFACE = "remote";
      private static final String BEAN_CLASS       = "ejb-class";
      private static final String PK_CLASS         = "prim-key-class";
  
      /**
       * Instance variable used to store the name of the current element being
       * processed by the SAX parser.  Accessed by the SAX parser call-back methods
       * startElement() and endElement().
       */
      private String currentElement = null;
  
      /**
       * The text of the current element
       */
      private String currentText = null;
  
      /**
       * Instance variable that stores the names of the files as they will be
       * put into the jar file, mapped to File objects  Accessed by the SAX
       * parser call-back method characters().
       */
      private Hashtable ejbFiles = null;
  
      private Hashtable fileDTDs = new Hashtable();
      
      private Hashtable resourceDTDs = new Hashtable();
  
      /**
       * The directory containing the bean classes and interfaces. This is 
       * used for performing dependency file lookups.
       */
      private File srcDir;
  
      public DescriptorHandler(File srcDir) {
          this.srcDir = srcDir;
      }
      
  
      public void registerFileDTD(String publicId, File dtdFile) {
          fileDTDs.put(publicId, dtdFile);
      }
      
      public void registerResourceDTD(String publicId, String resourceName) {
          resourceDTDs.put(publicId, resourceName);
      }
  
      public InputSource resolveEntity(String publicId, String systemId)
          throws SAXException
      {
          
          File dtdFile = (File) fileDTDs.get(publicId);
          if (dtdFile != null && dtdFile.exists()) {
              try {
                  return new InputSource(new FileInputStream(dtdFile));
              } catch( FileNotFoundException ex ) {
                  // ignore
              }
          }
  
          String dtdResourceName = (String)resourceDTDs.get(publicId); 
          if (dtdResourceName != null) {
              InputStream is = this.getClass().getResourceAsStream(dtdResourceName);
              if( is != null ) {
                  return new InputSource(is);
              }
          }
          
          return null;
      }
  
      /**
       * Getter method that returns the set of files to include in the EJB jar.
       */
      public Hashtable getFiles() {
          return (ejbFiles == null) ? new Hashtable() : ejbFiles;
      }
  
  
      /**
       * SAX parser call-back method that is used to initialize the values of some
       * instance variables to ensure safe operation.
       */
      public void startDocument() throws SAXException {
          this.ejbFiles         = new Hashtable(10, 1);
          this.currentElement = null;
      }
  
  
      /**
       * SAX parser call-back method that is invoked when a new element is entered
       * into.  Used to store the context (attribute name) in the currentAttribute
       * instance variable.
       * @param name The name of the element being entered.
       * @param attrs Attributes associated to the element.
       */
      public void startElement(String name, AttributeList attrs) 
          throws SAXException {
          this.currentElement = name;
          currentText = "";            
      }
  
  
      /**
       * SAX parser call-back method that is invoked when an element is exited.
       * Used to blank out (set to the empty string, not nullify) the name of
       * the currentAttribute.  A better method would be to use a stack as an
       * instance variable, however since we are only interested in leaf-node
       * data this is a simpler and workable solution.
       * @param name The name of the attribute being exited. Ignored
       *        in this implementation.
       */
      public void endElement(String name) throws SAXException {
          processElement();
          currentText = "";
          this.currentElement = "";
      }
  
      /**
       * SAX parser call-back method invoked whenever characters are located within
       * an element.  currentAttribute (modified by startElement and endElement)
       * tells us whether we are in an interesting element (one of the up to four
       * classes of an EJB).  If so then converts the classname from the format
       * org.apache.tools.ant.Parser to the convention for storing such a class,
       * org/apache/tools/ant/Parser.class.  This is then resolved into a file
       * object under the srcdir which is stored in a Hashtable.
       * @param ch A character array containing all the characters in
       *        the element, and maybe others that should be ignored.
       * @param start An integer marking the position in the char
       *        array to start reading from.
       * @param length An integer representing an offset into the
       *        char array where the current data terminates.
       */
      public void characters(char[] ch, int start, int length)
          throws SAXException {
  
          currentText += new String(ch, start, length);
      }
      
      
      private void processElement() {
          if (currentElement.equals(HOME_INTERFACE)   ||
              currentElement.equals(REMOTE_INTERFACE) ||
              currentElement.equals(BEAN_CLASS)       ||
              currentElement.equals(PK_CLASS)) {
              
              // Get the filename into a String object
              File classFile = null;
              String className = currentText;
  
              // If it's a primitive wrapper then we shouldn't try and put
              // it into the jar, so ignore it.
              if (!className.startsWith("java.lang")) {
                  // Translate periods into path separators, add .class to the
                  // name, create the File object and add it to the Hashtable.
                  className = className.replace('.', File.separatorChar);
                  className += ".class";
                  classFile = new File(srcDir, className);
                  ejbFiles.put(className, classFile);
              }
          }
      }
  }
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/ejb/EJBDeploymentTool.java
  
  Index: EJBDeploymentTool.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.taskdefs.optional.ejb;
  
  import java.io.*;
  
  import javax.xml.parsers.SAXParser;
  
  import org.apache.tools.ant.BuildException;
  import org.apache.tools.ant.Task;
  
  public interface EJBDeploymentTool {
      /**
       * Process a deployment descriptor, generating the necessary vendor specifi
       * deployment files.
       *
       * @param descriptorFilename the name of the deployment descriptor
       * @param saxParser a SAX parser which can be used to parse the deployment descriptor. 
       */
      public void processDescriptor(File srcDir, String descriptorFilename, SAXParser saxParser) 
          throws BuildException;
      
      /**
       * Called to validate that the tool parameters have been configured.
       *
       */
      public void validateConfigured() throws BuildException;
  
      /**
       * Set the task which owns this tool
       */
      public void setTask(Task task);
      
      /**
       * Configure this tool for use in the ejbjar task.
       */
      public void configure(String basenameTerminator, boolean flatDestDir);     
  }
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/ejb/GenericDeploymentTool.java
  
  Index: GenericDeploymentTool.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.taskdefs.optional.ejb;
  
  import java.io.*;
  import java.util.*;
  import java.util.jar.*;
  import java.util.zip.*;
  
  import javax.xml.parsers.SAXParser;
  import org.xml.sax.InputSource;
  import org.xml.sax.SAXException;
  
  import org.apache.tools.ant.BuildException;
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.Task;
  
  public class GenericDeploymentTool implements EJBDeploymentTool {
      /** Private constants that are used when constructing the standard jarfile */
      protected static final String META_DIR  = "META-INF/";
      protected static final String EJB_DD    = "ejb-jar.xml";
  
      /** Stores a handle to the directory to put the Jar files in */
      private File destDir = null;
      
      /**
       * Instance variable that determines whether to use a package structure
       * of a flat directory as the destination for the jar files.
       */
      private boolean flatDestDir = false;
      
      /** Instance variable that marks the end of the 'basename' */
      private String basenameTerminator = "-";
  
      /** Instance variable that stores the suffix for the generated jarfile. */
      private String genericjarsuffix = "-generic.jar";
  
      /**
       * The task to which this tool belongs.
       */
      private Task task;
      
      /**
       * Setter used to store the value of destination directory prior to execute()
       * being called.
       * @param inDir the destination directory.
       */
      public void setDestdir(File inDir) {
          this.destDir = inDir;
      }
  
      /**
       * Get the desitination directory.
       */
      protected File getDestDir() {
          return destDir;
      }
      
  
      /**
       * Set the task which owns this tool
       */
      public void setTask(Task task) {
          this.task = task;
      }
         
      /**
       * Get the task for this tool.
       */
      protected Task getTask() {
          return task;
      }
  
      /**
       * Get the basename terminator.
       */
      protected String getBasenameTerminator() {
          return basenameTerminator;
      }
      
      /**
       * Setter used to store the suffix for the generated jar file.
       * @param inString the string to use as the suffix.
       */
      public void setGenericjarsuffix(String inString) {
          this.genericjarsuffix = inString;
      }
  
      /**
       * Configure this tool for use in the ejbjar task.
       */
      public void configure(String basenameTerminator, boolean flatDestDir) {
          this.basenameTerminator = basenameTerminator;
          this.flatDestDir = flatDestDir;
      }
  
      /**
       * Utility method that encapsulates the logic of adding a file entry to
       * a .jar file.  Used by execute() to add entries to the jar file as it is
       * constructed.
       * @param jStream A JarOutputStream into which to write the
       *        jar entry.
       * @param iStream A FileInputStream from which to read the
       *        contents the file being added.
       * @param filename A String representing the name, including
       *        all relevant path information, that should be stored for the entry
       *        being added.
       */
      protected void addFileToJar(JarOutputStream jStream,
                                  FileInputStream iStream,
                                  String          filename)
          throws BuildException {
          try {
              // Create the zip entry and add it to the jar file
              ZipEntry zipEntry = new ZipEntry(filename);
              jStream.putNextEntry(zipEntry);
              
              // Create the file input stream, and buffer everything over
              // to the jar output stream
              byte[] byteBuffer = new byte[2 * 1024];
              int count = 0;
              do {
                  jStream.write(byteBuffer, 0, count);
                  count = iStream.read(byteBuffer, 0, byteBuffer.length);
              } while (count != -1);
              
              // Close up the file input stream for the class file
              iStream.close();
          }
          catch (IOException ioe) {
              String msg = "IOException while adding entry "
                           + filename + "to jarfile."
                           + ioe.getMessage();
              throw new BuildException(msg, ioe);
          }
      }
  
      protected DescriptorHandler getDescriptorHandler(File srcDir) {
          return new DescriptorHandler(srcDir);
      }
      
      public void processDescriptor(File srcDir, String descriptorFilename, SAXParser saxParser) {
          try {
              DescriptorHandler handler = getDescriptorHandler(srcDir);
              
              /* Parse the ejb deployment descriptor.  While it may not
               * look like much, we use a SAXParser and an inner class to
               * get hold of all the classfile names for the descriptor.
               */
              saxParser.parse(new InputSource
                              (new FileInputStream
                               (new File(srcDir, descriptorFilename))),
                              handler);
                              
              Hashtable ejbFiles = handler.getFiles();
              
              String baseName = "";
              
              // Work out what the base name is
              int lastSeparatorIndex = descriptorFilename.lastIndexOf(File.separator);
              int endBaseName = -1;
              if (lastSeparatorIndex != -1) {
                  endBaseName = descriptorFilename.indexOf(basenameTerminator, 
                                                           lastSeparatorIndex);
              }
              else {
                  endBaseName = descriptorFilename.indexOf(basenameTerminator);
              }
              
              if (endBaseName != -1) {
                  baseName = descriptorFilename.substring(0, endBaseName);
              }
  
              // First the regular deployment descriptor
              ejbFiles.put(META_DIR + EJB_DD,
                           new File(srcDir, descriptorFilename));
                           
              addVendorFiles(ejbFiles, srcDir, baseName);
  
              // Lastly create File object for the Jar files. If we are using
              // a flat destination dir, then we need to redefine baseName!
              if (flatDestDir && baseName.length() != 0) {
                  int startName = baseName.lastIndexOf(File.separator);
                  int endName   = baseName.length();
                  baseName = baseName.substring(startName, endName);
              }
              
              File jarFile = getVendorOutputJarFile(baseName);
              
              // By default we assume we need to build.
              boolean needBuild = true;
  
              if (jarFile.exists()) {
                  long    lastBuild = jarFile.lastModified();
                  Iterator fileIter = ejbFiles.values().iterator();
                  // Set the need build to false until we find out otherwise.
                  needBuild = false;
  
                  // Loop through the files seeing if any has been touched
                  // more recently than the destination jar.
                  while( (needBuild == false) && (fileIter.hasNext()) ) {
                      File currentFile = (File) fileIter.next();
                      needBuild = ( lastBuild < currentFile.lastModified() );
                  }
              }
              
              // Check to see if we need a build and start
              // doing the work!
              if (needBuild) {
                  // Log that we are going to build...
                  getTask().log( "building "
                                + jarFile.getName()
                                + " with "
                                + String.valueOf(ejbFiles.size())
                                + " files",
                                Project.MSG_INFO);
      
                  // Use helper method to write the jarfile
                  writeJar(baseName, jarFile, ejbFiles);
  
              }
              else {
                  // Log that the file is up to date...
                  getTask().log(jarFile.toString() + " is up to date.",
                                Project.MSG_INFO);
              }
  
          }
          catch (SAXException se) {
              String msg = "SAXException while parsing '"
                  + descriptorFilename.toString()
                  + "'. This probably indicates badly-formed XML."
                  + "  Details: "
                  + se.getMessage();
              throw new BuildException(msg, se);
          }
          catch (IOException ioe) {
              String msg = "IOException while parsing'"
                  + descriptorFilename.toString()
                  + "'.  This probably indicates that the descriptor"
                  + " doesn't exist. Details:"
                  + ioe.getMessage();
              throw new BuildException(msg, ioe);
          }
      }
      
      /**
       * Add any vendor specific files which should be included in the 
       * EJB Jar.
       */
      protected void addVendorFiles(Hashtable ejbFiles, File srcDir, String baseName) {
      }
  
  
      /**
       * Get the vendor specific name of the Jar that will be output. The modification date
       * of this jar will be checked against the dependent bean classes.
       */
      File getVendorOutputJarFile(String baseName) {
          return new File(destDir, baseName + genericjarsuffix);
      }
  
      /**
       * Method used to encapsulate the writing of the JAR file. Iterates over the
       * filenames/java.io.Files in the Hashtable stored on the instance variable
       * ejbFiles.
       */
      protected void writeJar(String baseName, File jarfile, Hashtable files) throws BuildException{
          JarOutputStream jarStream = null;
          Iterator entryIterator = null;
          String entryName = null;
          File entryFile = null;
  
          try {
              /* If the jarfile already exists then whack it and recreate it.
               * Should probably think of a more elegant way to handle this
               * so that in case of errors we don't leave people worse off
               * than when we started =)
               */
              if (jarfile.exists()) {
                  jarfile.delete();
              }
              jarfile.getParentFile().mkdirs();
              jarfile.createNewFile();
              
              // Create the streams necessary to write the jarfile
              jarStream = new JarOutputStream(new FileOutputStream(jarfile));
              jarStream.setMethod(JarOutputStream.DEFLATED);
              
              // Loop through all the class files found and add them to the jar
              entryIterator = files.keySet().iterator();
              while (entryIterator.hasNext()) {
                  entryName = (String) entryIterator.next();
                  entryFile = (File) files.get(entryName);
                  
                  getTask().log("adding file '" + entryName + "'",
                                Project.MSG_VERBOSE);
  
                  addFileToJar(jarStream,
                               new FileInputStream(entryFile),
                               entryName);
              }
              // All done.  Close the jar stream.
              jarStream.close();
          }
          catch(IOException ioe) {
              String msg = "IOException while processing ejb-jar file '"
                  + jarfile.toString()
                  + "'. Details: "
                  + ioe.getMessage();
              throw new BuildException(msg, ioe);
          }
      } // end of writeJar
      
  
      /**
       * Called to validate that the tool parameters have been configured.
       *
       */
      public void validateConfigured() throws BuildException {
          if (destDir == null) {
              throw new BuildException("The destdir attribute must be specified");
          }
      }
  }
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/ejb/WeblogicDeploymentTool.java
  
  Index: WeblogicDeploymentTool.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2000 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.taskdefs.optional.ejb;
  
  import java.io.*;
  import java.util.*;
  
  import org.apache.tools.ant.BuildException;
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.Task;
  import org.apache.tools.ant.types.Path;
  import org.apache.tools.ant.taskdefs.Java;
  
  public class WeblogicDeploymentTool extends GenericDeploymentTool {
      protected static final String WL_DD     = "weblogic-ejb-jar.xml";
      protected static final String WL_CMP_DD = "weblogic-cmp-rdbms-jar.xml";
  
      /** Instance variable that stores the suffix for the weblogic jarfile. */
      private String jarSuffix = "-wl.jar";
  
      private Path classpath;
  
      /** Instance variable that determines whether generic ejb jars are kept. */
      private boolean keepgeneric = true;
      
      /**
       * Set the classpath to be used for this compilation.
       */
      public void setClasspath(Path classpath) {
          this.classpath = classpath;
      }
  
      /**
       * Setter used to store the suffix for the generated weblogic jar file.
       * @param inString the string to use as the suffix.
       */
      public void setSuffix(String inString) {
          this.jarSuffix = inString;
      }
  
      /**
       * Setter used to store the value of keepgeneric
       * @param inValue a string, either 'true' or 'false'.
       */
      public void setKeepgeneric(String inValue) {
          this.keepgeneric = Boolean.valueOf(inValue).booleanValue();
      }
      
      protected DescriptorHandler getDescriptorHandler(File srcDir) {
          DescriptorHandler handler = new DescriptorHandler(srcDir);
          handler.registerResourceDTD("-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN",
                                      "/weblogic/ejb/deployment/xml/ejb-jar.dtd");
          return handler;                                    
      }
  
      /**
       * Add any vendor specific files which should be included in the 
       * EJB Jar.
       */
      protected void addVendorFiles(Hashtable ejbFiles, File srcdir, String baseName) {
          // Then the weblogic deployment descriptor
          File weblogicDD = new File(srcdir,
                                baseName + getBasenameTerminator() + WL_DD);
  
          if (weblogicDD.exists()) {
              ejbFiles.put(META_DIR + WL_DD,
                           weblogicDD);
          }
  
          // The the weblogic cmp deployment descriptor
          File weblogicCMPDD = new File(srcdir,
                                baseName + getBasenameTerminator() + WL_CMP_DD);
  
          if (weblogicCMPDD.exists()) {
              ejbFiles.put(META_DIR + WL_CMP_DD,
                           weblogicCMPDD);
          }
      }
      
      /**
       * Get the vendor specific name of the Jar that will be output. The modification date
       * of this jar will be checked against the dependent bean classes.
       */
      File getVendorOutputJarFile(String baseName) {
          return new File(getDestDir(), baseName + jarSuffix);
      }
  
      /**
       * Helper method invoked by execute() for each WebLogic jar to be built.
       * Encapsulates the logic of constructing a java task for calling
       * weblogic.ejbc and executing it.
       * @param sourceJar java.io.File representing the source (EJB1.1) jarfile.
       * @param destJar java.io.File representing the destination, WebLogic
       *        jarfile.
       */
      private void buildWeblogicJar(File sourceJar, File destJar) {
          org.apache.tools.ant.taskdefs.Java javaTask = null;
          
          try {
              String args = "-noexit " + sourceJar.getPath().replace('\\', '/') + " " + destJar.getPath().replace('\\', '/');
              
              javaTask = (Java) getTask().getProject().createTask("java");
              javaTask.setClassname("weblogic.ejbc");
              javaTask.setArgs(args);
              if (classpath != null) {
                  javaTask.setClasspath(classpath);
                  javaTask.setFork(true);
              }
              else {
                  javaTask.setFork(false);
              }
              
  
              getTask().log("Calling weblogic.ejbc for " + sourceJar.toString(),
                            Project.MSG_VERBOSE);
  
              javaTask.execute();
          }
          catch (Exception e) {
              // Have to catch this because of the semantics of calling main()
              String msg = "Exception while calling ejbc. Details: " + e.toString();
              throw new BuildException(msg, e);
          }
      }
  
      /**
       * Method used to encapsulate the writing of the JAR file. Iterates over the
       * filenames/java.io.Files in the Hashtable stored on the instance variable
       * ejbFiles.
       */
      protected void writeJar(String baseName, File jarFile, Hashtable files) throws BuildException {
          // need to create a generic jar first.
          File genericJarFile = super.getVendorOutputJarFile(baseName);
          super.writeJar(baseName, genericJarFile, files);
          
          buildWeblogicJar(genericJarFile, jarFile);
          if (!keepgeneric) {
               getTask().log("deleting generic jar " + genericJarFile.toString(),
                             Project.MSG_VERBOSE);
               genericJarFile.delete();
          }
      }
  
      /**
       * Called to validate that the tool parameters have been configured.
       *
       */
      public void validateConfigured() throws BuildException {
          super.validateConfigured();
      }
  }
  
  
  

Re: cvs commit: jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/ejb DescriptorHandler.java EJBDeploymentTool.java GenericDeploymentTool.java WeblogicDeploymentTool.java EjbJar.java

Posted by Stefan Bodewig <bo...@bost.de>.
>>>>> "SB" == Stefan Bodewig <bo...@bost.de> writes:

>>>>> "CM" == Conor MacNeill <co...@m64.com> writes:
 CM> Let me know what you think about this approach.

 SB> First of all, I'm afraid it won't work, createWeblogic needs to
 SB> return WeblogicDeploymentTool instead of EJBDeploymentTool.

Wrong, sorry. It will work because ProjectHelper doesn't ask
IntrospectionHelper for its opinion.

You will break the antstructure task though.

Stefan

Re: cvs commit: jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/ejb DescriptorHandler.java EJBDeploymentTool.java GenericDeploymentTool.java WeblogicDeploymentTool.java EjbJar.java

Posted by Stefan Bodewig <bo...@bost.de>.
>>>>> "CM" == Conor MacNeill <co...@m64.com> writes:

 CM> Let me know what you think about this approach.

First of all, I'm afraid it won't work, createWeblogic needs to return
WeblogicDeploymentTool instead of EJBDeploymentTool.

IntrospectionHelper looks at the formal return type of the createXXX
methods and doesn't actually call it to look at the Object
returned. As EJBDeploymentTool doesn't have any setter, create or add
methods, the nested <weblogic> element doesn't have any attributes or
nested elements - from IntrospectionHelper's point of view.

Other than that:

This is the same approach as you could have it for javac, something
like

<javac>
  <jikes ... />
  <classic ... />
  <modern ... />
</javac>

which would be an improvement over the build.compiler.*
properties. 

You just need to be very careful that all the nested elements are
represented by classes everybody can compile and you will have to add
a createXXX method to the generic class for each implementation
around.

We can explore this road a little and see where it leads us though, it
can't be worse than adding ejb.jar.* properties in the same manner we
do for javac. Your approach works out for the scenarios I can come up
with and I don't have a better idea at hand.

Stefan

RE: cvs commit: jakarta-ant/src/main/org/apache/tools/ant/taskdefs/optional/ejb DescriptorHandler.java EJBDeploymentTool.java GenericDeploymentTool.java WeblogicDeploymentTool.java EjbJar.java

Posted by Conor MacNeill <co...@m64.com>.
This change fixes a few problems I encountered with the ejbjar task (mainly
downloading the EJB DTDs). It also tries to make ejbjar more expandable to
support other EJB Containers in the future. The basic strategy is to have a
nested element for each supported vendor tool.

<ejbjar ...>
  <weblogic .../>
  <vendorX ... />
</ejbjar>

This approach would allow a single build file to be used to deploy a bean in
different EJB Containers. Let me know what you think about this approach.

Conor