Package org.jboss.ejb3.interceptors.aop

Source Code of org.jboss.ejb3.interceptors.aop.DomainClassLoader

/*
* JBoss, Home of Professional Open Source.
* Copyright 2007, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file 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.ejb3.interceptors.aop;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.AccessController;
import java.security.CodeSource;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
import java.security.cert.Certificate;

import org.jboss.aop.Domain;
import org.jboss.ejb3.interceptors.lang.BootstrapClassLoader;
import org.jboss.logging.Logger;

/**
* Comment
*
* @author <a href="mailto:carlo.dewolf@jboss.com">Carlo de Wolf</a>
* @version $Revision: 68527 $
*/
public class DomainClassLoader extends ClassLoader
{
   private static final Logger log = Logger.getLogger(DomainClassLoader.class);
  
   /**
    * Load domain classes from here.
    */
   private ClassLoader delegate;
  
   /**
    * Load JDK classes from here.
    *
    * Do not confuse this with interceptor bootstrapping
    */
   private ClassLoader bootstrapClassLoader = new BootstrapClassLoader();
  
   private Domain domain;
  
   public DomainClassLoader(ClassLoader parent, ClassLoader delegate, Domain domain)
   {
      super(parent);
     
      assert delegate != null : "delegate is null";
      assert domain != null : "domain is null";
     
      this.delegate = delegate;
      this.domain = domain;
     
      //domain.registerClassLoader(this); // TODO: What does this do?
   }
  
   /**
    * Copy of SystemClassLoader.defineClassFromBytes
    * @param name
    * @param bytes
    * @param resolve
    * @return
    */
   private Class<?> defineClassFromBytes(String name, ClassBytes bytes, boolean resolve)
   {
      definePackage(name);
      byte[] b = bytes.bytes;
      Class<?> clazz = defineClass(name, b, 0, b.length, bytes.protectionDomain);
      if (resolve) resolveClass(clazz);
      return clazz;
   }

   /**
    * Copy of SystemClassLoader.definePackage
    *
    * TODO: do this properly
    *
    * @param className
    */
   private void definePackage(String className)
   {
      int i = className.lastIndexOf('.');
      if (i == -1)
         return;

      // we are not allowed to synchronize on ClassLoader.packages
      try
      {
         definePackage(className.substring(0, i), null, null, null, null, null, null, null);
      }
      catch (IllegalArgumentException alreadyDone)
      {
      }
   }

   private ClassLoader getDelegate()
   {
      return delegate;
   }
  
   /**
    * Purely for scoping class loader policy
    *
    * Do not use, it might be gone in later versions.
    *
    * @return   the domain of this class loader
    */
   public Domain getDomain()
   {
      return domain;
   }
  
   /**
    * Load a class, overridden to transform aop enhanced classes
    * and load non jre classes through this classloader.
    *
    * @param name the class name
    * @param resolve whether to resolve the class
    * @return the class
    * @throws ClassNotFoundException when there is no class
    */
   protected synchronized Class<?> loadClass(String name, boolean resolve)
      throws ClassNotFoundException
   {
      if(log.isTraceEnabled()) log.trace("loadClass " + name);
     
      // Have we already loaded the class?
      Class<?> clazz = findLoadedClass(name);
      if (clazz != null)
      {
         if (resolve) resolveClass(clazz);
         return clazz;
      }

      // Is it a JRE class?
      try
      {
         clazz = bootstrapClassLoader.loadClass(name);
         if (resolve) resolveClass(clazz);
         return clazz;
      }
      catch(ClassNotFoundException e)
      {
         // it's not a jdk class
         log.trace("Can't find class '" + name + "' in bootstrap.");
      }
     
      final String classFileName = name.replace('.', '/') + ".class";
      final URL url = getDelegate().getResource(classFileName);
      if(url == null)
      {
         if(log.isTraceEnabled()) log.trace("Did not find an url for '" + name + "'.");
         clazz = getParent().loadClass(name);
         if(resolve) resolveClass(clazz);
         return clazz;
      }
     
      log.debug(name + " found on " + url);
      // Load the class
      try
      {
         ClassBytes origBytes = loadClassBytes(name, classFileName, url);
         ClassBytes classBytes = new ClassBytes();

         assert !name.startsWith("org.jboss.aop") : "We should not have found a valid url";
        
         classBytes.bytes = domain.transform(this, name, null, origBytes.protectionDomain, origBytes.bytes);
         classBytes.protectionDomain = origBytes.protectionDomain;
           
         if (classBytes.bytes == null)
            classBytes = origBytes;

         // Define the class
         Class<?> cls = defineClassFromBytes(name, classBytes, resolve);
         if(resolve) resolveClass(cls);
         //assert Advised.class.isAssignableFrom(cls) : "Class " + cls + " is not really transformed";
         return cls;
      }
      catch(ClassNotFoundException e)
      {
         // TODO: We can't find any bytes for it, let's just pass it over
         log.warn("Unable to instrument '" + name + "'", e);
         return super.loadClass(name, resolve);
      }
      catch (IOException ioe)
      {
         throw new ClassNotFoundException("Unable to load " + name, ioe);
      }
      catch (IllegalAccessException iae)
      {
         // TODO: this might kill a thread
         throw new Error(iae);
      }
      catch (Exception e)
      {
         // TODO: this might kill a thread
         throw new Error("Error transforming the class " + name, e);
      }
   }

