/*
* JBoss, Home of Professional Open Source
* Copyright 2006, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software 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
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.classloading.spi;

import java.net.URL;

/**
 * DelegatingClassLoader.
 * 
 * @author <a href="adrian@jboss.com">Adrian Brock</a>
 * @author anil.saldhana@redhat.com
 * @version $Revision: 1.1 $
 */
public class DelegatingClassLoader extends ClassLoader
{
   /** The parent classloader */
   private RealClassLoader parent;

   /** Whether to use standard loading */
   protected boolean standard = false;

   /**
    * Check the parent really is a classloader
    * 
    * @param parent the parent
    * @return the classloader
    */
   private static ClassLoader checkParent(RealClassLoader parent)
   {
      if (parent == null)
         throw new IllegalArgumentException("Null parent");
      if (parent instanceof ClassLoader == false)
         throw new IllegalArgumentException("Parent is not a classloader");
      
      return ClassLoader.class.cast(parent);
   }
   
   /**
    * Create a new DelegatingClassLoader.
    * 
    * @param parent the parent
    */
   public DelegatingClassLoader(RealClassLoader parent)
   {
      super(checkParent(parent));
      this.parent = parent;
   }

   protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException
   {
      // First see if we already know it
      Class<?> clazz = findLoadedClass(name);

      // Next see if it is cached at a more global level
      if (clazz == null)
         clazz = parent.getCachedClass(name);

      // Not cached
      if (clazz == null)
      {
         // Standard loading looks at the bootstrap classloader
         if  (standard)
            clazz = super.loadClass(name, resolve);
         // We should really let the parent decide to do that
         else
         {  
            if(System.getSecurityManager() == null)
               clazz = getParent().loadClass(name);
            else
            {
               clazz = SecurityActions.getParentClassLoader(this).loadClass(name); 
            }
         }        
      }
      
      // Do we need to resolve the class?
      if (resolve)
         resolveClass(clazz);
      return clazz;
   }

   public URL getResource(String name)
   {
      // See if it is cached at a global level
      URL resource = parent.getCachedResource(name);

      // Not cached
      if (resource == null)
      {
         // Standard loading looks at the bootstrap classloader
         if  (standard)
            resource = super.getResource(name);
         // We should really let the parent decide to do that
         else
         { 
            if(System.getSecurityManager() == null)
              resource = getParent().getResource(name);
            else
              resource = SecurityActions.getParentClassLoader(this).getResource(name);
         }
      }
      return resource; 
   } 
}
