00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
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
00061
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();
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
00115
00116
00117
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
00132
00133 Class cl = loadedClass.get(s);
00134
00135
00136
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
00200 if (constructorParameters == null) {
00201 constructorParameters = EMPTY_OBJECT_ARRAY;
00202 }
00203 if (proxyParameters == null) {
00204 proxyParameters = EMPTY_OBJECT_ARRAY;
00205 }
00206
00207
00208 Class targetClass = forName(nameOfClass);
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223 StubObject stub = createStubObject(nameOfStubClass, targetClass, genericParameters);
00224
00225
00226 ConstructorCall reifiedCall = buildTargetObjectConstructorCall(targetClass,
00227 constructorParameters);
00228
00229
00230 Proxy proxy = createProxyObject(nameOfProxy, proxyParameters,
00231 reifiedCall);
00232
00233
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
00246 if (constructorParameters == null) {
00247 constructorParameters = EMPTY_OBJECT_ARRAY;
00248 }
00249 if (proxyParameters == null) {
00250 proxyParameters = EMPTY_OBJECT_ARRAY;
00251 }
00252
00253
00254 Class targetClass = null;
00255
00256
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
00268 }
00269
00270
00271 StubObject stub = createStubObject(stubClass.getName(), targetClass, genericParameters);
00272
00273
00274 ConstructorCall reifiedCall = buildTargetObjectConstructorCall(targetClass,
00275 constructorParameters);
00276
00277
00278 Proxy proxy = createProxyObject(nameOfProxy, proxyParameters,
00279 reifiedCall);
00280
00281
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
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
00367
00368 if (proxyParameters == null) {
00369 proxyParameters = EMPTY_OBJECT_ARRAY;
00370 }
00371
00372
00373 Class targetClass = target.getClass();
00374
00375
00376 StubObject stub = createStubObject(nameOfStubClass, targetClass, genericParameters);
00377
00378
00379
00380
00381
00382 ConstructorCall reifiedCall = new FakeConstructorCall(target);
00383
00384
00385 Proxy proxy = createProxyObject(nameOfProxyClass, proxyParameters,
00386 reifiedCall);
00387
00388
00389 stub.setProxy(proxy);
00390 return stub;
00391 }
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
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
00443
00444 return;
00445 } else {
00446
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
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
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
00543 stubConstructor = (Constructor) stubTable.get(new GenericStubKey(nameOfClass, genericParameters));
00544
00545
00546
00547
00548
00549 if (stubConstructor == null) {
00550 Class stubClass;
00551 try {
00552 stubClass = forName(Utils.convertClassNameToStubClassName(
00553 nameOfClass, genericParameters));
00554 } catch (ClassNotFoundException e) {
00555
00556 stubClass = createStubClass(nameOfClass, genericParameters,
00557 targetClass.getClassLoader());
00558
00559
00560 }
00561
00562
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
00586 proxyConstructor = proxyTable.get(proxyClass.getName());
00587
00588
00589
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
00628
00629
00630
00631
00632
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
00642
00643 if (!(baseClass.isAssignableFrom(targetClass))) {
00644 throw new ReifiedCastException("Cannot convert " +
00645 targetClass.getName() + "into " + baseClass.getName());
00646 }
00647
00648
00649 checkClassIsReifiable(baseClass);
00650
00651
00652
00653
00654 Constructor stubConstructor = findStubConstructor(baseClass, genericParameters);
00655
00656
00657 return instantiateStubObject(stubConstructor);
00658 }
00659
00660
00661 protected static void addClassToCache(String name, Class cl) {
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676 loadedClass.put(name, cl);
00677 }
00678
00679
00680 public static Proxy createProxyObject(String nameOfProxy,
00681 Object[] proxyParameters, ConstructorCall reifiedCall)
00682 throws ConstructionOfProxyObjectFailedException, ClassNotFoundException,
00683 InvalidProxyClassException {
00684
00685 Class proxyClass = forName(nameOfProxy);
00686
00687
00688 Constructor proxyConstructor = findProxyConstructor(proxyClass);
00689
00690
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
00713
00714
00715 Constructor targetConstructor;
00716
00717
00718 Class[] targetConstructorArgs = new Class[constructorParameters.length];
00719 for (int i = 0; i < constructorParameters.length; i++) {
00720
00721 targetConstructorArgs[i] = constructorParameters[i].getClass();
00722
00723 }
00724
00725
00726
00727
00728 try {
00729
00730 if (targetClass.isInterface()) {
00731
00732
00733 targetConstructor = null;
00734 } else {
00735 targetConstructor = targetClass.getDeclaredConstructor(targetConstructorArgs);
00736 }
00737 } catch (NoSuchMethodException e) {
00738
00739 targetConstructor = findReifiedConstructor(targetClass,
00740 targetConstructorArgs);
00741
00742 if (targetConstructor == null)
00743
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
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;
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
00856 for (int i = 0; i < publicConstructors.length; i++) {
00857 currentConstructor = publicConstructors[i];
00858 currentConstructorParameterTypes = currentConstructor.getParameterTypes();
00859 match = true;
00860
00861
00862
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
00898 }
00899 }
00900
00909 private static Object castInto(Object sourceObject, Class<?> targetType, Class[] genericParameters)
00910 throws ReifiedCastException {
00911
00912 if (!(isReifiedObject(sourceObject))) {
00913 throw new ReifiedCastException(
00914 "Cannot perform a reified cast on an object that is not reified");
00915 }
00916
00917
00918 Class<?> sourceType = sourceObject.getClass().getSuperclass();
00919
00920
00921
00922
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
00931 Constructor stubConstructor = findStubConstructor(targetType, genericParameters);
00932
00933
00934 StubObject stub = instantiateStubObject(stubConstructor);
00935
00936
00937 stub.setProxy(((StubObject) sourceObject).getProxy());
00938 return stub;
00939 }
00940
00941 public static Class loadClass(String name) throws ClassNotFoundException {
00942
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
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 }