All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.opensymphony.xwork2.util.finder.ClassFinder Maven / Gradle / Ivy

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 com.opensymphony.xwork2.util.finder;

import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;

/**
 * ClassFinder searches the classpath of the specified ClassLoaderInterface for
 * packages, classes, constructors, methods, or fields with specific annotations.
 *
 * For security reasons ASM is used to find the annotations.  Classes are not
 * loaded unless they match the requirements of a called findAnnotated* method.
 * Once loaded, these classes are cached.
 *
 * The getClassesNotLoaded() method can be used immediately after any find*
 * method to get a list of classes which matched the find requirements (i.e.
 * contained the annotation), but were unable to be loaded.
 */
public interface ClassFinder {

    boolean isAnnotationPresent(Class annotation);

    /**
     * 

* Returns a list of classes that could not be loaded in last invoked findAnnotated* method. *

* *

* The list will only contain entries of classes whose byte code matched the requirements * of last invoked find* method, but were unable to be loaded and included in the results. *

* *

* The list returned is unmodifiable. Once obtained, the returned list will be a live view of the * results from the last findAnnotated* method call. *

* *

* This method is not thread safe. *

* * @return an unmodifiable live view of classes that could not be loaded in previous findAnnotated* call. */ List getClassesNotLoaded(); List findAnnotatedPackages(Class annotation); List findAnnotatedClasses(Class annotation); List findAnnotatedMethods(Class annotation); List findAnnotatedConstructors(Class annotation); List findAnnotatedFields(Class annotation); List findClassesInPackage(String packageName, boolean recursive); List findClasses(Test test); List findClasses(); ClassLoaderInterface getClassLoaderInterface(); public static interface Info { String getName(); List getAnnotations(); } public class AnnotationInfo extends Annotatable implements Info { private final String name; public AnnotationInfo(Annotation annotation){ this(annotation.getClass().getName()); } public AnnotationInfo(Class annotation) { this.name = annotation.getName().intern(); } public AnnotationInfo(String name) { name = name.replaceAll("^L|;$", ""); name = name.replace('/', '.'); this.name = name.intern(); } public String getName() { return name; } @Override public String toString() { return name; } } public class Annotatable { private final List annotations = new ArrayList<>(); public Annotatable(AnnotatedElement element) { for (Annotation annotation : element.getAnnotations()) { annotations.add(new AnnotationInfo(annotation.annotationType().getName())); } } public Annotatable() { } public List getAnnotations() { return annotations; } } public class PackageInfo extends Annotatable implements Info { private final String name; private final ClassInfo info; private final Package pkg; public PackageInfo(Package pkg){ super(pkg); this.pkg = pkg; this.name = pkg.getName(); this.info = null; } public PackageInfo(String name, ClassFinder classFinder) { info = new ClassInfo(name, null, classFinder); this.name = name; this.pkg = null; } public String getName() { return name; } public Package get() throws ClassNotFoundException { return (pkg != null)?pkg:info.get().getPackage(); } } public class ClassInfo extends Annotatable implements Info { private final String name; private final List methods = new ArrayList<>(); private final List constructors = new ArrayList<>(); private final String superType; private final List interfaces = new ArrayList<>(); private final List superInterfaces = new ArrayList<>(); private final List fields = new ArrayList<>(); private Class clazz; private ClassFinder classFinder; private ClassNotFoundException notFound; public ClassInfo(Class clazz, ClassFinder classFinder) { super(clazz); this.clazz = clazz; this.classFinder = classFinder; this.name = clazz.getName(); Class superclass = clazz.getSuperclass(); this.superType = superclass != null ? superclass.getName(): null; } public ClassInfo(String name, String superType, ClassFinder classFinder) { this.name = name; this.superType = superType; this.classFinder = classFinder; } public String getPackageName(){ return name.indexOf('.') > 0 ? name.substring(0, name.lastIndexOf('.')) : "" ; } public List getConstructors() { return constructors; } public List getInterfaces() { return interfaces; } public List getSuperInterfaces() { return superInterfaces; } public List getFields() { return fields; } public List getMethods() { return methods; } public String getName() { return name; } public String getSuperType() { return superType; } public Class get() throws ClassNotFoundException { if (clazz != null) return clazz; if (notFound != null) throw notFound; try { this.clazz = classFinder.getClassLoaderInterface().loadClass(name); return clazz; } catch (ClassNotFoundException notFound) { classFinder.getClassesNotLoaded().add(name); this.notFound = notFound; throw notFound; } } @Override public String toString() { return name; } } public class MethodInfo extends Annotatable implements Info { private final ClassInfo declaringClass; private final String returnType; private final String name; private final List> parameterAnnotations = new ArrayList<>(); public MethodInfo(ClassInfo info, Constructor constructor){ super(constructor); this.declaringClass = info; this.name = ""; this.returnType = Void.TYPE.getName(); } public MethodInfo(ClassInfo info, Method method){ super(method); this.declaringClass = info; this.name = method.getName(); this.returnType = method.getReturnType().getName(); } public MethodInfo(ClassInfo declarignClass, String name, String returnType) { this.declaringClass = declarignClass; this.name = name; this.returnType = returnType; } public List> getParameterAnnotations() { return parameterAnnotations; } public List getParameterAnnotations(int index) { if (index >= parameterAnnotations.size()) { for (int i = parameterAnnotations.size(); i <= index; i++) { List annotationInfos = new ArrayList<>(); parameterAnnotations.add(i, annotationInfos); } } return parameterAnnotations.get(index); } public String getName() { return name; } public ClassInfo getDeclaringClass() { return declaringClass; } public String getReturnType() { return returnType; } @Override public String toString() { return declaringClass + "@" + name; } } public class FieldInfo extends Annotatable implements Info { private final String name; private final String type; private final ClassInfo declaringClass; public FieldInfo(ClassInfo info, Field field){ super(field); this.declaringClass = info; this.name = field.getName(); this.type = field.getType().getName(); } public FieldInfo(ClassInfo declaringClass, String name, String type) { this.declaringClass = declaringClass; this.name = name; this.type = type; } public String getName() { return name; } public ClassInfo getDeclaringClass() { return declaringClass; } public String getType() { return type; } @Override public String toString() { return declaringClass + "#" + name; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy