/*
 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 *
 */

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
import java.util.Set;
import java.util.Vector;
import jdk.internal.org.objectweb.asm.*;
// Compile with -XDignore.symbol.file=true

public class BogoLoader extends ClassLoader {

    static interface VisitorMaker {
    ClassVisitor make(ClassVisitor visitor);
    }


    /**
     * Use this property to verify that the desired classloading is happening.
     */
    private final boolean verbose = Boolean.getBoolean("bogoloader.verbose");
    /**
     * Use this property to disable replacement for testing purposes.
     */
    private final boolean noReplace = Boolean.getBoolean("bogoloader.noreplace");

    /**
     * Set of class names that should be loaded with this loader.
     * Others are loaded with the system class loader, except for those
     * that are transformed.
     */
    private Set<String> nonSystem;

    /**
     * Map from class names to a bytecode transformer factory.
     */
    private Map<String, VisitorMaker> replaced;

    /**
     * Keep track (not terribly efficiently) of which classes have already
     * been loaded by this class loader.
     */
    private final Vector<String> history = new Vector<String>();

    private boolean useSystemLoader(String name) {
        return ! nonSystem.contains(name) && ! replaced.containsKey(name);
    }

    public BogoLoader(Set<String> non_system, Map<String, VisitorMaker> replaced) {
        super(Thread.currentThread().getContextClassLoader());
        this.nonSystem = non_system;
        this.replaced = replaced;
    }

    private byte[] readResource(String className) throws IOException {
        return readResource(className, "class");
    }

    private byte[] readResource(String className, String suffix) throws IOException {
        // Note to the unwary -- "/" works on Windows, leave it alone.
        String fileName = className.replace('.', '/') + "." + suffix;
        InputStream origStream = getResourceAsStream(fileName);
        if (origStream == null) {
            throw new IOException("Resource not found : " + fileName);
        }
        BufferedInputStream stream = new java.io.BufferedInputStream(origStream);
        byte[] data = new byte[stream.available()];
        int how_many = stream.read(data);
        // Really ought to deal with the corner cases of stream.available()
        return data;
    }

    protected byte[] getClass(String name) throws ClassNotFoundException,
    IOException {
        return readResource(name, "class");
    }

    /**
     * Loads the named class from the system class loader unless
     * the name appears in either replaced or nonSystem.
     * nonSystem classes are loaded into this classloader,
     * and replaced classes get their content from the specified array
     * of bytes (and are also loaded into this classloader).
     */
    protected Class<?> loadClass(String name, boolean resolve)
            throws ClassNotFoundException {
        Class<?> clazz;

        if (history.contains(name)) {
            Class<?> c = this.findLoadedClass(name);
            return c;
        }
        if (useSystemLoader(name)) {
            clazz = findSystemClass(name);
            if (verbose) System.err.println("Loading system class " + name);
        } else {
            history.add(name);
            try {
                if (verbose) {
                    System.err.println("Loading classloader class " + name);
                }
                byte[] classData = getClass(name);;
                boolean expanded = false;
                if (!noReplace && replaced.containsKey(name)) {
                    if (verbose) {
                        System.err.println("Replacing class " + name);
                    }
                    ClassReader cr = new ClassReader(classData);
                    ClassWriter cw = new ClassWriter(0);
                    VisitorMaker vm = replaced.get(name);
                    cr.accept(vm.make(cw), 0);
                    classData = cw.toByteArray();
                }
                clazz = defineClass(name, classData, 0, classData.length);
            } catch (java.io.EOFException ioe) {
                throw new ClassNotFoundException(
                        "IO Exception in reading class : " + name + " ", ioe);
            } catch (ClassFormatError ioe) {
                throw new ClassNotFoundException(
                        "ClassFormatError in reading class file: ", ioe);
            } catch (IOException ioe) {
                throw new ClassNotFoundException(
                        "IO Exception in reading class file: ", ioe);
            }
        }
        if (clazz == null) {
            throw new ClassNotFoundException(name);
        }
        if (resolve) {
            resolveClass(clazz);
        }
        return clazz;
    }
}
