| /* This Source Code Form is subject to the terms of the Mozilla Public |
| * License, v. 2.0. If a copy of the MPL was not distributed with this |
| * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
| |
| package org.mozilla.gecko.annotationProcessors.utils; |
| |
| import org.mozilla.gecko.annotationProcessors.AnnotationInfo; |
| |
| import java.lang.reflect.Constructor; |
| import java.lang.reflect.Field; |
| import java.lang.reflect.Member; |
| import java.lang.reflect.Method; |
| import java.lang.reflect.Modifier; |
| import java.util.HashMap; |
| |
| /** |
| * A collection of utility methods used by CodeGenerator. Largely used for translating types. |
| */ |
| public class Utils { |
| |
| // A collection of lookup tables to simplify the functions to follow... |
| private static final HashMap<String, String> NATIVE_TYPES = new HashMap<String, String>(); |
| |
| static { |
| NATIVE_TYPES.put("void", "void"); |
| NATIVE_TYPES.put("boolean", "bool"); |
| NATIVE_TYPES.put("byte", "int8_t"); |
| NATIVE_TYPES.put("char", "char16_t"); |
| NATIVE_TYPES.put("short", "int16_t"); |
| NATIVE_TYPES.put("int", "int32_t"); |
| NATIVE_TYPES.put("long", "int64_t"); |
| NATIVE_TYPES.put("float", "float"); |
| NATIVE_TYPES.put("double", "double"); |
| } |
| |
| private static final HashMap<String, String> NATIVE_ARRAY_TYPES = new HashMap<String, String>(); |
| |
| static { |
| NATIVE_ARRAY_TYPES.put("boolean", "mozilla::jni::BooleanArray"); |
| NATIVE_ARRAY_TYPES.put("byte", "mozilla::jni::ByteArray"); |
| NATIVE_ARRAY_TYPES.put("char", "mozilla::jni::CharArray"); |
| NATIVE_ARRAY_TYPES.put("short", "mozilla::jni::ShortArray"); |
| NATIVE_ARRAY_TYPES.put("int", "mozilla::jni::IntArray"); |
| NATIVE_ARRAY_TYPES.put("long", "mozilla::jni::LongArray"); |
| NATIVE_ARRAY_TYPES.put("float", "mozilla::jni::FloatArray"); |
| NATIVE_ARRAY_TYPES.put("double", "mozilla::jni::DoubleArray"); |
| } |
| |
| private static final HashMap<String, String> CLASS_DESCRIPTORS = new HashMap<String, String>(); |
| |
| static { |
| CLASS_DESCRIPTORS.put("void", "V"); |
| CLASS_DESCRIPTORS.put("boolean", "Z"); |
| CLASS_DESCRIPTORS.put("byte", "B"); |
| CLASS_DESCRIPTORS.put("char", "C"); |
| CLASS_DESCRIPTORS.put("short", "S"); |
| CLASS_DESCRIPTORS.put("int", "I"); |
| CLASS_DESCRIPTORS.put("long", "J"); |
| CLASS_DESCRIPTORS.put("float", "F"); |
| CLASS_DESCRIPTORS.put("double", "D"); |
| } |
| |
| /** |
| * Get the C++ type corresponding to the provided type parameter. |
| * |
| * @param type Class to determine the corresponding JNI type for. |
| * @return C++ type as a String |
| */ |
| public static String getNativeParameterType(Class<?> type, AnnotationInfo info) { |
| final String name = type.getName().replace('.', '/'); |
| |
| if (NATIVE_TYPES.containsKey(name)) { |
| return NATIVE_TYPES.get(name); |
| } |
| |
| if (type.isArray()) { |
| final String compName = type.getComponentType().getName(); |
| if (NATIVE_ARRAY_TYPES.containsKey(compName)) { |
| return NATIVE_ARRAY_TYPES.get(compName) + "::Param"; |
| } |
| return "mozilla::jni::ObjectArray::Param"; |
| } |
| |
| if (type.equals(String.class) || type.equals(CharSequence.class)) { |
| return "mozilla::jni::String::Param"; |
| } |
| |
| if (type.equals(Class.class)) { |
| // You're doing reflection on Java objects from inside C, returning Class objects |
| // to C, generating the corresponding code using this Java program. Really?! |
| return "mozilla::jni::ClassObject::Param"; |
| } |
| |
| if (type.equals(Throwable.class)) { |
| return "mozilla::jni::Throwable::Param"; |
| } |
| |
| return "mozilla::jni::Object::Param"; |
| } |
| |
| public static String getNativeReturnType(Class<?> type, AnnotationInfo info) { |
| final String name = type.getName().replace('.', '/'); |
| |
| if (NATIVE_TYPES.containsKey(name)) { |
| return NATIVE_TYPES.get(name); |
| } |
| |
| if (type.isArray()) { |
| final String compName = type.getComponentType().getName(); |
| if (NATIVE_ARRAY_TYPES.containsKey(compName)) { |
| return NATIVE_ARRAY_TYPES.get(compName) + "::LocalRef"; |
| } |
| return "mozilla::jni::ObjectArray::LocalRef"; |
| } |
| |
| if (type.equals(String.class)) { |
| return "mozilla::jni::String::LocalRef"; |
| } |
| |
| if (type.equals(Class.class)) { |
| // You're doing reflection on Java objects from inside C, returning Class objects |
| // to C, generating the corresponding code using this Java program. Really?! |
| return "mozilla::jni::ClassObject::LocalRef"; |
| } |
| |
| if (type.equals(Throwable.class)) { |
| return "mozilla::jni::Throwable::LocalRef"; |
| } |
| |
| return "mozilla::jni::Object::LocalRef"; |
| } |
| |
| /** |
| * Get the JNI class descriptor corresponding to the provided type parameter. |
| * |
| * @param type Class to determine the corresponding JNI descriptor for. |
| * @return Class descripor as a String |
| */ |
| public static String getClassDescriptor(Class<?> type) { |
| final String name = type.getName().replace('.', '/'); |
| |
| if (CLASS_DESCRIPTORS.containsKey(name)) { |
| return CLASS_DESCRIPTORS.get(name); |
| } |
| |
| if (type.isArray()) { |
| // Array names are already in class descriptor form. |
| return name; |
| } |
| |
| return "L" + name + ';'; |
| } |
| |
| /** |
| * Get the JNI signaure for a member. |
| * |
| * @param member Member to get the signature for. |
| * @return JNI signature as a string |
| */ |
| public static String getSignature(Member member) { |
| return member instanceof Field ? getSignature((Field) member) : |
| member instanceof Method ? getSignature((Method) member) : |
| getSignature((Constructor<?>) member); |
| } |
| |
| /** |
| * Get the JNI signaure for a field. |
| * |
| * @param member Field to get the signature for. |
| * @return JNI signature as a string |
| */ |
| public static String getSignature(Field member) { |
| return getClassDescriptor(member.getType()); |
| } |
| |
| private static String getSignature(Class<?>[] args, Class<?> ret) { |
| final StringBuilder sig = new StringBuilder("("); |
| for (int i = 0; i < args.length; i++) { |
| sig.append(getClassDescriptor(args[i])); |
| } |
| return sig.append(')').append(getClassDescriptor(ret)).toString(); |
| } |
| |
| /** |
| * Get the JNI signaure for a method. |
| * |
| * @param member Method to get the signature for. |
| * @return JNI signature as a string |
| */ |
| public static String getSignature(Method member) { |
| return getSignature(member.getParameterTypes(), member.getReturnType()); |
| } |
| |
| /** |
| * Get the JNI signaure for a constructor. |
| * |
| * @param member Constructor to get the signature for. |
| * @return JNI signature as a string |
| */ |
| public static String getSignature(Constructor<?> member) { |
| return getSignature(member.getParameterTypes(), void.class); |
| } |
| |
| /** |
| * Get the C++ name for a member. |
| * |
| * @param member Member to get the name for. |
| * @return JNI name as a string |
| */ |
| public static String getNativeName(Member member) { |
| final String name = getMemberName(member); |
| return name.substring(0, 1).toUpperCase() + name.substring(1); |
| } |
| |
| /** |
| * Get the JNI name for a member. |
| * |
| * @param member Member to get the name for. |
| * @return JNI name as a string |
| */ |
| public static String getMemberName(Member member) { |
| if (member instanceof Constructor) { |
| return "<init>"; |
| } |
| return member.getName(); |
| } |
| |
| public static String getUnqualifiedName(String name) { |
| return name.substring(name.lastIndexOf(':') + 1); |
| } |
| |
| /** |
| * Determine if a member is declared static. |
| * |
| * @param member The Member to check. |
| * @return true if the member is declared static, false otherwise. |
| */ |
| public static boolean isStatic(final Member member) { |
| return Modifier.isStatic(member.getModifiers()); |
| } |
| |
| /** |
| * Determine if a member is declared final. |
| * |
| * @param member The Member to check. |
| * @return true if the member is declared final, false otherwise. |
| */ |
| public static boolean isFinal(final Member member) { |
| return Modifier.isFinal(member.getModifiers()); |
| } |
| } |