/*
 * 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.jdo.enhancer;

import java.io.IOException;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.PrintWriter;

import java.util.List;
import java.util.Iterator;
import java.util.Properties;

import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import org.apache.jdo.impl.enhancer.ClassFileEnhancer;
import org.apache.jdo.impl.enhancer.ClassFileEnhancerHelper;
import org.apache.jdo.impl.enhancer.ClassFileEnhancerTimer;
import org.apache.jdo.impl.enhancer.EnhancerFatalError;
import org.apache.jdo.impl.enhancer.EnhancerOptions;
import org.apache.jdo.impl.enhancer.EnhancerUserException;
import org.apache.jdo.impl.enhancer.JdoMetaMain;
import org.apache.jdo.impl.enhancer.OutputStreamWrapper;
import org.apache.jdo.impl.enhancer.core.EnhancerFilter;



/**
 * JDO command line enhancer.
 *
 * @author Martin Zaun
 */
public class EnhancerMain
    extends JdoMetaMain
{
    /**
     *  The options and arguments.
     */
    protected EnhancerOptions options;

    /**
     *  The byte code enhancer.
     */
    protected ClassFileEnhancer enhancer;

    /**
     * Creates an instance.
     */
    public EnhancerMain(PrintWriter out,
                        PrintWriter err)
    {
        this(out, err, new EnhancerOptions(out, err));
    }

    /**
     * Creates an instance.
     */
    public EnhancerMain(PrintWriter out,
                        PrintWriter err,
                        EnhancerOptions options)
    {
        super(out, err, options);
        this.options = options;
    }

    // ----------------------------------------------------------------------

    /**
     * Enhances all files entered in the command line.
     *
     * @param  classNames  List of class names.
     * @param  classFileNames  List of class file names.
     * @param  archiveFileNames  List of archive file names.
     */
    private int enhanceInputFiles(List classNames,
                                  List classFileNames,
                                  List archiveFileNames)
    {
        int res = 0;
        try {
            String name = null;
            for (Iterator i = archiveFileNames.iterator(); i.hasNext();) {
                try {
                    name = (String)i.next();
                    enhanceArchiveFile(name);
                } catch (EnhancerUserException ex) {
                    printlnErr("Error while enhancing " + name, ex, 
                               options.verbose.value);
                    res++;
                    continue;
                }
            }
            for (Iterator i = classFileNames.iterator(); i.hasNext();) {
                try {
                    name = (String)i.next();
                    enhanceClassFile(openFileInputStream(name));
                } catch (EnhancerUserException ex) {
                    printlnErr("Error while enhancing " + name, ex, 
                               options.verbose.value);
                    res++;
                    continue;
                }
            }
            for (Iterator i = classNames.iterator(); i.hasNext();) {
                try {
                    name = (String)i.next();
                    enhanceClassFile(openClassInputStream(name));
                } catch (EnhancerUserException ex) {
                    printlnErr("Error while enhancing " + name, ex, 
                               options.verbose.value);
                    res++;
                    continue;
                }
            }
        } catch (IOException ex) {
            printlnErr("IO Error while enhancing", ex, options.verbose.value);
            return ++res;
        } catch (EnhancerFatalError ex) {
            // enhancer is not anymore guaranteed to be consistent
            printlnErr("Fatal error while enhancing", ex, options.verbose.value);
            enhancer = null;
            return ++res;
        }
        return res;
    }

    /**
     * Enhances a classfile.
     *
     * @param  in  The input stream of the classfile.
     */
    private void enhanceClassFile(InputStream in)
        throws IOException, EnhancerUserException, EnhancerFatalError
    {
        OutputStream out = null;
        try {
            final File temp = File.createTempFile("enhancer", ".class");
            out = new BufferedOutputStream(new FileOutputStream(temp));

            //enhance
            final OutputStreamWrapper wrapper = new OutputStreamWrapper(out);
            final boolean enhanced = enhancer.enhanceClassFile(in, wrapper);

            closeOutputStream(out);
            out = null;
            createOutputFile(enhanced,
                             getClassFileName(wrapper.getClassName()), temp);
        } finally {
            closeInputStream(in);
            closeOutputStream(out);
        }
    }

    /**
     * Enhances a archive file.
     *
     * @param  fileName  The filename of the archive file.
     */
    private void enhanceArchiveFile(String fileName)
        throws IOException, EnhancerUserException, EnhancerFatalError
    {
        ZipInputStream in = null;
        ZipOutputStream out = null;
        try {
            final File temp = File.createTempFile("enhancer", ".zip");
            in = new ZipInputStream(new BufferedInputStream(
                new FileInputStream(new File(fileName))));
            out = new ZipOutputStream(new BufferedOutputStream(
                new FileOutputStream(temp)));

            // enhance the archive file
            final boolean enhanced
                = ClassFileEnhancerHelper.enhanceZipFile(enhancer, in, out);

            // create the output file
            closeOutputStream(out);
            out = null;
            createOutputFile(enhanced, new File(fileName).getName(), temp);
        } finally {
            closeOutputStream(out);
            closeInputStream(in);
        }
    }

    /**
     * Creates a file object that represents the output archive file for
     * a given archive file to enhance.
     *
     * @param  archiveFileName  the input archive file name
     * @return  the output archive file
     */
    private File createArchiveOutputFile(String archiveFileName)
    {
        return new File(options.destDir.value,
                        new File(archiveFileName).getName());
    }

    /**
     * Creates the output file for an enhanced class- or archive file. If the
     * enhanced file is written back depends on the command line options.
     *
     * @param  enhanced  Has the input file been enhanced?
     * @param  fileName  The name of the output file.
     * @param  temp      The temp file, the output is written to.
     * @exception  IOException  If the file could not be created.
     */
    private void createOutputFile(boolean enhanced,
                                  String fileName,
                                  File temp)
        throws IOException
    {
        //noWrite or (not enhanced and not forceWrite)
        if (options.noWrite.value
            || (!enhanced && !options.forceWrite.value)) {
            temp.deleteOnExit();
            return;
        }

        // create file and its parent directory
        final File file = new File(options.destDir.value, fileName);
        final File dir = file.getAbsoluteFile().getParentFile();
        if (!dir.exists() && !dir.mkdirs()) {
            throw new IOException("Error creating directory '"
                                  + dir.getAbsolutePath() + "'.");
        }

        file.delete();  //delete old file if exists
        boolean renamed = temp.renameTo(file);
        if (!renamed) {
            //@dave: empirical evidence shows that renameTo does not allow for
            // crossing filesystem boundaries.  If it fails, try "by hand".
            InputStream in = null;
            OutputStream out = null;
            try {
                in = new FileInputStream(temp);
                out = new FileOutputStream(file);
                int PAGESIZE = 4096; // Suggest a better size?
                byte data[] = new byte[PAGESIZE];
                while (in.available() > 0) {
                    int numRead = in.read(data, 0, PAGESIZE);
                    out.write(data, 0, numRead);
                }
                renamed = true;
            } catch (IOException ex) {
                throw new IOException("Could not rename temp file '" +
                                      temp.getAbsolutePath() +
                                      "' to '" + file.getAbsolutePath()
                                      + "': " + ex);
            } finally {
                closeInputStream(in);
                closeOutputStream(out);
            }
            if (renamed) {
                temp.delete();  //delete temporary file
            }
            else {
                throw new IOException("Could not rename temp file '" +
                                      temp.getAbsolutePath() +
                                      "' to '" + file.getAbsolutePath() + "'.");
            }
        }
    }

    /**
     * Closes an output stream.
     *
     * @param  out  the output stream
     */
    private void closeOutputStream(OutputStream out)
    {
        if (out != null) {
            try {
                out.close();
            } catch (IOException ex) {
                printlnErr("", ex, options.verbose.value);
            }
        }
    }

    // ----------------------------------------------------------------------

    /**
     * Initializes all components.
     */
    protected void init()
        throws EnhancerFatalError, EnhancerUserException
    {
        super.init();

        final Properties props = new Properties();
        if (options.verbose.value) {
            props.put(EnhancerFilter.VERBOSE_LEVEL,
                      EnhancerFilter.VERBOSE_LEVEL_VERBOSE);
        }
        
        if (options.doTiming.value) {
            props.put(EnhancerFilter.DO_TIMING_STATISTICS,
                      Boolean.TRUE.toString());
        }

        if (options.dumpClass.value) {
            props.put(EnhancerFilter.DUMP_CLASS,
                      Boolean.TRUE.toString());
        }

        if (options.noAugment.value) {
            props.put(EnhancerFilter.NO_AUGMENT,
                      Boolean.TRUE.toString());
        }

        if (options.noAnnotate.value) {
            props.put(EnhancerFilter.NO_ANNOTATE,
                      Boolean.TRUE.toString());
        }

        try {
            enhancer = new EnhancerFilter(jdoMeta, props, out, err);
            if (options.doTiming.value) {
                // wrap with timing byte-code enhancer
                enhancer = new ClassFileEnhancerTimer(enhancer);
            }
        } catch (EnhancerUserException ex) {
            printlnErr("Error while creating the enhancer", ex, 
                       options.verbose.value);
            throw ex;
        } catch (EnhancerFatalError ex) {
            // enhancer is not anymore guaranteed to be consistent
            printlnErr("Fatal error while creating the enhancer", ex, 
                       options.verbose.value);
            enhancer = null;
            throw ex;
        } catch (RuntimeException ex) {
            // enhancer is not anymore guaranteed to be consistent
            printlnErr("Internal error while creating the enhancer", ex, 
                       options.verbose.value);
            enhancer = null;
            throw new EnhancerFatalError(ex);
        }
    }

    /**
     * Run the enhancer.
     */
    protected int process()
    {
        return enhanceInputFiles(options.classNames,
                                 options.classFileNames,
                                 options.archiveFileNames);
    }

    // ----------------------------------------------------------------------

    /**
     * Runs this class
     */
    static public void main(String[] args)
    {
        final PrintWriter out = new PrintWriter(System.out, true);
        out.println("--> EnhancerMain.main()");
        //out.println("JDO RI Class-File Enhancer");
        final EnhancerMain main = new EnhancerMain(out, out);
        int res = main.run(args);
        //out.println("done.");
        out.println("<-- EnhancerMain.main(): exit = " + res);
        System.exit(res);
    }
}
