package xapi.dev.scanner.impl; import java.util.Iterator; import java.util.concurrent.ExecutorService; import xapi.bytecode.ClassFile; import xapi.collect.api.Fifo; import xapi.collect.api.HasPrefixed; import xapi.collect.impl.SimpleFifo; import xapi.dev.resource.impl.ByteCodeResource; import xapi.util.api.MatchesValue; /** * Finds all classes that have any annotation. * * If you want more fine-grained search capabilities, * override {@link #matches(ClassFile)}. * * @author "James X. Nelson (james@wetheinter.net)" * */ class AnnotatedClassIterator implements Iterable<ClassFile>, MatchesValue<ClassFile> { final Iterator<ClassFile> allClasses; Fifo<ClassFile> results = new SimpleFifo<ClassFile>(); boolean working = true, waiting = false; public AnnotatedClassIterator(final ExecutorService executor, final HasPrefixed<ByteCodeResource> bytecode) { allClasses = new ClassFileIterator(this, bytecode).iterator(); executor.submit(new Runnable() { @Override public void run() { try { while (allClasses.hasNext()) { final ClassFile next = allClasses.next(); results.give(next); if (waiting) { synchronized(allClasses) { allClasses.notifyAll(); } waiting = false; } } } finally { working = false; } if (waiting) { synchronized(allClasses) { allClasses.notifyAll(); } } } }); } class Itr implements Iterator<ClassFile> { Iterator<ClassFile> itr = results.forEach().iterator(); @Override public boolean hasNext() { while (working) { if (itr.hasNext()) { return true; } try { synchronized (allClasses) { waiting = true; allClasses.wait(0, 25000); } } catch (final InterruptedException e) { Thread.currentThread().interrupt(); break; } } return itr.hasNext(); } @Override public ClassFile next() { return itr.next(); } @Override public void remove() { throw new UnsupportedOperationException(); } } @Override public Iterator<ClassFile> iterator() { return new Itr(); } @Override public boolean matches(final ClassFile value) { return value.getAnnotations().length > 0; } }