/*
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You under the Apache License, Version 2.0
 *  (the "License"); you may not use this file except in compliance with
 *  the License.  You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 */
package org.apache.tools.ant.taskdefs.optional.ejb;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.Collections;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Map;
import java.util.Set;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;

import javax.xml.parsers.SAXParser;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Location;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.optional.ejb.EjbJar.DTDLocation;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.util.depend.DependencyAnalyzer;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;


/**
 * A deployment tool which creates generic EJB jars. Generic jars contains
 * only those classes and META-INF entries specified in the EJB 1.1 standard
 *
 * This class is also used as a framework for the creation of vendor specific
 * deployment tools. A number of template methods are provided through which the
 * vendor specific tool can hook into the EJB creation process.
 *
 */
public class GenericDeploymentTool implements EJBDeploymentTool {
    /** The default buffer byte size to use for IO */
    public static final int DEFAULT_BUFFER_SIZE = 1024;
    /** The level to use for compression */
    public static final int JAR_COMPRESS_LEVEL  = 9;

    /** The standard META-INF directory in jar files */
    protected static final String META_DIR  = "META-INF/";

    /** The standard MANIFEST file */
    protected static final String MANIFEST  = META_DIR + "MANIFEST.MF";

    /** Name for EJB Deployment descriptor within EJB jars */
    protected static final String EJB_DD    = "ejb-jar.xml";

    /** A dependency analyzer name to find ancestor classes */
    public static final String ANALYZER_SUPER = "super";
    /** A dependency analyzer name to find all related classes */
    public static final String ANALYZER_FULL = "full";
    /** A dependency analyzer name for no analyzer */
    public static final String ANALYZER_NONE = "none";

    /** The default analyzer */
    public static final String DEFAULT_ANALYZER = ANALYZER_SUPER;

    /** The analyzer class for the super analyzer */
    public static final String ANALYZER_CLASS_SUPER
        = "org.apache.tools.ant.util.depend.bcel.AncestorAnalyzer";
    /** The analyzer class for the super analyzer */
    public static final String ANALYZER_CLASS_FULL
        = "org.apache.tools.ant.util.depend.bcel.FullAnalyzer";

    /**
     * The configuration from the containing task. This config combined
     * with the settings of the individual attributes here constitues the
     * complete config for this deployment tool.
     */
    private EjbJar.Config config;

    /** Stores a handle to the directory to put the Jar files in */
    private File destDir;

    /** The classpath to use with this deployment tool. This is appended to
        any paths from the ejbjar task itself.*/
    private Path classpath;

    /** Instance variable that stores the suffix for the generated jarfile. */
    private String genericJarSuffix = "-generic.jar";

    /**
     * The task to which this tool belongs. This is used to access services
     * provided by the ant core, such as logging.
     */
    private Task task;

    /**
     * The classloader generated from the given classpath to load
     * the super classes and super interfaces.
     */
    private ClassLoader classpathLoader = null;

     /**
     * Set of files have been loaded into the EJB jar
     */
    private Set<String> addedfiles;

    /**
     * Handler used to parse the EJB XML descriptor
     */
    private DescriptorHandler handler;

    /**
     * Dependency analyzer used to collect class dependencies
     */
    private DependencyAnalyzer dependencyAnalyzer;

    /**
     * Set the destination directory; required.
     * @param inDir the destination directory.
     */
    public void setDestdir(File inDir) {
        this.destDir = inDir;
    }

    /**
     * Get the destination directory.
     *
     * @return the destination directory into which EJB jars are to be written
     */
    protected File getDestDir() {
        return destDir;
    }

    /**
     * Set the task which owns this tool
     *
     * @param task the Task to which this deployment tool is associated.
     */
    @Override
    public void setTask(Task task) {
        this.task = task;
    }

    /**
     * Get the task for this tool.
     *
     * @return the Task instance this tool is associated with.
     */
    protected Task getTask() {
        return task;
    }

    /**
     * Get the basename terminator.
     *
     * @return an ejbjar task configuration
     */
    protected EjbJar.Config getConfig() {
        return config;
    }

    /**
     * Indicate if this build is using the base jar name.
     *
     * @return true if the name of the generated jar is coming from the
     *              basejarname attribute
     */
    protected boolean usingBaseJarName() {
        return config.baseJarName != null;
    }

    /**
     * Set the suffix for the generated jar file.
     * @param inString the string to use as the suffix.
     */
    public void setGenericJarSuffix(String inString) {
        this.genericJarSuffix = inString;
    }

