/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2001-2003 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 "Ant" 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.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Java;
import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.tools.ant.types.Environment;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.util.FileUtils;

/**
 * Websphere deployment tool that augments the ejbjar task.
 * Searches for the websphere specific deployment descriptors and
 * adds them to the final ejb jar file. Websphere has two specific descriptors for session
 * beans:
 * <ul>
 *    <li>ibm-ejb-jar-bnd.xmi</li>
 *    <li>ibm-ejb-jar-ext.xmi</li>
 * </ul>
 * and another two for container managed entity beans:
 * <ul>
 *    <li>Map.mapxmi</li>
 *    <li>Schema.dbxmi</li>
 * </ul>
 * In terms of WebSphere, the generation of container code and stubs is
 * called <code>deployment</code>. This step can be performed by the websphere
 * element as part of the jar generation process. If the switch
 * <code>ejbdeploy</code> is on, the ejbdeploy tool from the websphere toolset
 * is called for every ejb-jar. Unfortunately, this step only works, if you
 * use the ibm jdk. Otherwise, the rmic (called by ejbdeploy) throws a
 * ClassFormatError. Be sure to switch ejbdeploy off, if run ant with
 * sun jdk.
 *
 * @author <a href="mailto:msahu@interkeel.com">Maneesh Sahu</a>
 */
public class WebsphereDeploymentTool extends GenericDeploymentTool {
    /**
     * Enumerated attribute with the values for the database vendor types
     *
     */
    public static class DBVendor extends EnumeratedAttribute {
        public String[] getValues() {
            return new String[]{
                "SQL92", "SQL99", "DB2UDBWIN_V71", "DB2UDBOS390_V6", "DB2UDBAS400_V4R5",
                "ORACLE_V8", "INFORMIX_V92", "SYBASE_V1192", "MSSQLSERVER_V7", "MYSQL_V323"
                };
        }
    }


    public static final String PUBLICID_EJB11
         = "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 1.1//EN";
    public static final String PUBLICID_EJB20
         = "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN";
    protected static final String SCHEMA_DIR = "Schema/";

    protected static final String WAS_EXT = "ibm-ejb-jar-ext.xmi";
    protected static final String WAS_BND = "ibm-ejb-jar-bnd.xmi";
    protected static final String WAS_CMP_MAP = "Map.mapxmi";
    protected static final String WAS_CMP_SCHEMA = "Schema.dbxmi";

    /** Instance variable that stores the suffix for the websphere jarfile. */
    private String jarSuffix = ".jar";

    /** Instance variable that stores the location of the ejb 1.1 DTD file. */
    private String ejb11DTD;

    /** Instance variable that determines whether generic ejb jars are kept. */

    private boolean keepGeneric = false;

    private boolean alwaysRebuild = true;

    private boolean ejbdeploy = true;

    /** Indicates if the old CMP location convention is to be used. */
    private boolean newCMP = false;

    /** The classpath to the websphere classes. */
    private Path wasClasspath = null;

    /** The DB Vendor name, the EJB is persisted against */
    private String dbVendor;

    /** The name of the database to create. (For top-down mapping only) */
    private String dbName;

    /** The name of the schema to create. (For top-down mappings only) */
    private String dbSchema;

    /** true - Only generate the deployment code, do not run RMIC or Javac */
    private boolean codegen;

    /** true - Only output error messages, suppress informational messages */
    private boolean quiet = true;

    /** true - Disable the validation steps */
    private boolean novalidate;

    /** true - Disable warning and informational messages */
    private boolean nowarn;

    /** true - Disable informational messages */
    private boolean noinform;

    /** true - Enable internal tracing */
    private boolean trace;

    /** Additional options for RMIC */
    private String rmicOptions;

    /** true- Use the WebSphere 3.5 compatible mapping rules */
    private boolean use35MappingRules;

    /** the scratchdir for the ejbdeploy operation */
    private String tempdir = "_ejbdeploy_temp";

    /** the home directory for websphere */
    private File websphereHome;

    /** Get the classpath to the websphere classpaths */
    public Path createWASClasspath() {
        if (wasClasspath == null) {
            wasClasspath = new Path(getTask().getProject());
        }
        return wasClasspath.createPath();
    }


