Wed, 31 Dec 2014 06:09:35 +0100
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 }