/*
 * The Apache Software License, Version 1.1
 *
 * Copyright (c) 2002 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", "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 org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.taskdefs.Java;
import org.apache.tools.ant.util.FileUtils;

import java.io.File;
import java.io.IOException;
import java.util.Hashtable;

/**
 * The deployment tool to add the jonas specific deployment descriptors to the
 * ejb jar file. JONAS only requires one additional file jonas-ejb-jar.xml.
 *
 * @author <a href="cmorvan@ingenosya.com">Cyrille Morvan</a> , <a
 *      href="http://www.ingenosya.com">Ingenosya France</a>
 * @version 1.0
 * @see EjbJar#createJonas
 */
public class JonasDeploymentTool extends GenericDeploymentTool {

    protected static final String JONAS_DD = "jonas-ejb-jar.xml";

    protected static final String GENIC_CLASS =
        "org.objectweb.jonas_ejb.tools.GenWholeIC";

    protected static final String OLD_GENIC_CLASS =
        "org.objectweb.jonas_ejb.tools.GenIC";

    protected static final String DEFAULT_ORB = "RMI";

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

    /**
     * Instance variable that stores the fully qualified classname of the
     * JOnAS GenIC compiler.
     */
    private String genicClass;

    private String additionalArgs = "";

    /**
     * Instance variable that determines do not delete intermediate generated
     * source files
     */
    private boolean keepgenerated = false;

    /** as websphere and WebLogic taskes */
    private boolean keepGeneric = false;

    /** Instance variable that determines the JOnAS Root directory */
    private File jonasroot;

    /** Instance variable that determines if we could -secpropag */
    private boolean secpropag = false;

    /** Instance variable that determines the ouput directory */
    private File ouputdirectory;

    /** Instance variable that determines the path to the compiler to use */
    private String compiler;

    /** Instance variable that determines if GenIC is verbose */
    private boolean verbose;

    /** Instance variable that determines the ORB to use (RMI, JEREMIE, DAVID) */
    private String orb;

    /** clean the working directory after work * */
    private boolean cleanWorkDir = false;

    private boolean noGENIC = false;


    /** set the name of the GenIC compiler class.  */
    public void setGenicClass(final String inGenicClass) {
        genicClass = inGenicClass;
    }


    /**
     * Set the ORB to construct classpath.
     *
     * @param inValue RMI, JEREMIE, DAVID,...
     */
    public void setOrb(final String inValue) {
        orb = inValue;
    }


    /** The compiler (switch <code>-javac</code>) to use.  */
    public void setCompiler(final String inCompiler) {
        compiler = inCompiler;
    }


    /**
     * Setter used to store the value of keepGeneric
     *
     * @param inValue a string, either 'true' or 'false'.
     */
    public void setKeepgeneric(boolean inValue) {
        this.keepGeneric = inValue;
    }


    /**
     * GenIC verbose or not
     *
     * @param inValue either 'true' or 'false'
     */
    public void setVerbose(final boolean inValue) {
        verbose = inValue;
    }


    /**
     * GenIC run or not.
     *
     * @param inValue run or not
     */
    public void setNoGENIC(final boolean inValue) {
        noGENIC = inValue;
    }


    /**
     * Sets whether -keepgenerated is passed to GenIC (that is, the .java
     * source files are kept).
     *
     * @param inValue either 'true' or 'false'
     */
    public void setKeepgenerated(final boolean inValue) {
        keepgenerated = inValue;
    }


    /**
     * set the jonas root directory (-Dinstall.root=).
     *
     * @throws BuildException if the file doesn't exist.
     */
    public void setJonasroot(final File inValue) {
        jonasroot = inValue;
    }


    /**
     * Modify the RMI Skeleton and Stub to implement the implicit propagation
     * of the transactionnal context and security context. For JOnAS 2.4 and
     * next.
     */
    public void setSecpropag(final boolean inValue) {
        secpropag = inValue;
    }


    /**
     * set the output directory (-d ...). <br>
     * It's the GenIC working directory. It's not the DestDir, which is the
     * 'jar' destination directory.
     *
     * @param inValue a file
     */
    public void setOuputdir(final File inValue) {
        ouputdirectory = inValue;
    }


    /**
     * set the output directory (-d ...). Same as setOuputdir(). <br>
     * But do not override setDestDir()
     */
    public void setWorkdir(final File inValue) {
        setOuputdir(inValue);
    }