    /**
     * Add the classpath for the user classes
     *
     * @return a Path instance to be configured by Ant.
     */
    public Path createClasspath() {
        if (classpath == null) {
            classpath = new Path(task.getProject());
        }
        return classpath.createPath();
    }

    /**
     * Set the classpath to be used for this compilation.
     *
     * @param classpath the classpath to be used for this build.
     */
    public void setClasspath(Path classpath) {
        this.classpath = classpath;
    }

    /**
     * Get the classpath by combining the one from the surrounding task, if any
     * and the one from this tool.
     *
     * @return the combined classpath
     */
    protected Path getCombinedClasspath() {
        Path combinedPath = classpath;
        if (config.classpath != null) {
            if (combinedPath == null) {
                combinedPath = config.classpath;
            } else {
                combinedPath.append(config.classpath);
            }
        }
        return combinedPath;
    }

    /**
     * Log a message to the Ant output.
     *
     * @param message the message to be logged.
     * @param level the severity of this message.
     */
    protected void log(String message, int level) {
        getTask().log(message, level);
    }

    /**
     * Get the build file location associated with this element's task.
     *
     * @return the task's location instance.
     */
    protected Location getLocation() {
        return getTask().getLocation();
    }

    private void createAnalyzer() {
        String analyzer = config.analyzer;
        if (analyzer == null) {
            analyzer = DEFAULT_ANALYZER;
        }

        if (analyzer.equals(ANALYZER_NONE)) {
            return;
        }

        String analyzerClassName = null;
        switch (analyzer) {
            case ANALYZER_SUPER:
                analyzerClassName = ANALYZER_CLASS_SUPER;
                break;
            case ANALYZER_FULL:
                analyzerClassName = ANALYZER_CLASS_FULL;
                break;
            default:
                analyzerClassName = analyzer;
                break;
        }

        try {
            Class<? extends DependencyAnalyzer> analyzerClass =
                Class.forName(analyzerClassName).asSubclass(DependencyAnalyzer.class);
            dependencyAnalyzer = analyzerClass.getDeclaredConstructor().newInstance();
            dependencyAnalyzer.addClassPath(new Path(task.getProject(),
                config.srcDir.getPath()));
            dependencyAnalyzer.addClassPath(config.classpath);
        } catch (NoClassDefFoundError e) {
            dependencyAnalyzer = null;
            task.log("Unable to load dependency analyzer: " + analyzerClassName
                + " - dependent class not found: " + e.getMessage(),
                Project.MSG_WARN);
        } catch (Exception e) {
            dependencyAnalyzer = null;
            task.log("Unable to load dependency analyzer: " + analyzerClassName
                     + " - exception: " + e.getMessage(),
                Project.MSG_WARN);
        }
    }

    /**
     * Configure this tool for use in the ejbjar task.
     *
     * @param config the configuration from the surrounding ejbjar task.
     */
    @Override
    public void configure(EjbJar.Config config) {
        this.config = config;

        createAnalyzer();
        classpathLoader = null;
    }

    /**
     * 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 inputFile A File from which to read the
     *        contents the file being added.
     * @param logicalFilename A String representing the name, including
     *        all relevant path information, that should be stored for the entry
     *        being added.
     * @throws BuildException if there is a problem.
     */
    protected void addFileToJar(JarOutputStream jStream,
                                File inputFile,
                                String logicalFilename)
        throws BuildException {
        if (!addedfiles.contains(logicalFilename)) {
            try (InputStream iStream = Files.newInputStream(inputFile.toPath())) {
                // Create the zip entry and add it to the jar file
                ZipEntry zipEntry =
                    new ZipEntry(logicalFilename.replace('\\', '/'));
                jStream.putNextEntry(zipEntry);

                // Create the file input stream, and buffer everything over
                // to the jar output stream
                byte[] byteBuffer = new byte[2 * DEFAULT_BUFFER_SIZE];
                int count = 0;
                do {
                    jStream.write(byteBuffer, 0, count);
                    count = iStream.read(byteBuffer, 0, byteBuffer.length);
                } while (count != -1);

                //add it to list of files in jar
                addedfiles.add(logicalFilename);
            } catch (IOException ioe) {
                log("WARNING: IOException while adding entry " + logicalFilename
                    + " to jarfile from " + inputFile.getPath() + " "
                    + ioe.getClass().getName() + "-" + ioe.getMessage(),
                    Project.MSG_WARN);
            }
        }
    }

