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.io.IOException;
00034 import java.io.Serializable;
00035 import java.util.ArrayList;
00036 import java.util.HashMap;
00037 import java.util.Iterator;
00038 import java.util.List;
00039 import java.util.Map;
00040 import java.util.Vector;
00041 
00042 import javassist.CannotCompileException;
00043 import javassist.ClassPool;
00044 import javassist.CtClass;
00045 import javassist.CtField;
00046 import javassist.CtMethod;
00047 import javassist.CtNewMethod;
00048 import javassist.Modifier;
00049 import javassist.NotFoundException;
00050 
00051 import org.objectweb.fractal.api.Component;
00052 import org.objectweb.fractal.api.factory.InstantiationException;
00053 import org.objectweb.proactive.core.component.ItfStubObject;
00054 import org.objectweb.proactive.core.component.ProActiveInterface;
00055 import org.objectweb.proactive.core.component.ProActiveInterfaceImpl;
00056 import org.objectweb.proactive.core.component.exceptions.InterfaceGenerationFailedException;
00057 import org.objectweb.proactive.core.component.type.ProActiveInterfaceType;
00058 import org.objectweb.proactive.core.component.type.ProActiveTypeFactory;
00059 import org.objectweb.proactive.core.component.type.ProActiveTypeFactoryImpl;
00060 import org.objectweb.proactive.core.group.ProActiveGroup;
00061 import org.objectweb.proactive.core.mop.JavassistByteCodeStubBuilder;
00062 import org.objectweb.proactive.core.mop.StubObject;
00063 import org.objectweb.proactive.core.util.ClassDataCache;
00064 
00065 
00073 public class RepresentativeInterfaceClassGenerator extends AbstractInterfaceClassGenerator {
00074     private static RepresentativeInterfaceClassGenerator instance;
00075 
00076     
00077     protected boolean isPrimitive = false;
00078 
00079     public RepresentativeInterfaceClassGenerator() {
00080     }
00081 
00082     public static RepresentativeInterfaceClassGenerator instance() {
00083 
00084         if (instance == null) {
00085             return new RepresentativeInterfaceClassGenerator();
00086         } else {
00087             return instance;
00088         }
00089     }
00090 
00091 
00092     public ProActiveInterface generateInterface(final String interfaceName, Component owner,
00093         ProActiveInterfaceType interfaceType, boolean isInternal, boolean isFunctionalInterface)
00094         throws InterfaceGenerationFailedException {
00095 
00096         try {
00097             Class generated_class = generateInterfaceClass(interfaceType, isFunctionalInterface);
00098 
00099             ProActiveInterfaceImpl reference = (ProActiveInterfaceImpl) generated_class.newInstance();
00100             reference.setFcItfName(interfaceName);
00101             reference.setFcItfOwner(owner);
00102             reference.setFcType(interfaceType);
00103             reference.setFcIsInternal(isInternal);
00104 
00105             return reference;
00106         } catch (Exception e) {
00107             throw new InterfaceGenerationFailedException(
00108                     "Cannot generate representative on interface [" + interfaceName + "] with signature [" +  interfaceType.getFcItfSignature() + "] with javassist",
00109                     e);
00110         }
00111     }
00112 
00113     public Class generateInterfaceClass(ProActiveInterfaceType itfType,
00114         boolean isFunctionalInterface)
00115         throws NotFoundException, CannotCompileException, IOException {
00116         
00117         if (ProActiveTypeFactory.GATHER_CARDINALITY.equals(itfType.getFcCardinality())) {
00118             
00119             try {
00120                 Class gatherProxyItf = GatherInterfaceGenerator.generateInterface(itfType);
00121                 itfType = (ProActiveInterfaceType)ProActiveTypeFactoryImpl.instance().createFcItfType(itfType.getFcItfName(), gatherProxyItf.getName(), itfType.isFcClientItf(), itfType.isFcOptionalItf(), itfType.getFcCardinality());
00122             } catch (InterfaceGenerationFailedException e) {
00123                 
00124                 e.printStackTrace();
00125             } catch (InstantiationException e) {
00126                 
00127                 e.printStackTrace();
00128             }
00129         }
00130         
00131         String representativeClassName = org.objectweb.proactive.core.component.gen.Utils
00132             .getMetaObjectComponentRepresentativeClassName(
00133                     itfType.getFcItfName(),
00134                     itfType.getFcItfSignature());
00135         Class generated_class;
00136 
00137         
00138         try {
00139             generated_class = loadClass(representativeClassName);
00140         } catch (ClassNotFoundException cnfe) {
00141             byte[] bytecode = generateInterfaceByteCode(representativeClassName, itfType);
00142 
00143             try {
00144             
00145             generated_class = Utils.defineClass(representativeClassName, bytecode);
00146             } catch (Exception e) {
00147                 e.printStackTrace();
00148                 return null;
00149             }
00150         }
00151 
00152         return generated_class;
00153     }
00154 
00155     public static byte[] generateInterfaceByteCode(String representativeClassName,
00156         ProActiveInterfaceType itfType) {
00157 
00158         try {
00159                 
00160                 if (itfType == null) {
00161                         
00162                 String name = Utils.getInterfaceNameFromRepresentativeClassName(representativeClassName);
00163                 String signature = Utils.getInterfaceSignatureFromRepresentativeClassName(representativeClassName);
00164                 itfType = (ProActiveInterfaceType)ProActiveTypeFactoryImpl.instance().createFcItfType(name, signature, false, false, false);
00165                 }
00166                 String interfaceName = Utils.getMetaObjectComponentRepresentativeClassName(itfType.getFcItfName(), itfType.getFcItfSignature());
00167             CtMethod[] reifiedMethods;
00168             CtClass generatedCtClass = pool.makeClass(representativeClassName);
00169             
00170 
00171             List interfacesToImplement = new ArrayList();
00172 
00173             
00174             CtClass functional_itf = pool.get(itfType.getFcItfSignature());
00175             
00176             generatedCtClass.addInterface(functional_itf);
00177 
00178             interfacesToImplement.add(functional_itf);
00179 
00180             
00181             interfacesToImplement.add(pool.get(Serializable.class.getName()));
00182             generatedCtClass.addInterface(pool.get(Serializable.class.getName()));
00183 
00184             
00185             generatedCtClass.addInterface(pool.get(StubObject.class.getName()));
00186             
00187             
00188             generatedCtClass.addInterface(pool.get(ItfStubObject.class.getName()));
00189             Utils.createItfStubObjectMethods(generatedCtClass);
00190 
00191             
00192             List interfacesToImplementAndSuperInterfaces = new ArrayList(interfacesToImplement);
00193             addSuperInterfaces(interfacesToImplementAndSuperInterfaces);
00194             generatedCtClass.setSuperclass(pool.get(ProActiveInterfaceImpl.class.getName()));
00195             JavassistByteCodeStubBuilder.createStubObjectMethods(generatedCtClass);
00196             CtField interfaceNameField = new CtField(
00197                         ClassPool.getDefault().get(String.class.getName()),
00198                         "interfaceName",
00199                         generatedCtClass);
00200             interfaceNameField.setModifiers(Modifier.STATIC);
00201             generatedCtClass.addField(interfaceNameField, "\"" + interfaceName + "\"");
00202 
00203             CtField methodsField = new CtField(
00204                         pool.get("java.lang.reflect.Method[]"),
00205                         "overridenMethods",
00206                         generatedCtClass);
00207             methodsField.setModifiers(Modifier.STATIC);
00208 
00209             generatedCtClass.addField(methodsField);
00210             
00211             
00212             CtField genericTypesMappingField = new CtField(pool.get(
00213             "java.util.Map"), "genericTypesMapping",
00214             generatedCtClass);
00215 
00216             genericTypesMappingField.setModifiers(Modifier.STATIC);
00217             generatedCtClass.addField(genericTypesMappingField);
00218             
00219             
00220             String bodyForImplGetterAndSetter = "{throw new org.objectweb.proactive.core.ProActiveRuntimeException(\" representative interfaces do not implement getFcItfImpl or setFcItfImpl methods\");}";
00221             
00222             CtMethod implGetter = CtNewMethod.make("public Object getFcItfImpl() " + bodyForImplGetterAndSetter, generatedCtClass);
00223             generatedCtClass.addMethod(implGetter);
00224             CtMethod implSetter = CtNewMethod.make("public Object setFcItfImpl() " + bodyForImplGetterAndSetter, generatedCtClass);
00225             generatedCtClass.addMethod(implSetter);
00226             
00227             
00228             Map methodsToImplement = new HashMap();
00229             List classesIndexer = new Vector();
00230 
00231             CtClass[] params;
00232             CtClass itf;
00233 
00234             
00235             Iterator it = interfacesToImplementAndSuperInterfaces.iterator();
00236 
00237             while (it.hasNext()) {
00238                 itf = (CtClass) it.next();
00239 
00240                 if (!classesIndexer.contains(itf.getName())) {
00241                     classesIndexer.add(itf.getName());
00242                 }
00243 
00244                 CtMethod[] declaredMethods = itf.getDeclaredMethods();
00245 
00246                 for (int i = 0; i < declaredMethods.length; i++) {
00247                     CtMethod currentMethod = declaredMethods[i];
00248 
00249                     
00250                     
00251                     String key = "";
00252                     key = key + currentMethod.getName();
00253                     params = currentMethod.getParameterTypes();
00254 
00255                     for (int k = 0; k < params.length; k++) {
00256                         key = key + params[k].getName();
00257                     }
00258 
00259                     
00260                     methodsToImplement.put(key, currentMethod);
00261                 }
00262             }
00263 
00264             reifiedMethods = (CtMethod[]) (
00265                     methodsToImplement.values().toArray(new CtMethod[methodsToImplement.size()])
00266                 );
00267 
00268             
00269             
00270             
00271             Vector v = new Vector();
00272             int initialNumberOfMethods = reifiedMethods.length;
00273 
00274             for (int i = 0; i < initialNumberOfMethods; i++) {
00275 
00276                 if (JavassistByteCodeStubBuilder.checkMethod(reifiedMethods[i])) {
00277                     v.addElement(reifiedMethods[i]);
00278                 }
00279             }
00280 
00281             CtMethod[] validMethods = new CtMethod[v.size()];
00282             v.copyInto(validMethods);
00283 
00284             reifiedMethods = validMethods;
00285 
00286             JavassistByteCodeStubBuilder.createStaticInitializer(
00287                     generatedCtClass,
00288                     reifiedMethods,
00289                     classesIndexer, itfType.getFcItfSignature(), null);
00290 
00291             createReifiedMethods(generatedCtClass, reifiedMethods, itfType);
00292 
00293 
00294 
00295 
00296             byte[] bytecode = generatedCtClass.toBytecode();
00297             ClassDataCache.instance().addClassData(representativeClassName,
00298                     generatedCtClass.toBytecode());
00299 
00300             if (logger.isDebugEnabled()) {
00301                 logger.debug("added " + representativeClassName + " to cache");
00302             }
00303 
00304 
00305             return bytecode;
00306         } catch (Exception e) {
00307             e.printStackTrace();
00308             logger.error("Cannot generate class : " + representativeClassName);
00309             return null;
00310         }
00311     }
00312 
00313     protected static void createReifiedMethods(CtClass generatedClass, CtMethod[] reifiedMethods,
00314         ProActiveInterfaceType itfType) throws NotFoundException, CannotCompileException {
00315 
00316         for (int i = 0; i < reifiedMethods.length; i++) {
00317             CtClass[] paramTypes = reifiedMethods[i].getParameterTypes();
00318             String body = ("{\nObject[] parameters = new Object[" + paramTypes.length + "];\n");
00319 
00320             for (int j = 0; j < paramTypes.length; j++) {
00321 
00322                 if (paramTypes[j].isPrimitive()) {
00323                     body += (
00324                         "  parameters[" + j + "]="
00325                         + JavassistByteCodeStubBuilder.wrapPrimitiveParameter(
00326                                 paramTypes[j],
00327                                 "$" + (j + 1)) + ";\n"
00328                     );
00329                 } else {
00330                     body += ("  parameters[" + j + "]=$" + (j + 1) + ";\n");
00331                 }
00332             }
00333 
00334             CtClass returnType = reifiedMethods[i].getReturnType();
00335             String postWrap = null;
00336             String preWrap = null;
00337 
00338             if (returnType != CtClass.voidType) {
00339                 
00340                 if (itfType!=null && itfType.isFcMulticastItf()) {
00341                     preWrap = ProActiveGroup.class.getName()+".getGroup(";
00342                     postWrap=")";
00343                 } else if (!returnType.isPrimitive()) {
00344                     preWrap = "(" + returnType.getName() + ")";
00345                 } else {
00346 
00347                     
00348                     if (returnType.equals(CtClass.booleanType)) {
00349                         preWrap = "((Boolean)";
00350                         postWrap = ").booleanValue()";
00351                     }
00352 
00353                     if (returnType.equals(CtClass.byteType)) {
00354                         preWrap = "((Byte)";
00355                         postWrap = ").byteValue()";
00356                     }
00357 
00358                     if (returnType.equals(CtClass.charType)) {
00359                         preWrap = "((Character)";
00360                         postWrap = ").charValue()";
00361                     }
00362 
00363                     if (returnType.equals(CtClass.shortType)) {
00364                         preWrap = "((Short)";
00365                         postWrap = ").shortValue()";
00366                     }
00367 
00368                     if (returnType.equals(CtClass.intType)) {
00369                         preWrap = "((Integer)";
00370                         postWrap = ").intValue()";
00371                     }
00372 
00373                     if (returnType.equals(CtClass.longType)) {
00374                         preWrap = "((Long)";
00375                         postWrap = ").longValue()";
00376                     }
00377 
00378                     if (returnType.equals(CtClass.floatType)) {
00379                         preWrap = "((Float)";
00380                         postWrap = ").floatValue()";
00381                     }
00382 
00383                     if (returnType.equals(CtClass.doubleType)) {
00384                         preWrap = "((Double)";
00385                         postWrap = ").doubleValue()";
00386                     }
00387                 }
00388 
00389                 body += "return ";
00390 
00391                 if (preWrap != null) {
00392                     body += preWrap;
00393                 }
00394             }
00395 
00396             body += (
00397                 "myProxy.reify(org.objectweb.proactive.core.mop.MethodCall.getComponentMethodCall("
00398                 + "(java.lang.reflect.Method)overridenMethods[" + i + "]"
00399                 + ", parameters, null, getFcItfName(), senderItfID))"
00400             );
00401 
00402             if (postWrap != null) {
00403                 body += postWrap;
00404             }
00405 
00406             body += ";";
00407             body += "\n}";
00408 
00409 
00410             CtMethod methodToGenerate = CtNewMethod.make(
00411                         reifiedMethods[i].getReturnType(),
00412                         reifiedMethods[i].getName(),
00413                         reifiedMethods[i].getParameterTypes(),
00414                         reifiedMethods[i].getExceptionTypes(),
00415                         body,
00416                         generatedClass);
00417             generatedClass.addMethod(methodToGenerate);
00418         }
00419     }
00420 }