/*
 * 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.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.bcel.Constants;
import org.apache.bcel.Repository;
import org.apache.bcel.classfile.ClassParser;
import org.apache.bcel.classfile.Code;
import org.apache.bcel.classfile.Constant;
import org.apache.bcel.classfile.ConstantClass;
import org.apache.bcel.classfile.ConstantPool;
import org.apache.bcel.classfile.ConstantUtf8;
import org.apache.bcel.classfile.JavaClass;
import org.apache.bcel.classfile.Method;

/**
 * Read class file(s) and display its contents. The command line usage is:
 *
 * <pre>java listclass [-constants] [-code] [-brief] [-dependencies] [-nocontents] [-recurse] class... [-exclude <list>]</pre>
 * where
 * <ul>
 * <li>{@code -code} List byte code of methods</li>
 * <li>{@code -brief} List byte codes briefly</li>
 * <li>{@code -constants} Print constants table (constant pool)</li>
 * <li>{@code -recurse}  Usually intended to be used along with
 * {@code -dependencies}  When this flag is set, listclass will also print information
 * about all classes which the target class depends on.</li>
 *
 * <li>{@code -dependencies}  Setting this flag makes listclass print a list of all
 * classes which the target class depends on.  Generated from getting all
 * CONSTANT_Class constants from the constant pool.</li>
 *
 * <li>{@code -exclude}  All non-flag arguments after this flag are added to an
 * 'exclusion list'.  Target classes are compared with the members of the
 * exclusion list.  Any target class whose fully qualified name begins with a
 * name in the exclusion list will not be analyzed/listed.  This is meant
 * primarily when using both {@code -recurse} to exclude java, javax, and sun classes,
 * and is recommended as otherwise the output from {@code -recurse} gets quite long and
 * most of it is not interesting.  Note that {@code -exclude} prevents listing of
 * classes, it does not prevent class names from being printed in the
 * {@code -dependencies} list.</li>
 * <li>{@code -nocontents} Do not print JavaClass.toString() for the class. I added
 * this because sometimes I'm only interested in dependency information.</li>
 * </ul>
 * <p>Here's a couple examples of how I typically use listclass:<br>
 * <pre>java listclass -code MyClass</pre>
 * Print information about the class and the byte code of the methods
 * <pre>java listclass -nocontents -dependencies MyClass</pre>
 * Print a list of all classes which MyClass depends on.
 * <pre>java listclass -nocontents -recurse MyClass -exclude java. javax. sun.</pre>
 * Print a recursive listing of all classes which MyClass depends on.  Do not
 * analyze classes beginning with "java.", "javax.", or "sun.".
 * <pre>java listclass -nocontents -dependencies -recurse MyClass -exclude java.javax. sun.</pre>
 * Print a recursive listing of dependency information for MyClass and its
 * dependents.  Do not analyze classes beginning with "java.", "javax.", or "sun."
 * </p>
 *
 *         <a href="mailto:twheeler@objectspace.com">Thomas Wheeler</A>
 * @version $Id$
 */
public class listclass {

    boolean code;
    boolean constants;
    boolean verbose;
    boolean classdep;
    boolean nocontents;
    boolean recurse;
    Map<String, String> listedClasses;
    List<String> exclude_name;

    public static void main(String[] argv) {
        List<String> file_name = new ArrayList<String>();
        List<String> exclude_name = new ArrayList<String>();
        boolean code = false;
        boolean constants = false;
        boolean verbose = true;
        boolean classdep = false;
        boolean nocontents = false;
        boolean recurse = false;
        boolean exclude = false;
        String name;

        // Parse command line arguments.
        for (String arg : argv) {
            if (arg.charAt(0) == '-') {  // command line switch
                if (arg.equals("-constants")) {
                    constants = true;
                } else if (arg.equals("-code")) {
                    code = true;
                } else if (arg.equals("-brief")) {
                    verbose = false;
                } else if (arg.equals("-dependencies")) {
                    classdep = true;
                } else if (arg.equals("-nocontents")) {
                    nocontents = true;
                } else if (arg.equals("-recurse")) {
                    recurse = true;
                } else if (arg.equals("-exclude")) {
                    exclude = true;
                } else if (arg.equals("-help")) {
                    System.out.println("Usage: java listclass [-constants] [-code] [-brief] " +
                            "[-dependencies] [-nocontents] [-recurse] class... " +
                            "[-exclude <list>]\n" +
                            "-constants       Print constants table (constant pool)\n" +
                            "-code            Dump byte code of methods\n" +
                            "-brief           Brief listing\n" +
                            "-dependencies    Show class dependencies\n" +
                            "-nocontents      Do not print field/method information\n" +
                            "-recurse         Recurse into dependent classes\n" +
                            "-exclude <list>  Do not list classes beginning with " +
                            "strings in <list>");
                    System.exit(0);
                } else {
                    System.err.println("Unknown switch " + arg + " ignored.");
                }
            } else { // add file name to list
                if (exclude) {
                    exclude_name.add(arg);
                } else {
                    file_name.add(arg);
                }
            }
        }

        if (file_name.size() == 0) {
            System.err.println("list: No input files specified");
        } else {
            listclass listClass = new listclass(code, constants, verbose, classdep,
                    nocontents, recurse, exclude_name);

            for (int i = 0; i < file_name.size(); i++) {
                name = file_name.get(i);

                listClass.list(name);
            }
        }
    }