    /**
     * Get a descriptionHandler.
     * @param srcDir the source directory.
     * @return a handler.
     */
    protected DescriptorHandler getDescriptorHandler(File srcDir) {
        DescriptorHandler h = new DescriptorHandler(getTask(), srcDir);

        registerKnownDTDs(h);

        // register any DTDs supplied by the user
        for (DTDLocation dtdLocation : getConfig().dtdLocations) {
            h.registerDTD(dtdLocation.getPublicId(), dtdLocation.getLocation());
        }
        return h;
    }

    /**
     * Register the locations of all known DTDs.
     *
     * vendor-specific subclasses should override this method to define
     * the vendor-specific locations of the EJB DTDs
     * @param handler no used in this class.
     */
    protected void registerKnownDTDs(DescriptorHandler handler) {
        // none to register for generic
    }

    /** {@inheritDoc}. */
    @Override
    public void processDescriptor(String descriptorFileName, SAXParser saxParser) {

        checkConfiguration(descriptorFileName, saxParser);

        try {
            handler = getDescriptorHandler(config.srcDir);

            // Retreive the files to be added to JAR from EJB descriptor
            Hashtable<String, File> ejbFiles = parseEjbFiles(descriptorFileName, saxParser);

            // Add any support classes specified in the build file
            addSupportClasses(ejbFiles);

            // Determine the JAR filename (without filename extension)
            String baseName = getJarBaseName(descriptorFileName);

            String ddPrefix = getVendorDDPrefix(baseName, descriptorFileName);

            File manifestFile = getManifestFile(ddPrefix);
            if (manifestFile != null) {
                ejbFiles.put(MANIFEST, manifestFile);
            }

            // First the regular deployment descriptor
            ejbFiles.put(META_DIR + EJB_DD,
                         new File(config.descriptorDir, descriptorFileName));

            // now the vendor specific files, if any
            addVendorFiles(ejbFiles, ddPrefix);

            // add any dependent files
            checkAndAddDependants(ejbFiles);

            // Lastly create File object for the Jar files. If we are using
            // a flat destination dir, then we need to redefine baseName!
            if (config.flatDestDir && !baseName.isEmpty()) {
                int startName = baseName.lastIndexOf(File.separator);
                if (startName == -1) {
                    startName = 0;
                }

                int endName   = baseName.length();
                baseName = baseName.substring(startName, endName);
            }

            File jarFile = getVendorOutputJarFile(baseName);

            // Check to see if we need a build and start doing the work!
            if (needToRebuild(ejbFiles, jarFile)) {
                // Log that we are going to build...
                log("building "
                              + jarFile.getName()
                              + " with "
                              + String.valueOf(ejbFiles.size())
                              + " files",
                              Project.MSG_INFO);

                // Use helper method to write the jarfile
                String publicId = getPublicId();
                writeJar(baseName, jarFile, ejbFiles, publicId);
            } else {
                // Log that the file is up to date...
                log(jarFile.toString() + " is up to date.",
                              Project.MSG_VERBOSE);
            }
        } catch (SAXException se) {
            throw new BuildException(
                "SAXException while parsing '" + descriptorFileName
                    + "'. This probably indicates badly-formed XML."
                    + "  Details: " + se.getMessage(),
                se);
        } catch (IOException ioe) {
            throw new BuildException(
                "IOException while parsing'" + descriptorFileName
                    + "'.  This probably indicates that the descriptor"
                    + " doesn't exist. Details: " + ioe.getMessage(),
                ioe);
        }
    }

    /**
     * This method is called as the first step in the processDescriptor method
     * to allow vendor-specific subclasses to validate the task configuration
     * prior to processing the descriptor.  If the configuration is invalid,
     * a BuildException should be thrown.
     *
     * @param descriptorFileName String representing the file name of an EJB
     *                           descriptor to be processed
     * @param saxParser          SAXParser which may be used to parse the XML
     *                           descriptor
     * @throws BuildException if there is a problem.
     */
    protected void checkConfiguration(String descriptorFileName,
                                    SAXParser saxParser) throws BuildException {
        /*
         * For the GenericDeploymentTool, do nothing.  Vendor specific
         * subclasses should throw a BuildException if the configuration is
         * invalid for their server.
         */
    }