    public void setWASClasspath(Path wasClasspath) {
        this.wasClasspath = wasClasspath;
    }


    /** Sets the DB Vendor for the Entity Bean mapping ; optional.
     * Valid options are for example:
     * <ul>
     * <li>SQL92</li> <li>SQL99</li> <li>DB2UDBWIN_V71</li>
     * <li>DB2UDBOS390_V6</li> <li>DB2UDBAS400_V4R5</li> <li>ORACLE_V8</li>
     * <li>INFORMIX_V92</li> <li>SYBASE_V1192</li> <li>MYSQL_V323</li>
     * </ul>
     * This is also used to determine the name of the Map.mapxmi and
     * Schema.dbxmi files, for example Account-DB2UDBWIN_V71-Map.mapxmi
     * and Account-DB2UDBWIN_V71-Schema.dbxmi.
     */
    public void setDbvendor(DBVendor dbvendor) {
        this.dbVendor = dbvendor.getValue();
    }


    /**
     * Sets the name of the Database to create; optional.
     *
     * @param dbName name of the database
     */
    public void setDbname(String dbName) {
        this.dbName = dbName;
    }


    /**
     * Sets the name of the schema to create; optional.
     *
     * @param dbSchema name of the schema
     */
    public void setDbschema(String dbSchema) {
        this.dbSchema = dbSchema;
    }


    /**
     * Flag, default false, to only generate the deployment
     * code, do not run RMIC or Javac
     *
     * @param codegen option
     */
    public void setCodegen(boolean codegen) {
        this.codegen = codegen;
    }


    /**
     * Flag, default true, to only output error messages.
     *
     * @param quiet option
     */
    public void setQuiet(boolean quiet) {
        this.quiet = quiet;
    }


    /**
     * Flag to disable the validation steps; optional, default false.
     *
     * @param novalidate option
     */
    public void setNovalidate(boolean novalidate) {
        this.novalidate = novalidate;
    }


    /**
     * Flag to disable warning and informational messages; optional, default false.
     *
     * @param nowarn option
     */
    public void setNowarn(boolean nowarn) {
        this.nowarn = nowarn;
    }


    /**
     * Flag to disable informational messages; optional, default false.
     *
     * @param noinform if true disables informational messages
     */
    public void setNoinform(boolean noinform) {
        this.noinform = noinform;
    }


    /**
     * Flag to enable internal tracing when set, optional, default false.
     *
     * @param trace
     */
    public void setTrace(boolean trace) {
        this.trace = trace;
    }

    /**
     * Set the rmic options.
     *
     * @param options
     */
    public void setRmicoptions(String options) {
        this.rmicOptions = options;
    }

    /**
     * Flag to use the WebSphere 3.5 compatible mapping rules ; optional, default false.
     *
     * @param attr
     */
    public void setUse35(boolean attr) {
        use35MappingRules = attr;
    }


    /**
     * Set the rebuild flag to false to only update changes in the jar rather
     * than rerunning ejbdeploy; optional, default true.
     */
    public void setRebuild(boolean rebuild) {
        this.alwaysRebuild = rebuild;
    }


    /**
     * String value appended to the basename of the deployment
     * descriptor to create the filename of the WebLogic EJB
     * jar file. Optional, default '.jar'.
     * @param inString the string to use as the suffix.
     */
    public void setSuffix(String inString) {
        this.jarSuffix = inString;
    }


    /**
     * This controls whether the generic file used as input to
     * ejbdeploy is retained; optional, default false.
     * @param inValue either 'true' or 'false'.
     */
    public void setKeepgeneric(boolean inValue) {
        this.keepGeneric = inValue;
    }


    /**
     * Decide, wether ejbdeploy should be called or not;
     * optional, default true.
     *
     * @param ejbdeploy
     */
    public void setEjbdeploy(boolean ejbdeploy) {
        this.ejbdeploy = ejbdeploy;
    }


    /**
     * Setter used to store the location of the Sun's Generic EJB DTD. This
     * can be a file on the system or a resource on the classpath.
     *
     * @param inString the string to use as the DTD location.
     */
    public void setEJBdtd(String inString) {
        this.ejb11DTD = inString;
    }


