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 }