org/objectweb/proactive/core/component/gen/MetaObjectInterfaceClassGenerator.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.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"; //delegatee
00081     private static MetaObjectInterfaceClassGenerator instance;
00082 
00083     // this boolean for deciding of a possible indirection for the functionnal calls
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             // check whether class has already been generated
00114             try {
00115                 generated_class = loadClass(generatedClassFullName);
00116             } catch (ClassNotFoundException cnfe) {
00117                 CtMethod[] reifiedMethods;
00118                 CtClass generatedCtClass = pool.makeClass(generatedClassFullName);
00119 
00120                 //this.fcInterfaceName = fcInterfaceName;
00121                 //isPrimitive = ((ProActiveComponentRepresentativeImpl) owner).getHierarchicalType()
00122                 //                                                    .equals(ComponentParameters.PRIMITIVE);
00123                 List interfacesToImplement = new ArrayList();
00124 
00125                 // add interface to reify
00126                 CtClass functional_itf = pool.get(interfaceType.getFcItfSignature());
00127                 generatedCtClass.addInterface(functional_itf);
00128 
00129                 interfacesToImplement.add(functional_itf);
00130 
00131                 // add Serializable interface
00132                 interfacesToImplement.add(pool.get(Serializable.class.getName()));
00133                 generatedCtClass.addInterface(pool.get(
00134                         Serializable.class.getName()));
00135 
00136                 // add StubObject, so we can set the proxy
00137                 generatedCtClass.addInterface(pool.get(
00138                         StubObject.class.getName()));
00139 
00140                 //interfacesToImplement.add(pool.get(StubObject.class.getName()));
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                                 // field for overriden methods
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                 // field for generics parameters
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                 // list all methods to implement
00174                 Map methodsToImplement = new HashMap();
00175                 List classesIndexer = new Vector();
00176 
00177                 CtClass[] params;
00178                 CtClass itf;
00179 
00180                 // now get the methods from implemented interfaces
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                         // Build a key with the simple name of the method
00194                         // and the names of its parameters in the right order
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                         // this gives the actual declaring Class of this method
00203                         methodsToImplement.put(key, currentMethod);
00204                     }
00205                 }
00206 
00207                 reifiedMethods = (CtMethod[]) (methodsToImplement.values()
00208                                                                  .toArray(new CtMethod[methodsToImplement.size()]));
00209 
00210                 // Determines which reifiedMethods are valid for reification
00211                 // It is the responsibility of method checkMethod in class Utils
00212                 // to decide if a method is valid for reification or not
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 //                                generatedCtClass.writeFile("generated/");
00233 //                                System.out.println("[JAVASSIST] generated class : " +
00234 //                                    generatedClassFullName);
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                 // convert the bytes into a Class
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             //            System.out.println("method : " + reifiedMethods[i].getName() +
00286             //                " : \n" + body);
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 }

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