    /**
     * Set the value of the oldCMP scheme. This is an antonym for newCMP
     * @ant.attribute ignore="true"
     */
    public void setOldCMP(boolean oldCMP) {
        this.newCMP = !oldCMP;
    }


    /**
     * Set the value of the newCMP scheme. The old CMP scheme locates the
     * websphere CMP descriptor based on the naming convention where the
     * websphere CMP file is expected to be named with the bean name as the
     * prefix. Under this scheme the name of the CMP descriptor does not match
     * the name actually used in the main websphere EJB descriptor. Also,
     * descriptors which contain multiple CMP references could not be used.
     */
    public void setNewCMP(boolean newCMP) {
        this.newCMP = newCMP;
    }


    /**
     * The directory, where ejbdeploy will write temporary files;
     * optional, defaults to '_ejbdeploy_temp'.
     */

    public void setTempdir(String tempdir) {
        this.tempdir = tempdir;
    }


    protected DescriptorHandler getDescriptorHandler(File srcDir) {
        DescriptorHandler handler = new DescriptorHandler(getTask(), srcDir);
        // register all the DTDs, both the ones that are known and
        // any supplied by the user
        handler.registerDTD(PUBLICID_EJB11, ejb11DTD);

        for (Iterator i = getConfig().dtdLocations.iterator(); i.hasNext();) {
            EjbJar.DTDLocation dtdLocation = (EjbJar.DTDLocation) i.next();

            handler.registerDTD(dtdLocation.getPublicId(), dtdLocation.getLocation());
        }

        return handler;
    }


    protected DescriptorHandler getWebsphereDescriptorHandler(final File srcDir) {
        DescriptorHandler handler =
            new DescriptorHandler(getTask(), srcDir) {
                protected void processElement() {
                }
            };

        for (Iterator i = getConfig().dtdLocations.iterator(); i.hasNext();) {
            EjbJar.DTDLocation dtdLocation = (EjbJar.DTDLocation) i.next();

            handler.registerDTD(dtdLocation.getPublicId(), dtdLocation.getLocation());
        }
        return handler;
    }


    /**
     * Add any vendor specific files which should be included in the EJB Jar.
     */
    protected void addVendorFiles(Hashtable ejbFiles, String baseName) {

        String ddPrefix = (usingBaseJarName() ? "" : baseName);
        String dbPrefix = (dbVendor == null) ? "" : dbVendor + "-";

        // Get the Extensions document
        File websphereEXT = new File(getConfig().descriptorDir, ddPrefix + WAS_EXT);

        if (websphereEXT.exists()) {
            ejbFiles.put(META_DIR + WAS_EXT,
                websphereEXT);
        } else {
            log("Unable to locate websphere extensions. "
                + "It was expected to be in "
                + websphereEXT.getPath(), Project.MSG_VERBOSE);
        }

        File websphereBND = new File(getConfig().descriptorDir, ddPrefix + WAS_BND);

        if (websphereBND.exists()) {
            ejbFiles.put(META_DIR + WAS_BND,
                websphereBND);
        } else {
            log("Unable to locate websphere bindings. "
                + "It was expected to be in "
                + websphereBND.getPath(), Project.MSG_VERBOSE);
        }

        if (!newCMP) {
            log("The old method for locating CMP files has been DEPRECATED.",
                Project.MSG_VERBOSE);
            log("Please adjust your websphere descriptor and set "
                + "newCMP=\"true\" to use the new CMP descriptor "
                + "inclusion mechanism. ", Project.MSG_VERBOSE);
        } else {
            // We attempt to put in the MAP and Schema files of CMP beans
            try {
                // Add the Map file
                File websphereMAP = new File(getConfig().descriptorDir,
                    ddPrefix + dbPrefix + WAS_CMP_MAP);

                if (websphereMAP.exists()) {
                    ejbFiles.put(META_DIR + WAS_CMP_MAP,
                        websphereMAP);
                } else {
                    log("Unable to locate the websphere Map: "
                        + websphereMAP.getPath(), Project.MSG_VERBOSE);
                }

                File websphereSchema = new File(getConfig().descriptorDir,
                    ddPrefix + dbPrefix + WAS_CMP_SCHEMA);

                if (websphereSchema.exists()) {
                    ejbFiles.put(META_DIR + SCHEMA_DIR + WAS_CMP_SCHEMA,
                        websphereSchema);
                } else {
                    log("Unable to locate the websphere Schema: "
                        + websphereSchema.getPath(), Project.MSG_VERBOSE);
                }
                // Theres nothing else to see here...keep moving sonny
            } catch (Exception e) {
                String msg = "Exception while adding Vendor specific files: "
                    + e.toString();

                throw new BuildException(msg, e);
            }
        }
    }