    /**
     * Clean the specified Work dir after work.
     *
     * @param inValue true : clean ; false : not clean
     */
    public void setCleanworkdir(final boolean inValue) {
        cleanWorkDir = inValue;
    }


    /**
     * Setter used to store the suffix for the generated JOnAS jar file.
     *
     * @param inString the string to use as the suffix.
     */
    public void setSuffix(String inString) {
        this.jarSuffix = inString;
    }


    /** sets some additional args to send to GenIC.  */
    public void setArgs(final String inArgs) {
        additionalArgs = inArgs;
    }


    /**
     * Add any vendor specific files which should be included in the EJB Jar.
     *
     * @param aDdPrefix MyDirectories/MyEjb- or MyDirectories/
     */
    protected void addVendorFiles(final Hashtable someEjbFiles,
                                        final String aDdPrefix) {
        // Use Ant Naming convention
        File aJonasDD
             = new File(getConfig().descriptorDir, aDdPrefix + JONAS_DD);

        if (aJonasDD.exists()) {
            someEjbFiles.put(META_DIR + JONAS_DD, aJonasDD);
        } else {
            // try with JOnAS Naming convention
            if (!addJonasVendorFiles(someEjbFiles, aDdPrefix)) {
                log("Unable to locate JOnAS deployment descriptor. It was "
                     + "expected to be in " + aJonasDD.getPath()
                     + ". Alternatively, please use JOnAS naming convention.",
                    Project.MSG_WARN);
            }
        }
    }


    /**
     * try to add JOnAS specific file, using JOnAS naming convention. For
     * example : jonas-Account.xml or jonas-ejb-jar.xml
     *
     * @param aDdPrefix MyDirectories/MyEjb- or MyDirectories/
     * @return true if Ok
     */
    private boolean addJonasVendorFiles(final Hashtable someEjbFiles,
                                              final String aDdPrefix) {
        // replace \ by /, remove the last letter ( a dash - )
        final String aCanonicalDD
             = aDdPrefix.replace('\\', '/').substring(0, aDdPrefix.length() - 1);
        final int index = aCanonicalDD.lastIndexOf('/') + 1;
        String anEjbJarName = aCanonicalDD.substring(index);

        if ("ejb".equals(anEjbJarName)) {
            anEjbJarName = "ejb-jar";
        }
        final String aNewDdPrefix =
            aDdPrefix.substring(0, index) + "jonas-" + anEjbJarName + ".xml";
        File aConventionNamingJonasDD
             = new File(getConfig().descriptorDir, aNewDdPrefix);

        log("look for jonas specific file using jonas naming convention "
             + aConventionNamingJonasDD,
            Project.MSG_VERBOSE);

        if (aConventionNamingJonasDD.exists()) {
            someEjbFiles.put(META_DIR + JONAS_DD, aConventionNamingJonasDD);
            return true;
        } else {
            return false;
        }
    }

    // include javadoc
    // Determine the JAR filename (without filename extension)
    protected String getJarBaseName(String aDescriptorFileName) {
        String aBaseName = null;
        EjbJar.Config aConfig = super.getConfig();

        if (aConfig.namingScheme.getValue().equals(EjbJar.NamingScheme.DESCRIPTOR)) {
            // try to find JOnAS specific convention name
            // ??/MyEJB.xml ( I will find later the ??/jonas-MyEJB.xml file )
            if (aDescriptorFileName.indexOf(aConfig.baseNameTerminator) == -1) {
                String aCanonicalDescriptor = aDescriptorFileName.replace('\\', '/');
                int lastSeparatorIndex = aCanonicalDescriptor.lastIndexOf('/');
                int endBaseName;

                if (lastSeparatorIndex != -1) {
                    endBaseName = aDescriptorFileName.indexOf(".xml", lastSeparatorIndex);
                } else {
                    endBaseName = aDescriptorFileName.indexOf(".xml");
                }

                if (endBaseName != -1) {
                    aBaseName = aDescriptorFileName.substring(0, endBaseName);
                }
            }
        }

        if (aBaseName == null) {
            // else get standard BaseName
            aBaseName = super.getJarBaseName(aDescriptorFileName);
        }
        return aBaseName;
    }