   /**
    * Load the bytecode for a class
    */
   private ClassBytes loadClassBytes(String name, final String classFileName, final URL url)
      throws ClassNotFoundException, IOException
   {
//      final String classFileName = name.replace('.', '/') + ".class";
//      final URL url = AccessController.doPrivileged(new PrivilegedAction<URL>()
//      {
//         public URL run()
//         {
//            return getParent().getResource(classFileName);
//         }
//      });
      ProtectionDomain protectionDomain = null;
      InputStream in = null;
      if (url != null)
      {
         try
         {
            in = AccessController.doPrivileged(new PrivilegedExceptionAction<InputStream>()
            {
               public InputStream run() throws Exception
               {
                  return url.openStream();
               }
            });
         }
         catch (PrivilegedActionException e)
         {
            throw new ClassNotFoundException(name, e);
         }
         String urlstring = url.toExternalForm();
         URL urlCS = url;
         if (urlstring.startsWith("jar:"))
         {
            int i = urlstring.indexOf('!');
            String cs = urlstring.substring(4, i);
            urlCS = new URL(cs);
         }
         else
         {
            int i = urlstring.indexOf(classFileName);
            if (i != -1)
            {
               String cs = urlstring.substring(0, i);
               urlCS = new URL(cs);
            }
         }
         CodeSource codeSource = new CodeSource(urlCS, (Certificate[]) null);
         protectionDomain = new ProtectionDomain(codeSource, null, this, null);
      }
      else
      {
         /* Try the system tmpdir/aopdynclasses, the default location
         the AOPClassPool writes dynamic class files to.
         */
         try
         {
            in = AccessController.doPrivileged(new PrivilegedExceptionAction<InputStream>()
            {
               public InputStream run() throws Exception
               {
                  String tmpdir = System.getProperty("java.io.tmpdir");
                  File aopdynclasses = new File(tmpdir, "aopdynclasses");
                  File classFile = new File(aopdynclasses, classFileName);
                  return new FileInputStream(classFile);
               }
            });
         }
         catch (PrivilegedActionException e)
         {
            throw new ClassNotFoundException(name, e);
         }
      }

      byte[][] bufs = new byte[8][];
      int bufsize = 4096;

      for (int i = 0; i < 8; ++i)
      {
         bufs[i] = new byte[bufsize];
         int size = 0;
         int len = 0;
         do
         {
            len = in.read(bufs[i], size, bufsize - size);
            if (len >= 0)
               size += len;
            else
            {
               byte[] result = new byte[bufsize - 4096 + size];
               int s = 0;
               for (int j = 0; j < i; ++j)
               {
                  System.arraycopy(bufs[j], 0, result, s, s + 4096);
                  s = s + s + 4096;
               }

               System.arraycopy(bufs[i], 0, result, s, size);
               ClassBytes classBytes = new ClassBytes();
               classBytes.bytes = result;
               classBytes.protectionDomain = protectionDomain;
               return classBytes;
            }
         }
         while (size < bufsize);
         bufsize *= 2;
      }

      throw new IOException("too much data loading class " + name);
   }
  
   /**
    * ClassBytes.
    */
   private static class ClassBytes
   {
      public ProtectionDomain protectionDomain;
      public byte[] bytes;
   }
}
TOP

Related Classes of org.jboss.ejb3.interceptors.aop.DomainClassLoader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.