/* 
 * 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
 * 
 *     http://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.harmony.tools.javac;

import java.io.File;
import java.io.PrintWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import org.apache.harmony.tools.toolutils.Util;

/**
 * A proxy to the Java source code compiler itself.
 */
class Compiler {

    /* FIXME: Hard-coded for now, the name of the ECJ JAR file */
    static final String ECJ_JAR_FILE = "ecj-3.4.2.jar"; //$NON-NLS-1$

    static final String TOOLS_JAR_FILE = "tools.jar"; //$NON-NLS-1$

    /* The name of the ECJ compiler class */
    static final String MAIN_CLASS_NAME = "org.eclipse.jdt.internal.compiler.batch.Main"; //$NON-NLS-1$

    /*
     * Invokes the compiler with the given command-line arguments. The supported
     * arguments can be determined form the usage message.
     * 
     * Answers the result of the compilation from ECJ; i.e. true if the compile
     * succeeded, and false otherwise.
     */
    public static boolean main(String[] args) {
        return main(args, Util.getDefaultWriter(System.out), Util.getDefaultWriter(System.err));
    }

    public static boolean main(String[] args, PrintWriter out, PrintWriter err) {
        Compiler myself = new Compiler(out, err);

        // If there is a problem invoking the method, simply dump the trace for
        // now
        try {
            Object result = myself.staticCompileMth.invoke(myself.mainInst,
                    new Object[] { args });
            return (Boolean) result;
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return false;
    }

    // Reference to ECJ 'Main' compiler class.
    Class<?> ecjCompilerClass;

    // An instance of the ECJ compiler
    Object mainInst;

    // The Main#printUsage() method.
    Method printUsageMth;

    // The static Main#compile(string[]) method on the ECJ compiler
    Method staticCompileMth;

    /**
     * Default constructor. Returns a new initialized instance of the Java
     * compiler.
     */
    public Compiler(PrintWriter out, PrintWriter err) {
        super();
        initialize(out, err);
    }

    /*
     * Initialize our local variables. Called during type construction.
     */
    protected void initialize(PrintWriter out, PrintWriter err) {
        try {
            initializeMainClass();
            initializeInstance(out, err);
            initializeMethods();
        } catch (Exception e) {
            // If there is a problem we log it to the console
            e.printStackTrace();
        }
    }

    /*
     * Defines the local instance of the ECJ compiler
     */
    protected void initializeInstance(PrintWriter out, PrintWriter err) throws SecurityException,
            NoSuchMethodException, IllegalArgumentException,
            InstantiationException, IllegalAccessException,
            InvocationTargetException {

        // Create a new instance of the compiler
        Constructor<?> ctor = ecjCompilerClass.getConstructor(new Class[] {
                PrintWriter.class, PrintWriter.class, Boolean.TYPE });

        mainInst = ctor.newInstance(new Object[] { out, err,
                Boolean.FALSE });
    }

    /*
     * Defines the compiler class from the ECJ jar file
     */
    protected void initializeMainClass() throws ClassNotFoundException,
            SecurityException, NoSuchMethodException, MalformedURLException,
            IllegalArgumentException, InstantiationException,
            IllegalAccessException, InvocationTargetException {

        // Find the ECJ JAR file, prefer those found near loaders
        URL ecjURL = searchLoaders();
        if (ecjURL == null) {
            ecjURL = searchPaths();
        }
        if (ecjURL == null) {
            throw new RuntimeException("Cannot find file " + ECJ_JAR_FILE);
        }

        // Load the ECJ main class
        URLClassLoader loader = new URLClassLoader(new URL[] { ecjURL });
        ecjCompilerClass = loader.loadClass(MAIN_CLASS_NAME);
    }

    /*
     * Looks for the ECJ JAR file in the current working directory, and in the
     * jdk/lib of the current runtime. Answers with a URL of the JAR file if
     * found, or null if not found.
     */
    private URL searchPaths() throws MalformedURLException {
        // Search in current working directory
        File cwdFile = new File(ECJ_JAR_FILE);
        if (cwdFile.exists()) {
            return cwdFile.toURL();
        }

        // Look for it via the java.home
        File javaHomeFile = new File(System.getProperty("java.home")); //$NON-NLS-1$
        String pathFromJDK = "lib" + File.separator + ECJ_JAR_FILE; //$NON-NLS-1$

        // Is java.home pointing at a JDK?
        File jdkBasedFile = new File(javaHomeFile, pathFromJDK);
        if (jdkBasedFile.exists()) {
            return jdkBasedFile.toURL();
        }
        // Maybe it is pointing at a JRE.
        File jdkHomeFile = javaHomeFile.getParentFile();
        if (jdkHomeFile == null) {
            return null;
        }
        File jreBasedFile = new File(jdkHomeFile, pathFromJDK);
        if (jreBasedFile.exists()) {
            return jreBasedFile.toURL();
        }

        // We didn't find it
        return null;
    }

    /*
     * Find the ECJ jar by searching for the tools.jar location and figuring
     * that it is alongside that.
     */
    private URL searchLoaders() throws MalformedURLException {
        URLClassLoader bogusLoader = new URLClassLoader(new URL[] {});
        ClassLoader parentLoader = bogusLoader.getParent();
        while (parentLoader instanceof URLClassLoader) {
            URLClassLoader parentURLLoader = (URLClassLoader) parentLoader;
            URL[] uls = parentURLLoader.getURLs();
            for (int i = 0; i < uls.length; i++) {
                URL l = uls[i];
                String filename = new File(l.getFile()).getName();
                if (filename.equals(TOOLS_JAR_FILE)) {
                    return new URL(l, ECJ_JAR_FILE);
                }
            }
            // Not found here, move up a level
            parentLoader = parentLoader.getParent();
        }
        // We didn't find it
        return null;
    }

    /*
     * Initialize our local references to compiler methods we may wish to
     * invoke.
     */
    protected void initializeMethods() throws SecurityException,
            NoSuchMethodException {
        staticCompileMth = ecjCompilerClass.getMethod("compile", //$NON-NLS-1$
                new Class[] { String[].class });
        printUsageMth = ecjCompilerClass
                .getMethod("printUsage", (Class[]) null); //$NON-NLS-1$
    }

    /**
     * Prints the compiler usage message out on the console.
     */
    public void printUsage() {
        // If there is a problem invoking the method, simply dump the trace for
        // now
        try {
            printUsageMth.invoke(mainInst);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
    }
}
