/* * Copyright 2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package jdave.runner; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Collection; import java.util.List; import net.sf.cglib.asm.Attribute; import net.sf.cglib.asm.ClassAdapter; import net.sf.cglib.asm.ClassReader; import net.sf.cglib.asm.ClassWriter; import net.sf.cglib.asm.attrs.Annotation; import net.sf.cglib.asm.attrs.Attributes; import net.sf.cglib.asm.attrs.RuntimeVisibleAnnotations; /** * @author Joni Freeman */ public abstract class AnnotatedSpecScanner { private Scanner scanner; public AnnotatedSpecScanner(String path) { scanner = new Scanner(path); } public void forEach(final IAnnotatedSpecHandler annotatedSpecHandler) { scanner.forEach("class", new IFileHandler() { public void handle(File file) { try { AnnotationReader reader = new AnnotationReader(new BufferedInputStream(new FileInputStream(file))); if (reader.getGroups() != null) { annotatedSpecHandler.handle(reader.getClassname(), reader.getGroups()); } } catch (IOException e) { throw new RuntimeException(e); } } }); } public abstract boolean isInDefaultGroup(String classname, Collection<Annotation> annotations); class AnnotationReader extends ClassAdapter { private String classname; private String[] groups; public AnnotationReader(InputStream classAsStream) throws IOException { super(new ClassWriter(false)); ClassReader reader = new ClassReader(classAsStream); reader.accept(this, Attributes.getDefaultAttributes(), true); classAsStream.close(); } public String[] getGroups() { return groups; } public String getClassname() { return classname; } @Override public void visit(int access, int arg1, String name, String superName, String[] interfaces, String sourceFile) { classname = name.replace('/', '.'); } @Override public void visitAttribute(Attribute attr) { if (attr instanceof RuntimeVisibleAnnotations) { visitRuntimeVisibleAnnotations((RuntimeVisibleAnnotations) attr); } } private void visitRuntimeVisibleAnnotations(RuntimeVisibleAnnotations annotations) { checkIfGroupAnnotationPresent(annotations); if (groups == null) { checkIfInDefaultGroup(annotations); } } private void checkIfGroupAnnotationPresent(RuntimeVisibleAnnotations annotations) { for (Object object : annotations.annotations) { Annotation annotation = (Annotation) object; if (annotation.type.equals("Ljdave/Group;")) { visitGroupAnnotation(annotation); } } } @SuppressWarnings("unchecked") private void checkIfInDefaultGroup(RuntimeVisibleAnnotations annotations) { if (isInDefaultGroup(classname, annotations.annotations)) { groups = new String[] { Groups.DEFAULT }; } } private void visitGroupAnnotation(Annotation annotation) { List<?> elementValues = annotation.elementValues; for (Object elementValue : elementValues) { Object[] values = (Object[]) elementValue; for (Object param : values) { if (param.getClass().isArray()) { Object[] params = (Object[]) param; groups = new String[params.length]; for (int j = 0; j < params.length; j++) { groups[j] = (String) params[j]; } } } } } } }