org/objectweb/proactive/core/mop/MOP.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.Constructor;
00034 import java.lang.reflect.InvocationTargetException;
00035 import java.lang.reflect.Modifier;
00036 import java.util.Arrays;
00037 import java.util.HashMap;
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 
00047 public abstract class MOP {
00048 
00052     protected static String STUB_OBJECT_INTERFACE_NAME = "org.objectweb.proactive.core.mop.StubObject";
00053     protected static Class<?> STUB_OBJECT_INTERFACE;
00054     static Logger logger = ProActiveLogger.getLogger(Loggers.MOP);
00055 
00060     //protected static String ROOT_INTERFACE_NAME = "org.objectweb.proactive.core.mop.Reflect";
00061     //protected static Class ROOT_INTERFACE;
00062 
00066     protected static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
00067 
00071     public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
00072 
00076     protected static Class[] PROXY_CONSTRUCTOR_PARAMETERS_TYPES_ARRAY = new Class[2];
00077 
00081     protected static java.util.Hashtable<GenericStubKey, Constructor> stubTable = new java.util.Hashtable<GenericStubKey, Constructor>();
00082 
00086     protected static java.util.Hashtable<String, Constructor> proxyTable = new java.util.Hashtable<String, Constructor>();
00087 
00092     protected static java.util.Hashtable secondProxyTable = new java.util.Hashtable();
00093     
00094     protected static MOPClassLoader singleton = MOPClassLoader.getMOPClassLoader(); //MOPClassLoader.createMOPClassLoader();
00095 
00100     protected static HashMap<String, Class<?>> loadedClass = new HashMap<String, Class<?>>();
00101 
00102     static {
00103         PROXY_CONSTRUCTOR_PARAMETERS_TYPES_ARRAY = new Class[] {
00104                 org.objectweb.proactive.core.mop.ConstructorCall.class,
00105                 EMPTY_OBJECT_ARRAY.getClass()
00106             };
00107 
00108         try {
00109             STUB_OBJECT_INTERFACE = forName(STUB_OBJECT_INTERFACE_NAME);
00110         } catch (ClassNotFoundException e) {
00111             throw new CannotFindClassException(STUB_OBJECT_INTERFACE_NAME);
00112         }
00113 
00114         //try {
00115         //  ROOT_INTERFACE = forName(ROOT_INTERFACE_NAME);
00116         //} catch (ClassNotFoundException e) {
00117         //  throw new CannotFindClassException(ROOT_INTERFACE_NAME);
00118         //}
00119     }
00120 
00126     public static Class forName(String s)
00127         throws java.lang.ClassNotFoundException {
00128         try {
00129             return Class.forName(s);
00130         } catch (ClassNotFoundException e) {
00131             //                System.out.println(
00132             //                   "MOP forName failed for class " + s + ", looking in table");
00133             Class cl = loadedClass.get(s);
00134 
00135             //                  System.out.println("MOP forName failed, result is " +
00136             //                       cl);
00137             if (cl == null) {
00138                 throw e;
00139             } else {
00140                 return cl;
00141             }
00142         }
00143     }
00144 
00153     public static Object newInstance(String nameOfClass,
00154         Class[] genericParameters, Object[] constructorParameters,
00155         String nameOfProxy, Object[] proxyParameters)
00156         throws ClassNotFoundException, ClassNotReifiableException, 
00157             InvalidProxyClassException, 
00158             ConstructionOfProxyObjectFailedException, 
00159             ConstructionOfReifiedObjectFailedException {
00160         try {
00161             return newInstance(nameOfClass, nameOfClass, genericParameters,
00162                 constructorParameters, nameOfProxy, proxyParameters);
00163         } catch (ReifiedCastException e) {
00164             throw new InternalException(e);
00165         }
00166     }
00167 
00168     public static Object newInstance(Class clazz,
00169         Object[] constructorParameters, String nameOfProxy,
00170         Object[] proxyParameters)
00171         throws ClassNotFoundException, ClassNotReifiableException, 
00172             InvalidProxyClassException, 
00173             ConstructionOfProxyObjectFailedException, 
00174             ConstructionOfReifiedObjectFailedException {
00175         try {
00176             return newInstance(clazz, clazz.getName(), null,
00177                 constructorParameters, nameOfProxy, proxyParameters);
00178         } catch (ReifiedCastException e) {
00179             throw new InternalException(e);
00180         }
00181     }
00182 
00192     public static Object newInstance(String nameOfStubClass,
00193         String nameOfClass, Class[] genericParameters, Object[] constructorParameters,
00194         String nameOfProxy, Object[] proxyParameters)
00195         throws ClassNotFoundException, ClassNotReifiableException, 
00196             ReifiedCastException, InvalidProxyClassException, 
00197             ConstructionOfProxyObjectFailedException, 
00198             ConstructionOfReifiedObjectFailedException {
00199         // For convenience, allows 'null' to be equivalent to an empty array
00200         if (constructorParameters == null) {
00201             constructorParameters = EMPTY_OBJECT_ARRAY;
00202         }
00203         if (proxyParameters == null) {
00204             proxyParameters = EMPTY_OBJECT_ARRAY;
00205         }
00206 
00207         // Throws a ClassNotFoundException
00208         Class targetClass = forName(nameOfClass);
00209 
00210         // Class stubClass = null;
00211         //        try {
00212         //            targetClass = forName(nameOfStubClass);
00213         //        } catch (ClassNotFoundException e) {
00214         //              //if (targetClass.getClassLoader() != null) {
00215         //           // targetClass = targetClass.getClassLoader().loadClass(nameOfClass);
00216         //              //} else {
00217         //        //            System.out.println("TargetClass  " + targetClass + " has null classloader");
00218         //                      
00219         //        //    }
00220         //            MOP.forName(nameOfClass);//   addClassToCache(nameOfStubClass, targetClass);
00221         //        }
00222         // Instanciates the stub object
00223         StubObject stub = createStubObject(nameOfStubClass, targetClass, genericParameters);
00224 
00225         // build the constructor call for the target object to create
00226         ConstructorCall reifiedCall = buildTargetObjectConstructorCall(targetClass,
00227                 constructorParameters);
00228 
00229         // Instanciates the proxy object
00230         Proxy proxy = createProxyObject(nameOfProxy, proxyParameters,
00231                 reifiedCall);
00232 
00233         // Connects the proxy to the stub
00234         stub.setProxy(proxy);
00235         return stub;
00236     }
00237 
00238     public static Object newInstance(Class stubClass, String nameOfClass,
00239         Class[] genericParameters, Object[] constructorParameters,
00240         String nameOfProxy, Object[] proxyParameters)
00241         throws ClassNotFoundException, ClassNotReifiableException, 
00242             ReifiedCastException, InvalidProxyClassException, 
00243             ConstructionOfProxyObjectFailedException, 
00244             ConstructionOfReifiedObjectFailedException {
00245         // For convenience, allows 'null' to be equivalent to an empty array
00246         if (constructorParameters == null) {
00247             constructorParameters = EMPTY_OBJECT_ARRAY;
00248         }
00249         if (proxyParameters == null) {
00250             proxyParameters = EMPTY_OBJECT_ARRAY;
00251         }
00252 
00253         // Throws a ClassNotFoundException
00254         Class targetClass = null; // forName(nameOfClass);
00255 
00256         //  Class stubClass = null;
00257         try {
00258             targetClass = forName(nameOfClass);
00259         } catch (ClassNotFoundException e) {
00260             if (stubClass.getClassLoader() != null) {
00261                 targetClass = stubClass.getClassLoader().loadClass(nameOfClass);
00262             } else {
00263                 logger.info("TargetClass  " + targetClass +
00264                     " has null classloader");
00265             }
00266 
00267             // MOP.forName(nameOfClass);//   addClassToCache(nameOfStubClass, targetClass);
00268         }
00269 
00270         // Instanciates the stub object
00271         StubObject stub = createStubObject(stubClass.getName(), targetClass, genericParameters);
00272 
00273         // build the constructor call for the target object to create
00274         ConstructorCall reifiedCall = buildTargetObjectConstructorCall(targetClass,
00275                 constructorParameters);
00276 
00277         // Instanciates the proxy object
00278         Proxy proxy = createProxyObject(nameOfProxy, proxyParameters,
00279                 reifiedCall);
00280 
00281         // Connects the proxy to the stub
00282         stub.setProxy(proxy);
00283         return stub;
00284     }
00285 
00323     public static Object turnReified(String nameOfProxyClass, 
00324         Object[] proxyParameters, Object target, Class[] genericParameters)
00325         throws ClassNotFoundException, ClassNotReifiableException, 
00326             InvalidProxyClassException, 
00327             ConstructionOfProxyObjectFailedException {
00328         try {
00329             return turnReified(target.getClass().getName(), nameOfProxyClass,
00330                 proxyParameters, target, genericParameters);
00331             //   return turnReifiedFAb(target.getClass(), nameOfProxyClass, proxyParameters, target);
00332         } catch (ReifiedCastException e) {
00333             throw new InternalException(e);
00334         }
00335     }
00336 
00361     public static Object turnReified(String nameOfStubClass,
00362         String nameOfProxyClass, Object[] proxyParameters, Object target, Class[] genericParameters)
00363         throws ClassNotFoundException, ReifiedCastException, 
00364             ClassNotReifiableException, InvalidProxyClassException, 
00365             ConstructionOfProxyObjectFailedException {
00366         // For convenience, allows 'null' to be equivalent to an empty array
00367         // System.out.println("MOP.turnReified");
00368         if (proxyParameters == null) {
00369             proxyParameters = EMPTY_OBJECT_ARRAY;
00370         }
00371 
00372         // Throws a ClassNotFoundException
00373         Class targetClass = target.getClass();
00374 
00375         // Instanciates the stub object
00376         StubObject stub = createStubObject(nameOfStubClass, targetClass, genericParameters);
00377 
00378         // First, build the FakeConstructorCall object to pass to the constructor
00379         // of the proxy Object
00380         // FakeConstructorCall fakes a ConstructorCall object by returning
00381         // an already-existing object as the result of its execution
00382         ConstructorCall reifiedCall = new FakeConstructorCall(target);
00383 
00384         // Instanciates the proxy object
00385         Proxy proxy = createProxyObject(nameOfProxyClass, proxyParameters,
00386                 reifiedCall);
00387 
00388         // Connects the proxy to the stub
00389         stub.setProxy(proxy);
00390         return stub;
00391     }
00392 
00393     //  public static Object turnReifiedFAb(Class targetClass, String nameOfProxyClass, Object[] proxyParameters, Object target)
00394     //  throws ClassNotFoundException, ReifiedCastException, ClassNotReifiableException, InvalidProxyClassException, ConstructionOfProxyObjectFailedException {
00395     //   For convenience, allows 'null' to be equivalent to an empty array
00396     //   System.out.println("MOP.turnReified");
00397     //  System.out.println("turnReifiedFAb");
00398     //  if (proxyParameters == null)
00399     //    proxyParameters = EMPTY_OBJECT_ARRAY;
00400     //   Throws a ClassNotFoundException
00401     //  Class targetClass = target.getClass();
00402     //   Instanciates the stub object
00403     //  StubObject stub = createStubObjectFAb(targetClass);
00404     //   First, build the FakeConstructorCall object to pass to the constructor
00405     //   of the proxy Object
00406     //   FakeConstructorCall fakes a ConstructorCall object by returning
00407     //   an already-existing object as the result of its execution
00408     //  ConstructorCall reifiedCall = new FakeConstructorCall(target);
00409     //   Instanciates the proxy object
00410     //  Proxy proxy = createProxyObject(nameOfProxyClass, proxyParameters, reifiedCall);
00411     //   Connects the proxy to the stub
00412     //  stub.setProxy(proxy);
00413     //  return stub;
00414     //  }
00415 
00433     static void checkClassIsReifiable(String className)
00434         throws ClassNotReifiableException, ClassNotFoundException {
00435         checkClassIsReifiable(forName(className));
00436     }
00437 
00438     public static void checkClassIsReifiable(Class cl)
00439         throws ClassNotReifiableException {
00440         int mods = cl.getModifiers();
00441         if (cl.isInterface()) {
00442             // Interfaces are always reifiable, although some of the methods
00443             // they contain may not be reifiable
00444             return;
00445         } else {
00446             // normal case, this is a class
00447             if (cl.isPrimitive()) {
00448                 throw new ClassNotReifiableException(
00449                     "Cannot reify primitive types: " + cl.getName());
00450             } else if (Modifier.isFinal(mods)) {
00451                 throw new ClassNotReifiableException(
00452                     "Cannot reify final classes: " + cl.getName());
00453             } else if (!(checkNoArgsConstructor(cl))) {
00454                 throw new ClassNotReifiableException("Class " + cl.getName() +
00455                     " needs to have an empty noarg constructor.");
00456             } else {
00457                 return;
00458             }
00459         }
00460     }
00461 
00465     protected static boolean checkNoArgsConstructor(Class cl) {
00466         try {
00467             cl.getConstructor(EMPTY_CLASS_ARRAY);
00468             return true;
00469         } catch (NoSuchMethodException e) {
00470             return false;
00471         }
00472     }
00473 
00483     public static boolean isReifiedObject(Object o) {
00484         if (o != null) {
00485             return (STUB_OBJECT_INTERFACE.isAssignableFrom(o.getClass()));
00486         } else {
00487             return false;
00488         }
00489     }
00490 
00496     private static Class createStubClass(String nameOfBaseClass, Class[] genericParameters) {
00497         try {
00498             //return Class.forName(Utils.convertClassNameToStubClassName(nameOfClass), true, singleton);
00499             return singleton.loadClass(Utils.convertClassNameToStubClassName(
00500                     nameOfBaseClass, genericParameters));
00501         } catch (ClassNotFoundException e) {
00502             throw new GenerationOfStubClassFailedException(
00503                 "Cannot create the Stub class : " +
00504                 Utils.convertClassNameToStubClassName(nameOfBaseClass, genericParameters) +
00505                 "\nThe class \"" + nameOfBaseClass +
00506                 "\" must have a public access ");
00507         }
00508     }
00509 
00510     private static Class createStubClass(String nameOfClass, Class[] genericParameters, ClassLoader cl) {
00511         try {
00512             //return Class.forName(Utils.convertClassNameToStubClassName(nameOfClass), true, singleton);
00513             return singleton.loadClass(Utils.convertClassNameToStubClassName(
00514                     nameOfClass, genericParameters), genericParameters, cl);
00515         } catch (ClassNotFoundException e) {
00516             throw new GenerationOfStubClassFailedException(
00517                 "Cannot load Stub class : " +
00518                 Utils.convertClassNameToStubClassName(nameOfClass, genericParameters));
00519         }
00520     }
00521 
00528     static Constructor findStubConstructor(String nameOfClass, Class[] genericParameters)
00529         throws ClassNotFoundException {
00530         return findStubConstructor(forName(nameOfClass), genericParameters);
00531     }
00532 
00538     private static Constructor findStubConstructor(Class targetClass, Class[] genericParameters) {
00539         Constructor stubConstructor;
00540         String nameOfClass = targetClass.getName();
00541 
00542         // Is it cached in Hashtable ?
00543         stubConstructor = (Constructor) stubTable.get(new GenericStubKey(nameOfClass, genericParameters));
00544 
00545         //System.out.println("xxxxxx targetClass is " + targetClass);
00546         // On cache miss, finds the constructor
00547         
00548         
00549         if (stubConstructor == null) {
00550             Class stubClass;
00551             try {
00552                 stubClass = forName(Utils.convertClassNameToStubClassName(
00553                             nameOfClass, genericParameters));
00554             } catch (ClassNotFoundException e) {
00555                 // No stub class can be found, let's create it from scratch
00556                 stubClass = createStubClass(nameOfClass, genericParameters,
00557                         targetClass.getClassLoader());
00558                 //                stubClass = createStubClass(nameOfClass,
00559                 //          targetClass.getClassLoader());
00560             }
00561 
00562             // Verifies that the stub has a noargs constructor and caches it
00563             try {
00564                 stubConstructor = stubClass.getConstructor(EMPTY_CLASS_ARRAY);
00565                 stubTable.put(new GenericStubKey(nameOfClass, genericParameters), stubConstructor);
00566             } catch (NoSuchMethodException e) {
00567                 throw new GenerationOfStubClassFailedException(
00568                     "Stub for class " + nameOfClass +
00569                     "has no noargs constructor. This is a bug in ProActive.");
00570             }
00571         }
00572         return stubConstructor;
00573     }
00574 
00581     private static Constructor findProxyConstructor(Class proxyClass)
00582         throws InvalidProxyClassException {
00583         Constructor proxyConstructor;
00584 
00585         // Localizes the proxy class constructor
00586         proxyConstructor = proxyTable.get(proxyClass.getName());
00587 
00588         //System.out.println("MOP: The class of the proxy is " + proxyClass.getName());
00589         // Cache miss
00590         if (proxyConstructor == null) {
00591             try {
00592                 proxyConstructor = proxyClass.getConstructor(PROXY_CONSTRUCTOR_PARAMETERS_TYPES_ARRAY);
00593                 proxyTable.put(proxyClass.getName(), proxyConstructor);
00594             } catch (NoSuchMethodException e) {
00595                 throw new InvalidProxyClassException(
00596                     "No constructor matching (ConstructorCall, Object[]) found in proxy class " +
00597                     proxyClass.getName());
00598             }
00599         }
00600         return proxyConstructor;
00601     }
00602 
00603     private static StubObject instantiateStubObject(Constructor stubConstructor)
00604         throws ConstructionOfStubObjectFailedException {
00605         try {
00606             Object o = stubConstructor.newInstance(EMPTY_OBJECT_ARRAY);
00607             return (StubObject) o;
00608         } catch (InstantiationException e) {
00609             throw new ConstructionOfStubObjectFailedException("Constructor " +
00610                 stubConstructor + " belongs to an abstract class.");
00611         } catch (IllegalArgumentException e) {
00612             throw new ConstructionOfStubObjectFailedException(
00613                 "Wrapping problem with constructor " + stubConstructor);
00614         } catch (IllegalAccessException e) {
00615             throw new ConstructionOfStubObjectFailedException(
00616                 "Access denied to constructor " + stubConstructor);
00617         } catch (InvocationTargetException e) {
00618             throw new ConstructionOfStubObjectFailedException("The constructor of the stub has thrown an exception: ",
00619                 e.getTargetException());
00620         }
00621     }
00622 
00623     private static StubObject createStubObject(String nameOfBaseClass, 
00624         Class targetClass, Class[] genericParameters)
00625         throws ClassNotFoundException, ReifiedCastException, 
00626             ClassNotReifiableException {
00627         //System.out.println("StubClass is " + nameOfBaseClass);
00628         // BUG ID: #327
00629         //this has been added to deal with downloaded classes
00630         //if we cannot load the stub class using its name
00631         //it is probably because it has been downloaded by another classloader
00632         //thus we ask the classloader of the target class to load it
00633         Class<?> baseClass = null;
00634         try {
00635             baseClass = forName(nameOfBaseClass);
00636         } catch (ClassNotFoundException e) {
00637             baseClass = targetClass.getClassLoader().loadClass(nameOfBaseClass);
00638             MOP.addClassToCache(nameOfBaseClass, baseClass);
00639         }
00640 
00641         // Class stubClass = forName(nameOfStubClass,targetClass.getClassLoader());
00642         // Check that the type of the class is compatible with the type of the stub
00643         if (!(baseClass.isAssignableFrom(targetClass))) {
00644             throw new ReifiedCastException("Cannot convert " +
00645                 targetClass.getName() + "into " + baseClass.getName());
00646         }
00647 
00648         // Throws a ClassNotReifiableException exception if not reifiable
00649         checkClassIsReifiable(baseClass);
00650 
00651         // Finds the constructor of the stub class
00652         // If the stub class has not yet been created,
00653         // it is created within this call
00654         Constructor stubConstructor = findStubConstructor(baseClass, genericParameters);
00655 
00656         // Instanciates the stub object
00657         return instantiateStubObject(stubConstructor);
00658     }
00659 
00660     // BUG ID: #327
00661     protected static void addClassToCache(String name, Class cl) {
00662         //        System.out.println("MOP: puting " + nameOfStubClass +
00663         //            " in loadedClass");
00664         //        loadedClass.put(nameOfStubClass, stubClass);
00665         //        Field[] clArray = stubClass.getDeclaredFields();
00666         //        System.out.println("MOP: nuumber of declared classes " +
00667         //            clArray.length);
00668         //        for (int i = 0; i < clArray.length; i++) {
00669         //            Field ob1 = clArray[i];
00670         //            System.out.println("MOP: field " + ob1.getName());
00671         //            Class cl = ob1.getType();
00672         //            System.out.println("MOP: key = " + cl.getName() + " value =  " +
00673         //                cl);
00674         //            loadedClass.put(cl.getName(), cl);
00675         //        }
00676         loadedClass.put(name, cl);
00677     }
00678 
00679     // Instanciates the proxy object
00680     public static Proxy createProxyObject(String nameOfProxy,
00681         Object[] proxyParameters, ConstructorCall reifiedCall)
00682         throws ConstructionOfProxyObjectFailedException, ClassNotFoundException, 
00683             InvalidProxyClassException {
00684         // Throws a ClassNotFoundException
00685         Class proxyClass = forName(nameOfProxy);
00686 
00687         // Finds constructor of the proxy class
00688         Constructor proxyConstructor = findProxyConstructor(proxyClass);
00689 
00690         // Now calls the constructor of the proxy
00691         Object[] params = new Object[] { reifiedCall, proxyParameters };
00692         try {
00693             return (Proxy) proxyConstructor.newInstance(params);
00694         } catch (InstantiationException e) {
00695             throw new ConstructionOfProxyObjectFailedException("Constructor " +
00696                 proxyConstructor + " belongs to an abstract class");
00697         } catch (IllegalArgumentException e) {
00698             throw new ConstructionOfProxyObjectFailedException(
00699                 "Wrapping problem with constructor " + proxyConstructor);
00700         } catch (IllegalAccessException e) {
00701             throw new ConstructionOfProxyObjectFailedException(
00702                 "Access denied to constructor " + proxyConstructor);
00703         } catch (InvocationTargetException e) {
00704             throw new ConstructionOfProxyObjectFailedException("The constructor of the proxy object has thrown an exception: ",
00705                 e.getTargetException());
00706         }
00707     }
00708 
00709     public static ConstructorCall buildTargetObjectConstructorCall(
00710         Class targetClass, Object[] constructorParameters)
00711         throws ConstructionOfReifiedObjectFailedException {
00712         // First, build the ConstructorCall object to pass to the constructor
00713         // of the proxy Object. It represents the construction of the reified
00714         // object.
00715         Constructor targetConstructor;
00716 
00717         // Locates the right constructor (should use a cache here ?)
00718         Class[] targetConstructorArgs = new Class[constructorParameters.length];
00719         for (int i = 0; i < constructorParameters.length; i++) {
00720             //  System.out.println("MOP: constructorParameters[i] = " + constructorParameters[i]);
00721             targetConstructorArgs[i] = constructorParameters[i].getClass();
00722             //  System.out.println("MOP: targetConstructorArgs[i] = " + targetConstructorArgs[i]);
00723         }
00724 
00725         //System.out.println("MOP: targetClass is " + targetClass);
00726         //      System.out.println("MOP: targetConstructorArgs = " + targetConstructorArgs);
00727         //      System.out.println("MOP: targetConstructorArgs.length = " + targetConstructorArgs.length);
00728         try {
00729             //MODIFIED 4/5/00
00730             if (targetClass.isInterface()) {
00731                 //there is no point in looking for the constructor of an interface
00732                 //      System.out.println("MOP: WARNING Interface detected");
00733                 targetConstructor = null;
00734             } else {
00735                 targetConstructor = targetClass.getDeclaredConstructor(targetConstructorArgs);
00736             }
00737         } catch (NoSuchMethodException e) {
00738             // This may have failed because getConstructor does not allow subtypes
00739             targetConstructor = findReifiedConstructor(targetClass,
00740                     targetConstructorArgs);
00741 
00742             if (targetConstructor == null) // This may have failed because some wrappers should be interpreted
00743             // as primitive types. Let's investigate it
00744              {
00745                 targetConstructor = investigateAmbiguity(targetClass,
00746                         targetConstructorArgs);
00747                 if (targetConstructor == null) {
00748                     throw new ConstructionOfReifiedObjectFailedException(
00749                         "Cannot locate this constructor in class " +
00750                         targetClass + " : " + targetConstructorArgs);
00751                 }
00752             }
00753         }
00754         return new ConstructorCallImpl(targetConstructor, constructorParameters);
00755     }
00756 
00820     private static Constructor investigateAmbiguity(Class targetClass,
00821         Class[] targetConstructorArgs) {
00822         // Find the number of possible constructors ambiguities
00823         int n = 1;
00824         for (int i = 0; i < targetConstructorArgs.length; i++) {
00825             if (Utils.isWrapperClass(targetConstructorArgs[i])) {
00826                 n = n * 2;
00827             }
00828         }
00829         if (n == 1) {
00830             return null; // No wrapper found
00831         }
00832 
00833         for (int i = 0; i < targetConstructorArgs.length; i++) {
00834             if (Utils.isWrapperClass(targetConstructorArgs[i])) {
00835                 targetConstructorArgs[i] = Utils.getPrimitiveType(targetConstructorArgs[i]);
00836             }
00837         }
00838         return findReifiedConstructor(targetClass, targetConstructorArgs);
00839     }
00840 
00847     private static Constructor findReifiedConstructor(Class targetClass,
00848         Class<?>[] targetConstructorArgs) {
00849         Constructor[] publicConstructors;
00850         Constructor currentConstructor;
00851         Class<?>[] currentConstructorParameterTypes;
00852         boolean match;
00853 
00854         publicConstructors = targetClass.getConstructors();
00855         // For each public constructor of the reified class
00856         for (int i = 0; i < publicConstructors.length; i++) {
00857             currentConstructor = publicConstructors[i];
00858             currentConstructorParameterTypes = currentConstructor.getParameterTypes();
00859             match = true;
00860 
00861             // Check if the parameters types of this constructor are
00862             // assignable from the actual parameter types.
00863             if (currentConstructorParameterTypes.length == targetConstructorArgs.length) {
00864                 for (int j = 0; j < currentConstructorParameterTypes.length;
00865                         j++) {
00866                     if (!(currentConstructorParameterTypes[j].isAssignableFrom(
00867                                 targetConstructorArgs[j]))) {
00868                         match = false;
00869                         break;
00870                     }
00871                 }
00872             } else {
00873                 match = false;
00874             }
00875             if (match == true) {
00876                 return currentConstructor;
00877             }
00878         }
00879         return null;
00880     }
00881 
00889     private static Object castInto(Object sourceObject, String targetTypeName)
00890         throws ReifiedCastException {
00891         try {
00892             Class cl = forName(targetTypeName);
00893             return castInto(sourceObject, cl, null);
00894         } catch (ClassNotFoundException e) {
00895             throw new ReifiedCastException("Cannot load class " +
00896                 targetTypeName);
00897             //          throw new ReifiedCastException ("Cannot cast "+sourceObject.getClass().getName()+" into "+targetTypeName);
00898         }
00899     }
00900 
00909     private static Object castInto(Object sourceObject, Class<?> targetType, Class[] genericParameters)
00910         throws ReifiedCastException {
00911         // First, check if sourceObject is a reified object
00912         if (!(isReifiedObject(sourceObject))) {
00913             throw new ReifiedCastException(
00914                 "Cannot perform a reified cast on an object that is not reified");
00915         }
00916 
00917         // Gets a Class object representing the type of sourceObject
00918         Class<?> sourceType = sourceObject.getClass().getSuperclass();
00919 
00920         // Check if types are compatible
00921         // Here we assume that the 'type of the stub' (i.e, the type of the
00922         // reified object) is its direct superclass
00923         if (!((sourceType.isAssignableFrom(targetType)) ||
00924                 (targetType.isAssignableFrom(sourceType)))) {
00925             throw new ReifiedCastException("Cannot cast " +
00926                 sourceObject.getClass().getName() + " into " +
00927                 targetType.getName());
00928         }
00929 
00930         // Let's create a stub object for the target type
00931         Constructor stubConstructor = findStubConstructor(targetType, genericParameters);
00932 
00933         // Instanciates the stub object
00934         StubObject stub = instantiateStubObject(stubConstructor);
00935 
00936         // Connects the proxy of the old stub to the new stub
00937         stub.setProxy(((StubObject) sourceObject).getProxy());
00938         return stub;
00939     }
00940 
00941     public static Class loadClass(String name) throws ClassNotFoundException {
00942         //return singleton.loadClass(name);
00943         return forName(name);
00944     }
00945     
00946     
00947     static class GenericStubKey {
00948         
00949         String className;
00950         Class[] genericParameters;
00951         
00952         public GenericStubKey(String className, Class[] genericParameters) {
00953                 this.className = className;
00954                 this.genericParameters = genericParameters;
00955         }
00956         
00957         
00958         
00959         public boolean equals(Object o) {
00960                 if (! (o instanceof GenericStubKey)) {
00961                         return false;
00962                 }
00963                 // className cannot be null
00964                 return (className.equals(((GenericStubKey)o).getClassName()) 
00965                                 && (Arrays.equals(genericParameters, ((GenericStubKey)o).getGenericParameters())));
00966         }
00967         
00968         public int hashCode() {
00969                 return className.hashCode()+Arrays.deepHashCode(genericParameters);
00970         }
00971 
00972 
00973 
00974                 public String getClassName() {
00975                         return className;
00976                 }
00977 
00978 
00979 
00980                 public Class[] getGenericParameters() {
00981                         return genericParameters;
00982                 }
00983 
00984 
00985 
00986     }
00987 }

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