    /**
     * This method returns a list of EJB files found when the specified EJB
     * descriptor is parsed and processed.
     *
     * @param descriptorFileName String representing the file name of an EJB
     *                           descriptor to be processed
     * @param saxParser          SAXParser which may be used to parse the XML
     *                           descriptor
     * @return                   Hashtable of EJB class (and other) files to be
     *                           added to the completed JAR file
     * @throws SAXException      Any SAX exception, possibly wrapping another
     *                           exception
     * @throws IOException       An IOException from the parser, possibly from a
     *                           the byte stream or character stream
     */
    protected Hashtable<String, File> parseEjbFiles(String descriptorFileName, SAXParser saxParser)
                            throws IOException, SAXException {
        /* 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.
         */
        try (InputStream descriptorStream = Files.newInputStream(
            new File(config.descriptorDir, descriptorFileName).toPath())) {
            saxParser.parse(new InputSource(descriptorStream), handler);
            return handler.getFiles();
        }
    }

    /**
     * Adds any classes the user specifies using <i>support</i> nested elements
     * to the <code>ejbFiles</code> Hashtable.
     *
     * @param ejbFiles Hashtable of EJB classes (and other) files that will be
     *                 added to the completed JAR file
     */
    protected void addSupportClasses(Hashtable<String, File> ejbFiles) {
        // add in support classes if any
        Project project = task.getProject();
        for (FileSet supportFileSet : config.supportFileSets) {
            File supportBaseDir = supportFileSet.getDir(project);
            DirectoryScanner supportScanner = supportFileSet.getDirectoryScanner(project);
            for (String supportFile : supportScanner.getIncludedFiles()) {
                ejbFiles.put(supportFile, new File(supportBaseDir, supportFile));
            }
        }
    }

    /**
     * Using the EJB descriptor file name passed from the <code>ejbjar</code>
     * task, this method returns the "basename" which will be used to name the
     * completed JAR file.
     *
     * @param descriptorFileName String representing the file name of an EJB
     *                           descriptor to be processed
     * @return                   The "basename" which will be used to name the
     *                           completed JAR file
     */
    protected String getJarBaseName(String descriptorFileName) {

        String baseName = "";

        // Work out what the base name is
        if (EjbJar.NamingScheme.BASEJARNAME.equals(config.namingScheme.getValue())) {
            String canonicalDescriptor = descriptorFileName.replace('\\', '/');
            int index = canonicalDescriptor.lastIndexOf('/');
            if (index != -1) {
                baseName = descriptorFileName.substring(0, index + 1);
            }
            baseName += config.baseJarName;
        } else if (EjbJar.NamingScheme.DESCRIPTOR.equals(config.namingScheme.getValue())) {
            int lastSeparatorIndex = descriptorFileName.lastIndexOf(File.separator);
            int endBaseName = -1;
            if (lastSeparatorIndex != -1) {
                endBaseName = descriptorFileName.indexOf(config.baseNameTerminator,
                                                            lastSeparatorIndex);
            } else {
                endBaseName = descriptorFileName.indexOf(config.baseNameTerminator);
            }

            if (endBaseName != -1) {
                baseName = descriptorFileName.substring(0, endBaseName);
            } else {
                throw new BuildException(
                    "Unable to determine jar name from descriptor \"%s\"",
                    descriptorFileName);
            }
        } else if (EjbJar.NamingScheme.DIRECTORY.equals(config.namingScheme.getValue())) {
            File descriptorFile = new File(config.descriptorDir, descriptorFileName);
            String path = descriptorFile.getAbsolutePath();
            int lastSeparatorIndex
                = path.lastIndexOf(File.separator);
            if (lastSeparatorIndex == -1) {
                throw new BuildException("Unable to determine directory name holding descriptor");
            }
            String dirName = path.substring(0, lastSeparatorIndex);
            int dirSeparatorIndex = dirName.lastIndexOf(File.separator);
            if (dirSeparatorIndex != -1) {
                dirName = dirName.substring(dirSeparatorIndex + 1);
            }
            baseName = dirName;
        } else if (EjbJar.NamingScheme.EJB_NAME.equals(config.namingScheme.getValue())) {
            baseName = handler.getEjbName();
        }
        return baseName;
    }

