[WEAVER-12] Provide a mechanism for working with all classfiles found in the weave environment
git-svn-id: https://svn.apache.org/repos/asf/commons/proper/weaver/trunk@1743444 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/processor/src/main/java/org/apache/commons/weaver/Finder.java b/processor/src/main/java/org/apache/commons/weaver/Finder.java
index 475a008..b31a8a2 100644
--- a/processor/src/main/java/org/apache/commons/weaver/Finder.java
+++ b/processor/src/main/java/org/apache/commons/weaver/Finder.java
@@ -28,11 +28,14 @@
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collection;
import java.util.IdentityHashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
+import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.collections4.Predicate;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
@@ -390,23 +393,40 @@
return result;
}
+ /**
+ * Get the list of objects representing all scanned classes.
+ * @since 1.3
+ * @return {@link List} of {@link Annotated}{@code <Class<?>>}
+ */
+ public List<Annotated<Class<?>>> getAllClasses() {
+ return annotate(originalInfos.values());
+ }
+
public List<Annotated<Class<?>>> findAnnotatedClasses(final Class<? extends Annotation> annotation) {
Finder.this.findAnnotatedClasses(annotation);
+
+ final List<Annotated<Class<?>>> annotatedClasses = annotate(getAnnotationInfos(annotation.getName()));
+ CollectionUtils.filter(annotatedClasses, new Predicate<Annotated<Class<?>>>() {
+
+ @Override
+ public boolean evaluate(Annotated<Class<?>> annotatedClass) {
+ return annotatedClass.isAnnotationPresent(annotation);
+ }
+ });
+ return annotatedClasses;
+ }
+
+ private List<Annotated<Class<?>>> annotate(Collection<? extends Info> infos) {
final List<Annotated<Class<?>>> result = new ArrayList<Annotated<Class<?>>>();
- for (final Info info : getAnnotationInfos(annotation.getName())) {
+ for (final Info info : infos) {
if (info instanceof ClassInfo) {
final ClassInfo classInfo = (ClassInfo) info;
- IncludesClassfile<Class<?>> annotated;
try {
- annotated =
- new IncludesClassfile<Class<?>>(classInfo.get(), classfileAnnotationsFor(classInfo));
+ result.add(new IncludesClassfile<Class<?>>(classInfo.get(), classfileAnnotationsFor(classInfo)));
} catch (final ClassNotFoundException e) {
continue;
}
- if (annotated.isAnnotationPresent(annotation)) {
- result.add(annotated);
- }
}
}
return result;
@@ -660,57 +680,63 @@
public ScanResult scan(final ScanRequest request) {
final ScanResult result = new ScanResult();
- for (final WeaveInterest interest : request.getInterests()) {
- switch (interest.target) {
- case PACKAGE:
- for (final Annotated<Package> pkg : this.withAnnotations().findAnnotatedPackages(
- interest.annotationType)) {
- result.getWeavable(pkg.get()).addAnnotations(pkg.getAnnotations());
+ if (!request.isConstrained() || request.getSupertypes().contains(Object.class)) {
+ for (final Annotated<Class<?>> type : this.withAnnotations().getAllClasses()) {
+ result.getWeavable(type.get()).addAnnotations(type.getAnnotations());
+ }
+ } else {
+ for (final WeaveInterest interest : request.getInterests()) {
+ switch (interest.target) {
+ case PACKAGE:
+ for (final Annotated<Package> pkg : this.withAnnotations().findAnnotatedPackages(
+ interest.annotationType)) {
+ result.getWeavable(pkg.get()).addAnnotations(pkg.getAnnotations());
+ }
+ break;
+ case TYPE:
+ for (final Annotated<Class<?>> type : this.withAnnotations().findAnnotatedClasses(
+ interest.annotationType)) {
+ result.getWeavable(type.get()).addAnnotations(type.getAnnotations());
+ }
+ break;
+ case METHOD:
+ for (final Annotated<Method> method : this.withAnnotations().findAnnotatedMethods(
+ interest.annotationType)) {
+ result.getWeavable(method.get()).addAnnotations(method.getAnnotations());
+ }
+ break;
+ case CONSTRUCTOR:
+ for (final Annotated<Constructor<?>> ctor : this.withAnnotations().findAnnotatedConstructors(
+ interest.annotationType)) {
+ result.getWeavable(ctor.get()).addAnnotations(ctor.getAnnotations());
+ }
+ break;
+ case FIELD:
+ for (final Annotated<Field> fld : this.withAnnotations().findAnnotatedFields(interest.annotationType)) {
+ result.getWeavable(fld.get()).addAnnotations(fld.getAnnotations());
+ }
+ break;
+ case PARAMETER:
+ for (final Annotated<Parameter<Method>> parameter : this.withAnnotations()
+ .findAnnotatedMethodParameters(interest.annotationType)) {
+ result.getWeavable(parameter.get().getDeclaringExecutable())
+ .getWeavableParameter(parameter.get().getIndex()).addAnnotations(parameter.getAnnotations());
+ }
+ for (final Annotated<Parameter<Constructor<?>>> parameter : this.withAnnotations()
+ .findAnnotatedConstructorParameters(interest.annotationType)) {
+ result.getWeavable(parameter.get().getDeclaringExecutable())
+ .getWeavableParameter(parameter.get().getIndex()).addAnnotations(parameter.getAnnotations());
+ }
+ break;
+ default:
+ // should we log something?
+ break;
}
- break;
- case TYPE:
- for (final Annotated<Class<?>> type : this.withAnnotations().findAnnotatedClasses(
- interest.annotationType)) {
+ }
+ for (final Class<?> supertype : request.getSupertypes()) {
+ for (final Annotated<Class<?>> type : this.withAnnotations().findAssignableTypes(supertype)) {
result.getWeavable(type.get()).addAnnotations(type.getAnnotations());
}
- break;
- case METHOD:
- for (final Annotated<Method> method : this.withAnnotations().findAnnotatedMethods(
- interest.annotationType)) {
- result.getWeavable(method.get()).addAnnotations(method.getAnnotations());
- }
- break;
- case CONSTRUCTOR:
- for (final Annotated<Constructor<?>> ctor : this.withAnnotations().findAnnotatedConstructors(
- interest.annotationType)) {
- result.getWeavable(ctor.get()).addAnnotations(ctor.getAnnotations());
- }
- break;
- case FIELD:
- for (final Annotated<Field> fld : this.withAnnotations().findAnnotatedFields(interest.annotationType)) {
- result.getWeavable(fld.get()).addAnnotations(fld.getAnnotations());
- }
- break;
- case PARAMETER:
- for (final Annotated<Parameter<Method>> parameter : this.withAnnotations()
- .findAnnotatedMethodParameters(interest.annotationType)) {
- result.getWeavable(parameter.get().getDeclaringExecutable())
- .getWeavableParameter(parameter.get().getIndex()).addAnnotations(parameter.getAnnotations());
- }
- for (final Annotated<Parameter<Constructor<?>>> parameter : this.withAnnotations()
- .findAnnotatedConstructorParameters(interest.annotationType)) {
- result.getWeavable(parameter.get().getDeclaringExecutable())
- .getWeavableParameter(parameter.get().getIndex()).addAnnotations(parameter.getAnnotations());
- }
- break;
- default:
- // should we log something?
- break;
- }
- }
- for (final Class<?> supertype : request.getSupertypes()) {
- for (final Annotated<Class<?>> type : this.withAnnotations().findAssignableTypes(supertype)) {
- result.getWeavable(type.get()).addAnnotations(type.getAnnotations());
}
}
return inflater.inflate(result);
diff --git a/processor/src/main/java/org/apache/commons/weaver/model/ScanRequest.java b/processor/src/main/java/org/apache/commons/weaver/model/ScanRequest.java
index 08de040..06638b4 100644
--- a/processor/src/main/java/org/apache/commons/weaver/model/ScanRequest.java
+++ b/processor/src/main/java/org/apache/commons/weaver/model/ScanRequest.java
@@ -77,4 +77,13 @@
return Collections.unmodifiableSet(supertypes);
}
+ /**
+ * Learn whether this {@link ScanRequest} has been constrained. An unconstrained {@link ScanRequest} will return all
+ * known types.
+ * @return {@code boolean}
+ * @since 1.3
+ */
+ public boolean isConstrained() {
+ return !interests.isEmpty() || !supertypes.isEmpty();
+ }
}
diff --git a/processor/src/test/java/org/apache/commons/weaver/FinderTest.java b/processor/src/test/java/org/apache/commons/weaver/FinderTest.java
index bdceb42..d3832ad 100644
--- a/processor/src/test/java/org/apache/commons/weaver/FinderTest.java
+++ b/processor/src/test/java/org/apache/commons/weaver/FinderTest.java
@@ -26,17 +26,22 @@
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import java.io.IOException;
import java.lang.reflect.Field;
import java.net.URLClassLoader;
+import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.Set;
+import org.apache.commons.lang3.Validate;
import org.apache.commons.weaver.test.WeaverTestBase;
import org.apache.commons.weaver.test.beans.AbstractTestBean;
import org.apache.commons.weaver.test.beans.ComplexAnnotations;
@@ -49,6 +54,7 @@
import org.apache.commons.weaver.utils.URLArray;
import org.apache.xbean.finder.Annotated;
import org.apache.xbean.finder.archive.FileArchive;
+import org.hamcrest.Matchers;
import org.junit.Test;
public class FinderTest extends WeaverTestBase {
@@ -282,4 +288,28 @@
assertTrue(subclasses.contains(TestBeanWithClassAnnotation.class));
assertTrue(subclasses.contains(TestBeanWithMethodAnnotation.class));
}
+
+ @Test
+ public void testFindAllTypes() throws IOException {
+ addClassForScanning(TestBeanInterface.class);
+ addClassForScanning(AbstractTestBean.class);
+ addClassForScanning(TestBeanWithClassAnnotation.class);
+ addClassForScanning(TestBeanWithMethodAnnotation.class);
+
+ List<Annotated<Class<?>>> allClasses = finder().withAnnotations().getAllClasses();
+ assertThat(extract(allClasses), Matchers.<Class<?>> containsInAnyOrder(TestBeanInterface.class,
+ AbstractTestBean.class, TestBeanWithClassAnnotation.class, TestBeanWithMethodAnnotation.class));
+ }
+
+ private List<Class<?>> extract(List<Annotated<Class<?>>> input) {
+ Validate.noNullElements(input);
+ if (input.isEmpty()) {
+ return Collections.emptyList();
+ }
+ final List<Class<?>> result = new ArrayList<Class<?>>(input.size());
+ for (Annotated<Class<?>> c : input) {
+ result.add(c.get());
+ }
+ return result;
+ }
}