/*   Copyright 2004 The Apache Software Foundation
 *
 *   Licensed 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.xmlbeans.impl.tool;

import java.util.ArrayList;
import java.util.List;
import java.util.Iterator;
import java.util.Arrays;
import java.io.File;
import java.io.InputStream;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.FileFilter;
import java.io.FileWriter;
import java.net.URI;
import java.net.URISyntaxException;

public class CodeGenUtil
{
    public static String DEFAULT_MEM_START = "8m";
    public static String DEFAULT_MEM_MAX = "256m";
    public static String DEFAULT_COMPILER = "javac";
    public static String DEFAULT_JAR = "jar";

    //workaround for Sun bug # 4723726
    public static URI resolve(URI base, URI child)
    {
        URI ruri = base.resolve(child);
        
        //fix up normalization bug
        if ("file".equals(ruri.getScheme()) && ! child.equals(ruri))
        {
            if (base.getPath().startsWith("//") && !ruri.getPath().startsWith("//"))
            {
                String path = "///".concat(ruri.getPath());
                try
                {
                    ruri = new URI("file", null, path, ruri.getQuery(), ruri.getFragment());
                }
                catch(URISyntaxException uris)
                {}
            }
        }
        return ruri;
    }
    
    static void addAllJavaFiles(List srcFiles, List args)
    {
        for (Iterator i = srcFiles.iterator(); i.hasNext(); )
        {
            File f = (File)i.next();
            if (!f.isDirectory())
            {
                args.add(quoteAndEscapeFilename(f.getAbsolutePath()));
            }
            else
            {
                List inside = (Arrays.asList(f.listFiles(
                    new FileFilter()
                    {
                        public boolean accept(File file)
                            { return (file.isFile() && file.getName().endsWith(".java")) || file.isDirectory(); }
                    }
                )));
                addAllJavaFiles(inside, args);
            }
        }
    }

    static private String quoteAndEscapeFilename(String filename)
    {
        // don't quote if there's no space
        if (filename.indexOf(" ") < 0)
            return filename;

        // bizarre.  javac expects backslash escaping if we quote the classpath
        // bizarre also.  replaceAll expects replacement backslashes to be double escaped.
        return "\"" + filename.replaceAll("\\\\", "\\\\\\\\") + "\"";
    }

    static private String quoteNoEscapeFilename(String filename)
    {
        // don't quote if there's no space, and don't quote on linux
        if (filename.indexOf(" ") < 0 || File.separatorChar == '/')
            return filename;

        return "\"" + filename + "\"";
    }

    /**
     * Invokes javac on the generated source files in order to turn them
     * into binary files in the output directory.  This will return a list of
     * <code>GenFile</code>s for all of the classes produced or null if an
     * error occurred.
     *
     * @deprecated
     */
    static public boolean externalCompile(List srcFiles, File outdir, File[] cp, boolean debug)
    {
        return externalCompile(srcFiles, outdir, cp, debug, DEFAULT_COMPILER, DEFAULT_MEM_START, DEFAULT_MEM_MAX, false, false);
    }

    /**
     * Invokes javac on the generated source files in order to turn them
     * into binary files in the output directory.  This will return a list of
     * <code>GenFile</code>s for all of the classes produced or null if an
     * error occurred.
     */
    static public boolean externalCompile(List srcFiles, File outdir, File[] cp, boolean debug, String javacPath, String memStart, String memMax,  boolean quiet, boolean verbose)
    {
        List args = new ArrayList();

        File javac = findJavaTool(javacPath == null ? DEFAULT_COMPILER : javacPath);
        assert (javac.exists()) : "compiler not found " + javac;
        args.add(javac.getAbsolutePath());

        if (outdir == null)
        {
            outdir = new File(".");
        }
        else
        {
            args.add("-d");
            args.add(quoteAndEscapeFilename(outdir.getAbsolutePath()));
        }

        if (cp == null)
        {
            cp = systemClasspath();
        }

        if (cp.length > 0)
        {
            StringBuffer classPath = new StringBuffer();
            // Add the output directory to the classpath.  We do this so that
            // javac will be able to find classes that were compiled
            // previously but are not in the list of sources this time.
            classPath.append(outdir.getAbsolutePath());

            // Add everything on our classpath.
            for (int i = 0; i < cp.length; i++)
            {
                classPath.append(File.pathSeparator);
                classPath.append(cp[i].getAbsolutePath());
            }

            args.add("-classpath");

            // bizarre.  javac expects backslash escaping if we quote the classpath
            args.add(quoteAndEscapeFilename(classPath.toString()));
        }

        args.add("-source");
        args.add("1.4");

        args.add(debug ? "-g" : "-g:none");

        if (verbose)
            args.add("-verbose");

        addAllJavaFiles(srcFiles, args);

        File clFile = null;
        try
        {
            clFile = File.createTempFile("javac", "");
            FileWriter fw = new FileWriter(clFile);
            Iterator i = args.iterator();
            for (i.next(); i.hasNext();)
            {
                String arg = (String)i.next();
                fw.write(arg);
                fw.write('\n');
            }
            fw.close();
            List newargs = new ArrayList();
            newargs.add(args.get(0));
            
            if (memStart != null && memStart.length() != 0)
                newargs.add("-J-Xms" + memStart);
            if (memMax != null && memMax.length() != 0)
                newargs.add("-J-Xmx" + memMax);
            
            newargs.add("@" + clFile.getAbsolutePath());
            args = newargs;
        }
        catch (Exception e)
        {
            System.err.println("Could not create command-line file for javac");
        }

        try
        {
            String[] strArgs = (String[]) args.toArray(new String[args.size()]);

            if (verbose)
            {
                System.out.print("compile command:");
                for (int i = 0; i < strArgs.length; i++)
                    System.out.print(" " + strArgs[i]);
                System.out.println();
            }

            final Process proc = Runtime.getRuntime().exec(strArgs);

            StringBuffer errorBuffer = new StringBuffer();
            StringBuffer outputBuffer = new StringBuffer();

            ThreadedReader out = new ThreadedReader(proc.getInputStream(), outputBuffer);
            ThreadedReader err = new ThreadedReader(proc.getErrorStream(), errorBuffer);

            proc.waitFor();

            if (verbose || proc.exitValue() != 0)
            {
                if (outputBuffer.length() > 0) {
                    System.out.println(outputBuffer.toString());
                    System.out.flush();
                }
                if (errorBuffer.length() > 0) {
                    System.err.println(errorBuffer.toString());
                    System.err.flush();
                }
                
                if (proc.exitValue() != 0)
                    return false;
            }
        }
        catch (Throwable e)
        {
            System.err.println(e.toString());
            System.err.println(e.getCause());
            e.printStackTrace(System.err);
            return false;
        }

        if (clFile != null)
            clFile.delete();

        return true;
    }

    public static File[] systemClasspath()
    {
        List cp = new ArrayList();
        String[] systemcp = System.getProperty("java.class.path").split(File.pathSeparator);
        for (int i = 0; i < systemcp.length; i++)
        {
            cp.add(new File(systemcp[i]));
        }
        return (File[])cp.toArray(new File[cp.size()]);
    }

  //Note - I have added a new class, JarHelper, in impl.common which provides
  //more jarring functionality and does not require invoking jar.exe.  You
  //may want to consider migrating your code to use this as it will be
  //considerably faster.  pcal  12/10/2003

  /**
   * @deprecated Use org.apache.xmlbeans.impl.common.JarHelper instead.
   */
    static public boolean externalJar(File srcdir, File outfile)
    {
        return externalJar(srcdir, outfile, DEFAULT_JAR, false, false);
    }

  /**
   * @deprecated Use org.apache.xmlbeans.impl.common.JarHelper instead.
   */
    static public boolean externalJar(File srcdir, File outfile, String jarPath, boolean quiet, boolean verbose)
    {
        List args = new ArrayList();

        File jar = findJavaTool(jarPath == null ? DEFAULT_JAR : jarPath);
        assert (jar.exists()) : "jar not found " + jar;
        args.add(jar.getAbsolutePath());

        args.add("cf" + (verbose ? "v" : ""));
        args.add(quoteNoEscapeFilename(outfile.getAbsolutePath()));

        args.add("-C");
        args.add(quoteNoEscapeFilename(srcdir.getAbsolutePath()));

        args.add(".");

        try
        {
            String[] strArgs = (String[]) args.toArray(new String[args.size()]);

            if (verbose)
            {
                System.out.print("jar command:");
                for (int i = 0; i < strArgs.length; i++)
                    System.out.print(" " + strArgs[i]);
                System.out.println();
            }

            final Process proc = Runtime.getRuntime().exec(strArgs);

            StringBuffer errorBuffer = new StringBuffer();
            StringBuffer outputBuffer = new StringBuffer();

            ThreadedReader out = new ThreadedReader(proc.getInputStream(), outputBuffer);
            ThreadedReader err = new ThreadedReader(proc.getErrorStream(), errorBuffer);

            proc.waitFor();

            if (verbose || proc.exitValue() != 0)
            {
                if (outputBuffer.length() > 0) {
                    System.out.println(outputBuffer.toString());
                    System.out.flush();
                }
                if (errorBuffer.length() > 0) {
                    System.err.println(errorBuffer.toString());
                    System.err.flush();
                }

                if (proc.exitValue() != 0)
                    return false;
            }
        }
        catch (Throwable e)
        {
            e.printStackTrace(System.err);
            return false;
        }
        return true;
    }

    /**
     * Look for tool in current directory and ${JAVA_HOME}/../bin and
     * try with .exe file extension.
     */ 
    private static File findJavaTool(String tool)
    {
        File toolFile = new File(tool);
        if (toolFile.isFile()) {
            return toolFile;
        }

        File result = new File(tool + ".exe");
        if (result.isFile()) {
            return result;
        }
        
        String home = System.getProperty("java.home");

        String sep  = File.separator;
        result = new File(home + sep + ".." + sep + "bin", tool);
        
        if (result.isFile()) {
            return result;
        }
        
        result = new File(result.getPath() + ".exe");
        if (result.isFile()) {
            return result;
        }

        result = new File(home + sep + "bin", tool);
        if (result.isFile()) {
            return result;
        }

        result = new File(result.getPath() + ".exe");
        if (result.isFile()) {
            return result;
        }

        // just return the original toolFile and hope that it is on the PATH.
        return toolFile;
    }

    /**
     * Reads the given input stream into the given buffer until there is
     * nothing left to read.
     */
    static private class ThreadedReader
    {
        public ThreadedReader(InputStream stream, final StringBuffer output)
        {
            final BufferedReader reader =
                new BufferedReader(new InputStreamReader(stream));

            Thread readerThread = new Thread(new Runnable() {
                public void run()
                {
                    String s;
                    try
                    {
                        while ((s = reader.readLine()) != null)
                            output.append(s + "\n");
                    }
                    catch (Exception e)
                    {}
                }
            });
            readerThread.start();
        }
    }
}
