/*
 * Copyright 2002-2007 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package com.sun.jmx.mbeanserver;


import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;

import javax.management.ObjectName;
import javax.management.loading.PrivateClassLoader;

/**
 * This class keeps the list of Class Loaders registered in the MBean Server.
 * It provides the necessary methods to load classes using the
 * registered Class Loaders.
 *
 * @since 1.5
 */
final class ClassLoaderRepositorySupport
    implements ModifiableClassLoaderRepository {

    /* We associate an optional ObjectName with each entry so that
       we can remove the correct entry when unregistering an MBean
       that is a ClassLoader.  The same object could be registered
       under two different names (even though this is not recommended)
       so if we did not do this we could disturb the defined
       semantics for the order of ClassLoaders in the repository.  */
    private static class LoaderEntry {
        ObjectName name; // can be null
        ClassLoader loader;

        LoaderEntry(ObjectName name,  ClassLoader loader) {
            this.name = name;
            this.loader = loader;
        }
    }

    private static final LoaderEntry[] EMPTY_LOADER_ARRAY = new LoaderEntry[0];

    /**
     * List of class loaders
     * Only read-only actions should be performed on this object.
     *
     * We do O(n) operations on this array, e.g. when removing
     * a ClassLoader.  The assumption is that the number of elements
     * is small, probably less than ten, and that the vast majority
     * of operations are searches (loadClass) which are by definition
     * linear.
     */
    private LoaderEntry[] loaders = EMPTY_LOADER_ARRAY;

    /**
     * Same behavior as add(Object o) in {@link java.util.List}.
     * Replace the loader list with a new one in which the new
     * loader has been added.
     **/
    private synchronized boolean add(ObjectName name, ClassLoader cl) {
        List<LoaderEntry> l =
            new ArrayList<LoaderEntry>(Arrays.asList(loaders));
        l.add(new LoaderEntry(name, cl));
        loaders = l.toArray(EMPTY_LOADER_ARRAY);
        return true;
    }

    /**
     * Same behavior as remove(Object o) in {@link java.util.List}.
     * Replace the loader list with a new one in which the old loader
     * has been removed.
     *
     * The ObjectName may be null, in which case the entry to
     * be removed must also have a null ObjectName and the ClassLoader
     * values must match.  If the ObjectName is not null, then
     * the first entry with a matching ObjectName is removed,
     * regardless of whether ClassLoader values match.  (In fact,
     * the ClassLoader parameter will usually be null in this case.)
     **/
    private synchronized boolean remove(ObjectName name, ClassLoader cl) {
        final int size = loaders.length;
        for (int i = 0; i < size; i++) {
            LoaderEntry entry = loaders[i];
            boolean match =
                (name == null) ?
                cl == entry.loader :
                name.equals(entry.name);
            if (match) {
                LoaderEntry[] newloaders = new LoaderEntry[size - 1];
                System.arraycopy(loaders, 0, newloaders, 0, i);
                System.arraycopy(loaders, i + 1, newloaders, i,
                                 size - 1 - i);
                loaders = newloaders;
                return true;
            }
        }
        return false;
    }


    /**
     * List of valid search
     */
    private final Map<String,List<ClassLoader>> search =
        new Hashtable<String,List<ClassLoader>>(10);

    /**
     * List of named class loaders.
     */
    private final Map<ObjectName,ClassLoader> loadersWithNames =
        new Hashtable<ObjectName,ClassLoader>(10);

    // from javax.management.loading.DefaultLoaderRepository
    public final Class loadClass(String className)
        throws ClassNotFoundException {
        return  loadClass(loaders, className, null, null);
    }


    // from javax.management.loading.DefaultLoaderRepository
    public final Class loadClassWithout(ClassLoader without, String className)
            throws ClassNotFoundException {
        if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
            MBEANSERVER_LOGGER.logp(Level.FINER,
                    ClassLoaderRepositorySupport.class.getName(),
                    "loadClassWithout", className + " without " + without);
        }

        // without is null => just behave as loadClass
        //
        if (without == null)
            return loadClass(loaders, className, null, null);

        // We must try to load the class without the given loader.
        //
        startValidSearch(without, className);
        try {
            return loadClass(loaders, className, without, null);
        } finally {
            stopValidSearch(without, className);
        }
    }


    public final Class loadClassBefore(ClassLoader stop, String className)
            throws ClassNotFoundException {
        if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
            MBEANSERVER_LOGGER.logp(Level.FINER,
                    ClassLoaderRepositorySupport.class.getName(),
                    "loadClassBefore", className + " before " + stop);
        }

        if (stop == null)
            return loadClass(loaders, className, null, null);

        startValidSearch(stop, className);
        try {
            return loadClass(loaders, className, null, stop);
        } finally {
            stopValidSearch(stop, className);
        }
    }


    private Class loadClass(final LoaderEntry list[],
                            final String className,
                            final ClassLoader without,
                            final ClassLoader stop)
            throws ClassNotFoundException {
        final int size = list.length;
        for(int i=0; i<size; i++) {
            try {
                final ClassLoader cl = list[i].loader;
                if (cl == null) // bootstrap class loader
                    return Class.forName(className, false, null);
                if (cl == without)
                    continue;
                if (cl == stop)
                    break;
                if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
                    MBEANSERVER_LOGGER.logp(Level.FINER,
                            ClassLoaderRepositorySupport.class.getName(),
                            "loadClass", "Trying loader = " + cl);
                }
                /* We used to have a special case for "instanceof
                   MLet" here, where we invoked the method
                   loadClass(className, null) to prevent infinite
                   recursion.  But the rule whereby the MLet only
                   consults loaders that precede it in the CLR (via
                   loadClassBefore) means that the recursion can't
                   happen, and the test here caused some legitimate
                   classloading to fail.  For example, if you have
                   dependencies C->D->E with loaders {E D C} in the
                   CLR in that order, you would expect to be able to
                   load C.  The problem is that while resolving D, CLR
                   delegation is disabled, so it can't find E.  */
                return Class.forName(className, false, cl);
            } catch (ClassNotFoundException e) {
                // OK: continue with next class
            }
        }

        throw new ClassNotFoundException(className);
    }

    private synchronized void startValidSearch(ClassLoader aloader,
                                               String className)
        throws ClassNotFoundException {
        // Check if we have such a current search
        //
        List<ClassLoader> excluded = search.get(className);
        if ((excluded!= null) && (excluded.contains(aloader))) {
            if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
                MBEANSERVER_LOGGER.logp(Level.FINER,
                        ClassLoaderRepositorySupport.class.getName(),
                        "startValidSearch", "Already requested loader = " +
                        aloader + " class = " + className);
            }
            throw new ClassNotFoundException(className);
        }

        // Add an entry
        //
        if (excluded == null) {
            excluded = new ArrayList<ClassLoader>(1);
            search.put(className, excluded);
        }
        excluded.add(aloader);
        if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
            MBEANSERVER_LOGGER.logp(Level.FINER,
                    ClassLoaderRepositorySupport.class.getName(),
                    "startValidSearch",
                    "loader = " + aloader + " class = " + className);
        }
    }

    private synchronized void stopValidSearch(ClassLoader aloader,
                                              String className) {

        // Retrieve the search.
        //
        List<ClassLoader> excluded = search.get(className);
        if (excluded != null) {
            excluded.remove(aloader);
            if (MBEANSERVER_LOGGER.isLoggable(Level.FINER)) {
                MBEANSERVER_LOGGER.logp(Level.FINER,
                        ClassLoaderRepositorySupport.class.getName(),
                        "stopValidSearch",
                        "loader = " + aloader + " class = " + className);
            }
        }
    }

    public final void addClassLoader(ClassLoader loader) {
        add(null, loader);
    }

    public final void removeClassLoader(ClassLoader loader) {
        remove(null, loader);
    }

    public final synchronized void addClassLoader(ObjectName name,
                                                  ClassLoader loader) {
        loadersWithNames.put(name, loader);
        if (!(loader instanceof PrivateClassLoader))
            add(name, loader);
    }

    public final synchronized void removeClassLoader(ObjectName name) {
        ClassLoader loader = loadersWithNames.remove(name);
        if (!(loader instanceof PrivateClassLoader))
            remove(name, loader);
    }

    public final ClassLoader getClassLoader(ObjectName name) {
        return loadersWithNames.get(name);
    }

}
