org/objectweb/proactive/core/component/gen/RepresentativeInterfaceClassGenerator.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.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     // this boolean for deciding of a possible indirection for the functionnal calls
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             // modify signature in type
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                 // TODO Auto-generated catch block
00124                 e.printStackTrace();
00125             } catch (InstantiationException e) {
00126                 // TODO Auto-generated catch block
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         // check whether class has already been generated
00138         try {
00139             generated_class = loadClass(representativeClassName);
00140         } catch (ClassNotFoundException cnfe) {
00141             byte[] bytecode = generateInterfaceByteCode(representativeClassName, itfType);
00142 
00143             try {
00144             // convert the bytes into a Class
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                         // infer a mock type from signature of representative
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             // add interface to reify
00174             CtClass functional_itf = pool.get(itfType.getFcItfSignature());
00175             
00176             generatedCtClass.addInterface(functional_itf);
00177 
00178             interfacesToImplement.add(functional_itf);
00179 
00180             // add Serializable interface
00181             interfacesToImplement.add(pool.get(Serializable.class.getName()));
00182             generatedCtClass.addInterface(pool.get(Serializable.class.getName()));
00183 
00184             // add StubObject, so we can set the proxy
00185             generatedCtClass.addInterface(pool.get(StubObject.class.getName()));
00186             
00187             // add ItfStubObject, so we can set the sender itf
00188             generatedCtClass.addInterface(pool.get(ItfStubObject.class.getName()));
00189             Utils.createItfStubObjectMethods(generatedCtClass);
00190 
00191             //interfacesToImplement.add(pool.get(StubObject.class.getName()));
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             // field for remembering generic parameters
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             // list all methods to implement
00228             Map methodsToImplement = new HashMap();
00229             List classesIndexer = new Vector();
00230 
00231             CtClass[] params;
00232             CtClass itf;
00233 
00234             // now get the methods from implemented interfaces
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                     // Build a key with the simple name of the method
00250                     // and the names of its parameters in the right order
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                     // this gives the actual declaring Class of this method
00260                     methodsToImplement.put(key, currentMethod);
00261                 }
00262             }
00263 
00264             reifiedMethods = (CtMethod[]) (
00265                     methodsToImplement.values().toArray(new CtMethod[methodsToImplement.size()])
00266                 );
00267 
00268             // Determines which reifiedMethods are valid for reification
00269             // It is the responsibility of method checkMethod in class Utils
00270             // to decide if a method is valid for reification or not
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 //                                    generatedCtClass.writeFile("generated/");
00294 //                                    System.out.println("[JAVASSIST] generated class : " +
00295 //                                        representativeClassName);
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                     //boolean, byte, char, short, int, long, float, double
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 //                     System.out.println("method : " + reifiedMethods[i].getName() +
00409 //                         " : \n" + body);
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 }

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