/* DefaultLoaderRepository.java -- Manages class loaders for the servers.
   Copyright (C) 2007 Free Software Foundation, Inc.

This file is part of GNU Classpath.

GNU Classpath is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.

GNU Classpath 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 for more details.

You should have received a copy of the GNU General Public License
along with GNU Classpath; see the file COPYING.  If not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA.

Linking this library statically or dynamically with other modules is
making a combined work based on this library.  Thus, the terms and
conditions of the GNU General Public License cover the whole
combination.

As a special exception, the copyright holders of this library give you
permission to link this library with independent modules to produce an
executable, regardless of the license terms of these independent
modules, and to copy and distribute the resulting executable under
terms of your choice, provided that you also meet, for each linked
independent module, the terms and conditions of the license of that
module.  An independent module is a module which is not derived from
or based on this library.  If you modify this library, you may extend
this exception to your version of the library, but you are not
obligated to do so.  If you do not wish to do so, delete this
exception statement from your version. */

package javax.management;

import java.util.List;

/**
 * Maintains a list of the {@link ClassLoader} instances
 * registered with the management servers, allowing it
 * to be used to load classes.  In early versions of the
 * JMX API, this class represented a shared repository for
 * the classloaders of all management servers.  The management
 * of classloaders is now decentralised and this class is
 * deprecated.  The old behaviour is emulated by consulting
 * the {@link MBeanServer#getClassLoaderRepository()} method
 * of all the servers obtained from
 * {@link MBeanServerFactory#findMBeanServer(String)}.  Use of
 * this class should be avoided in new code.
 *
 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 * @since 1.5
 * @deprecated Use {@link MBeanServer#getClassLoaderRepository()}
 *             instead.
 */
@Deprecated public class DefaultLoaderRepository
{

  /**
   * Attempts to load the given class using class loaders
   * supplied by the repository of each {@link MBeanServer}.
   * The {@link ClassLoader#loadClass(String)}
   * method of each class loader is called.  If the method
   * returns successfully, then the returned {@link Class} instance
   * is returned.  If a {@link ClassNotFoundException} is thrown,
   * then the next loader is tried.  Any other exception thrown
   * by the method is passed back to the caller.  This method
   * throws a {@link ClassNotFoundException} itself if all the
   * class loaders listed prove fruitless.
   *
   * @param name the name of the class to load.
   * @return the loaded class.
   * @throws ClassNotFoundException if all the class loaders fail
   *                                to load the class.
   */
  // API issue with lack of <?> on Class
  @SuppressWarnings("unchecked")
  public static Class loadClass(String name)
    throws ClassNotFoundException
  {
    List<MBeanServer> servers = MBeanServerFactory.findMBeanServer(null);
    for (MBeanServer server : servers)
      {
	try
	  {
	    return server.getClassLoaderRepository().loadClass(name);
	  }
	catch (ClassNotFoundException e)
	  {
	    /* Ignored; try the next server. */
	  }
      }
    throw new ClassNotFoundException("The class loaders of all registered " +
				     "servers failed to load the class, " +
				     name);
  }

  /**
   * <p>
   * Attempts to load the given class using class loaders
   * supplied by the repository of each {@link MBeanServer}.
   * The {@link ClassLoader#loadClass(String)}
   * method of each class loader is called.  If the method
   * returns successfully, then the returned {@link Class} instance
   * is returned.  If a {@link ClassNotFoundException} is thrown,
   * then the next loader is tried.  Any other exception thrown
   * by the method is passed back to the caller.  This method
   * throws a {@link ClassNotFoundException} itself if all the
   * class loaders listed prove fruitless.
   * </p>
   * <p>
   * Note that this method may deadlock if called simultaneously
   * by two class loaders in the list.
   * {@link loadClassBefore(ClassLoader, String)} should be used
   * in preference to this method to avoid this.
   * </p>
   *
   * @param exclude the class loader to exclude, or <code>null</code>
   *             to obtain the same behaviour as {@link #loadClass(String)}.
   * @param name the name of the class to load.
   * @return the loaded class.
   * @throws ClassNotFoundException if all the class loaders fail
   *                                to load the class.
   */
  // API issue with lack of <?> on Class
  @SuppressWarnings("unchecked")
  public static Class loadClassWithout(ClassLoader exclude, String name)
    throws ClassNotFoundException
  {
    List<MBeanServer> servers = MBeanServerFactory.findMBeanServer(null);
    for (MBeanServer server : servers)
      {
	try
	  {
	    return server.getClassLoaderRepository().loadClassWithout(exclude,
								      name);
	  }
	catch (ClassNotFoundException e)
	  {
	    /* Ignored; try the next server. */
	  }
      }
    throw new ClassNotFoundException("The class loaders of all registered " +
				     "servers failed to load the class, " +
				     name);
  }

}
