org/objectweb/proactive/core/mop/MOPClassLoader.java

00001 /* 
00002  * ################################################################
00003  * 
00004  * ProActive: The Java(TM) library for Parallel, Distributed, 
00005  *            Concurrent computing with Security and Mobility
00006  * 
00007  * Copyright (C) 1997-2007 INRIA/University of Nice-Sophia Antipolis
00008  * Contact: proactive@objectweb.org
00009  * 
00010  * This library is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU Lesser General Public
00012  * License as published by the Free Software Foundation; either
00013  * version 2.1 of the License, or any later version.
00014  *  
00015  * This library is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00018  * Lesser General Public License for more details.
00019  * 
00020  * You should have received a copy of the GNU Lesser General Public
00021  * License along with this library; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
00023  * USA
00024  *  
00025  *  Initial developer(s):               The ProActive Team
00026  *                        http://www.inria.fr/oasis/ProActive/contacts.html
00027  *  Contributor(s): 
00028  * 
00029  * ################################################################
00030  */ 
00031 package org.objectweb.proactive.core.mop;
00032 
00033 import java.lang.reflect.InvocationTargetException;
00034 import java.lang.reflect.Method;
00035 import java.net.URL;
00036 import java.net.URLClassLoader;
00037 import java.util.Hashtable;
00038 
00039 import org.apache.log4j.Logger;
00040 import org.objectweb.proactive.core.util.log.Loggers;
00041 import org.objectweb.proactive.core.util.log.ProActiveLogger;
00042 
00043 
00044 public class MOPClassLoader extends URLClassLoader {
00045     static Logger logger = ProActiveLogger.getLogger(Loggers.MOP);
00046 
00047     // retreives the optionnal byteCodeManipulator JVM arg
00048     // javassist is used by default
00049     public static String BYTE_CODE_MANIPULATOR = (System.getProperty(
00050             "byteCodeManipulator") != null)
00051         ? System.getProperty("byteCodeManipulator") : "javassist";
00052     protected static Hashtable<String, byte[]> classDataCache = new Hashtable<String, byte[]>();
00053     protected static MOPClassLoader mopCl = null;
00054 
00059     public static synchronized MOPClassLoader getMOPClassLoader() {
00060         if (MOPClassLoader.mopCl == null) {
00061             MOPClassLoader.mopCl = MOPClassLoader.createMOPClassLoader();
00062         }
00063         return MOPClassLoader.mopCl;
00064     }
00065 
00066     public MOPClassLoader() {
00067         super(new URL[] {  });
00068     }
00069 
00077     public byte[] getClassData(String classname) {
00078         byte[] cb = null;
00079         cb = classDataCache.get(classname);
00080         if (cb == null) {
00081                 if (logger.isDebugEnabled()) {
00082                         logger.debug(
00083                         "MOPClassLoader: class " + classname + " not found, trying to generate it");
00084                 }
00085             try {
00086                 this.loadClass(classname);
00087             } catch (ClassNotFoundException e) {
00088                 e.printStackTrace();
00089             }
00090             cb = classDataCache.get(classname);
00091         }
00092         return cb;
00093     }
00094 
00095     private MOPClassLoader(ClassLoader parent, URL[] urls) {
00096         super(urls, parent);
00097     }
00098 
00099     public void launchMain(String[] args) throws Throwable {
00100         try {
00101             // Looks up the class that contains main
00102             Class cl = Class.forName(args[0], true, this);
00103 
00104             // Looks up method main
00105             Class[] argTypes = { args.getClass() };
00106             Method mainMethod = cl.getMethod("main", argTypes);
00107 
00108             // And calls it
00109             String[] newArgs = new String[args.length - 1];
00110             System.arraycopy(args, 1, newArgs, 0, args.length - 1);
00111 
00112             Object[] mainArgs = { newArgs };
00113             mainMethod.invoke(null, mainArgs);
00114         } catch (ClassNotFoundException e) {
00115             logger.error("Launcher: cannot find class " + args[0]);
00116         } catch (NoSuchMethodException e) {
00117             logger.error("Launcher: class " + args[0] +
00118                 " does not contain have method void 'public void main (String[])'");
00119         } catch (InvocationTargetException e) {
00120             throw e.getTargetException();
00121         }
00122         return;
00123     }
00124 
00125     protected static MOPClassLoader createMOPClassLoader() {
00126         // Gets the current classloader
00127         ClassLoader currentClassLoader = null;
00128 
00129         try {
00130             Class c = Class.forName(
00131                     "org.objectweb.proactive.core.mop.MOPClassLoader");
00132             currentClassLoader = c.getClassLoader();
00133         } catch (ClassNotFoundException e) {
00134             e.printStackTrace();
00135         }
00136         URL[] urls = null;
00137 
00138         // Checks if the current classloader is actually an instance of
00139         // java.net.URLClassLoader, or of one of its subclasses.
00140         if (currentClassLoader instanceof java.net.URLClassLoader) {
00141             // Retrieves the set of URLs from the current classloader     
00142             urls = ((URLClassLoader) currentClassLoader).getURLs();
00143         } else {
00144             urls = new URL[0];
00145         }
00146 
00147         // Creates a new MOPClassLoader
00148         return new MOPClassLoader(currentClassLoader, urls);
00149     }
00150 
00151     protected Class<?> findClass(String name) throws ClassNotFoundException {
00152         return super.findClass(name);
00153     }
00154 
00155     public Class<?> loadClass(String name) throws ClassNotFoundException {
00156         return this.loadClass(name, null, null, false);
00157     }
00158     
00159     
00160     public Class loadClass(String name, Class[] genericParameters) throws ClassNotFoundException {
00161         return this.loadClass(name, genericParameters, null, false);
00162     }
00163 
00164     public Class loadClass(String name, Class[] genericParameters, ClassLoader cl)
00165         throws ClassNotFoundException {
00166         return this.loadClass(name, genericParameters, cl, false);
00167     }
00168 
00169     protected synchronized Class loadClass(String name, Class[] genericParameters, ClassLoader cl,
00170         boolean resolve) throws ClassNotFoundException {
00171         if (this.getParent() != null) {
00172             try {
00173                 return this.getParent().loadClass(name);
00174             } catch (ClassNotFoundException e) {
00175                 // proceeding
00176             }
00177         } else {
00178             //ok, we don't have any parent, so maybe we previously
00179             //defined the stub class using the context class loader
00180             //we check here
00181             try {
00182                 return Thread.currentThread().getContextClassLoader().loadClass(name);
00183             } catch (ClassNotFoundException e) {
00184                 //no luck, proceed
00185             }
00186         }
00187         try {
00188             if (cl != null) {
00189                 return cl.loadClass(name);
00190             } else {
00191                 return Class.forName(name);
00192             }
00193         } catch (ClassNotFoundException e) {
00194             // Test if the name of the class is actually a request for
00195             // a stub class to be created
00196             if (Utils.isStubClassName(name)) {
00197                 logger.info("Generating class : " + name);
00198                 //    e.printStackTrace();
00199                 String classname = Utils.convertStubClassNameToClassName(name);
00200 
00201                 byte[] data = null;
00202 //                if (BYTE_CODE_MANIPULATOR.equals("ASM")) {
00203 //                    ASMBytecodeStubBuilder bsb = new ASMBytecodeStubBuilder(classname);
00204 //                    data = bsb.create();
00205 //                    MOPClassLoader.classDataCache.put(name, data);
00206 //                } else 
00207                     if (BYTE_CODE_MANIPULATOR.equals("javassist")) {
00208                     data = JavassistByteCodeStubBuilder.create(classname, genericParameters);
00209                     MOPClassLoader.classDataCache.put(name, data);
00210                 } else {
00211                     // that shouldn't happen, unless someone manually sets the BYTE_CODE_MANIPULATOR static variable
00212                     logger.error(
00213                         "byteCodeManipulator argument is optionnal. If specified, it can only be set to javassist (ASM is no longer supported).");
00214                     logger.error(
00215                         "Any other setting will result in the use of javassist, the default bytecode manipulator framework");
00216                 }
00217 
00218                 // We use introspection to invoke the defineClass method to avoid the normal 
00219                 // class Access checking. This method is supposed to be protected which means 
00220                 // we should not be accessing it but the access policy file allows us to access it freely.
00221                 try {
00222                     Class clc = Class.forName("java.lang.ClassLoader");
00223                     Class[] argumentTypes = new Class[5];
00224                     argumentTypes[0] = name.getClass();
00225                     argumentTypes[1] = data.getClass();
00226                     argumentTypes[2] = Integer.TYPE;
00227                     argumentTypes[3] = Integer.TYPE;
00228                     argumentTypes[4] = Class.forName(
00229                             "java.security.ProtectionDomain");
00230 
00231                     Method m = clc.getDeclaredMethod("defineClass",
00232                             argumentTypes);
00233                     m.setAccessible(true);
00234 
00235                     Object[] effectiveArguments = new Object[5];
00236                     effectiveArguments[0] = name;
00237                     effectiveArguments[1] = data;
00238                     effectiveArguments[2] = new Integer(0);
00239                     effectiveArguments[3] = new Integer(data.length);
00240                     effectiveArguments[4] = this.getClass().getProtectionDomain();
00241 
00242                     //  we have been loaded through the bootclasspath
00243                     // so we use the context classloader
00244                     if (this.getParent() == null) {
00245                         return (Class) m.invoke(Thread.currentThread()
00246                                                       .getContextClassLoader(),
00247                             effectiveArguments);
00248                     } else {
00249                         return (Class) m.invoke(this.getParent(),
00250                             effectiveArguments);
00251                     }
00252                 } catch (Exception ex) {
00253                     ex.printStackTrace();
00254                     throw new ClassNotFoundException(ex.getMessage());
00255                 }
00256             } else {
00257                 logger.debug("Cannot generate class " + name + " as a stub class");
00258                 throw e;
00259             }
00260         }
00261     }
00262 }

Generated on Mon Jan 22 15:16:08 2007 for ProActive by  doxygen 1.5.1