    /**
     * 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);
    }


    /**
     * Gets the options for the EJB Deploy operation
     *
     * @return String
     */
    protected String getOptions() {
        // Set the options
        StringBuffer options = new StringBuffer();

        if (dbVendor != null) {
            options.append(" -dbvendor ").append(dbVendor);
        }
        if (dbName != null) {
            options.append(" -dbname \"").append(dbName).append("\"");
        }

        if (dbSchema != null) {
            options.append(" -dbschema \"").append(dbSchema).append("\"");
        }

        if (codegen) {
            options.append(" -codegen");
        }

        if (quiet) {
            options.append(" -quiet");
        }

        if (novalidate) {
            options.append(" -novalidate");
        }

        if (nowarn) {
            options.append(" -nowarn");
        }

        if (noinform) {
            options.append(" -noinform");
        }

        if (trace) {
            options.append(" -trace");
        }

        if (use35MappingRules) {
            options.append(" -35");
        }

        if (rmicOptions != null) {
            options.append(" -rmic \"").append(rmicOptions).append("\"");
        }

        return options.toString();
    }


    /**
     * Helper method invoked by execute() for each websphere jar to be built.
     * Encapsulates the logic of constructing a java task for calling
     * websphere.ejbdeploy and executing it.
     *
     * @param sourceJar java.io.File representing the source (EJB1.1) jarfile.
     * @param destJar java.io.File representing the destination, websphere
     *      jarfile.
     */
    private void buildWebsphereJar(File sourceJar, File destJar) {
        try {
            if (ejbdeploy) {
                Java javaTask = (Java) getTask().getProject().createTask("java");
                // Set the JvmArgs
                javaTask.createJvmarg().setValue("-Xms64m");
                javaTask.createJvmarg().setValue("-Xmx128m");

                // Set the Environment variable
                Environment.Variable var = new Environment.Variable();

                var.setKey("websphere.lib.dir");
                File libdir = new File(websphereHome, "lib");
                var.setValue(libdir.getAbsolutePath());
                javaTask.addSysproperty(var);

                // Set the working directory
                javaTask.setDir(websphereHome);

                // Set the Java class name
                javaTask.setTaskName("ejbdeploy");
                javaTask.setClassname("com.ibm.etools.ejbdeploy.EJBDeploy");

                javaTask.createArg().setValue(sourceJar.getPath());
                javaTask.createArg().setValue(tempdir);
                javaTask.createArg().setValue(destJar.getPath());
                javaTask.createArg().setLine(getOptions());
                if (getCombinedClasspath() != null
                    && getCombinedClasspath().toString().length() > 0) {
                    javaTask.createArg().setValue("-cp");
                    javaTask.createArg().setValue(getCombinedClasspath().toString());
                }

                Path classpath = wasClasspath;

                if (classpath == null) {
                    classpath = getCombinedClasspath();
                }

                if (classpath != null) {
                    javaTask.setClasspath(classpath);
                    javaTask.setFork(true);
                } else {
                    javaTask.setFork(true);
                }

                log("Calling websphere.ejbdeploy 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 ejbdeploy. 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, String publicId)
         throws BuildException {
        if (ejbdeploy) {
            // create the -generic.jar, if required
            File genericJarFile = super.getVendorOutputJarFile(baseName);

            super.writeJar(baseName, genericJarFile, files, publicId);

            // create the output .jar, if required
            if (alwaysRebuild || isRebuildRequired(genericJarFile, jarFile)) {
                buildWebsphereJar(genericJarFile, jarFile);
            }
            if (!keepGeneric) {
                log("deleting generic jar " + genericJarFile.toString(),
                    Project.MSG_VERBOSE);
                genericJarFile.delete();
            }
        } else {
            // create the "undeployed" output .jar, if required
            super.writeJar(baseName, jarFile, files, publicId);
        }
    }


    /**
     * Called to validate that the tool parameters have been configured.
     */
    public void validateConfigured() throws BuildException {
        super.validateConfigured();
        if (ejbdeploy) {
            String home = getTask().getProject().getProperty("websphere.home");
            if (home == null) {
                throw new BuildException("The 'websphere.home' property must "
                    + "be set when 'ejbdeploy=true'");
            }
            websphereHome = getTask().getProject().resolveFile(home);
        }
    }


    /**
     * Helper method to check to see if a websphere EBJ1.1 jar needs to be
     * rebuilt using ejbdeploy. Called from writeJar it sees if the "Bean"
     * classes are the only thing that needs to be updated and either updates
     * the Jar with the Bean classfile or returns true, saying that the whole
     * websphere jar needs to be regened with ejbdeploy. This allows faster
     * build times for working developers. <p>
     *
     * The way websphere ejbdeploy works is it creates wrappers for the
     * publicly defined methods as they are exposed in the remote interface.
     * If the actual bean changes without changing the the method signatures
     * then only the bean classfile needs to be updated and the rest of the
     * websphere jar file can remain the same. If the Interfaces, ie. the
     * method signatures change or if the xml deployment descriptors changed,
     * the whole jar needs to be rebuilt with ejbdeploy. This is not strictly
     * true for the xml files. If the JNDI name changes then the jar doesnt
     * have to be rebuild, but if the resources references change then it
     * does. At this point the websphere jar gets rebuilt if the xml files
     * change at all.
     *
     * @param genericJarFile java.io.File The generic jar file.
     * @param websphereJarFile java.io.File The websphere jar file to check to
     *      see if it needs to be rebuilt.
     */
    protected boolean isRebuildRequired(File genericJarFile, File websphereJarFile) {
        boolean rebuild = false;

        JarFile genericJar = null;
        JarFile wasJar = null;
        File newwasJarFile = null;
        JarOutputStream newJarStream = null;

        try {
            log("Checking if websphere Jar needs to be rebuilt for jar "
                + websphereJarFile.getName(), Project.MSG_VERBOSE);
            // Only go forward if the generic and the websphere file both exist
            if (genericJarFile.exists() && genericJarFile.isFile()
                 && websphereJarFile.exists() && websphereJarFile.isFile()) {
                //open jar files
                genericJar = new JarFile(genericJarFile);
                wasJar = new JarFile(websphereJarFile);

                Hashtable genericEntries = new Hashtable();
                Hashtable wasEntries = new Hashtable();
                Hashtable replaceEntries = new Hashtable();

                //get the list of generic jar entries
                for (Enumeration e = genericJar.entries(); e.hasMoreElements();) {
                    JarEntry je = (JarEntry) e.nextElement();

                    genericEntries.put(je.getName().replace('\\', '/'), je);
                }
                //get the list of websphere jar entries
                for (Enumeration e = wasJar.entries(); e.hasMoreElements();) {
                    JarEntry je = (JarEntry) e.nextElement();

                    wasEntries.put(je.getName(), je);
                }

                //Cycle Through generic and make sure its in websphere
                ClassLoader genericLoader = getClassLoaderFromJar(genericJarFile);

                for (Enumeration e = genericEntries.keys(); e.hasMoreElements();) {
                    String filepath = (String) e.nextElement();

                    if (wasEntries.containsKey(filepath)) {
                        // File name/path match
                        // Check files see if same
                        JarEntry genericEntry = (JarEntry) genericEntries.get(filepath);
                        JarEntry wasEntry = (JarEntry) wasEntries.get(filepath);

                        if ((genericEntry.getCrc() != wasEntry.getCrc())
                            || (genericEntry.getSize() != wasEntry.getSize())) {

                            if (genericEntry.getName().endsWith(".class")) {
                                //File are different see if its an object or an interface
                                String classname
                                    = genericEntry.getName().replace(File.separatorChar, '.');

                                classname = classname.substring(0, classname.lastIndexOf(".class"));

                                Class genclass = genericLoader.loadClass(classname);

                                if (genclass.isInterface()) {
                                    //Interface changed   rebuild jar.
                                    log("Interface " + genclass.getName()
                                        + " has changed", Project.MSG_VERBOSE);
                                    rebuild = true;
                                    break;
                                } else {
                                    //Object class Changed   update it.
                                    replaceEntries.put(filepath, genericEntry);
                                }
                            } else {
                                // is it the manifest. If so ignore it
                                if (!genericEntry.getName().equals("META-INF/MANIFEST.MF")) {
                                    //File other then class changed   rebuild
                                    log("Non class file " + genericEntry.getName()
                                        + " has changed", Project.MSG_VERBOSE);
                                    rebuild = true;
                                }
                                break;
                            }
                        }
                    } else {
                        // a file doesn't exist rebuild

                        log("File " + filepath + " not present in websphere jar",
                            Project.MSG_VERBOSE);
                        rebuild = true;
                        break;
                    }
                }

                if (!rebuild) {
                    log("No rebuild needed - updating jar", Project.MSG_VERBOSE);
                    newwasJarFile = new File(websphereJarFile.getAbsolutePath() + ".temp");
                    if (newwasJarFile.exists()) {
                        newwasJarFile.delete();
                    }

                    newJarStream = new JarOutputStream(new FileOutputStream(newwasJarFile));
                    newJarStream.setLevel(0);

                    //Copy files from old websphere jar
                    for (Enumeration e = wasEntries.elements(); e.hasMoreElements();) {
                        byte[] buffer = new byte[1024];
                        int bytesRead;
                        InputStream is;
                        JarEntry je = (JarEntry) e.nextElement();

                        if (je.getCompressedSize() == -1
                            || je.getCompressedSize() == je.getSize()) {
                            newJarStream.setLevel(0);
                        } else {
                            newJarStream.setLevel(9);
                        }

                        // Update with changed Bean class
                        if (replaceEntries.containsKey(je.getName())) {
                            log("Updating Bean class from generic Jar " + je.getName(),
                                Project.MSG_VERBOSE);
                            // Use the entry from the generic jar
                            je = (JarEntry) replaceEntries.get(je.getName());
                            is = genericJar.getInputStream(je);
                        } else {
                            //use fle from original websphere jar

                            is = wasJar.getInputStream(je);
                        }
                        newJarStream.putNextEntry(new JarEntry(je.getName()));

                        while ((bytesRead = is.read(buffer)) != -1) {
                            newJarStream.write(buffer, 0, bytesRead);
                        }
                        is.close();
                    }
                } else {
                    log("websphere Jar rebuild needed due to changed "
                        + "interface or XML", Project.MSG_VERBOSE);
                }
            } else {
                rebuild = true;
            }
        } catch (ClassNotFoundException cnfe) {
            String cnfmsg = "ClassNotFoundException while processing ejb-jar file"
                 + ". Details: "
                 + cnfe.getMessage();

            throw new BuildException(cnfmsg, cnfe);
        } catch (IOException ioe) {
            String msg = "IOException while processing ejb-jar file "
                 + ". Details: "
                 + ioe.getMessage();

            throw new BuildException(msg, ioe);
        } finally {
            // need to close files and perhaps rename output
            if (genericJar != null) {
                try {
                    genericJar.close();
                } catch (IOException closeException) {
                }
            }

            if (wasJar != null) {
                try {
                    wasJar.close();
                } catch (IOException closeException) {
                }
            }

            if (newJarStream != null) {
                try {
                    newJarStream.close();
                } catch (IOException closeException) {
                }

                try {
                    FileUtils.newFileUtils().rename(newwasJarFile,
                                                    websphereJarFile);
                } catch (IOException renameException) {
                    log(renameException.getMessage(), Project.MSG_WARN);
                    rebuild = true;
                }
            }
        }

        return rebuild;
    }


    /**
     * Helper method invoked by isRebuildRequired to get a ClassLoader for a
     * Jar File passed to it.
     *
     * @param classjar java.io.File representing jar file to get classes from.
     */
    protected ClassLoader getClassLoaderFromJar(File classjar) throws IOException {
        Path lookupPath = new Path(getTask().getProject());

        lookupPath.setLocation(classjar);

        Path classpath = getCombinedClasspath();

        if (classpath != null) {
            lookupPath.append(classpath);
        }

        return getTask().getProject().createClassLoader(lookupPath);
    }
}

