build/annotationProcessors/utils/GeneratableElementIterator.java

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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 org.mozilla.gecko.annotationProcessors.AnnotationInfo;
     8 import org.mozilla.gecko.annotationProcessors.classloader.AnnotatableEntity;
    10 import java.lang.annotation.Annotation;
    11 import java.lang.reflect.AnnotatedElement;
    12 import java.lang.reflect.InvocationTargetException;
    13 import java.lang.reflect.Member;
    14 import java.lang.reflect.Method;
    15 import java.util.Arrays;
    16 import java.util.Iterator;
    18 /**
    19  * Iterator over the methods in a given method list which have the WrappedJNIMethod
    20  * annotation. Returns an object containing both the annotation (Which may contain interesting
    21  * parameters) and the argument.
    22  */
    23 public class GeneratableElementIterator implements Iterator<AnnotatableEntity> {
    24     private final Member[] mObjects;
    25     private AnnotatableEntity mNextReturnValue;
    26     private int mElementIndex;
    28     private boolean mIterateEveryEntry;
    30     public GeneratableElementIterator(Class<?> aClass) {
    31         // Get all the elements of this class as AccessibleObjects.
    32         Member[] aMethods = aClass.getDeclaredMethods();
    33         Member[] aFields = aClass.getDeclaredFields();
    34         Member[] aCtors = aClass.getConstructors();
    36         // Shove them all into one buffer.
    37         Member[] objs = new Member[aMethods.length + aFields.length + aCtors.length];
    39         int offset = 0;
    40         System.arraycopy(aMethods, 0, objs, 0, aMethods.length);
    41         offset += aMethods.length;
    42         System.arraycopy(aFields, 0, objs, offset, aFields.length);
    43         offset += aFields.length;
    44         System.arraycopy(aCtors, 0, objs, offset, aCtors.length);
    46         // Sort the elements to ensure determinism.
    47         Arrays.sort(objs, new AlphabeticAnnotatableEntityComparator());
    48         mObjects = objs;
    50         // Check for "Wrap ALL the things" flag.
    51         for (Annotation annotation : aClass.getDeclaredAnnotations()) {
    52             final String annotationTypeName = annotation.annotationType().getName();
    53             if (annotationTypeName.equals("org.mozilla.gecko.mozglue.generatorannotations.WrapEntireClassForJNI")) {
    54                 mIterateEveryEntry = true;
    55                 break;
    56             }
    57         }
    59         findNextValue();
    60     }
    62     /**
    63      * Find and cache the next appropriately annotated method, plus the annotation parameter, if
    64      * one exists. Otherwise cache null, so hasNext returns false.
    65      */
    66     private void findNextValue() {
    67         while (mElementIndex < mObjects.length) {
    68             Member candidateElement = mObjects[mElementIndex];
    69             mElementIndex++;
    70             for (Annotation annotation : ((AnnotatedElement) candidateElement).getDeclaredAnnotations()) {
    71                 // WrappedJNIMethod has parameters. Use Reflection to obtain them.
    72                 Class<? extends Annotation> annotationType = annotation.annotationType();
    73                 final String annotationTypeName = annotationType.getName();
    74                 if (annotationTypeName.equals("org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI")) {
    75                     String stubName = null;
    76                     boolean isStaticStub = false;
    77                     boolean isMultithreadedStub = false;
    78                     boolean noThrow = false;
    79                     try {
    80                         // Determine the explicitly-given name of the stub to generate, if any.
    81                         final Method stubNameMethod = annotationType.getDeclaredMethod("stubName");
    82                         stubNameMethod.setAccessible(true);
    83                         stubName = (String) stubNameMethod.invoke(annotation);
    85                         // Detemine if the generated stub should be static.
    86                         final Method staticStubMethod = annotationType.getDeclaredMethod("generateStatic");
    87                         staticStubMethod.setAccessible(true);
    88                         isStaticStub = (Boolean) staticStubMethod.invoke(annotation);
    90                         // Determine if the generated stub is to allow calls from multiple threads.
    91                         final Method multithreadedStubMethod = annotationType.getDeclaredMethod("allowMultithread");
    92                         multithreadedStubMethod.setAccessible(true);
    93                         isMultithreadedStub = (Boolean) multithreadedStubMethod.invoke(annotation);
    95                         // Determine if ignoring exceptions
    96                         final Method noThrowMethod = annotationType.getDeclaredMethod("noThrow");
    97                         noThrowMethod.setAccessible(true);
    98                         noThrow = (Boolean) noThrowMethod.invoke(annotation);
   100                     } catch (NoSuchMethodException e) {
   101                         System.err.println("Unable to find expected field on WrapElementForJNI annotation. Did the signature change?");
   102                         e.printStackTrace(System.err);
   103                         System.exit(3);
   104                     } catch (IllegalAccessException e) {
   105                         System.err.println("IllegalAccessException reading fields on WrapElementForJNI annotation. Seems the semantics of Reflection have changed...");
   106                         e.printStackTrace(System.err);
   107                         System.exit(4);
   108                     } catch (InvocationTargetException e) {
   109                         System.err.println("InvocationTargetException reading fields on WrapElementForJNI annotation. This really shouldn't happen.");
   110                         e.printStackTrace(System.err);
   111                         System.exit(5);
   112                     }
   114                     // If the method name was not explicitly given in the annotation generate one...
   115                     if (stubName.isEmpty()) {
   116                         String aMethodName = candidateElement.getName();
   117                         stubName = aMethodName.substring(0, 1).toUpperCase() + aMethodName.substring(1);
   118                     }
   120                     AnnotationInfo annotationInfo = new AnnotationInfo(
   121                         stubName, isStaticStub, isMultithreadedStub, noThrow);
   122                     mNextReturnValue = new AnnotatableEntity(candidateElement, annotationInfo);
   123                     return;
   124                 }
   125             }
   127             // If no annotation found, we might be expected to generate anyway using default arguments,
   128             // thanks to the "Generate everything" annotation.
   129             if (mIterateEveryEntry) {
   130                 AnnotationInfo annotationInfo = new AnnotationInfo(
   131                     candidateElement.getName(), false, false, false);
   132                 mNextReturnValue = new AnnotatableEntity(candidateElement, annotationInfo);
   133                 return;
   134             }
   135         }
   136         mNextReturnValue = null;
   137     }
   139     @Override
   140     public boolean hasNext() {
   141         return mNextReturnValue != null;
   142     }
   144     @Override
   145     public AnnotatableEntity next() {
   146         AnnotatableEntity ret = mNextReturnValue;
   147         findNextValue();
   148         return ret;
   149     }
   151     @Override
   152     public void remove() {
   153         throw new UnsupportedOperationException("Removal of methods from GeneratableElementIterator not supported.");
   154     }
   155 }

mercurial