/*
 * Copyright (C) 2016 The Android Open Source Project
 *
 * 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.
 */

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;

/**
 * A class loader with atypical behavior: we try to load a private
 * class implementation before asking the system or boot loader.  This
 * is used to create multiple classes with identical names in a single VM.
 *
 * If DexFile is available, we use that; if not, we assume we're not in
 * Dalvik and instantiate the class with defineClass().
 *
 * The location of the DEX files and class data is dependent upon the
 * test framework.
 */
public class DefiningLoader extends ClassLoader {
    static {
        // For JVM, register as parallel capable.
        // Android treats all class loaders as parallel capable and makes this a no-op.
        registerAsParallelCapable();
    }

    /* this is where the .class files live */
    static final String CLASS_PATH1 = "classes/";
    static final String CLASS_PATH2 = "classes2/";

    /* this is the DEX/Jar file */
    static final String DEX_FILE = System.getenv("DEX_LOCATION") + "/626-const-class-linking.jar";

    /* on Dalvik, this is a DexFile; otherwise, it's null */
    private Class<?> mDexClass;

    private Object mDexFile;

    /**
     * Construct DefiningLoader, grabbing a reference to the DexFile class
     * if we're running under Dalvik.
     */
    public DefiningLoader(ClassLoader parent) {
        super(parent);

        try {
            mDexClass = parent.loadClass("dalvik.system.DexFile");
        } catch (ClassNotFoundException cnfe) {
            // ignore -- not running Dalvik
        }
    }

    /**
     * Finds the class with the specified binary name.
     *
     * We search for a file in CLASS_PATH or pull an entry from DEX_FILE.
     * If we don't find a match, we throw an exception.
     */
    protected Class<?> findClass(String name) throws ClassNotFoundException
    {
        if (mDexClass != null) {
            return findClassDalvik(name);
        } else {
            return findClassNonDalvik(name);
        }
    }

    /**
     * Finds the class with the specified binary name, from a DEX file.
     */
    private Class<?> findClassDalvik(String name)
        throws ClassNotFoundException {

        if (mDexFile == null) {
            synchronized (DefiningLoader.class) {
                Constructor<?> ctor;
                /*
                 * Construct a DexFile object through reflection.
                 */
                try {
                    ctor = mDexClass.getConstructor(String.class);
                } catch (NoSuchMethodException nsme) {
                    throw new ClassNotFoundException("getConstructor failed",
                        nsme);
                }

                try {
                    mDexFile = ctor.newInstance(DEX_FILE);
                } catch (InstantiationException ie) {
                    throw new ClassNotFoundException("newInstance failed", ie);
                } catch (IllegalAccessException iae) {
                    throw new ClassNotFoundException("newInstance failed", iae);
                } catch (InvocationTargetException ite) {
                    throw new ClassNotFoundException("newInstance failed", ite);
                }
            }
        }

        /*
         * Call DexFile.loadClass(String, ClassLoader).
         */
        Method meth;

        try {
            meth = mDexClass.getMethod("loadClass", String.class, ClassLoader.class);
        } catch (NoSuchMethodException nsme) {
            throw new ClassNotFoundException("getMethod failed", nsme);
        }

        try {
            meth.invoke(mDexFile, name, this);
        } catch (IllegalAccessException iae) {
            throw new ClassNotFoundException("loadClass failed", iae);
        } catch (InvocationTargetException ite) {
            throw new ClassNotFoundException("loadClass failed",
                ite.getCause());
        }

        return null;
    }

    /**
     * Finds the class with the specified binary name, from .class files.
     */
    private Class<?> findClassNonDalvik(String name)
        throws ClassNotFoundException {

        String[] pathNames = { CLASS_PATH1 + name + ".class", CLASS_PATH2 + name + ".class" };

        String pathName = null;
        RandomAccessFile raf = null;

        for (String pn : pathNames) {
            pathName = pn;
            try {
                //System.out.println("--- Defining: looking for " + pathName);
                raf = new RandomAccessFile(new File(pathName), "r");
                break;
            } catch (FileNotFoundException fnfe) {
            }
        }
        if (raf == null) {
            throw new ClassNotFoundException("Not found: " + pathNames[0] + ":" + pathNames[1]);
        }

        /* read the entire file in */
        byte[] fileData;
        try {
            fileData = new byte[(int) raf.length()];
            raf.readFully(fileData);
        } catch (IOException ioe) {
            throw new ClassNotFoundException("Read error: " + pathName);
        } finally {
            try {
                raf.close();
            } catch (IOException ioe) {
                // drop
            }
        }

        /* create the class */
        //System.out.println("--- Defining: defining " + name);
        try {
            return defineClass(name, fileData, 0, fileData.length);
        } catch (Throwable th) {
            throw new ClassNotFoundException("defineClass failed", th);
        }
    }

    /**
     * Load a class.
     *
     * Normally a class loader wouldn't override this, but we want our
     * version of the class to take precedence over an already-loaded
     * version.
     *
     * We still want the system classes (e.g. java.lang.Object) from the
     * bootstrap class loader.
     */
    synchronized protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        Class<?> res;

        /*
         * 1. Invoke findLoadedClass(String) to check if the class has
         * already been loaded.
         *
         * This doesn't change.
         */
        res = findLoadedClass(name);
        if (res != null) {
            // System.out.println("FancyLoader.loadClass: " + name + " already loaded");
            if (resolve)
                resolveClass(res);
            return res;
        }

        /*
         * 3. Invoke the findClass(String) method to find the class.
         */
        try {
            res = findClass(name);
            if (resolve)
                resolveClass(res);
        }
        catch (ClassNotFoundException e) {
            // we couldn't find it, so eat the exception and keep going
        }

        /*
         * 2. Invoke the loadClass method on the parent class loader.  If
         * the parent loader is null the class loader built-in to the
         * virtual machine is used, instead.
         *
         * (Since we're not in java.lang, we can't actually invoke the
         * parent's loadClass() method, but we passed our parent to the
         * super-class which can take care of it for us.)
         */
        res = super.loadClass(name, resolve);   // returns class or throws
        return res;
    }
}
