JarClassIterator.java 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  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/. */
  4. package org.mozilla.gecko.annotationProcessors.classloader;
  5. import java.util.Iterator;
  6. /**
  7. * Class for iterating over an IterableJarLoadingURLClassLoader's classes.
  8. *
  9. * This class is not thread safe: use it only from a single thread.
  10. */
  11. public class JarClassIterator implements Iterator<ClassWithOptions> {
  12. private IterableJarLoadingURLClassLoader mTarget;
  13. private Iterator<String> mTargetClassListIterator;
  14. private ClassWithOptions lookAhead;
  15. public JarClassIterator(IterableJarLoadingURLClassLoader aTarget) {
  16. mTarget = aTarget;
  17. mTargetClassListIterator = aTarget.classNames.iterator();
  18. }
  19. @Override
  20. public boolean hasNext() {
  21. return fillLookAheadIfPossible();
  22. }
  23. @Override
  24. public ClassWithOptions next() {
  25. if (!fillLookAheadIfPossible()) {
  26. throw new IllegalStateException("Failed to look ahead in next()!");
  27. }
  28. ClassWithOptions next = lookAhead;
  29. lookAhead = null;
  30. return next;
  31. }
  32. private boolean fillLookAheadIfPossible() {
  33. if (lookAhead != null) {
  34. return true;
  35. }
  36. if (!mTargetClassListIterator.hasNext()) {
  37. return false;
  38. }
  39. String className = mTargetClassListIterator.next();
  40. try {
  41. Class<?> ret = mTarget.loadClass(className);
  42. // Incremental builds can leave stale classfiles in the jar. Such classfiles will cause
  43. // an exception at this point. We can safely ignore these classes - they cannot possibly
  44. // ever be loaded as they conflict with their parent class and will be killed by
  45. // Proguard later on anyway.
  46. final Class<?> enclosingClass;
  47. try {
  48. enclosingClass = ret.getEnclosingClass();
  49. } catch (IncompatibleClassChangeError e) {
  50. return fillLookAheadIfPossible();
  51. }
  52. if (enclosingClass != null) {
  53. // Anonymous inner class - unsupported.
  54. // Or named inner class, which will be processed when we process the outer class.
  55. return fillLookAheadIfPossible();
  56. }
  57. lookAhead = new ClassWithOptions(ret, ret.getSimpleName());
  58. return true;
  59. } catch (ClassNotFoundException e) {
  60. System.err.println("Unable to enumerate class: " + className + ". Corrupted jar file?");
  61. e.printStackTrace();
  62. System.exit(2);
  63. }
  64. return false;
  65. }
  66. @Override
  67. public void remove() {
  68. throw new UnsupportedOperationException("Removal of classes from iterator not supported.");
  69. }
  70. }