org/objectweb/proactive/core/component/gen/Utils.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.lang.reflect.InvocationTargetException;
00034 import java.lang.reflect.Method;
00035 import java.util.ArrayList;
00036 
00037 import javassist.CannotCompileException;
00038 import javassist.ClassPool;
00039 import javassist.CtClass;
00040 import javassist.CtField;
00041 import javassist.CtMethod;
00042 import javassist.CtNewMethod;
00043 import javassist.NotFoundException;
00044 
00045 import org.objectweb.proactive.core.ProActiveRuntimeException;
00046 import org.objectweb.proactive.core.component.representative.ItfID;
00047 import org.objectweb.proactive.core.component.type.ProActiveInterfaceType;
00048 import org.objectweb.proactive.core.util.ClassDataCache;
00049 
00050 
00057 public class Utils {
00058 
00062     public static final char GEN_ESCAPE_CHAR = 'C';
00063     public static final String GEN_ESCAPE = "" + GEN_ESCAPE_CHAR +
00064         GEN_ESCAPE_CHAR;
00065 
00069     public static final char GEN_PACKAGE_SEPARATOR_CHAR = 'P';
00070     public static final String GEN_PACKAGE_SEPARATOR = "" + GEN_ESCAPE_CHAR +
00071         GEN_PACKAGE_SEPARATOR_CHAR;
00072 
00076     public static final char GEN_ITF_NAME_SEPARATOR_CHAR = 'I';
00077     public static final String GEN_ITF_NAME_SEPARATOR = "" + GEN_ESCAPE_CHAR +
00078         GEN_ITF_NAME_SEPARATOR_CHAR;
00079 
00083     public static final char GEN_MIDDLE_SEPARATOR_CHAR = 'O';
00084     public static final String GEN_MIDDLE_SEPARATOR = "" + GEN_ESCAPE_CHAR +
00085         GEN_MIDDLE_SEPARATOR_CHAR;
00086 
00087     // prefix and suffix
00088     public static final String GENERATED_DEFAULT_PREFIX = GEN_ESCAPE_CHAR +
00089         "generated";
00090     public static final String REPRESENTATIVE_DEFAULT_SUFFIX = GEN_ESCAPE_CHAR +
00091         "representative";
00092     public static final String GATHERCAST_ITF_PROXY_DEFAULT_SUFFIX = GEN_ESCAPE_CHAR +
00093         "gathercastItfProxy";
00094     public static final String COMPOSITE_REPRESENTATIVE_SUFFIX = GEN_ESCAPE_CHAR +
00095         "composite";
00096     public static final String OUTPUT_INTERCEPTOR_SUFFIX = GEN_ESCAPE_CHAR +
00097         "outputInterceptor";
00098 
00099     // packages
00100     public static final String STUB_DEFAULT_PACKAGE = null;
00101 
00102     public static boolean isRepresentativeClassName(String classname) {
00103         return (classname.startsWith(GENERATED_DEFAULT_PREFIX) &&
00104         classname.endsWith(REPRESENTATIVE_DEFAULT_SUFFIX));
00105     }
00106 
00107     public static boolean isMetaObjectClassName(String classname) {
00108         throw new ProActiveRuntimeException("not implemented yet");
00109     }
00110 
00111     public static boolean isGathercastProxyClassName(String classname) {
00112         return (classname.startsWith(GENERATED_DEFAULT_PREFIX) &&
00113         classname.endsWith(GATHERCAST_ITF_PROXY_DEFAULT_SUFFIX));
00114     }
00115 
00121     public static String getInterfaceSignatureFromRepresentativeClassName(
00122         String className) {
00123         if (!isRepresentativeClassName(className)) {
00124             return null;
00125         }
00126         String tmp = className.replaceAll("^" + GENERATED_DEFAULT_PREFIX, "");
00127         tmp = tmp.replaceAll(REPRESENTATIVE_DEFAULT_SUFFIX + "$", "");
00128         tmp = unEscapeClassesName(tmp, false).get(0).toString();
00129 
00130         return tmp;
00131     }
00132 
00133     public static String getInterfaceNameFromRepresentativeClassName(
00134         String className) {
00135         if (!isRepresentativeClassName(className)) {
00136             return null;
00137         }
00138         String tmp = className.replaceAll("^" + GENERATED_DEFAULT_PREFIX, "");
00139         tmp = tmp.replaceAll(REPRESENTATIVE_DEFAULT_SUFFIX + "$", "");
00140         tmp = unEscapeClassesName(tmp, true).get(1).toString();
00141 
00142         return tmp;
00143     }
00144 
00145     public static String getInterfaceSignatureFromGathercastProxyClassName(
00146         String className) {
00147         if (!isGathercastProxyClassName(className)) {
00148             return null;
00149         }
00150         String tmp = className.replaceAll("^" + GENERATED_DEFAULT_PREFIX, "");
00151         tmp = tmp.replaceAll(GATHERCAST_ITF_PROXY_DEFAULT_SUFFIX + "$", "");
00152         tmp = unEscapeClassesName(tmp, false).get(0).toString();
00153 
00154         return tmp;
00155     }
00156 
00157     public static String getMetaObjectClassName(
00158         String functionalInterfaceName, String javaInterfaceName) {
00159         // just a way to have an identifier (possibly not unique ? ... but readable)
00160         return (GENERATED_DEFAULT_PREFIX + escapeString(javaInterfaceName) +
00161         GEN_MIDDLE_SEPARATOR +
00162         escapeString(functionalInterfaceName)
00163         );
00164     }
00165 
00166     public static String getMetaObjectComponentRepresentativeClassName(
00167         String functionalInterfaceName, String javaInterfaceName) {
00168         // just a way to have an identifier (possibly not unique ... but readable)
00169         return (getMetaObjectClassName(functionalInterfaceName,
00170             javaInterfaceName) + REPRESENTATIVE_DEFAULT_SUFFIX);
00171     }
00172 
00173     public static String getGatherProxyItfClassName(
00174         ProActiveInterfaceType gatherItfType) {
00175         return (getMetaObjectClassName(gatherItfType.getFcItfName(),
00176             gatherItfType.getFcItfSignature()) +
00177         GATHERCAST_ITF_PROXY_DEFAULT_SUFFIX);
00178     }
00179 
00180     public static String getOutputInterceptorClassName(
00181         String functionalInterfaceName, String javaInterfaceName) {
00182         // just a way to have an identifier (possibly not unique ... but readable)
00183         return (getMetaObjectClassName(functionalInterfaceName,
00184             javaInterfaceName) + OUTPUT_INTERCEPTOR_SUFFIX);
00185     }
00186 
00187     public static Class defineClass(final String className, final byte[] bytes)
00188         throws ClassNotFoundException, SecurityException, NoSuchMethodException,
00189             IllegalArgumentException, IllegalAccessException,
00190             InvocationTargetException {
00191         // The following code invokes defineClass on the current thread classloader by reflection
00192         Class clc = Class.forName("java.lang.ClassLoader");
00193         Class[] argumentTypes = new Class[4];
00194         argumentTypes[0] = className.getClass();
00195         argumentTypes[1] = bytes.getClass();
00196         argumentTypes[2] = Integer.TYPE;
00197         argumentTypes[3] = Integer.TYPE;
00198 
00199         Method method = clc.getDeclaredMethod("defineClass", argumentTypes);
00200         method.setAccessible(true);
00201 
00202         Object[] effectiveArguments = new Object[4];
00203         effectiveArguments[0] = className;
00204         effectiveArguments[1] = bytes;
00205         effectiveArguments[2] = new Integer(0);
00206         effectiveArguments[3] = new Integer(bytes.length);
00207 
00208         return (Class) method.invoke(Thread.currentThread()
00209                                            .getContextClassLoader(),
00210             effectiveArguments);
00211     }
00212 
00213     public static void createItfStubObjectMethods(CtClass generatedClass)
00214         throws CannotCompileException, NotFoundException {
00215         // FIXME namespace pollution !
00216         CtField senderItfIDField = new CtField(ClassPool.getDefault()
00217                                                         .get(ItfID.class.getName()),
00218                 "senderItfID", generatedClass);
00219         CtField.Initializer initializer = CtField.Initializer.byExpr("null");
00220         generatedClass.addField(senderItfIDField, initializer);
00221         CtMethod senderItfIDGetter = CtNewMethod.getter("getSenderItfID",
00222                 senderItfIDField);
00223         generatedClass.addMethod(senderItfIDGetter);
00224         CtMethod senderItfIDSetter = CtNewMethod.setter("setSenderItfID",
00225                 senderItfIDField);
00226         generatedClass.addMethod(senderItfIDSetter);
00227     }
00228 
00232     public static byte[] getClassData(String classname) {
00233         byte[] bytecode = (byte[]) ClassDataCache.instance()
00234                                                  .getClassData(classname);
00235         if (bytecode != null) {
00236             return bytecode;
00237         }
00238         if (Utils.isRepresentativeClassName(classname)) {
00239             // try to generate a representative
00240             //            logger.info("Trying to generate representative class : " + classname);
00241             bytecode = RepresentativeInterfaceClassGenerator.generateInterfaceByteCode(classname,
00242                     null);
00243 
00244             if (bytecode != null) {
00245                 return bytecode;
00246             }
00247         }
00248 
00249         if (Utils.isGathercastProxyClassName(classname)) {
00250             // try to generate a representative
00251             //            logger.info("Trying to generate representative class : " + classname);
00252             bytecode = GatherInterfaceGenerator.generateInterfaceByteCode(classname);
00253 
00254             if (bytecode != null) {
00255                 return bytecode;
00256             }
00257         }
00258 
00259         return null;
00260     }
00261 
00267     private static String escapeString(String str) {
00268         StringBuilder sb = new StringBuilder(str.length() * 2);
00269         for (int i = 0; i < str.length(); i++) {
00270             switch (str.charAt(i)) {
00271             case GEN_ESCAPE_CHAR:
00272                 sb.append(GEN_ESCAPE);
00273                 break;
00274             case '.':
00275                 sb.append(GEN_PACKAGE_SEPARATOR);
00276                 break;
00277             case '-':
00278                 sb.append(GEN_ITF_NAME_SEPARATOR);
00279                 break;
00280             default:
00281                 sb.append(str.charAt(i));
00282                 break;
00283             }
00284         }
00285         return sb.toString();
00286     }
00287 
00294     private static ArrayList<CharSequence> unEscapeClassesName(
00295         String generatedClassName, boolean withItfName)
00296         throws IllegalArgumentException {
00297         ArrayList<CharSequence> result = new ArrayList<CharSequence>();
00298         StringBuilder sb = new StringBuilder(generatedClassName.length());
00299         boolean middleFlag = false;
00300 
00301         // if (isStubClassName(generatedClassName)) {
00302         int begin;
00303         if ((begin = generatedClassName.lastIndexOf('.')) == -1) {
00304             begin = 0;
00305         }
00306         for (int i = begin; i < generatedClassName.length(); i++) {
00307             char c = generatedClassName.charAt(i);
00308             if (c != GEN_ESCAPE_CHAR) {
00309                 sb.append(c);
00310             } else {
00311                 i++;
00312                 switch (generatedClassName.charAt(i)) {
00313                 // one char Flags : 'GEN_ESCAPE_CHAR''a_char' 
00314                 case GEN_ESCAPE_CHAR:
00315                     sb.append(GEN_ESCAPE_CHAR);
00316                     ;
00317                     break;
00318                 case GEN_PACKAGE_SEPARATOR_CHAR:
00319                     sb.append('.');
00320                     break;
00321                 case GEN_ITF_NAME_SEPARATOR_CHAR:
00322                     if (!middleFlag) {
00323                         throw new IllegalArgumentException(
00324                             "The generatedClassName is not a well formed escaped string at index " +
00325                             i + ", the flag GEN_ITF_NAME_SEPARATOR (" +
00326                             GEN_ITF_NAME_SEPARATOR +
00327                             ") is present whereasthis is not the interface name part : " +
00328                             generatedClassName);
00329                     }
00330                     sb.append('-');
00331                     break;
00332                 case GEN_MIDDLE_SEPARATOR_CHAR:
00333                     result.add(sb);
00334                     middleFlag = true;
00335                     if (!withItfName) {
00336                         return result;
00337                     }
00338                     sb = new StringBuilder(generatedClassName.length());
00339                     break;
00340                 default:
00341                     //ERROR
00342                     throw new IllegalArgumentException(
00343                         "The generatedClassName is not a well formed escaped string at index " +
00344                         i + " : " + generatedClassName);
00345                 }
00346             }
00347         }
00348         result.add(sb);
00349         return result;
00350         //            } else {
00351         //                result.add(generatedClassName);
00352         //                return result;
00353         //            }
00354     }
00355 }

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