package org.jboss.forge.furnace.util;

import java.util.concurrent.Callable;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.jboss.forge.furnace.exception.ContainerException;

/**
 * Utility class for executing fragments of code within a specific {@link Thread#getContextClassLoader()}
 * 
 * @author <a href="mailto:lincolnbaxter@gmail.com">Lincoln Baxter, III</a>
 */
public class ClassLoaders
{
   private static Logger log = Logger.getLogger(ClassLoaders.class.getName());

   /**
    * Execute the given {@link Callable} in the {@link ClassLoader} provided. Return the result, if any.
    */
   public static <T> T executeIn(ClassLoader loader, Callable<T> task) throws Exception
   {
      if (task == null)
         return null;

      if (log.isLoggable(Level.FINE))
      {
         log.fine("ClassLoader [" + loader + "] task began.");
      }
      ClassLoader original = SecurityActions.getContextClassLoader();
      try
      {
         SecurityActions.setContextClassLoader(loader);
         return task.call();
      }
      finally
      {
         SecurityActions.setContextClassLoader(original);
         if (log.isLoggable(Level.FINE))
         {
            log.fine("ClassLoader [" + loader + "] task ended.");
         }
      }
   }

   public static boolean containsClass(ClassLoader loader, Class<?> type)
   {
      if (loader == null)
         throw new IllegalArgumentException("Class loader to inspect must not be null.");
      if (type == null)
         throw new IllegalArgumentException("Class to find must not be null.");

      try
      {
         return loader.loadClass(type.getName()) == type;
      }
      catch (ClassNotFoundException e)
      {
         return false;
      }
   }

   public static boolean containsClass(ClassLoader loader, String type)
   {
      if (loader == null)
         throw new IllegalArgumentException("Class loader to inspect must not be null.");
      if (type == null)
         throw new IllegalArgumentException("Class to find must not be null.");

      try
      {
         loader.loadClass(type);
         return true;
      }
      catch (ClassNotFoundException e)
      {
         return false;
      }
   }

   public static Class<?> loadClass(ClassLoader loader, String typeName)
   {
      if (loader == null)
         throw new IllegalArgumentException("Class loader to inspect must not be null.");
      if (typeName == null)
         throw new IllegalArgumentException("Class name to find must not be null.");

      try
      {
         return loader.loadClass(typeName);
      }
      catch (ClassNotFoundException e)
      {
         throw new ContainerException("Could not locate class [" + typeName + "] in Loader [" + loader + "]", e);
      }
   }

   public static Class<?> loadClass(ClassLoader loader, Class<?> type)
   {
      if (loader == null)
         throw new IllegalArgumentException("Class loader to inspect must not be null.");
      if (type == null)
         throw new IllegalArgumentException("Class to find must not be null.");

      try
      {
         return loader.loadClass(type.getName());
      }
      catch (ClassNotFoundException e)
      {
         throw new ContainerException("Could not locate class [" + type.getName() + "] in Loader [" + loader + "]", e);
      }
   }

   public static boolean ownsClass(ClassLoader loader, Class<?> type)
   {
      if (loader == null)
         throw new IllegalArgumentException("Class loader to inspect must not be null.");
      if (type == null)
         throw new IllegalArgumentException("Class to find must not be null.");

      try
      {
         Class<?> clazz = loader.loadClass(type.getName());
         return clazz.equals(type) && clazz.getClassLoader().equals(loader);
      }
      catch (ClassNotFoundException e)
      {
         return false;
      }
   }
}

@@ -1692,32 +1692,47 @@
 tFoundException 
+%7C LinkageError 
 e)%0A      %7B%0A     
@@ -2170,32 +2170,47 @@
 tFoundException 
+%7C LinkageError 
 e)%0A      %7B%0A     
@@ -2647,32 +2647,47 @@
 tFoundException 
+%7C LinkageError 
 e)%0A      %7B%0A     
@@ -3210,32 +3210,47 @@
 tFoundException 
+%7C LinkageError 
 e)%0A      %7B%0A     
@@ -3873,16 +3873,312 @@
 ception 
+%7C LinkageError e)%0A      %7B%0A         return false;%0A      %7D%0A   %7D%0A%0A   public static Throwable getClassLoadingExceptionFor(ClassLoader loader, String typeName)%0A   %7B%0A      try%0A      %7B%0A         loader.loadClass(typeName);%0A         return null;%0A      %7D%0A      catch (ClassNotFoundException %7C LinkageError 
 e)%0A     
@@ -4188,36 +4188,32 @@
          return 
-fals
 e;%0A      %7D%0A   %7D%0A

Add utility method to capture ClassLoading exceptions.