1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/build/annotationProcessors/classloader/JarClassIterator.java Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,92 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +package org.mozilla.gecko.annotationProcessors.classloader; 1.9 + 1.10 +import java.lang.annotation.Annotation; 1.11 +import java.lang.reflect.InvocationTargetException; 1.12 +import java.lang.reflect.Method; 1.13 +import java.util.Iterator; 1.14 + 1.15 +/** 1.16 + * Class for iterating over an IterableJarLoadingURLClassLoader's classes. 1.17 + */ 1.18 +public class JarClassIterator implements Iterator<ClassWithOptions> { 1.19 + private IterableJarLoadingURLClassLoader mTarget; 1.20 + private Iterator<String> mTargetClassListIterator; 1.21 + 1.22 + public JarClassIterator(IterableJarLoadingURLClassLoader aTarget) { 1.23 + mTarget = aTarget; 1.24 + mTargetClassListIterator = aTarget.classNames.iterator(); 1.25 + } 1.26 + 1.27 + @Override 1.28 + public boolean hasNext() { 1.29 + return mTargetClassListIterator.hasNext(); 1.30 + } 1.31 + 1.32 + @Override 1.33 + public ClassWithOptions next() { 1.34 + String className = mTargetClassListIterator.next(); 1.35 + try { 1.36 + Class<?> ret = mTarget.loadClass(className); 1.37 + final String canonicalName; 1.38 + 1.39 + // Incremental builds can leave stale classfiles in the jar. Such classfiles will cause 1.40 + // an exception at this point. We can safely ignore these classes - they cannot possibly 1.41 + // ever be loaded as they conflict with their parent class and will be killed by Proguard 1.42 + // later on anyway. 1.43 + try { 1.44 + canonicalName = ret.getCanonicalName(); 1.45 + } catch (IncompatibleClassChangeError e) { 1.46 + return next(); 1.47 + } 1.48 + 1.49 + if (canonicalName == null || "null".equals(canonicalName)) { 1.50 + // Anonymous inner class - unsupported. 1.51 + return next(); 1.52 + } else { 1.53 + String generateName = null; 1.54 + for (Annotation annotation : ret.getAnnotations()) { 1.55 + Class<?> annotationType = annotation.annotationType(); 1.56 + if (annotationType.getCanonicalName().equals("org.mozilla.gecko.mozglue.generatorannotations.GeneratorOptions")) { 1.57 + try { 1.58 + // Determine the explicitly-given name of the stub to generate, if any. 1.59 + final Method generateNameMethod = annotationType.getDeclaredMethod("generatedClassName"); 1.60 + generateNameMethod.setAccessible(true); 1.61 + generateName = (String) generateNameMethod.invoke(annotation); 1.62 + break; 1.63 + } catch (NoSuchMethodException e) { 1.64 + System.err.println("Unable to find expected field on GeneratorOptions annotation. Did the signature change?"); 1.65 + e.printStackTrace(System.err); 1.66 + System.exit(3); 1.67 + } catch (IllegalAccessException e) { 1.68 + System.err.println("IllegalAccessException reading fields on GeneratorOptions annotation. Seems the semantics of Reflection have changed..."); 1.69 + e.printStackTrace(System.err); 1.70 + System.exit(4); 1.71 + } catch (InvocationTargetException e) { 1.72 + System.err.println("InvocationTargetException reading fields on GeneratorOptions annotation. This really shouldn't happen."); 1.73 + e.printStackTrace(System.err); 1.74 + System.exit(5); 1.75 + } 1.76 + } 1.77 + } 1.78 + if (generateName == null) { 1.79 + generateName = ret.getSimpleName(); 1.80 + } 1.81 + return new ClassWithOptions(ret, generateName); 1.82 + } 1.83 + } catch (ClassNotFoundException e) { 1.84 + System.err.println("Unable to enumerate class: " + className + ". Corrupted jar file?"); 1.85 + e.printStackTrace(); 1.86 + System.exit(2); 1.87 + } 1.88 + return null; 1.89 + } 1.90 + 1.91 + @Override 1.92 + public void remove() { 1.93 + throw new UnsupportedOperationException("Removal of classes from iterator not supported."); 1.94 + } 1.95 +}