    /**
     * Get the prefix for vendor deployment descriptors.
     *
     * This will contain the path and the start of the descriptor name,
     * depending on the naming scheme
     * @param baseName the base name to use.
     * @param descriptorFileName the file name to use.
     * @return the prefix.
     */
    public String getVendorDDPrefix(String baseName, String descriptorFileName) {
        String ddPrefix = null;

        if (config.namingScheme.getValue().equals(EjbJar.NamingScheme.DESCRIPTOR)) {
            ddPrefix = baseName + config.baseNameTerminator;
        } else if (config.namingScheme.getValue().equals(EjbJar.NamingScheme.BASEJARNAME)
            || config.namingScheme.getValue().equals(EjbJar.NamingScheme.EJB_NAME)
            || config.namingScheme.getValue().equals(EjbJar.NamingScheme.DIRECTORY)) {
            String canonicalDescriptor = descriptorFileName.replace('\\', '/');
            int index = canonicalDescriptor.lastIndexOf('/');
            if (index == -1) {
                ddPrefix = "";
            } else {
                ddPrefix = descriptorFileName.substring(0, index + 1);
            }
        }
        return ddPrefix;
    }

    /**
     * Add any vendor specific files which should be included in the
     * EJB Jar.
     * @param ejbFiles a hashtable entryname -&gt; file.
     * @param ddPrefix a prefix to use.
     */
    protected void addVendorFiles(Hashtable<String, File> ejbFiles, String ddPrefix) {
        // nothing to add for generic tool.
    }

    /**
     * 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.
     *
     * @param baseName the basename to use.
     * @return File
     */
    File getVendorOutputJarFile(String baseName) {
        return new File(destDir, baseName + genericJarSuffix);
    }

    /**
     * This method checks the timestamp on each file listed in the <code>
     * ejbFiles</code> and compares them to the timestamp on the <code>jarFile
     * </code>.  If the <code>jarFile</code>'s timestamp is more recent than
     * each EJB file, <code>true</code> is returned.  Otherwise, <code>false
     * </code> is returned.
     * TODO: find a way to check the manifest-file, that is found by naming convention
     *
     * @param ejbFiles Hashtable of EJB classes (and other) files that will be
     *                 added to the completed JAR file
     * @param jarFile  JAR file which will contain all of the EJB classes (and
     *                 other) files
     * @return         boolean indicating whether or not the <code>jarFile</code>
     *                 is up to date
     */
    protected boolean needToRebuild(Hashtable<String, File> ejbFiles, File jarFile) {
        if (jarFile.exists()) {
            long lastBuild = jarFile.lastModified();

            // Loop through the files seeing if any has been touched
            // more recently than the destination jar.
            for (File currentFile : ejbFiles.values()) {
                if (lastBuild < currentFile.lastModified()) {
                    log("Build needed because " + currentFile.getPath() + " is out of date",
                        Project.MSG_VERBOSE);
                    return true;
                }
            }
            return false;
        }
        return true;
    }

    /**
     * Returns the Public ID of the DTD specified in the EJB descriptor.  Not
     * every vendor-specific <code>DeploymentTool</code> will need to reference
     * this value or may want to determine this value in a vendor-specific way.
     *
     * @return Public ID of the DTD specified in the EJB descriptor.
     */
    protected String getPublicId() {
        return handler.getPublicId();
    }

    /**
     * Get the manifest file to use for building the generic jar.
     *
     * If the file does not exist the global manifest from the config is used
     * otherwise the default Ant manifest will be used.
     *
     * @param prefix the prefix where to llook for the manifest file based on
     *        the naming convention.
     *
     * @return the manifest file or null if the manifest file does not exist
     */
    protected File getManifestFile(String prefix) {
        File manifestFile
            = new File(getConfig().descriptorDir, prefix + "manifest.mf");
        if (manifestFile.exists()) {
            return manifestFile;
        }
        if (config.manifest != null) {
            return config.manifest;
        }
        return null;
    }