    /**
     * 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 {
        // need to create a generic jar first.
        File genericJarFile = super.getVendorOutputJarFile(baseName);

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

        // todo ? if (alwaysRebuild || isRebuildRequired(genericJarFile, jarFile))
        buildJOnASJar(baseName, genericJarFile, jarFile, files, publicId);

        if (!keepGeneric) {
            log("deleting generic jar " + genericJarFile.toString(),
                Project.MSG_VERBOSE);
            genericJarFile.delete();
        }
    }


    /**
     * Helper method invoked by execute() for each JOnAS jar to be built.
     * Encapsulates the logic of constructing a java task for calling GenIC
     * and executing it.
     *
     * @param inBaseName the base name of the jar
     * @param inSourceJar java.io.File representing the source (EJB1.1)
     *      jarfile.
     * @param someFiles list of files in the jar. Add all the new genererated
     *      files.
     * @param inPublicId the link to DTD (to rewrite JAR).
     */
    private void buildJOnASJar(final String inBaseName,
                                     final File inSourceJar, final File inDestJar,
                                     final Hashtable someFiles, String inPublicId) {
        org.apache.tools.ant.taskdefs.Java aJavaTask = null;
        String aGenIcClassName = genicClass;
        boolean isOldGenIC = false;
        boolean isTempDirectory = false;
        File anOutputDirectoryFile = null;

        // do not call GenIC
        // only copy file
        if (noGENIC) {
            try {
                FileUtils.newFileUtils().copyFile(inSourceJar, inDestJar);
                return;
            } catch (IOException anIOException) {
                throw new BuildException("Unable to write EJB jar", anIOException);
            }
        }

        // call GenIC
        try {
            aJavaTask = (Java) getTask().getProject().createTask("java");
            aJavaTask.setTaskName("genic");
            if (aGenIcClassName == null) {
                aGenIcClassName = GENIC_CLASS;
            } else if (OLD_GENIC_CLASS.equals(aGenIcClassName)) {
                isOldGenIC = true;
            }
            // ClassName
            aJavaTask.setClassname(aGenIcClassName);

            // JVM Args
            if (jonasroot == null) {
                throw new BuildException("Error : set the jonasroot parameter");
            } else if (!jonasroot.isDirectory()) {
                log("jonasroot attribut '" + jonasroot + "' is not a valid directory",
                    Project.MSG_ERR);
            }
            aJavaTask.createJvmarg().setValue("-Dinstall.root=" + jonasroot);

            File aJavaPolicyFile = new File(jonasroot, "config/java.policy");

            if (aJavaPolicyFile.exists()) {
                aJavaTask.createJvmarg().setValue("-Djava.security.policy="
                     + aJavaPolicyFile.toString());
            }

            // Find output directory
            if (ouputdirectory == null) {
                anOutputDirectoryFile = createTempDir();
                isTempDirectory = true;
                log("Use temporary output directory : " +
                    anOutputDirectoryFile, Project.MSG_VERBOSE);
            } else {
                anOutputDirectoryFile = ouputdirectory;
                log("Use temporary specific output directory : " +
                    anOutputDirectoryFile, Project.MSG_VERBOSE);
            }
            aJavaTask.createArg().setValue("-d");
            aJavaTask.createArg().setFile(anOutputDirectoryFile);

            // Additionnal args
            aJavaTask.createArg().setLine(additionalArgs);
            // KeepGenerated
            if (keepgenerated) {
                aJavaTask.createArg().setValue("-keepgenerated");
            }

            // Verbose
            if (verbose) {
                aJavaTask.createArg().setValue("-verbose");
            }

            // -secpropag
            if (secpropag) {
                aJavaTask.createArg().setValue("-secpropag");
            }

            // The compiler
            if (compiler == null) {
                // try to use the compiler specified by build.compiler. Right now we are just going
                // to allow Jikes
                String aBuildCompiler = getTask().getProject().getProperty("build.compiler");

                if ("jikes".equals(aBuildCompiler)) {
                    aJavaTask.createArg().setValue("-javac");
                    aJavaTask.createArg().setValue("jikes");
                }
            } else {
                if (!"default".equals(compiler)) {
                    aJavaTask.createArg().setValue("-javac");
                    aJavaTask.createArg().setLine(compiler);
                }
            }

            if (!isOldGenIC) {
                // the add in jar features is buggy...
                aJavaTask.createArg().setValue("-noaddinjar");
            }

            aJavaTask.createArg().setValue(inSourceJar.getPath());

            // try to create the classpath for the correct ORB
            Path aClasspath = getCombinedClasspath();

            if (aClasspath == null) {
                aClasspath = new Path(getTask().getProject());
            }
            if (orb != null) {
                String aOrbJar = new File(jonasroot, "lib/" + orb + "_jonas.jar").toString();
                String aConfigDir = new File(jonasroot, "config/").toString();
                Path aJOnASOrbPath = new Path(aClasspath.getProject(),
                    aOrbJar + File.pathSeparator + aConfigDir);

                aClasspath.append(aJOnASOrbPath);
            } else {
                log("No ORB propertie setup (RMI, JEREMIE, DAVID).", Project.MSG_WARN);
            }

            // append the output directory
            aClasspath.append(new Path(aClasspath.getProject(), anOutputDirectoryFile.getPath()));
            aJavaTask.setClasspath(aClasspath);

            aJavaTask.setFork(true);

            log("Calling " + aGenIcClassName + " for " + inSourceJar.toString(),
                Project.MSG_VERBOSE);

            if (aJavaTask.executeJava() != 0) {
                throw new BuildException("GenIC reported an error");
            }
            // Update the list of files.
            addAllFiles(anOutputDirectoryFile, "", someFiles);

            // rewrite the jar with the new files
            super.writeJar(inBaseName, inDestJar, someFiles, inPublicId);
        } catch (BuildException aBuildException) {
            throw aBuildException;
        } catch (Exception e) {
            // Have to catch this because of the semantics of calling main()
            String msg = "Exception while calling " + aGenIcClassName + ". Details: " + e.toString();

            throw new BuildException(msg, e);
        } finally {
            if (isTempDirectory && anOutputDirectoryFile != null) {
                dellAllFiles(anOutputDirectoryFile);
            } else if (cleanWorkDir && anOutputDirectoryFile != null) {
                dellAllFilesInside(anOutputDirectoryFile);
            }
        }
    }


