Files
tubestation/build/annotationProcessors/classloader/JarClassIterator.java
Jim Chen 28393ad93c Bug 1192079 - Support inner classes in generated JNI wrapper; r=snorp
Currently, when we generate JNI wrapper for an inner class, the
resulting C++ class will not actually be a nested class of the enclosing
class. As a result, the class can be confusing to use. For example,
wrapping Java class GeckoThread.State results in two unrelated C++
classes, GeckoThread and State, and it'd be confusing to use State by
itself.

This patch adds support for inner classes. We start by scanning only for
top-level classes, and when processing each top-level class, we
recursively scan for inner classes through
JarClassIterator.getInnerClasses() and CodeGenerator.generateClasses().
For each Java inner classes, the resulting C++ class will be a nested
class. For example, wrapping GeckoThread.State will produce
widget::GeckoThread and widget::GeckoThread::State.
2015-08-13 00:53:39 -04:00

63 lines
2.2 KiB
Java

/* 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.classloader;
import java.util.Iterator;
/**
* Class for iterating over an IterableJarLoadingURLClassLoader's classes.
*/
public class JarClassIterator implements Iterator<ClassWithOptions> {
private IterableJarLoadingURLClassLoader mTarget;
private Iterator<String> mTargetClassListIterator;
public JarClassIterator(IterableJarLoadingURLClassLoader aTarget) {
mTarget = aTarget;
mTargetClassListIterator = aTarget.classNames.iterator();
}
@Override
public boolean hasNext() {
return mTargetClassListIterator.hasNext();
}
@Override
public ClassWithOptions next() {
String className = mTargetClassListIterator.next();
try {
Class<?> ret = mTarget.loadClass(className);
// Incremental builds can leave stale classfiles in the jar. Such classfiles will cause
// an exception at this point. We can safely ignore these classes - they cannot possibly
// ever be loaded as they conflict with their parent class and will be killed by
// Proguard later on anyway.
final Class<?> enclosingClass;
try {
enclosingClass = ret.getEnclosingClass();
} catch (IncompatibleClassChangeError e) {
return next();
}
if (enclosingClass != null) {
// Anonymous inner class - unsupported.
// Or named inner class, which will be processed when we process the outer class.
return next();
}
return new ClassWithOptions(ret, ret.getSimpleName());
} catch (ClassNotFoundException e) {
System.err.println("Unable to enumerate class: " + className + ". Corrupted jar file?");
e.printStackTrace();
System.exit(2);
}
return null;
}
@Override
public void remove() {
throw new UnsupportedOperationException("Removal of classes from iterator not supported.");
}
}