    /**
     * 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.
     * @param baseName the base name to use.
     * @param jarfile  the jar file to write to.
     * @param files    the files to write to the jar.
     * @param publicId the id to use.
     * @throws BuildException if there is a problem.
     */
    protected void writeJar(String baseName, File jarfile, Hashtable<String, File> files,
                            String publicId) throws BuildException {
        // clean the addedfiles set
        if (addedfiles == null) {
            addedfiles = new HashSet<>();
        } else {
            addedfiles.clear();
        }
        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();

            InputStream in = null;
            Manifest manifest = null;
            try {
                File manifestFile = files.get(MANIFEST);
                if (manifestFile != null && manifestFile.exists()) {
                    in = Files.newInputStream(manifestFile.toPath());
                } else {
                    String defaultManifest = "/org/apache/tools/ant/defaultManifest.mf";
                    in = this.getClass().getResourceAsStream(defaultManifest);
                    if (in == null) {
                        throw new BuildException(
                            "Could not find default manifest: %s",
                            defaultManifest);
                    }
                }
                manifest = new Manifest(in);
            } catch (IOException e) {
                throw new BuildException("Unable to read manifest", e, getLocation());
            } finally {
                if (in != null) {
                    in.close();
                }
            }

            // Create the streams necessary to write the jarfile

            try (JarOutputStream jarStream = new JarOutputStream(
                Files.newOutputStream(jarfile.toPath()), manifest)) {
                jarStream.setMethod(JarOutputStream.DEFLATED);

                // Loop through all the class files found and add them to the jar
                for (Map.Entry<String, File> entryFiles : files.entrySet()) {
                    String entryName = entryFiles.getKey();
                    if (entryName.equals(MANIFEST)) {
                        continue;
                    }
                    File entryFile = entryFiles.getValue();
                    log("adding file '" + entryName + "'", Project.MSG_VERBOSE);
                    addFileToJar(jarStream, entryFile, entryName);

                    // See if there are any inner classes for this class and add them in if there are
                    InnerClassFilenameFilter flt =
                        new InnerClassFilenameFilter(entryFile.getName());
                    File entryDir = entryFile.getParentFile();
                    String[] innerfiles = entryDir.list(flt);
                    if (innerfiles != null) {
                        for (String innerfile : innerfiles) {
                            //get and clean up innerclass name
                            int entryIndex =
                                entryName.lastIndexOf(entryFile.getName()) - 1;
                            if (entryIndex < 0) {
                                entryName = innerfile;
                            } else {
                                entryName = entryName.substring(0, entryIndex)
                                    + File.separatorChar + innerfile;
                            }
                            // link the file
                            entryFile = new File(config.srcDir, entryName);

                            log("adding innerclass file '" + entryName + "'",
                                Project.MSG_VERBOSE);

                            addFileToJar(jarStream, entryFile, entryName);
                        }
                    }
                }
            }
        } catch (IOException ioe) {
            String msg = "IOException while processing ejb-jar file '"
                + jarfile.toString()
                + "'. Details: "
                + ioe.getMessage();
            throw new BuildException(msg, ioe);
        }
    } // end of writeJar


    /**
     * Add all available classes, that depend on Remote, Home, Bean, PK
     * @param checkEntries files, that are extracted from the deployment descriptor
     * @throws BuildException if there is a problem.
     */
    protected void checkAndAddDependants(Hashtable<String, File> checkEntries)
        throws BuildException {

        if (dependencyAnalyzer == null) {
            return;
        }

        dependencyAnalyzer.reset();

        for (String entryName : checkEntries.keySet()) {
            if (entryName.endsWith(".class")) {
                String className = entryName.substring(0,
                    entryName.length() - ".class".length());
                className = className.replace(File.separatorChar, '/');
                className = className.replace('/', '.');

                dependencyAnalyzer.addRootClass(className);
            }
        }

        for (String classname : Collections.list(dependencyAnalyzer.getClassDependencies())) {
            String location = classname.replace('.', File.separatorChar) + ".class";
            File classFile = new File(config.srcDir, location);
            if (classFile.exists()) {
                checkEntries.put(location, classFile);
                log("dependent class: " + classname + " - " + classFile,
                    Project.MSG_VERBOSE);
            }
        }
    }

    /**
     * Returns a Classloader object which parses the passed in generic EjbJar classpath.
     * The loader is used to dynamically load classes from javax.ejb.* and the classes
     * being added to the jar.
     * @return a classloader.
     */
    protected ClassLoader getClassLoaderForBuild() {
        if (classpathLoader != null) {
            return classpathLoader;
        }
        Path combinedClasspath = getCombinedClasspath();

        // only generate a new ClassLoader if we have a classpath
        if (combinedClasspath == null) {
            classpathLoader = getClass().getClassLoader();
        } else {
            // Memory leak in line below
            classpathLoader
                = getTask().getProject().createClassLoader(combinedClasspath);
        }
        return classpathLoader;
    }

    /**
     * Called to validate that the tool parameters have been configured.
     *
     * @throws BuildException If the Deployment Tool's configuration isn't
     *                        valid
     */
    @Override
    public void validateConfigured() throws BuildException {
        if (destDir == null || !destDir.isDirectory()) {
            throw new BuildException(
                "A valid destination directory must be specified using the \"destdir\" attribute.",
                getLocation());
        }
    }
}
