/*
 * 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.
 *
 */

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry;

import org.apache.commons.bcel6.Constants;
import org.apache.commons.bcel6.classfile.ClassParser;
import org.apache.commons.bcel6.classfile.Constant;
import org.apache.commons.bcel6.classfile.ConstantClass;
import org.apache.commons.bcel6.classfile.ConstantPool;
import org.apache.commons.bcel6.classfile.ConstantUtf8;
import org.apache.commons.bcel6.classfile.JavaClass;
import org.apache.commons.bcel6.util.ClassPath;

/**
 * Package the client. Creates a jar file in the current directory
 * that contains a minimal set of classes needed to run the client.
 *
 * Use BCEL to extract class names and read/write classes
 *
 * @author First Hop Ltd / Torsten Rueger
 */
public class Package {

    /**
     * The name of the resulting jar is Client.jar
     */
    static String defaultJar = "Client.jar";

    /*
     * See usage() for arguments. Create an instance and run that
     *(just so not all members have to be static)
     */
    static void main(String args[]) {
        Package instance = new Package();
        try {
            instance.go(args);
        } catch (Exception e) {
            e.printStackTrace();
            instance.usage();
        }
    }

    /**
     * We use a "default ClassPath object which uses the environments
     * CLASSPATH
     */
    ClassPath classPath = ClassPath.SYSTEM_CLASS_PATH;

    /**
     * A map for all Classes, the ones we're going to package.
     * Store class name against the JavaClass. From the JavaClass
     * we get the bytes to create the jar.
     */
    Map<String, JavaClass> allClasses = new TreeMap<String, JavaClass>();

    /**
     * We start at the root classes, put them in here, then go through
     * this list, putting dependent classes in here and from there
     * into allClasses. Store class names against class names of their dependents
     */
    TreeMap<String, String> dependents = new TreeMap<String, String>();

    /**
     * Collect all classes that could not be found in the classpath.
     * Store class names against class names of their dependents
     */
    TreeMap<String, String> notFound = new TreeMap<String, String>();

    /**
     * See wheather we print the classes that were not found (default = false)
     */
    boolean showNotFound = false;
    /**
     * Remember wheather to print allClasses at the end (default = false)
     */
    boolean printClasses = false;
    /**
     * Wheather we log classes during processing (default = false)
     */
    boolean log = false;

    public void usage() {
        System.out.println(" This program packages classes and all their dependents");
        System.out.println(" into one jar. Give all starting classes (your main)");
        System.out.println(" on the command line. Use / as separator, the .class is");
        System.out.println(" optional. We use the environments CLASSPATH to resolve");
        System.out.println(" classes. Anything but java.* packages are packaged.");
        System.out.println(" If you use Class.forName (or similar), be sure to");
        System.out.println(" include the classes that you load dynamically on the");
        System.out.println(" command line.\n");
        System.out.println(" These options are recognized:");
        System.out.println(" -e -error  Show errors, meaning classes that could not ");
        System.out.println("   resolved + the classes that referenced them.");
        System.out.println(" -l -log  Show classes as they are processed. This will");
        System.out.println("   include doubles, java classes and is difficult to");
        System.out.println("   read. I use it as a sort of progress monitor");
        System.out.println(" -s -show  Prints all the classes that were packaged");
        System.out.println("   in alphabetical order, which is ordered by package");
        System.out.println("   for the most part.");
    }

