/*
 * 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.sling.jcr.classloader.internal;

import java.io.IOException;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedExceptionAction;
import java.security.SecureClassLoader;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Set;

import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;

import org.apache.sling.commons.classloader.DynamicClassLoader;
import org.apache.sling.jcr.classloader.internal.net.URLFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


/**
 * The <code>RepositoryClassLoader</code> class provides the
 * functionality to load classes and resources from the JCR Repository.
 * Additionally, this class supports the notion of getting 'dirty', which means,
 * that if a resource loaded through this class loader has been modified in the
 * repository, this class loader marks itself dirty, which flag can get
 * retrieved.
 */
public final class RepositoryClassLoader
    extends SecureClassLoader
    implements DynamicClassLoader {

    /** Logger */
    private final Logger logger = LoggerFactory.getLogger(this.getClass().getName());

    /** Set of loaded resources and classes. */
    private final Set<String> usedResources = new HashSet<String>();

    /**
     * Flag indicating whether there are loaded classes which have later been
     * expired (e.g. invalidated or modified)
     */
    private boolean dirty = false;

    /**
     * The path to use as a classpath.
     */
    private String repositoryPath;

    /**
     * The <code>Session</code> grants access to the Repository to access the
     * resources.
     * <p>
     * This field is not final such that it may be cleared when the class loader
     * is destroyed.
     */
    private Session session;

    /**
     * Flag indicating whether the {@link #destroy()} method has already been
     * called (<code>true</code>) or not (<code>false</code>)
     */
    private boolean destroyed = false;

    /**
     * Creates a <code>DynamicRepositoryClassLoader</code> from a list of item
     * path strings containing globbing pattens for the paths defining the
     * class path.
     *
     * @param session The <code>Session</code> to use to access the class items.
     * @param classPath The list of path strings making up the (initial) class
     *      path of this class loader. The strings may contain globbing
     *      characters which will be resolved to build the actual class path.
     * @param parent The parent <code>ClassLoader</code>, which may be
     *      <code>null</code>.
     *
     * @throws NullPointerException if either the session or the classPath
     *      is <code>null</code>.
     */
    public RepositoryClassLoader(final Session session,
                                 final String classPath,
                                 final ClassLoader parent) {
        // initialize the super class with an empty class path
        super(parent);

        // check session and handles
        if (session == null) {
            throw new NullPointerException("session");
        }
        if (classPath == null) {
            throw new NullPointerException("classPath");
        }

        // set fields
        this.session = session;
        this.repositoryPath = classPath;

        logger.debug("RepositoryClassLoader: {} ready", this);
    }

    /**
     * Destroys this class loader. This process encompasses all steps needed
     * to remove as much references to this class loader as possible.
     * <p>
     * <em>NOTE</em>: This method just clears all internal fields and especially
     * the class path to render this class loader unusable.
     * <p>
     * This implementation does not throw any exceptions.
     */
    public void destroy() {
        // we expect to be called only once, so we stop destroyal here
        if (destroyed) {
            logger.debug("Instance is already destroyed");
            return;
        }

        // set destroyal guard
        destroyed = true;

        // close session
        if ( session != null ) {
            session.logout();
            session = null;
        }
        repositoryPath = null;
        synchronized ( this.usedResources ) {
            this.usedResources.clear();
        }
    }

    /**
     * Finds and loads the class with the specified name from the class path.
     *
     * @param name the name of the class
     * @return the resulting class
     *
     * @throws ClassNotFoundException If the named class could not be found or
     *      if this class loader has already been destroyed.
     */
    protected Class<?> findClass(final String name) throws ClassNotFoundException {
        if (destroyed) {
            throw new ClassNotFoundException(name + " (Classloader destroyed)");
        }

        logger.debug("findClass: Try to find class {}", name);

        try {
            return AccessController.doPrivileged(
                new PrivilegedExceptionAction<Class<?>>() {

                    public Class<?> run() throws ClassNotFoundException {
                        return findClassPrivileged(name);
                    }
                });
        } catch (java.security.PrivilegedActionException pae) {
            throw (ClassNotFoundException) pae.getException();
        }
    }

    /**
     * Finds the resource with the specified name on the search path.
     *
     * @param name the name of the resource
     *
     * @return a <code>URL</code> for the resource, or <code>null</code>
     *      if the resource could not be found or if the class loader has
     *      already been destroyed.
     */
    public URL findResource(final String name) {
        if (destroyed) {
            logger.warn("Destroyed class loader cannot find a resource");
            return null;
        }

        logger.debug("findResource: Try to find resource {}", name);

        final String path = this.repositoryPath + '/' + name;
        final Node res = findClassLoaderResource(path);
        if (res != null) {
            logger.debug("findResource: Getting resource from {}",
                res);
            try {
                return URLFactory.createURL(session, res.getPath());
            } catch (Exception e) {
                logger.warn("findResource: Cannot getURL for " + name, e);
            }
        }

        return null;
    }

    /**
     * Returns an Enumeration of URLs representing all of the resources
     * on the search path having the specified name.
     *
     * @param name the resource name
     *
     * @return an <code>Enumeration</code> of <code>URL</code>s. This is an
     *      empty enumeration if no resources are found by this class loader
     *      or if this class loader has already been destroyed.
     */
    public Enumeration<URL> findResources(final String name) {
        if (destroyed) {
            logger.warn("Destroyed class loader cannot find resources");
            return new Enumeration<URL>() {
                public boolean hasMoreElements() {
                    return false;
                }
                public URL nextElement() {
                    throw new NoSuchElementException("No Entries");
                }
            };
        }

        logger.debug("findResources: Try to find resources for {}", name);

        final URL url = this.findResource(name);
        final List<URL> list = new LinkedList<URL>();
        if (url != null) {
            list.add(url);
        }

        // return the enumeration on the list
        return Collections.enumeration(list);
    }

    /**
     * Tries to find the class in the class path from within a
     * <code>PrivilegedAction</code>. Throws <code>ClassNotFoundException</code>
     * if no class can be found for the name.
     *
     * @param name the name of the class
     *
     * @return the resulting class
     *
     * @throws ClassNotFoundException if the class could not be found
     * @throws NullPointerException If this class loader has already been
     *      destroyed.
     */
    private Class<?> findClassPrivileged(final String name) throws ClassNotFoundException {

        // prepare the name of the class
        logger.debug("findClassPrivileged: Try to find path {class {}",
            name);

        final String path = this.repositoryPath + '/' + name.replace('.', '/') + (".class");
        final Node res = this.findClassLoaderResource(path);
        if (res != null) {

             // try defining the class, error aborts
             try {
                 logger.debug(
                    "findClassPrivileged: Loading class from {}", res);

                 final Class<?> c = defineClass(name, res);
                 if (c == null) {
                     logger.warn("defineClass returned null for class {}", name);
                     throw new ClassNotFoundException(name);
                 }
                 return c;

             } catch (final IOException ioe) {
                 logger.debug("defineClass failed", ioe);
                 throw new ClassNotFoundException(name, ioe);
             } catch (final Throwable t) {
                 logger.debug("defineClass failed", t);
                 throw new ClassNotFoundException(name, t);
             }
         }

        throw new ClassNotFoundException(name);
     }

    /**
     * Returns a {@link ClassLoaderResource} for the given <code>name</code> or
     * <code>null</code> if not existing. If the resource has already been
     * loaded earlier, the cached instance is returned. If the resource has
     * not been found in an earlier call to this method, <code>null</code> is
     * returned. Otherwise the resource is looked up in the class path. If
     * found, the resource is cached and returned. If not found, the
     * {@link #NOT_FOUND_RESOURCE} is cached for the name and <code>null</code>
     * is returned.
     *
     * @param name The name of the resource to return.
     *
     * @return The named <code>ClassLoaderResource</code> if found or
     *      <code>null</code> if not found.
     *
     * @throws NullPointerException If this class loader has already been
     *      destroyed.
     */
    private Node findClassLoaderResource(final String path) {
        Node res = null;
        try {
            if ( session.itemExists(path) ) {
                final Node node = (Node)session.getItem(path);
                logger.debug("Found resource at {}", path);
                res = node;
            } else {
                logger.debug("No classpath entry contains {}", path);
            }
        } catch (final RepositoryException re) {
            logger.debug("Error while trying to get node at " + path, re);
        }
        synchronized ( this.usedResources ) {
            this.usedResources.add(path);
        }
        return res;
    }

    /**
     * Defines a class getting the bytes for the class from the resource
     *
     * @param name The fully qualified class name
     * @param res The resource to obtain the class bytes from
     *
     * @throws RepositoryException If a problem occurrs getting at the data.
     * @throws IOException If a problem occurrs reading the class bytes from
     *      the resource.
     * @throws ClassFormatError If the class bytes read from the resource are
     *      not a valid class.
     */
    private Class<?> defineClass(final String name, final Node res)
    throws IOException, RepositoryException {
        logger.debug("defineClass({}, {})", name, res);

        final byte[] data = Util.getBytes(res);
        final Class<?> clazz = defineClass(name, data, 0, data.length);

        return clazz;
    }

    /**
     * Returns whether the class loader is dirty. This can be the case if any
     * of the loaded class has been expired through the observation.
     * <p>
     * This method may also return <code>true</code> if the <code>Session</code>
     * associated with this class loader is not valid anymore.
     * <p>
     * Finally the method always returns <code>true</code> if the class loader
     * has already been destroyed.
     * <p>
     *
     * @return <code>true</code> if the class loader is dirty and needs
     *      recreation.
     */
    public boolean isDirty() {
        return destroyed || dirty || !session.isLive();
    }

    /**
     * @see org.apache.sling.commons.classloader.DynamicClassLoader#isLive()
     */
    public boolean isLive() {
        return !this.isDirty();
    }

    /**
     * Handle a modification event.
     */
    public void handleEvent(final String path) {
        synchronized ( this.usedResources ) {
            if ( this.usedResources.contains(path) ) {
                logger.debug("handleEvent: Item {} has been modified - marking class loader as dirty {}", this);
                this.dirty = true;
            }
        }

    }
    //----------- Object overwrite ---------------------------------------------

    /**
     * Returns a string representation of this class loader.
     */
    public String toString() {
        StringBuilder buf = new StringBuilder(getClass().getName());
        if (destroyed) {
            buf.append(" - destroyed");
        } else {
            buf.append(": parent: { ");
            buf.append(getParent());
            buf.append(" }, user: ");
            buf.append(session.getUserID());
            buf.append(", dirty: ");
            buf.append(isDirty());
        }
        return buf.toString();
    }
}
