/*
 * 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.myfaces.extensions.scripting.sandbox.loader.support;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;

/**
 *
 */
public abstract class AbstractThrowAwayClassLoader extends URLClassLoader
        implements ThrowAwayClassLoader {

    /**
     * The size of the buffer we're going to use to copy the contents from a stream to a byte array.
     */
    private static final int BUFFER_SIZE = 4096;

    /**
     * Indicates when this ClassLoader has been created.
     */
    private final long _timestamp;

    /**
     * The name of the class that this class loader is going to load.
     */
    private final String _className;

    // ------------------------------------------ Constructors

    public AbstractThrowAwayClassLoader(String className, ClassLoader parentClassLoader) {
        super(new URL[0], parentClassLoader);

        if (className == null) {
            throw new IllegalArgumentException("The given class name must not be null.");
        }

        // Save a timestamp of the time this class loader has been created. In doing
        // so, we're able to tell if this class loader is already outdated or not.
        this._timestamp = System.currentTimeMillis();
        this._className = className;
    }

    // ------------------------------------------ ThrowAwayClassLoader methods

    /**
     * <p>Loads the class with the specified class name. However, note that implementing
     * classes are just supposed to load a single class, so if you want to load a different
     * class than that, this class loader will just delegate to the parent class loader.</p>
     *
     * @param className the name of the class you want to load
     * @param resolve   if <tt>true</tt> then resolve the class
     * @return the resulting Class reference
     * @throws ClassNotFoundException if the class could not be found
     */
    public Class loadClass(String className, boolean resolve) throws ClassNotFoundException {
        Class c;

        // Note that this class loader is only supposed to load a specific Class reference,
        // hence the check against the class name. Otherwise this class loader would try to
        // resolve class files for dependent classes as well, which means that there would
        // be different versions of the same Class reference in the system.
        if (isEligibleForLoading(className)) {
            // First, check if the class has already been loaded
            c = findLoadedClass(className);
            if (c == null) {
                // Note that execution reaches this point only if we're either updating a
                // dynamically loaded class or loading it for the first time. Otherwise
                // this ClassLoader would have returned an already loaded class (see the
                // call to findLoadedClass()).
                c = findClass(className);
                if (resolve) {
                    resolveClass(c);
                }
            }
        }

        // If this class loader isn't supposed to load the given class it doesn't
        // necessarily mean, that we're not dealing with a dynamic class here.
        // However, if that's the case, we really want to use the same class loader
        // (i.e. the same ClassFileLoader instance) as Spring does, hence the
        // delegation to the parent class loader (i.e. the ReloadingClassLoader
        // again).
        else {
            c = super.loadClass(className, resolve);
        }

        return c;
    }

    /**
     * <p>Returns <code>true</code> if the given "last modified"-timestamp is
     * more recent than the time stamp of this class loader, i.e. if this class loader
     * is to be destroyed as there is a newer class file available.
     *
     * @param lastModified the "last modified"-timestamp of the class file you want to load
     * @return <code>true</code> if the given "last modified"-timestamp is
     *         more recent than the time stamp of this ClassLoader
     */
    public boolean isOutdated(long lastModified) {
        return _timestamp < lastModified;
    }

    // ------------------------------------------ Utility methods

    /**
     * <p>Determines whether this class loader is supposed to load the given class.</p>
     *
     * @param className the name of the class
     * @return <code>true</code>, if this class loader is supposed to load the
     *         given class, <code>false</code> otherwise
     */
    protected boolean isEligibleForLoading(String className) {
        return getClassName().equals(className);
    }

    /**
     * <p>Finds and loads the class with the specified name from the compilation path.</p>
     *
     * @param className the name of the class
     * @return the resulting class
     * @throws ClassNotFoundException if the class could not be found
     */
    protected Class findClass(final String className) throws ClassNotFoundException {
        if (isEligibleForLoading(className)) {
            try {
                return AccessController.doPrivileged(new PrivilegedExceptionAction<Class<?>>() {
                    public Class<?> run() throws Exception {
                        InputStream stream = null;

                        try {
                            // Load the raw bytes of the class file into the memory ..
                            stream = openStreamForClass(className);
                            if (stream != null) {
                                byte[] buffer = loadClassFromStream(stream);

                                // .. and create an according Class object.
                                return defineClass(className, buffer, 0, buffer.length);
                            } else {
                                throw new ClassNotFoundException(
                                        "Cannot find the resource that defines the class '" + className + "'.");
                            }
                        }
                        catch (IOException ex) {
                            throw new ClassNotFoundException(
                                    "Cannot load the raw byte contents for the class '" + className + "'.", ex);
                        }
                        finally {
                            if (stream != null) {
                                stream.close();
                            }
                        }
                    }
                });
            }
            catch (PrivilegedActionException e) {
                throw (ClassNotFoundException) e.getException();
            }
        } else {
            throw new ClassNotFoundException(
                    "This class loader only knows how to load the class '" + getClassName() + "'.");
        }
    }

    /**
     * <p>Returns the name of the class that this class loader is going to load.</p>
     *
     * @return the name of the class that this class loader is going to load
     */
    protected String getClassName() {
        return _className;
    }

    /**
     * <p>Loads the byte array that you can use to define the given class
     * afterwards using a call to {@link #defineClass}.</p>
     *
     * @param stream a stream referencing e.g. a .class file
     * @return the byte array that you can use to define the given class
     * @throws IOException if an I/O error occurs
     */
    private byte[] loadClassFromStream(InputStream stream) throws IOException {
        ByteArrayOutputStream result = new ByteArrayOutputStream(BUFFER_SIZE * 5);

        byte[] buffer = new byte[BUFFER_SIZE];

        int readBytes;
        while ((readBytes = stream.read(buffer)) != -1) {
            result.write(buffer, 0, readBytes);
        }

        return result.toByteArray();
    }

    // ------------------------------------------ Abstract methods

    /**
     * <p>Opens a stream to the resource that defines the given class. If it
     * cannot be found, return <code>null</code>.</p>
     *
     * @param className the class to load
     * @return a stream to the resource that defines the given class
     * @throws IOException if an I/O error occurs
     */
    protected abstract InputStream openStreamForClass(String className) throws IOException;

}
