/*
 * 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", "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.metamata;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.*;
import org.apache.tools.ant.types.Commandline;
import org.apache.tools.ant.types.CommandlineJava;
import org.apache.tools.ant.types.Path;

import java.io.*;
import java.util.*;

/**
 * Simple Metamata MParse task based on the original written by
 * <a href="mailto:thomas.haas@softwired-inc.com">Thomas Haas</a>
 * 
 * This version was written for Metamata 2.0 available at
 * <a href="http://www.metamata.com">http://www.metamata.com</a>
 *
 * @author <a href="mailto:sbailliez@imediation.com">Stephane Bailliez</a>
 */
public class MParse extends Task {

    private Path classpath = null;
    private Path sourcepath = null;
    private File metahome = null;
    private File target = null;
    private boolean verbose = false;
    private boolean debugparser = false;
    private boolean debugscanner = false;    
    private boolean cleanup = false;
    private CommandlineJava cmdl = new CommandlineJava();
    private File optionsFile = null;

    /** location of metamata dev environment */
    public void setMetamatahome(File metamatahome) {
        this.metahome = metamatahome;
    }

    /** the .jj file to process */
    public void setTarget(File target) {
        this.target = target;
    }

    /** create a classpath entry */
    public Path createClasspath() {
        if (classpath == null) {
            classpath = new Path(project);
        }        
        return classpath;
    }

    /** creates a sourcepath entry */
    public Path createSourcepath() {
        if (sourcepath == null) {
            sourcepath = new Path(project);
        }        
        return sourcepath;
    }

    /** set verbose mode */
    public void setVerbose(boolean flag){
        verbose = flag;
    }

    /** set scanner debug mode */
    public void setDebugscanner(boolean flag){
        debugscanner = flag;
    }

    /** set parser debug mode */
    public void setDebugparser(boolean flag){
        debugparser = flag;
    }

    /** set the hack to cleanup the temp file */
    public void setCleanup(boolean value) {
        cleanup = value;
    }

    /** Creates a nested jvmarg element. */
    public Commandline.Argument createJvmarg() {
        return cmdl.createVmArgument();
    }

    /**  -mx or -Xmx depending on VM version */
    public void setMaxmemory(String max){
        if (Project.getJavaVersion().startsWith("1.1")) {
            createJvmarg().setValue("-mx" + max);
        } else {
            createJvmarg().setValue("-Xmx" + max);
        }
    }

    public MParse() {
        cmdl.setVm("java");
        cmdl.setClassname("com.metamata.jj.MParse");
    }

   
    /** execute the command line */
    public void execute() throws BuildException {
        try {
            setUp();
            ExecuteStreamHandler handler = createStreamHandler();
            _execute(handler);
        } finally {
            cleanUp();
        }
    }
    
    /** return the default stream handler for this task */
    protected ExecuteStreamHandler createStreamHandler(){
        return new LogStreamHandler(this, Project.MSG_INFO, Project.MSG_INFO);
    }
    
    /**
     * check the options and build the command line
     */
    protected void setUp() throws BuildException {
        checkOptions();

        // set the classpath as the jar files
        File[] jars = getMetamataLibs();
        final Path classPath = cmdl.createClasspath(project);
        for (int i = 0; i < jars.length; i++){
            classPath.createPathElement().setLocation(jars[i]);
        }

        // set the metamata.home property
        final Commandline.Argument vmArgs = cmdl.createVmArgument();
        vmArgs.setValue("-Dmetamata.home=" + metahome.getAbsolutePath() );


        // write all the options to a temp file and use it ro run the process
        String[] options = getOptions();
        optionsFile = createTmpFile();
        generateOptionsFile(optionsFile, options);
        Commandline.Argument args = cmdl.createArgument();
        args.setLine("-arguments " + optionsFile.getAbsolutePath());
    }    

    
    /** execute the process with a specific handler */
    protected void _execute(ExecuteStreamHandler handler) throws BuildException {
        // target has been checked as a .jj, see if there is a matching
        // java file and if it is needed to run to process the grammar
        String pathname = target.getAbsolutePath();
        int pos = pathname.length() - ".jj".length();
        pathname = pathname.substring(0, pos) + ".java";
        File javaFile = new File(pathname);
        if (javaFile.exists() && target.lastModified() < javaFile.lastModified()) {
            project.log("Target is already build - skipping (" + target + ")");
            return;
        }
        
        final Execute process = new Execute(handler);
        log(cmdl.toString(), Project.MSG_VERBOSE);
        process.setCommandline(cmdl.getCommandline());
        try {
            if (process.execute() != 0) {
                throw new BuildException("Metamata task failed.");
            }
        } catch (IOException e){
            throw new BuildException("Failed to launch Metamata task: " + e);
        }
    }    
    
