org/objectweb/proactive/core/mop/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.mop;
00032 
00033 import java.lang.reflect.Field;
00034 import java.lang.reflect.Method;
00035 import java.lang.reflect.Modifier;
00036 import java.util.ArrayList;
00037 import java.util.List;
00038 
00039 
00043 public abstract class Utils extends Object {
00044 
00048     public static final Class<?> JAVA_LANG_NUMBER = silentForName(
00049             "java.lang.Number");
00050     public static final Class<?> JAVA_LANG_CHARACTER = silentForName(
00051             "java.lang.Character");
00052     public static final Class<?> JAVA_LANG_BOOLEAN = silentForName(
00053             "java.lang.Boolean");
00054     public static final Class<?> JAVA_LANG_VOID = silentForName(
00055             "java.lang.Void");
00056     public static final Class<?> JAVA_LANG_RUNTIMEEXCEPTION = silentForName(
00057             "java.lang.RuntimeException");
00058     public static final Class<?> JAVA_LANG_EXCEPTION = silentForName(
00059             "java.lang.Exception");
00060     public static final Class<?> JAVA_LANG_THROWABLE = silentForName(
00061             "java.lang.Throwable");
00062 
00066     public static final char STUB_ESCAPE_CHAR = '_';
00067     public static final String STUB_ESCAPE = "" + STUB_ESCAPE_CHAR +
00068         STUB_ESCAPE_CHAR;
00069 
00073     public static final char STUB_PACKAGE_SEPARATOR_CHAR = 'P';
00074     public static final String STUB_PACKAGE_SEPARATOR = "" + STUB_ESCAPE_CHAR +
00075         STUB_PACKAGE_SEPARATOR_CHAR;
00076 
00080     public static final char STUB_GENERICS_SEPARATOR_CHAR = 'D';
00081     public static final String STUB_GENERICS_SEPARATOR = "" + STUB_ESCAPE_CHAR +
00082         STUB_GENERICS_SEPARATOR_CHAR;
00083 
00084     //prefix and suffix
00085     public static final String STUB_DEFAULT_PREFIX = STUB_ESCAPE_CHAR + "Stub";
00086 
00087     // stub on generic types are generated with a suffix that indicates the parameterizing types
00088     public static final String STUB_GENERICS_SUFFIX = STUB_ESCAPE_CHAR +
00089         "Generics";
00090 
00091     //  packages
00092     public static final String STUB_DEFAULT_PACKAGE = "pa.stub.";
00093 
00094     //  stub on generic types are generated in a different package
00095     public static final String STUB_GENERICS_PACKAGE = "parameterized.";
00096 
00109     static public String getRidOfNative(String in) {
00110         String result;
00111         int leftindex;
00112         int rightindex;
00113 
00114         leftindex = in.indexOf("native");
00115         if (leftindex == -1) {
00116             return in;
00117         }
00118         rightindex = leftindex + 6;
00119 
00120         result = in.substring(0, leftindex) +
00121             in.substring(rightindex, in.length());
00122         return result;
00123     }
00124 
00125     static public String getRidOfAbstract(String in) {
00126         String result;
00127         int leftindex;
00128         int rightindex;
00129 
00130         leftindex = in.indexOf("abstract");
00131         if (leftindex == -1) {
00132             return in;
00133         }
00134         rightindex = leftindex + 8;
00135 
00136         result = in.substring(0, leftindex) +
00137             in.substring(rightindex, in.length());
00138         return result;
00139     }
00140 
00141     static public String getRidOfNativeAndAbstract(String in) {
00142         String s = in;
00143         s = getRidOfAbstract(s);
00144         return getRidOfNative(s);
00145     }
00146 
00160     static public boolean checkMethod(Method met) {
00161         int modifiers = met.getModifiers();
00162 
00163         // Final methods cannot be reified since we cannot redefine them
00164         // in a subclass
00165         if (Modifier.isFinal(modifiers)) {
00166             return false;
00167         }
00168 
00169         // Static methods cannot be reified since they are not 'virtual'
00170         if (Modifier.isStatic(modifiers)) {
00171             return false;
00172         }
00173         if (!(Modifier.isPublic(modifiers))) {
00174             return false;
00175         }
00176 
00177         // If method is finalize (), don't reify it
00178         if ((met.getName().equals("finalize")) &&
00179                 (met.getParameterTypes().length == 0)) {
00180             return false;
00181         }
00182         return true;
00183     }
00184 
00197     static public String sourceLikeForm(Class cl) {
00198         if (!(cl.isArray())) {
00199             //to fix an issue with jdk1.3 and inner class
00200             // A$B should be A.B in source code
00201             //System.out.println("Remplacing in " + cl.getName());
00202             return cl.getName().replace('$', '.');
00203         } else {
00204             int nb = 0;
00205             Class current = cl;
00206             String result = "";
00207 
00208             do {
00209                 current = current.getComponentType();
00210                 result = "[]" + result;
00211                 nb++;
00212             } while ((current.getComponentType()) != null);
00213 
00214             result = current.getName() + result;
00215             return result;
00216         }
00217     }
00218 
00219     /*
00220      * Returns the name of the wrapper class for class <code>cl</code>.
00221      * If <code>cl</code> is not a primitive type, returns <code>null</code>
00222      */
00223     static public String nameOfWrapper(Class cl) {
00224         String str = cl.getName();
00225 
00226         if (cl.isPrimitive()) {
00227             if (str.equals("int")) {
00228                 return "java.lang.Integer";
00229             } else if (str.equals("boolean")) {
00230                 return "java.lang.Boolean";
00231             } else if (str.equals("byte")) {
00232                 return "java.lang.Byte";
00233             } else if (str.equals("short")) {
00234                 return "java.lang.Short";
00235             } else if (str.equals("long")) {
00236                 return "java.lang.Long";
00237             } else if (str.equals("float")) {
00238                 return "java.lang.Float";
00239             } else if (str.equals("double")) {
00240                 return "java.lang.Double";
00241             } else if (str.equals("void")) {
00242                 return "void";
00243             } else if (str.equals("char")) {
00244                 return "java.lang.Character";
00245             } else {
00246                 throw new InternalException("Unknown primitive type: " +
00247                     cl.getName());
00248             }
00249         } else {
00250             return null;
00251         }
00252     }
00253 
00254     /*
00255      * Extract the package name from the fully qualified class name given as
00256      * an argument
00257      */
00258     public static String getPackageName(String fqnameofclass) {
00259         int indexoflastdot;
00260 
00261         indexoflastdot = fqnameofclass.lastIndexOf('.');
00262 
00263         if (indexoflastdot == -1) {
00264             return "";
00265         } else {
00266             return fqnameofclass.substring(0, indexoflastdot);
00267         }
00268     }
00269 
00273     public static String getSimpleName(String fullyQualifiedNameOfClass) {
00274         int indexOfLastDot = fullyQualifiedNameOfClass.lastIndexOf('.');
00275         if (indexOfLastDot == -1) // There are no dots
00276          {
00277             return fullyQualifiedNameOfClass;
00278         } else {
00279             // If last character is a dot, returns an empty string
00280             if (indexOfLastDot == (fullyQualifiedNameOfClass.length() - 1)) {
00281                 return "";
00282             } else {
00283                 return fullyQualifiedNameOfClass.substring(indexOfLastDot + 1);
00284             }
00285         }
00286     }
00287 
00292     public static Class getWrapperClass(Class cl) {
00293         if (!(cl.isPrimitive())) {
00294             return null;
00295         }
00296         String s = Utils.nameOfWrapper(cl);
00297         try {
00298             return MOP.forName(s);
00299         } catch (ClassNotFoundException e) {
00300             throw new InternalException("Cannot load wrapper class " + s);
00301         }
00302     }
00303 
00307     public static Class getPrimitiveType(Class cl) {
00308         Field cst;
00309         if (Utils.isWrapperClass(cl)) {
00310             // These types are not classes , yet class static variables
00311             // We want to locale the TYPE field in the class
00312             try {
00313                 cst = cl.getField("TYPE");
00314                 return (Class) cst.get(null);
00315             } catch (NoSuchFieldException e) {
00316                 throw new InternalException(
00317                     "Cannot locate constant TYPE in class " + cl.getName());
00318             } catch (SecurityException e) {
00319                 throw new InternalException("Access to field TYPE in class " +
00320                     cl.getName() + " denied");
00321             } catch (IllegalAccessException e) {
00322                 throw new InternalException("Access to field TYPE in class " +
00323                     cl.getName() + " denied");
00324             }
00325         } else {
00326             throw new InternalException("Not a wrapper class: " + cl.getName());
00327         }
00328     }
00329 
00334     public static boolean isWrapperClass(Class<?> cl) {
00335         if (Utils.JAVA_LANG_NUMBER.isAssignableFrom(cl)) {
00336             return true;
00337         } else if (Utils.JAVA_LANG_BOOLEAN.isAssignableFrom(cl)) {
00338             return true;
00339         } else if (Utils.JAVA_LANG_CHARACTER.isAssignableFrom(cl)) {
00340             return true;
00341         } else if (Utils.JAVA_LANG_VOID.isAssignableFrom(cl)) {
00342             return true;
00343         } else {
00344             return false;
00345         }
00346     }
00347 
00348     public static String getRelativePath(String className) {
00349         String packageName;
00350         String fileSeparator;
00351         String result;
00352         int indexOfDot;
00353         int indexOfLastDot;
00354 
00355         fileSeparator = System.getProperty("file.separator");
00356         packageName = Utils.getPackageName(className);
00357 
00358         indexOfDot = packageName.indexOf((int) '.', 0);
00359         result = "";
00360         indexOfLastDot = 0;
00361 
00362         while (indexOfDot != -1) {
00363             result = result + fileSeparator +
00364                 packageName.substring(indexOfLastDot, indexOfDot);
00365             indexOfLastDot = indexOfDot + 1;
00366             indexOfDot = packageName.indexOf((int) '.', indexOfDot + 1);
00367             if (indexOfDot == -1) {
00368                 result = result + fileSeparator +
00369                     packageName.substring(indexOfLastDot, packageName.length());
00370             }
00371         }
00372 
00373         if (result.equals("")) {
00374             result = fileSeparator + packageName;
00375         }
00376 
00377         return result;
00378     }
00379 
00380     /*
00381        public static String getStubName(String nameOfClass) {
00382          return Utils.getPackageName(nameOfClass) + "." + STUB_DEFAULT_PREFIX + Utils.getSimpleName(nameOfClass);
00383        }
00384      */
00385     public static boolean isNormalException(Class exc) {
00386         boolean result;
00387 
00388         if (Utils.JAVA_LANG_THROWABLE.isAssignableFrom(exc)) {
00389             // It is a subclass of Throwable
00390             if (Utils.JAVA_LANG_EXCEPTION.isAssignableFrom(exc)) {
00391                 if (Utils.JAVA_LANG_RUNTIMEEXCEPTION.isAssignableFrom(exc)) {
00392                     result = false;
00393                 } else {
00394                     result = true;
00395                 }
00396             } else {
00397                 result = false; // This must be an Error
00398             }
00399         } else {
00400             result = false;
00401         }
00402 
00403         return result;
00404     }
00405 
00406     public static Class decipherPrimitiveType(String str) {
00407         if (str.equals("int")) {
00408             return java.lang.Integer.TYPE;
00409         } else if (str.equals("boolean")) {
00410             return java.lang.Boolean.TYPE;
00411         } else if (str.equals("byte")) {
00412             return java.lang.Byte.TYPE;
00413         } else if (str.equals("short")) {
00414             return java.lang.Short.TYPE;
00415         } else if (str.equals("long")) {
00416             return java.lang.Long.TYPE;
00417         } else if (str.equals("float")) {
00418             return java.lang.Float.TYPE;
00419         } else if (str.equals("double")) {
00420             return java.lang.Double.TYPE;
00421         } else if (str.equals("void")) {
00422             return java.lang.Void.TYPE;
00423         } else if (str.equals("char")) {
00424             return java.lang.Character.TYPE;
00425         }
00426 
00427         return null;
00428     }
00429 
00430     public static boolean isSuperTypeInArray(String className, Class[] types) {
00431         try {
00432             Class c = MOP.forName(className);
00433             return isSuperTypeInArray(c, types);
00434         } catch (ClassNotFoundException e) {
00435             throw new InternalException(e);
00436         }
00437     }
00438 
00439     public static boolean isSuperTypeInArray(Class c, Class<?>[] types) {
00440         for (int i = 0; i < types.length; i++) {
00441             if (types[i].isAssignableFrom(c)) {
00442                 return true;
00443             }
00444         }
00445         return false;
00446     }
00447 
00448     public static Object makeDeepCopy(Object source) throws java.io.IOException {
00449         java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
00450 
00451         //java.io.ObjectOutputStream oos = new java.io.ObjectOutputStream(baos);
00452         java.io.ObjectOutputStream oos = new PAObjectOutputStream(baos);
00453         oos.writeObject(source);
00454         oos.flush();
00455         oos.close();
00456         java.io.ByteArrayInputStream bais = new java.io.ByteArrayInputStream(baos.toByteArray());
00457 
00458         //    java.io.ObjectInputStream ois = new java.io.ObjectInputStream(bais);
00459         java.io.ObjectInputStream ois = new PAObjectInputStream(bais);
00460         try {
00461             Object result = ois.readObject();
00462             ois.close();
00463             return result;
00464         } catch (ClassNotFoundException e) {
00465             throw new java.io.IOException("ClassNotFoundException e=" + e);
00466         }
00467     }
00468 
00469     public static String convertClassNameToStubClassName(String classname,
00470         Class[] genericParameters) {
00471         if (classname.length() == 0) {
00472             return classname;
00473         }
00474         String packageName = getPackageName(classname);
00475         if (!packageName.equals("")) {
00476             packageName += ".";
00477         }
00478         packageName = STUB_DEFAULT_PACKAGE +
00479             (((genericParameters == null) || (genericParameters.length == 0))
00480             ? "" : STUB_GENERICS_PACKAGE) + packageName;
00481 
00482         String genericsDifferentiator = "";
00483         if (genericParameters != null) {
00484             for (Class gClassName : genericParameters) {
00485                 if (!genericsDifferentiator.equals("")) {
00486                     genericsDifferentiator += STUB_GENERICS_SEPARATOR;
00487                 }
00488                 genericsDifferentiator += escapeClassName(gClassName.getName());
00489             }
00490             if (!genericsDifferentiator.equals("")) {
00491                 genericsDifferentiator = STUB_GENERICS_SUFFIX +
00492                     genericsDifferentiator;
00493             }
00494         }
00495 
00496         return packageName + STUB_DEFAULT_PREFIX +
00497         escapeClassName(getSimpleName(classname)) + genericsDifferentiator;
00498     }
00499 
00500     public static boolean isStubClassName(String classname) {
00501         if (classname.startsWith(STUB_DEFAULT_PACKAGE)) {
00502             // Extracts the simple name from the fully-qualified class name
00503             int index = classname.lastIndexOf(".");
00504             if (index != -1) {
00505                 return classname.startsWith(Utils.STUB_DEFAULT_PREFIX, index +
00506                     1);
00507             } else {
00508                 return classname.startsWith(Utils.STUB_DEFAULT_PREFIX);
00509             }
00510         } else {
00511             return false;
00512         }
00513     }
00514 
00515     public static String convertStubClassNameToClassName(String stubclassname) {
00516         return unEscapeStubClassesName(stubclassname, false).get(0).toString();
00517     }
00518 
00519     public static String[] getNamesOfParameterizingTypesFromStubClassName(
00520         String stubClassName) {
00521         if (!isStubClassName(stubClassName)) {
00522             return new String[] {  };
00523         }
00524         if (!stubClassName.startsWith(Utils.STUB_DEFAULT_PACKAGE +
00525                     Utils.STUB_GENERICS_PACKAGE)) {
00526             // no generics
00527             return new String[] {  };
00528         }
00529         List<CharSequence> classesName = unEscapeStubClassesName(stubClassName,
00530                 true);
00531         classesName.remove(0);
00532         String[] result = new String[classesName.size()];
00533         for (int i = 0; i < result.length; i++) {
00534             result[i] = classesName.get(i).toString();
00535         }
00536         return result;
00537     }
00538 
00545     private static String escapeClassName(String className) {
00546         StringBuilder sb = new StringBuilder(className.length() * 2);
00547         for (int i = 0; i < className.length(); i++) {
00548             switch (className.charAt(i)) {
00549             case '.':
00550                 sb.append(STUB_PACKAGE_SEPARATOR);
00551                 break;
00552             case STUB_ESCAPE_CHAR:
00553                 sb.append(STUB_ESCAPE);
00554                 break;
00555             default:
00556                 sb.append(className.charAt(i));
00557                 break;
00558             }
00559         }
00560         return sb.toString();
00561     }
00562 
00569     private static List<CharSequence> unEscapeStubClassesName(
00570         String stubClassName, boolean withParameterizingTypes)
00571         throws IllegalArgumentException {
00572         ArrayList<CharSequence> result = new ArrayList<CharSequence>();
00573         StringBuilder sb = new StringBuilder(stubClassName.length());
00574         boolean stubFlag = false;
00575         boolean genericFlag = false;
00576         boolean genericPackage = false;
00577 
00578         if (isStubClassName(stubClassName)) {
00579             String temp = "";
00580             if (stubClassName.startsWith(Utils.STUB_DEFAULT_PACKAGE +
00581                         Utils.STUB_GENERICS_PACKAGE)) {
00582                 genericPackage = true;
00583                 // remove generics stuff
00584                 temp = stubClassName.substring((Utils.STUB_DEFAULT_PACKAGE +
00585                         Utils.STUB_GENERICS_PACKAGE).length());
00586             } else {
00587                 temp = stubClassName.substring(Utils.STUB_DEFAULT_PACKAGE.length());
00588             }
00589             temp = Utils.getPackageName(temp);
00590             if (temp.length() != 0) {
00591                 sb.append(temp);
00592                 sb.append('.');
00593             }
00594 
00595             //a Stub classe is necessary under a package i.e. Utils.STUB_DEFAULT_PACKAGE
00596             int begin = stubClassName.lastIndexOf('.');
00597             if (begin == -1) {
00598                 begin = 0;
00599             }
00600             for (int i = begin + 1; i < stubClassName.length(); i++) {
00601                 char c = stubClassName.charAt(i);
00602                 if (c != STUB_ESCAPE_CHAR) {
00603                     sb.append(c);
00604                 } else {
00605                     i++;
00606                     switch (stubClassName.charAt(i)) {
00607                     // one char Flags : 'STUB_ESCAPE_CHAR''a_char' 
00608                     case STUB_PACKAGE_SEPARATOR_CHAR:
00609                         sb.append('.');
00610                         break;
00611                     case STUB_ESCAPE_CHAR:
00612                         sb.append(STUB_ESCAPE_CHAR);
00613                         ;
00614                         break;
00615                     case STUB_GENERICS_SEPARATOR_CHAR:
00616                         result.add(sb);
00617                         sb = new StringBuilder(stubClassName.length());
00618                         break;
00619 
00620                     // multiple char Flags <=> 'STUB_ESCAPE_CHAR'"a_string"
00621                     case 'S':
00622                         if (stubClassName.startsWith(STUB_DEFAULT_PREFIX, i -
00623                                     1)) { //Stub
00624                             if (stubFlag) {
00625                                 throw new IllegalArgumentException(
00626                                     "The escapedClassesName is not a well formed escaped string at index " +
00627                                     i + ", the flag STUB_DEFAULT_PREFIX (" +
00628                                     STUB_DEFAULT_PREFIX +
00629                                     ") are present twice : " + stubClassName);
00630                             }
00631                             stubFlag = true;
00632                             i += (STUB_DEFAULT_PREFIX.length() - 2); // 2 char _S
00633                         }
00634                         break;
00635                     case 'G':
00636                         if (stubClassName.startsWith(STUB_GENERICS_SUFFIX, i -
00637                                     1)) { //Generics
00638                             if (genericFlag || !genericPackage) {
00639                                 throw new IllegalArgumentException(
00640                                     "The escapedClassesName is not a well formed escaped string at index " +
00641                                     i + ", the flag STUB_GENERICS_SUFFIX (" +
00642                                     STUB_GENERICS_SUFFIX +
00643                                     ") are present twice  or this class is not in the STUB_GENERICS_PACKAGE (" +
00644                                     STUB_DEFAULT_PACKAGE +
00645                                     STUB_GENERICS_PACKAGE + "): " +
00646                                     stubClassName);
00647                             }
00648                             genericFlag = true;
00649                             i += (STUB_GENERICS_SUFFIX.length() - 2); // 2 char _G
00650 
00651                             result.add(sb);
00652                             if (!withParameterizingTypes) {
00653                                 return result;
00654                             } else {
00655                                 sb = new StringBuilder(stubClassName.length());
00656                             }
00657                         }
00658                         break;
00659                     default:
00660                         //ERROR
00661                         throw new IllegalArgumentException(
00662                             "The escapedClassesName is not a well formed escaped string at index " +
00663                             i + " : " + stubClassName);
00664                     }
00665                 }
00666             }
00667             result.add(sb);
00668             return result;
00669         } else {
00670             result.add(stubClassName);
00671             return result;
00672         }
00673     }
00674 
00680     public static void addSuperInterfaces(Class cl, List<Class> superItfs) {
00681         if (!cl.isInterface()) {
00682             return;
00683         }
00684         Class[] super_interfaces = cl.getInterfaces();
00685         for (int i = 0; i < super_interfaces.length; i++) {
00686             superItfs.add(super_interfaces[i]);
00687             addSuperInterfaces(super_interfaces[i], superItfs);
00688         }
00689     }
00690 
00696     public static void addSuperInterfaces(List<Class> interfaces) {
00697         for (int i = 0; i < interfaces.size(); i++) {
00698             Class[] super_itfs_table = interfaces.get(i).getInterfaces();
00699             List<Class> super_itfs = new ArrayList<Class>(super_itfs_table.length); // resizable list
00700             for (int j = 0; j < super_itfs_table.length; j++) {
00701                 super_itfs.add(super_itfs_table[j]);
00702             }
00703             addSuperInterfaces(super_itfs);
00704             for (int j = 0; j < super_itfs.size(); j++) {
00705                 if (!interfaces.contains(super_itfs.get(j))) {
00706                     interfaces.add(super_itfs.get(j));
00707                 }
00708             }
00709         }
00710     }
00711 
00712     private static final Class silentForName(String classname) {
00713         try {
00714             return MOP.forName(classname);
00715         } catch (ClassNotFoundException e) {
00716             System.err.println(
00717                 "Static initializer in class org.objectweb.proactive.core.mop.Utils: Cannot load class " +
00718                 classname);
00719             return null;
00720         }
00721     }
00722 }

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