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.Serializable;
00034 import java.util.ArrayList;
00035 import java.util.HashMap;
00036 import java.util.Iterator;
00037 import java.util.List;
00038 import java.util.Map;
00039 import java.util.Vector;
00040 
00041 import javassist.CannotCompileException;
00042 import javassist.CtClass;
00043 import javassist.CtField;
00044 import javassist.CtMethod;
00045 import javassist.CtNewMethod;
00046 import javassist.Modifier;
00047 import javassist.NotFoundException;
00048 
00049 import org.objectweb.fractal.api.Component;
00050 import org.objectweb.fractal.api.type.InterfaceType;
00051 import org.objectweb.proactive.core.component.ProActiveInterface;
00052 import org.objectweb.proactive.core.component.ProActiveInterfaceImpl;
00053 import org.objectweb.proactive.core.component.exceptions.InterfaceGenerationFailedException;
00054 import org.objectweb.proactive.core.component.type.ProActiveInterfaceType;
00055 import org.objectweb.proactive.core.mop.JavassistByteCodeStubBuilder;
00056 import org.objectweb.proactive.core.mop.StubObject;
00057 import org.objectweb.proactive.core.util.ClassDataCache;
00058 import org.objectweb.proactive.core.util.log.Loggers;
00059 import org.objectweb.proactive.core.util.log.ProActiveLogger;
00060 
00061 
00078 public class MetaObjectInterfaceClassGenerator
00079     extends AbstractInterfaceClassGenerator {
00080     protected static final String IMPL_FIELD_NAME = "impl"; 
00081     private static MetaObjectInterfaceClassGenerator instance;
00082 
00083     
00084     protected boolean isPrimitive = false;
00085 
00086     public MetaObjectInterfaceClassGenerator() {
00087     }
00088 
00089     public static MetaObjectInterfaceClassGenerator instance() {
00090         if (instance == null) {
00091             return new MetaObjectInterfaceClassGenerator();
00092         } else {
00093             return instance;
00094         }
00095     }
00096 
00097     public ProActiveInterface generateInterface(final String interfaceName,
00098         Component owner, ProActiveInterfaceType interfaceType, boolean isInternal,
00099         boolean isFunctionalInterface)
00100         throws InterfaceGenerationFailedException {
00101         try {
00102             if (ProActiveLogger.getLogger(
00103                         Loggers.COMPONENTS_GEN_ITFS).isDebugEnabled()) {
00104                 ProActiveLogger.getLogger(Loggers.COMPONENTS_GEN_ITFS)
00105                                .debug("generating metaobject interface reference");
00106             }
00107 
00108             String generatedClassFullName = org.objectweb.proactive.core.component.gen.Utils.getMetaObjectClassName(interfaceName,
00109                     interfaceType.getFcItfSignature());
00110 
00111             Class generated_class;
00112 
00113             
00114             try {
00115                 generated_class = loadClass(generatedClassFullName);
00116             } catch (ClassNotFoundException cnfe) {
00117                 CtMethod[] reifiedMethods;
00118                 CtClass generatedCtClass = pool.makeClass(generatedClassFullName);
00119 
00120                 
00121                 
00122                 
00123                 List interfacesToImplement = new ArrayList();
00124 
00125                 
00126                 CtClass functional_itf = pool.get(interfaceType.getFcItfSignature());
00127                 generatedCtClass.addInterface(functional_itf);
00128 
00129                 interfacesToImplement.add(functional_itf);
00130 
00131                 
00132                 interfacesToImplement.add(pool.get(Serializable.class.getName()));
00133                 generatedCtClass.addInterface(pool.get(
00134                         Serializable.class.getName()));
00135 
00136                 
00137                 generatedCtClass.addInterface(pool.get(
00138                         StubObject.class.getName()));
00139 
00140                 
00141                 List interfacesToImplementAndSuperInterfaces = new ArrayList(interfacesToImplement);
00142                 addSuperInterfaces(interfacesToImplementAndSuperInterfaces);
00143                 generatedCtClass.setSuperclass(pool.get(
00144                         ProActiveInterfaceImpl.class.getName()));
00145                 JavassistByteCodeStubBuilder.createStubObjectMethods(generatedCtClass);
00146 
00147                 CtField implField = new CtField(pool.get(Object.class.getName()),
00148                         IMPL_FIELD_NAME, generatedCtClass);
00149                 generatedCtClass.addField(implField);
00150                 CtMethod implGetter = CtNewMethod.getter("getFcItfImpl",
00151                         implField);
00152                 generatedCtClass.addMethod(implGetter);
00153                 CtMethod implSetter = CtNewMethod.setter("setFcItfImpl",
00154                         implField);
00155                 generatedCtClass.addMethod(implSetter);
00156 
00157                                 
00158                 CtField methodsField = new CtField(pool.get(
00159                             "java.lang.reflect.Method[]"), "overridenMethods",
00160                         generatedCtClass);
00161                 methodsField.setModifiers(Modifier.STATIC);
00162                 generatedCtClass.addField(methodsField);
00163                 
00164                 
00165                 CtField genericTypesMappingField = new CtField(pool.get(
00166                 "java.util.Map"), "genericTypesMapping",
00167                 generatedCtClass);
00168 
00169                 genericTypesMappingField.setModifiers(Modifier.STATIC);
00170                 generatedCtClass.addField(genericTypesMappingField);
00171 
00172 
00173                 
00174                 Map methodsToImplement = new HashMap();
00175                 List classesIndexer = new Vector();
00176 
00177                 CtClass[] params;
00178                 CtClass itf;
00179 
00180                 
00181                 Iterator it = interfacesToImplementAndSuperInterfaces.iterator();
00182                 while (it.hasNext()) {
00183                     itf = (CtClass) it.next();
00184                     if (!classesIndexer.contains(itf.getName())) {
00185                         classesIndexer.add(itf.getName());
00186                     }
00187 
00188                     CtMethod[] declaredMethods = itf.getDeclaredMethods();
00189 
00190                     for (int i = 0; i < declaredMethods.length; i++) {
00191                         CtMethod currentMethod = declaredMethods[i];
00192 
00193                         
00194                         
00195                         String key = "";
00196                         key = key + currentMethod.getName();
00197                         params = currentMethod.getParameterTypes();
00198                         for (int k = 0; k < params.length; k++) {
00199                             key = key + params[k].getName();
00200                         }
00201 
00202                         
00203                         methodsToImplement.put(key, currentMethod);
00204                     }
00205                 }
00206 
00207                 reifiedMethods = (CtMethod[]) (methodsToImplement.values()
00208                                                                  .toArray(new CtMethod[methodsToImplement.size()]));
00209 
00210                 
00211                 
00212                 
00213                 Vector v = new Vector();
00214                 int initialNumberOfMethods = reifiedMethods.length;
00215 
00216                 for (int i = 0; i < initialNumberOfMethods; i++) {
00217                     if (JavassistByteCodeStubBuilder.checkMethod(
00218                                 reifiedMethods[i])) {
00219                         v.addElement(reifiedMethods[i]);
00220                     }
00221                 }
00222                 CtMethod[] validMethods = new CtMethod[v.size()];
00223                 v.copyInto(validMethods);
00224 
00225                 reifiedMethods = validMethods;
00226                 
00227                 JavassistByteCodeStubBuilder.createStaticInitializer(generatedCtClass,
00228                     reifiedMethods, classesIndexer, interfaceType.getFcItfSignature(), null);
00229 
00230                 createMethods(generatedCtClass, reifiedMethods, interfaceType);
00231 
00232 
00233 
00234 
00235                 byte[] bytecode = generatedCtClass.toBytecode();
00236                 ClassDataCache.instance().addClassData(generatedClassFullName,
00237                     generatedCtClass.toBytecode());
00238                 if (logger.isDebugEnabled()) {
00239                     logger.debug("added " + generatedClassFullName +
00240                         " to cache");
00241                 }
00242                 if (logger.isDebugEnabled()) {
00243                     logger.debug("generated classes cache is : " +
00244                         ClassDataCache.instance().toString());
00245                 }
00246 
00247                 
00248                 generated_class = Utils.defineClass(generatedClassFullName, bytecode);
00249             }
00250 
00251             ProActiveInterfaceImpl reference = (ProActiveInterfaceImpl) generated_class.newInstance();
00252             reference.setFcItfName(interfaceName);
00253             reference.setFcItfOwner(owner);
00254             reference.setFcType(interfaceType);
00255             reference.setFcIsInternal(isInternal);
00256 
00257             return reference;
00258         } catch (Exception e) {
00259                 throw new InterfaceGenerationFailedException(
00260                     "Cannot generate meta object representative on interface [" + interfaceName + "] with signature [" +  interfaceType.getFcItfSignature() + "] with javassist",
00261                     e);
00262         }
00263     }
00264 
00265     private void createMethods(CtClass generatedCtClass,
00266         CtMethod[] reifiedMethods, InterfaceType interfaceType)
00267         throws CannotCompileException, NotFoundException {
00268         for (int i = 0; i < reifiedMethods.length; i++) {
00269             CtClass[] paramTypes = reifiedMethods[i].getParameterTypes();
00270 
00271             String body = "return ";
00272             body += ("((" + interfaceType.getFcItfSignature() + ")");
00273             body += (IMPL_FIELD_NAME + ")." + reifiedMethods[i].getName() +
00274             "(");
00275             for (int j = 0; j < paramTypes.length; j++) {
00276                 body += ("(" + paramTypes[j].getName() + ")" + ("$" + (j + 1)));
00277                 if (j < (paramTypes.length - 1)) {
00278                     body += ",";
00279                 }
00280             }
00281             body += ")";
00282 
00283             body += ";";
00284             body += "\n}";
00285             
00286             
00287             CtMethod methodToGenerate = CtNewMethod.make(reifiedMethods[i].getReturnType(),
00288                     reifiedMethods[i].getName(),
00289                     reifiedMethods[i].getParameterTypes(),
00290                     reifiedMethods[i].getExceptionTypes(), body,
00291                     generatedCtClass);
00292             generatedCtClass.addMethod(methodToGenerate);
00293         }
00294     }
00295 }