    public listclass(boolean code, boolean constants, boolean verbose, boolean classdep,
                     boolean nocontents, boolean recurse, List<String> exclude_name) {
        this.code = code;
        this.constants = constants;
        this.verbose = verbose;
        this.classdep = classdep;
        this.nocontents = nocontents;
        this.recurse = recurse;
        this.listedClasses = new HashMap<String, String>();
        this.exclude_name = exclude_name;
    }

    /**
     * Print the given class on screen
     */
    public void list(String name) {
        try {
            JavaClass java_class;

            if ((listedClasses.get(name) != null) || name.startsWith("[")) {
                return;
            }

            for (int idx = 0; idx < exclude_name.size(); idx++) {
                if (name.startsWith(exclude_name.get(idx))) {
                    return;
                }
            }

            if (name.endsWith(".class")) {
                java_class = new ClassParser(name).parse(); // May throw IOException
            } else {
                java_class = Repository.lookupClass(name);
            }

            if (nocontents) {
                System.out.println(java_class.getClassName());
            } else {
                System.out.println(java_class);             // Dump the contents
            }

            if (constants) {
                System.out.println(java_class.getConstantPool());
            }

            if (code) {
                printCode(java_class.getMethods(), verbose);
            }

            if (classdep) {
                printClassDependencies(java_class.getConstantPool());
            }

            listedClasses.put(name, name);

            if (recurse) {
                String[] dependencies = getClassDependencies(java_class.getConstantPool());

                for (String dependency : dependencies) {
                    list(dependency);
                }
            }
        } catch (IOException e) {
            System.out.println("Error loading class " + name + " (" + e.getMessage() + ")");
        } catch (Exception e) {
            System.out.println("Error processing class " + name + " (" + e.getMessage() + ")");
        }
    }

    /**
     * Dump the list of classes this class is dependent on
     */
    public static void printClassDependencies(ConstantPool pool) {
        System.out.println("Dependencies:");
        for (String name : getClassDependencies(pool)) {
            System.out.println("\t" + name);
        }
    }

    public static String[] getClassDependencies(ConstantPool pool) {
        String[] tempArray = new String[pool.getLength()];
        int size = 0;
        StringBuilder buf = new StringBuilder();

        for (int idx = 0; idx < pool.getLength(); idx++) {
            Constant c = pool.getConstant(idx);
            if (c != null && c.getTag() == Constants.CONSTANT_Class) {
                ConstantUtf8 c1 = (ConstantUtf8) pool.getConstant(((ConstantClass) c).getNameIndex());
                buf.setLength(0);
                buf.append(c1.getBytes());
                for (int n = 0; n < buf.length(); n++) {
                    if (buf.charAt(n) == '/') {
                        buf.setCharAt(n, '.');
                    }
                }

                tempArray[size++] = buf.toString();
            }
        }

        String[] dependencies = new String[size];
        System.arraycopy(tempArray, 0, dependencies, 0, size);
        return dependencies;
    }

    /**
     * Dump the disassembled code of all methods in the class.
     */
    public static void printCode(Method[] methods, boolean verbose) {
        for (Method method : methods) {
            System.out.println(method);

            Code code = method.getCode();
            if (code != null) {
                System.out.println(code.toString(verbose));
            }
        }
    }
}