    /**
     * 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(final String aBaseName) {
        return new File(getDestDir(), aBaseName + jarSuffix);
    }


    /**
     * Create a free tempory directory for GenIC output.
     *
     * @return directory file
     * @throws BuildException if impossible to find a tempory directory
     */
    private File createTempDir() {
        String theTempDir = System.getProperty("java.io.tmpdir");
        int anIndice = 0;
        File aFile = null;
        // try 50 times to find a free tempory directory
        while (anIndice < 50 && aFile == null) {
            aFile = new File(theTempDir, "GenicTemp" + anIndice);
            if (aFile.exists()) {
                anIndice++;
                aFile = null;
            }
        }

        if (aFile == null) {
            // problem in temp directory
            throw new BuildException("Impossible to find a free temp directory for output.");
        } else {
            aFile.mkdirs();
            return (aFile);
        }
    }


    /**
     * add all files in anOutputDir + ' / ' + aRootDir to the HashTable
     * someFiles.
     *
     * @param anOutputDir - start directory
     * @param aCurrentDirOrFile - a sub-directory to scan or a file to add.
     * @param someFiles - where to add the files
     */
    private void addAllFiles(final File anOutputDir, String aCurrentDirOrFile, Hashtable someFiles) {
        File aFile = new File(anOutputDir, aCurrentDirOrFile);

        if (aFile.isDirectory()) {
            String aCurrentDir = "";

            if (aCurrentDirOrFile.length() > 0) {
                aCurrentDir = aCurrentDirOrFile + '/';
            }
            File theFiles[] = aFile.listFiles();

            for (int i = 0; i < theFiles.length; i++) {
                addAllFiles(anOutputDir, aCurrentDir + theFiles[i].getName(), someFiles);
            }
        } else {
            // is a file
            someFiles.put(aCurrentDirOrFile, aFile);
        }
    }


    /**
     * Delete all the files in a directory
     *
     * @param aFile file to delete recursivly
     */
    private void dellAllFiles(File aFile) {
        if (aFile.isDirectory()) {
            File someFiles[] = aFile.listFiles();

            for (int i = 0; i < someFiles.length; i++) {
                dellAllFiles(someFiles[i]);
            }
        }
        aFile.delete();
    }


    /**
     * Delete all the files in a directory, but don't delete the directory
     *
     * @param aFile file to delete recursivly
     */
    private void dellAllFilesInside(File aFile) {
        if (aFile.isDirectory()) {
            File someFiles[] = aFile.listFiles();

            for (int i = 0; i < someFiles.length; i++) {
                dellAllFiles(someFiles[i]);
            }
        }
    }

}

