build/annotationProcessors/utils/Utils.java

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 package org.mozilla.gecko.annotationProcessors.utils;
     7 import java.lang.annotation.Annotation;
     8 import java.lang.reflect.Constructor;
     9 import java.lang.reflect.Field;
    10 import java.lang.reflect.Member;
    11 import java.lang.reflect.Method;
    12 import java.lang.reflect.Modifier;
    13 import java.util.HashMap;
    15 /**
    16  * A collection of utility methods used by CodeGenerator. Largely used for translating types.
    17  */
    18 public class Utils {
    20     // A collection of lookup tables to simplify the functions to follow...
    21     private static final HashMap<String, String> sBasicCTypes = new HashMap<String, String>();
    23     static {
    24         sBasicCTypes.put("void", "void");
    25         sBasicCTypes.put("int", "int32_t");
    26         sBasicCTypes.put("boolean", "bool");
    27         sBasicCTypes.put("long", "int64_t");
    28         sBasicCTypes.put("double", "jdouble");
    29         sBasicCTypes.put("float", "jfloat");
    30         sBasicCTypes.put("char", "uint16_t");
    31         sBasicCTypes.put("byte", "int8_t");
    32         sBasicCTypes.put("short", "int16_t");
    33     }
    35     private static final HashMap<String, String> sArrayCTypes = new HashMap<String, String>();
    37     static {
    38         sArrayCTypes.put("int", "jintArray");
    39         sArrayCTypes.put("boolean", "jbooleanArray");
    40         sArrayCTypes.put("long", "jlongArray");
    41         sArrayCTypes.put("double", "jdoubleArray");
    42         sArrayCTypes.put("float", "jfloatArray");
    43         sArrayCTypes.put("char", "jcharArray");
    44         sArrayCTypes.put("byte", "jbyteArray");
    45         sArrayCTypes.put("short", "jshortArray");
    46     }
    48     private static final HashMap<String, String> sStaticCallTypes = new HashMap<String, String>();
    50     static {
    51         sStaticCallTypes.put("void", "CallStaticVoidMethod");
    52         sStaticCallTypes.put("int", "CallStaticIntMethod");
    53         sStaticCallTypes.put("boolean", "CallStaticBooleanMethod");
    54         sStaticCallTypes.put("long", "CallStaticLongMethod");
    55         sStaticCallTypes.put("double", "CallStaticDoubleMethod");
    56         sStaticCallTypes.put("float", "CallStaticFloatMethod");
    57         sStaticCallTypes.put("char", "CallStaticCharMethod");
    58         sStaticCallTypes.put("byte", "CallStaticByteMethod");
    59         sStaticCallTypes.put("short", "CallStaticShortMethod");
    60     }
    62     private static final HashMap<String, String> sInstanceCallTypes = new HashMap<String, String>();
    64     static {
    65         sInstanceCallTypes.put("void", "CallVoidMethod");
    66         sInstanceCallTypes.put("int", "CallIntMethod");
    67         sInstanceCallTypes.put("boolean", "CallBooleanMethod");
    68         sInstanceCallTypes.put("long", "CallLongMethod");
    69         sInstanceCallTypes.put("double", "CallDoubleMethod");
    70         sInstanceCallTypes.put("float", "CallFloatMethod");
    71         sInstanceCallTypes.put("char", "CallCharMethod");
    72         sInstanceCallTypes.put("byte", "CallByteMethod");
    73         sInstanceCallTypes.put("short", "CallShortMethod");
    74     }
    76     private static final HashMap<String, String> sFieldTypes = new HashMap<String, String>();
    78     static {
    79         sFieldTypes.put("int", "Int");
    80         sFieldTypes.put("boolean", "Boolean");
    81         sFieldTypes.put("long", "Long");
    82         sFieldTypes.put("double", "Double");
    83         sFieldTypes.put("float", "Float");
    84         sFieldTypes.put("char", "Char");
    85         sFieldTypes.put("byte", "Byte");
    86         sFieldTypes.put("short", "Short");
    87     }
    89     private static final HashMap<String, String> sFailureReturns = new HashMap<String, String>();
    91     static {
    92         sFailureReturns.put("java.lang.Void", "");
    93         sFailureReturns.put("void", "");
    94         sFailureReturns.put("int", " 0");
    95         sFailureReturns.put("boolean", " false");
    96         sFailureReturns.put("long", " 0");
    97         sFailureReturns.put("double", " 0.0");
    98         sFailureReturns.put("float", " 0.0");
    99         sFailureReturns.put("char", " 0");
   100         sFailureReturns.put("byte", " 0");
   101         sFailureReturns.put("short", " 0");
   102     }
   104     private static final HashMap<String, String> sCanonicalSignatureParts = new HashMap<String, String>();
   106     static {
   107         sCanonicalSignatureParts.put("java/lang/Void", "V");
   108         sCanonicalSignatureParts.put("void", "V");
   109         sCanonicalSignatureParts.put("int", "I");
   110         sCanonicalSignatureParts.put("boolean", "Z");
   111         sCanonicalSignatureParts.put("long", "J");
   112         sCanonicalSignatureParts.put("double", "D");
   113         sCanonicalSignatureParts.put("float", "F");
   114         sCanonicalSignatureParts.put("char", "C");
   115         sCanonicalSignatureParts.put("byte", "B");
   116         sCanonicalSignatureParts.put("short", "S");
   117     }
   120     private static final HashMap<String, String> sDefaultParameterValues = new HashMap<String, String>();
   122     static {
   123         sDefaultParameterValues.put("int", "0");
   124         sDefaultParameterValues.put("boolean", "false");
   125         sDefaultParameterValues.put("long", "0");
   126         sDefaultParameterValues.put("double", "0");
   127         sDefaultParameterValues.put("float", "0.0");
   128         sDefaultParameterValues.put("char", "0");
   129         sDefaultParameterValues.put("byte", "0");
   130         sDefaultParameterValues.put("short", "0");
   131     }
   133     /**
   134      * Get the C type corresponding to the provided type parameter. Used for generating argument
   135      * types for the wrapper method.
   136      *
   137      * @param type Class to determine the corresponding JNI type for.
   138      * @return true if the type an object type, false otherwise.
   139      */
   140     public static String getCParameterType(Class<?> type) {
   141         String name = type.getCanonicalName();
   142         if (sBasicCTypes.containsKey(name)) {
   143             return sBasicCTypes.get(name);
   144         }
   145         // Are we dealing with an array type?
   146         int len = name.length();
   147         if (name.endsWith("[]")) {
   148             // Determine if it is a 2D array - these map to jobjectArrays
   149             name = name.substring(0, len - 2);
   150             if (name.endsWith("[]")) {
   151                 return "jobjectArray";
   152             } else {
   153                 // Which flavour of Array is it?
   154                 if (sArrayCTypes.containsKey(name)) {
   155                     return sArrayCTypes.get(name);
   156                 }
   157                 return "jobjectArray";
   158             }
   159         }
   160         // Not an array type, check the remaining possibilities before we fall back to jobject
   162         // Check for CharSequences (Strings and things that are string-like)
   163         if (isCharSequence(type)) {
   164             return "const nsAString&";
   165         }
   167         if (name.equals("java.lang.Class")) {
   168             // You're doing reflection on Java objects from inside C, returning Class objects
   169             // to C, generating the corresponding code using this Java program. Really?!
   170             return "jclass";
   171         }
   172         if (name.equals("java.lang.Throwable")) {
   173             return "jthrowable";
   174         }
   175         return "jobject";
   176     }
   178     /**
   179      * For a given Java type, get the corresponding C++ type if we're returning it from a function.
   180      *
   181      * @param type The Java return type.
   182      * @return A string representation of the C++ return type.
   183      */
   184     public static String getCReturnType(Class<?> type) {
   185         if (type.getCanonicalName().equals("java.lang.Void")) {
   186             return "void";
   187         }
   188         String cParameterType = getCParameterType(type);
   189         if (cParameterType.equals("const nsAString&")) {
   190             return "jstring";
   191         } else {
   192             return cParameterType;
   193         }
   194     }
   196     /**
   197      * Gets the type-specific part of the  JNI function to use to get or set a field of a given type.
   198      *
   199      * @param aFieldType The Java type of the field.
   200      * @return A string representation of the JNI call function substring to use.
   201      */
   202     public static String getFieldType(Class<?> aFieldType) {
   203         String name = aFieldType.getCanonicalName();
   205         if (sFieldTypes.containsKey(name)) {
   206             return sFieldTypes.get(name);
   207         }
   208         return "Object";
   209     }
   211     /**
   212      * Gets the appropriate JNI call function to use to invoke a Java method with the given return
   213      * type. This, plus a call postfix (Such as "A") forms a complete JNI call function name.
   214      *
   215      * @param aReturnType The Java return type of the method being generated.
   216      * @param isStatic Boolean indicating if the underlying Java method is declared static.
   217      * @return A string representation of the JNI call function prefix to use.
   218      */
   219     public static String getCallPrefix(Class<?> aReturnType, boolean isStatic) {
   220         String name = aReturnType.getCanonicalName();
   221         if (isStatic) {
   222             if (sStaticCallTypes.containsKey(name)) {
   223                 return sStaticCallTypes.get(name);
   224             }
   225             return "CallStaticObjectMethod";
   226         } else {
   227             if (sInstanceCallTypes.containsKey(name)) {
   228                 return sInstanceCallTypes.get(name);
   229             }
   230             return "CallObjectMethod";
   231         }
   232     }
   234     /**
   235      * On failure, the generated method returns a null-esque value. This helper method gets the
   236      * appropriate failure return value for a given Java return type, plus a leading space.
   237      *
   238      * @param type Java return type of method being generated
   239      * @return String representation of the failure return value to be used in the generated code.
   240      */
   241     public static String getFailureReturnForType(Class<?> type) {
   242         String name = type.getCanonicalName();
   243         if (sFailureReturns.containsKey(name)) {
   244             return sFailureReturns.get(name);
   245         }
   246         return " nullptr";
   247     }
   249     /**
   250      * Helper method to get the type signature for methods, given argument and return type.
   251      * Allows for the near-identical logic needed for constructors and methods to be shared.
   252      * (Alas, constructor does not extend method)
   253      *
   254      * @param arguments Argument types of the underlying method.
   255      * @param returnType Return type of the underlying method.
   256      * @return The canonical Java type string for the method. eg. (IIIIFZ)Lorg/mozilla/gecko/gfx/ViewTransform;
   257      */
   258     private static String getTypeSignatureInternal(Class<?>[] arguments, Class<?> returnType) {
   259         StringBuilder sb = new StringBuilder();
   260         sb.append('(');
   262         // For each argument, write its signature component to the buffer..
   263         for (int i = 0; i < arguments.length; i++) {
   264             writeTypeSignature(sb, arguments[i]);
   265         }
   266         sb.append(')');
   268         // Write the return value's signature..
   269         writeTypeSignature(sb, returnType);
   270         return sb.toString();
   271     }
   273     /**
   274      * Get the canonical JNI type signature for a Field.
   275      *
   276      * @param aField The field to generate a signature for.
   277      * @return The canonical JNI type signature for this method.
   278      */
   279     protected static String getTypeSignatureStringForField(Field aField) {
   280         StringBuilder sb = new StringBuilder();
   281         writeTypeSignature(sb, aField.getType());
   282         return sb.toString();
   283     }
   285     /**
   286      * Get the canonical JNI type signature for a method.
   287      *
   288      * @param aMethod The method to generate a signature for.
   289      * @return The canonical JNI type signature for this method.
   290      */
   291     protected static String getTypeSignatureStringForMethod(Method aMethod) {
   292         Class<?>[] arguments = aMethod.getParameterTypes();
   293         Class<?> returnType = aMethod.getReturnType();
   294         return getTypeSignatureInternal(arguments, returnType);
   295     }
   297     /**
   298      * Get the canonical JNI type signature for a Constructor.
   299      *
   300      * @param aConstructor The Constructor to generate a signature for.
   301      * @return The canonical JNI type signature for this method.
   302      */
   303     protected static String getTypeSignatureStringForConstructor(Constructor aConstructor) {
   304         Class<?>[] arguments = aConstructor.getParameterTypes();
   305         return getTypeSignatureInternal(arguments, Void.class);
   306     }
   308     public static String getTypeSignatureStringForMember(Member aMember) {
   309         if (aMember instanceof Method) {
   310             return getTypeSignatureStringForMethod((Method) aMember);
   311         } else if (aMember instanceof Field) {
   312             return getTypeSignatureStringForField((Field) aMember);
   313         } else {
   314             return getTypeSignatureStringForConstructor((Constructor) aMember);
   315         }
   316     }
   318     public static String getTypeSignatureString(Constructor aConstructor) {
   319         Class<?>[] arguments = aConstructor.getParameterTypes();
   320         StringBuilder sb = new StringBuilder();
   321         sb.append('(');
   323         // For each argument, write its signature component to the buffer..
   324         for (int i = 0; i < arguments.length; i++) {
   325             writeTypeSignature(sb, arguments[i]);
   326         }
   328         // Constructors always return Void.
   329         sb.append(")V");
   330         return sb.toString();
   331     }
   333     /**
   334      * Helper method used by getTypeSignatureStringForMethod to build the signature. Write the subsignature
   335      * of a given type into the buffer.
   336      *
   337      * @param sb The buffer to write into.
   338      * @param c  The type of the element to write the subsignature of.
   339      */
   340     private static void writeTypeSignature(StringBuilder sb, Class<?> c) {
   341         String name = c.getCanonicalName().replaceAll("\\.", "/");
   343         // Determine if this is an array type and, if so, peel away the array operators..
   344         int len = name.length();
   345         while (name.endsWith("[]")) {
   346             sb.append('[');
   347             name = name.substring(0, len - 2);
   348             len = len - 2;
   349         }
   351         if (c.isArray()) {
   352             c = c.getComponentType();
   353         }
   355         Class<?> containerClass = c.getDeclaringClass();
   356         if (containerClass != null) {
   357             // Is an inner class. Add the $ symbol.
   358             final int lastSlash = name.lastIndexOf('/');
   359             name = name.substring(0, lastSlash) + '$' + name.substring(lastSlash+1);
   360         }
   362         // Look in the hashmap for the remainder...
   363         if (sCanonicalSignatureParts.containsKey(name)) {
   364             // It was a primitive type, so lookup was a success.
   365             sb.append(sCanonicalSignatureParts.get(name));
   366         } else {
   367             // It was a reference type - generate.
   368             sb.append('L');
   369             sb.append(name);
   370             sb.append(';');
   371         }
   372     }
   374     /**
   375      * Produces a C method signature, sans semicolon, for the given Java Method. Useful for both
   376      * generating header files and method bodies.
   377      *
   378      * @param aArgumentTypes Argument types of the Java method being wrapped.
   379      * @param aReturnType Return type of the Java method being wrapped.
   380      * @param aCMethodName Name of the method to generate in the C++ class.
   381      * @param aCClassName Name of the C++ class into which the method is declared.
   382      * @return The C++ method implementation signature for the method described.
   383      */
   384     public static String getCImplementationMethodSignature(Class<?>[] aArgumentTypes, Class<?> aReturnType, String aCMethodName, String aCClassName) {
   385         StringBuilder retBuffer = new StringBuilder();
   387         retBuffer.append(getCReturnType(aReturnType));
   388         retBuffer.append(' ');
   389         retBuffer.append(aCClassName);
   390         retBuffer.append("::");
   391         retBuffer.append(aCMethodName);
   392         retBuffer.append('(');
   394         // Write argument types...
   395         for (int aT = 0; aT < aArgumentTypes.length; aT++) {
   396             retBuffer.append(getCParameterType(aArgumentTypes[aT]));
   397             retBuffer.append(" a");
   398             // We, imaginatively, call our arguments a1, a2, a3...
   399             // The only way to preserve the names from Java would be to parse the
   400             // Java source, which would be computationally hard.
   401             retBuffer.append(aT);
   402             if (aT != aArgumentTypes.length - 1) {
   403                 retBuffer.append(", ");
   404             }
   405         }
   406         retBuffer.append(')');
   407         return retBuffer.toString();
   408     }
   410     /**
   411      * Produces a C method signature, sans semicolon, for the given Java Method. Useful for both
   412      * generating header files and method bodies.
   413      *
   414      * @param aArgumentTypes Argument types of the Java method being wrapped.
   415      * @param aArgumentAnnotations The annotations on the Java method arguments. Used to specify
   416      *                             default values etc.
   417      * @param aReturnType Return type of the Java method being wrapped.
   418      * @param aCMethodName Name of the method to generate in the C++ class.
   419      * @param aCClassName Name of the C++ class into which the method is declared.e
   420      * @param aIsStaticStub true if the generated C++ method should be static, false otherwise.
   421      * @return The generated C++ header method signature for the method described.
   422      */
   423     public static String getCHeaderMethodSignature(Class<?>[] aArgumentTypes, Annotation[][] aArgumentAnnotations, Class<?> aReturnType, String aCMethodName, String aCClassName, boolean aIsStaticStub) {
   424         StringBuilder retBuffer = new StringBuilder();
   426         // Add the static keyword, if applicable.
   427         if (aIsStaticStub) {
   428             retBuffer.append("static ");
   429         }
   431         // Write return type..
   432         retBuffer.append(getCReturnType(aReturnType));
   433         retBuffer.append(' ');
   434         retBuffer.append(aCMethodName);
   435         retBuffer.append('(');
   437         // Write argument types...
   438         for (int aT = 0; aT < aArgumentTypes.length; aT++) {
   439             retBuffer.append(getCParameterType(aArgumentTypes[aT]));
   440             retBuffer.append(" a");
   441             // We, imaginatively, call our arguments a1, a2, a3...
   442             // The only way to preserve the names from Java would be to parse the
   443             // Java source, which would be computationally hard.
   444             retBuffer.append(aT);
   446             // Append the default value, if there is one..
   447             retBuffer.append(getDefaultValueString(aArgumentTypes[aT], aArgumentAnnotations[aT]));
   449             if (aT != aArgumentTypes.length - 1) {
   450                 retBuffer.append(", ");
   451             }
   452         }
   453         retBuffer.append(')');
   454         return retBuffer.toString();
   455     }
   457     /**
   458      * If the given Annotation[] contains an OptionalGeneratedParameter annotation then return a
   459      * string assigning an argument of type aArgumentType to the default value for that type.
   460      * Otherwise, return the empty string.
   461      *
   462      * @param aArgumentType        The type of the argument to consider.
   463      * @param aArgumentAnnotations The annotations on the argument to consider.
   464      * @return An appropriate string to append to the signature of this argument assigning it to a
   465      *         default value (Or not, as applicable).
   466      */
   467     public static String getDefaultValueString(Class<?> aArgumentType, Annotation[] aArgumentAnnotations) {
   468         for (int i = 0; i < aArgumentAnnotations.length; i++) {
   469             Class<? extends Annotation> annotationType = aArgumentAnnotations[i].annotationType();
   470             final String annotationTypeName = annotationType.getName();
   471             if (annotationTypeName.equals("org.mozilla.gecko.mozglue.generatorannotations.OptionalGeneratedParameter")) {
   472                 return " = " + getDefaultParameterValueForType(aArgumentType);
   473             }
   474         }
   475         return "";
   476     }
   478     /**
   479      * Helper method to return an appropriate default parameter value for an argument of a given type.
   480      * The lookup table contains values for primitive types and strings. All other object types default
   481      * to null pointers.
   482      *
   483      * @param aArgumentType The parameter type for which a default value is desired.
   484      * @return An appropriate string representation of the default value selected, for use in generated
   485      *         C++ code.
   486      */
   487     private static String getDefaultParameterValueForType(Class<?> aArgumentType) {
   488         String typeName = aArgumentType.getCanonicalName();
   489         if (sDefaultParameterValues.containsKey(typeName)) {
   490             return sDefaultParameterValues.get(typeName);
   491         } else if (isCharSequence(aArgumentType)) {
   492             return "EmptyString()";
   493         } else {
   494             return "nullptr";
   495         }
   496     }
   498     /**
   499      * Helper method that returns the number of reference types in the arguments of m.
   500      *
   501      * @param aArgs The method arguments to consider.
   502      * @return How many of the arguments of m are nonprimitive.
   503      */
   504     public static int enumerateReferenceArguments(Class<?>[] aArgs) {
   505         int ret = 0;
   506         for (int i = 0; i < aArgs.length; i++) {
   507             String name = aArgs[i].getCanonicalName();
   508             if (!sBasicCTypes.containsKey(name)) {
   509                 ret++;
   510             }
   511         }
   512         return ret;
   513     }
   515     /**
   516      * Helper method that returns true iff the given method has a string argument.
   517      *
   518      * @param m The method to consider.
   519      * @return True if the given method has a string argument, false otherwise.
   520      */
   521     public static boolean hasStringArgument(Method m) {
   522         Class<?>[] args = m.getParameterTypes();
   523         for (int i = 0; i < args.length; i++) {
   524             if (isCharSequence(args[i])) {
   525                 return true;
   526             }
   527         }
   528         return false;
   529     }
   531     /**
   532      * Write the argument array assignment line for the given argument type. Does not support array
   533      * types.
   534      *
   535      * @param type    Type of this argument according to the target Java method's signature.
   536      * @param argName Wrapper function argument name corresponding to this argument.
   537      */
   538     public static String getArrayArgumentMashallingLine(Class<?> type, String argName) {
   539         StringBuilder sb = new StringBuilder();
   541         String name = type.getCanonicalName();
   542         if (sCanonicalSignatureParts.containsKey(name)) {
   543             sb.append(sCanonicalSignatureParts.get(name).toLowerCase());
   544             sb.append(" = ").append(argName).append(";\n");
   545         } else {
   546             if (isCharSequence(type)) {
   547                 sb.append("l = AndroidBridge::NewJavaString(env, ").append(argName).append(");\n");
   548             } else {
   549                 sb.append("l = ").append(argName).append(";\n");
   550             }
   551         }
   553         return sb.toString();
   554     }
   556     /**
   557      * Returns true if the type provided is an object type. Returns false otherwise
   558      *
   559      * @param aType The type to consider.
   560      * @return true if the method provided is an object type, false otherwise.
   561      */
   562     public static boolean isObjectType(Class<?> aType) {
   563         return !sBasicCTypes.containsKey(aType.getCanonicalName());
   564     }
   566     /**
   567      * For a given Java class, get the name of the value in C++ which holds a reference to it.
   568      *
   569      * @param aClass Target Java class.
   570      * @return The name of the C++ jclass entity referencing the given class.
   571      */
   572     public static String getClassReferenceName(Class<?> aClass) {
   573         String className = aClass.getSimpleName();
   574         return 'm' + className + "Class";
   575     }
   577     /**
   578      * Generate a line to get a global reference to the Java class given.
   579      *
   580      * @param aClass The target Java class.
   581      * @return The generated code to populate the reference to the class.
   582      */
   583     public static String getStartupLineForClass(Class<?> aClass) {
   584         StringBuilder sb = new StringBuilder();
   585         sb.append("    ");
   586         sb.append(getClassReferenceName(aClass));
   587         sb.append(" = getClassGlobalRef(\"");
   589         String name = aClass.getCanonicalName().replaceAll("\\.", "/");
   590         Class<?> containerClass = aClass.getDeclaringClass();
   591         if (containerClass != null) {
   592             // Is an inner class. Add the $ symbol.
   593             final int lastSlash = name.lastIndexOf('/');
   594             name = name.substring(0, lastSlash) + '$' + name.substring(lastSlash+1);
   595         }
   597         sb.append(name);
   598         sb.append("\");\n");
   599         return sb.toString();
   600     }
   602     /**
   603      * Helper method to determine if this object implements CharSequence
   604      * @param aClass Class to check for CharSequence-esqueness
   605      * @return True if the given class implements CharSequence, false otherwise.
   606      */
   607     public static boolean isCharSequence(Class<?> aClass) {
   608         if (aClass.getCanonicalName().equals("java.lang.CharSequence")) {
   609             return true;
   610         }
   611         Class<?>[] interfaces = aClass.getInterfaces();
   612         for (Class<?> c : interfaces) {
   613             if (c.getCanonicalName().equals("java.lang.CharSequence")) {
   614                 return true;
   615             }
   616         }
   617         return false;
   618     }
   620     /**
   621      * Helper method to read the modifier bits of the given method to determine if it is static.
   622      * @param aMember The Member to check.
   623      * @return true of the method is declared static, false otherwise.
   624      */
   625     public static boolean isMemberStatic(Member aMember) {
   626         int aMethodModifiers = aMember.getModifiers();
   627         return Modifier.isStatic(aMethodModifiers);
   628     }
   630     /**
   631      * Helper method to read the modifier bits of the given method to determine if it is static.
   632      * @param aMember The Member to check.
   633      * @return true of the method is declared static, false otherwise.
   634      */
   635     public static boolean isMemberFinal(Member aMember) {
   636         int aMethodModifiers = aMember.getModifiers();
   637         return Modifier.isFinal(aMethodModifiers);
   638     }
   639 }

mercurial