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.component.gen;
00032 
00033 import java.lang.reflect.Method;
00034 import java.lang.reflect.ParameterizedType;
00035 import java.util.List;
00036 
00037 import javassist.ClassPool;
00038 import javassist.CtClass;
00039 import javassist.CtMethod;
00040 import javassist.CtNewMethod;
00041 
00042 import org.apache.log4j.Logger;
00043 import org.objectweb.proactive.core.component.exceptions.InterfaceGenerationFailedException;
00044 import org.objectweb.proactive.core.component.type.ProActiveInterfaceType;
00045 import org.objectweb.proactive.core.util.ClassDataCache;
00046 import org.objectweb.proactive.core.util.log.Loggers;
00047 import org.objectweb.proactive.core.util.log.ProActiveLogger;
00048 
00049 public class GatherInterfaceGenerator {
00050     
00051     protected static final transient ClassPool pool = ClassPool.getDefault();
00052     private static Logger gatherLogger = ProActiveLogger.getLogger(Loggers.COMPONENTS_GATHERCAST);
00053     
00054     public static Class generateInterface(ProActiveInterfaceType itfType) throws InterfaceGenerationFailedException {
00055         Class generated = null;
00056         String gatherProxyItfName = Utils.getGatherProxyItfClassName(itfType);
00057         try {
00058             
00059 
00060             generated = Thread.currentThread().getContextClassLoader().loadClass(gatherProxyItfName);
00061         } catch (ClassNotFoundException cnfe) {
00062             byte[] bytecode = generateInterfaceByteCode(gatherProxyItfName);
00063 
00064             try {
00065             
00066             generated = Utils.defineClass(gatherProxyItfName, bytecode);
00067             } catch (Exception e) {
00068                 e.printStackTrace();
00069                 return null;
00070             }
00071         }
00072 
00073         return generated;
00074     }
00075     
00076     
00077 
00078     
00079     static byte[] generateInterfaceByteCode(String gatherProxyItfName) {
00080         if (ClassDataCache.instance().getClassData(gatherProxyItfName) != null) {
00081             return ClassDataCache.instance().getClassData(gatherProxyItfName);
00082         }
00083         try {
00084             Class serverItfClass = Class.forName(Utils.getInterfaceSignatureFromGathercastProxyClassName(gatherProxyItfName));
00085             CtClass repGatherItfClass = pool.makeInterface(gatherProxyItfName);
00086         Method[] serverItfMethods = serverItfClass.getMethods();
00087 
00088         CtMethod[] repServerItfMethods = new CtMethod[serverItfMethods.length];
00089 
00090         for (int i = 0; i < serverItfMethods.length; i++) {
00091             
00092             CtClass repReturnType = null;
00093             java.lang.reflect.Type returnType = serverItfMethods[i].getGenericReturnType();
00094             CtClass[] repParameterTypes = new CtClass[serverItfMethods[i].getParameterTypes().length];
00095             
00096             if (Void.TYPE == returnType) {
00097                 repReturnType = CtClass.voidType;
00098             } else {
00099                 if (!(returnType instanceof ParameterizedType)) {
00100                     throw new InterfaceGenerationFailedException("gather method " + serverItfMethods[i].toGenericString() + " in gather interface of signature " + serverItfClass.getName() + " must return a parameterized list or void");
00101                 }
00102                 
00103                 if (!(List.class.isAssignableFrom((Class)((ParameterizedType)returnType).getRawType()))) {
00104                     throw new InterfaceGenerationFailedException("gather method " + serverItfMethods[i].toGenericString() + " in gather interface " + serverItfClass.getName() + " must return a parameterized list or void");
00105                 }
00106                 java.lang.reflect.Type[] actualTypeArguments = ((ParameterizedType)returnType).getActualTypeArguments();
00107                 if (actualTypeArguments.length != 1) {
00108                     throw new InterfaceGenerationFailedException("gather method " + serverItfMethods[i].toGenericString() + " in gather interface " + serverItfClass.getName() + " must return a parameterized type with one parameter");
00109                 }
00110                 repReturnType = pool.get(((Class)(((ParameterizedType)returnType).getActualTypeArguments()[0])).getName());
00111             }
00112             
00113             java.lang.reflect.Type[] paramTypes = serverItfMethods[i].getGenericParameterTypes();
00114             for (int j = 0; j < paramTypes.length; j++) {
00115                 java.lang.reflect.Type paramType = paramTypes[j];
00116                 if (!(paramType instanceof ParameterizedType)) {
00117                     throw new InterfaceGenerationFailedException("gather method " + serverItfMethods[i].toGenericString() + " in gather interface " + serverItfClass.getName() + " must have type-parameterized parameter types");
00118                 }
00119                 java.lang.reflect.Type[] actualTypeArguments = ((ParameterizedType)paramType).getActualTypeArguments();
00120                 if (actualTypeArguments.length != 1) {
00121                     throw new InterfaceGenerationFailedException("gather method " + serverItfMethods[i].toGenericString() + " in gather interface " + serverItfClass.getName() + " must have type-parameterized parameters with only one parameterizing element");
00122                 }
00123                 repParameterTypes[j] = pool.get(((Class)actualTypeArguments[0]).getName());
00124             }
00125             
00126             
00127             Class[] exceptions = serverItfMethods[i].getExceptionTypes();
00128             CtClass[] repExceptions = new CtClass[exceptions.length];
00129             for (int j = 0; j < exceptions.length; j++) {
00130                 repExceptions[j] = pool.get(exceptions[j].getName());
00131             }
00132             
00133             
00134             repServerItfMethods[i] = CtNewMethod.abstractMethod(repReturnType, serverItfMethods[i].getName(), repParameterTypes, repExceptions, repGatherItfClass);
00135             
00136             repGatherItfClass.addMethod(repServerItfMethods[i]);
00137 
00138             
00139         }
00140 
00141 
00142 
00143 
00144         
00145         byte[] bytecode = repGatherItfClass.toBytecode();
00146         ClassDataCache.instance().addClassData(gatherProxyItfName,
00147                         repGatherItfClass.toBytecode());
00148         
00149 
00150 
00151         
00152 
00153 
00154 
00155 
00156         return bytecode; 
00157         } catch (Exception e) {
00158             e.printStackTrace();
00159             gatherLogger.error("cannot generate gather proxy interface class " + gatherProxyItfName );
00160             return null;
00161         }
00162         
00163     }
00164 
00165 }