    /** clean up all the mess that we did with temporary objects */
    protected void cleanUp(){
        if (optionsFile != null){
            optionsFile.delete();
            optionsFile = null;
        }
        if (cleanup) {
            String name = target.getName();
            int pos = name.length() - ".jj".length();
            name = "__jj" + name.substring(0, pos) + ".sunjj";
            final File sunjj = new File(target.getParent(), name);
            if (sunjj.exists()) {
                project.log("Removing stale file: " + sunjj.getName());
                sunjj.delete();
            }
        }
    }
    
    /**
     * return an array of files containing the path to the needed
     * libraries to run metamata. The file are not checked for
     * existence. You should do this yourself if needed or simply let the
     * forked process do it for you.
     * @return array of jars/zips needed to run metamata.
     */
    protected File[] getMetamataLibs(){
        Vector files = new Vector();
        files.addElement( new File(metahome, "lib/metamata.jar") );
        files.addElement( new File(metahome, "bin/lib/JavaCC.zip") );
        
        File[] array = new File[ files.size() ];
        files.copyInto(array);
        return array;
    }
    
    
    /**
     * validate options set and resolve files and paths
     * @throws BuildException thrown if an option has an incorrect state.
     */
    protected void checkOptions() throws BuildException {       
        // check that the home is ok.
        if (metahome == null || !metahome.exists()){
            throw new BuildException("'metamatahome' must point to Metamata home directory.");
        }
        metahome = project.resolveFile(metahome.getPath());
        
        // check that the needed jar exists.
        File[] jars = getMetamataLibs();
        for (int i = 0; i < jars.length; i++){
            if (!jars[i].exists()){
                throw new BuildException( jars[i] + " does not exist. Check your metamata installation.");
            }           
        }
        
        // check that the target is ok and resolve it.
        if (target == null || !target.isFile() || !target.getName().endsWith(".jj") ) {
            throw new BuildException("Invalid target: " + target);
        }
        target = project.resolveFile(target.getPath());
    }    
    
    /**
     * return all options of the command line as string elements
     * @param an array of options corresponding to the setted options.
     */
    protected String[] getOptions(){
        Vector options = new Vector();
        if (verbose){
            options.addElement("-verbose");
        }
        if (debugscanner){
            options.addElement("-ds");
        }
        if (debugparser){
            options.addElement("-dp");
        }
        if (classpath != null){
            options.addElement("-classpath");
            options.addElement(classpath.toString());
        }
        if (sourcepath != null){
            options.addElement("-sourcepath");
            options.addElement(sourcepath.toString());
        }
        options.addElement(target.getAbsolutePath());
        
        String[] array = new String[options.size()];
        options.copyInto(array);
        return array;
    }
    
    /**
     * write all options to a file with one option / line
     * @param tofile the file to write the options to.
     * @param options the array of options element to write to the file.
     * @throws BuildException thrown if there is a problem while writing
     * to the file.
     */
    protected void generateOptionsFile(File tofile, String[] options) throws BuildException {
        FileWriter fw = null;
        try {
            fw = new FileWriter(tofile);
            PrintWriter pw = new PrintWriter(fw);
            for (int i = 0; i < options.length; i++){
                pw.println( options[i] );
            }
            pw.flush();
        } catch (IOException e){
            throw new BuildException("Error while writing options file " + tofile, e);
        } finally {
            if (fw != null){
                try {
                    fw.close();
                } catch (IOException ignored){}
            }
        }
    }
    
    /** create a temporary file in the current directory */
    protected final static File createTmpFile(){
        // must be compatible with JDK 1.1 !!!!
        final long rand = (new Random(System.currentTimeMillis())).nextLong();
        File file = new File("metamata" + rand + ".tmp");
        return file;
    }

}