    /**
     * the main of this class
     */
    void go(String[] args) throws IOException {
        JavaClass clazz;
        // sort the options
        for (String arg : args) {
            if (arg.startsWith("-e")) {
                showNotFound = true;
                continue;
            }
            if (arg.startsWith("-s")) {
                printClasses = true;
                continue;
            }
            if (arg.startsWith("-l")) {
                log = true;
                continue;
            }
            String clName = arg;
            if (clName.endsWith(".class")) {
                clName = clName.substring(0, clName.length() - 6);
            }
            clName = clName.replace('.', '/');
            clazz = new ClassParser(classPath.getInputStream(clName), clName).parse();
            // here we create the root set of classes to process
            addDependents(clazz);
            System.out.println("Packaging for class: " + clName);
        }

        if (dependents.isEmpty()) {
            usage();
            return;
        }

        System.out.println("Creating jar file: " + defaultJar);

        // starting processing: Grab from the dependents list an add back to it
        // and the allClasses list. see addDependents
        while (!dependents.isEmpty()) {
            String name = dependents.firstKey();
            String from = dependents.remove(name);
            if (allClasses.get(name) == null) {
                try {
                    InputStream is = classPath.getInputStream(name);
                    clazz = new ClassParser(is, name).parse();
                    addDependents(clazz);
                } catch (IOException e) {
                    //System.err.println("Error, class not found " + name );
                    notFound.put(name, from);
                }
            }
        }

        if (printClasses) { // if wanted show all classes
            printAllClasses();
        }

        // create the jar
        JarOutputStream jarFile = new JarOutputStream(new FileOutputStream(defaultJar));
        jarFile.setLevel(5); // use compression
        int written = 0;
        for (String name : allClasses.keySet()) { // add entries for every class
            JavaClass claz = allClasses.get(name);
            ZipEntry zipEntry = new ZipEntry(name + ".class");
            byte[] bytes = claz.getBytes();
            int length = bytes.length;
            jarFile.putNextEntry(zipEntry);
            jarFile.write(bytes, 0, length);
            written += length;  // for logging
        }
        jarFile.close();
        System.err.println("The jar file contains " + allClasses.size()
                + " classes and contains " + written + " bytes");

        if (!notFound.isEmpty()) {
            System.err.println(notFound.size() + " classes could not be found");
            if (showNotFound) { // if wanted show the actual classes that we not found
                while (!notFound.isEmpty()) {
                    String name = notFound.firstKey();
                    System.err.println(name + " (" + notFound.remove(name) + ")");
                }
            } else {
                System.err.println("Use '-e' option to view classes that were not found");
            }
        }
    }

    /**
     * Print all classes that were packaged. Sort alphabetically for better
     * overview. Enabled by -s option
     */
    void printAllClasses() {
        List<String> names = new ArrayList<String>(allClasses.keySet());
        Collections.sort(names);
        for (int i = 0; i < names.size(); i++) {
            String cl = names.get(i);
            System.err.println(cl);
        }
    }

    /**
     * Add this class to allClasses. Then go through all its dependents
     * and add them to the dependents list if they are not in allClasses
     */
    void addDependents(JavaClass clazz) throws IOException {
        String name = clazz.getClassName().replace('.', '/');
        allClasses.put(name, clazz);
        ConstantPool pool = clazz.getConstantPool();
        for (int i = 1; i < pool.getLength(); i++) {
            Constant cons = pool.getConstant(i);
            //System.out.println("("+i+") " + cons );
            if (cons != null && cons.getTag() == Constants.CONSTANT_Class) {
                int idx = ((ConstantClass) pool.getConstant(i)).getNameIndex();
                String clas = ((ConstantUtf8) pool.getConstant(idx)).getBytes();
                addClassString(clas, name);
            }
        }
    }

    /**
     * add given class to dependents (from is where its dependent from)
     * some fiddeling to be done because of array class notation
     */
    void addClassString(String clas, String from) throws IOException {
        if (log) {
            System.out.println("processing: " + clas + " referenced by " + from);
        }

        // must check if it's an arrary (start with "[")
        if (clas.startsWith("[")) {
            if (clas.length() == 2) {
                // it's an array of built in type, ignore
                return;
            }
            if ('L' == clas.charAt(1)) {
                // it's an array of objects, the class name is between [L and ;
                // like    [Ljava/lang/Object;
                addClassString(clas.substring(2, clas.length() - 1), from);
                return;
            }
            if ('[' == clas.charAt(1)) {
                // it's an array of arrays, call recursive
                addClassString(clas.substring(1), from);
                return;
            }
            throw new IOException("Can't recognize class name =" + clas);
        }

        if (!clas.startsWith("java/") && allClasses.get(clas) == null) {
            dependents.put(clas, from);
            //      System.out.println("       yes" );
        } else {
            //      System.out.println("       no" );
        }
    }
}
