diff --git a/core/src/main/java/com/opensymphony/xwork2/util/finder/ClassFinder.java b/core/src/main/java/com/opensymphony/xwork2/util/finder/ClassFinder.java
index fcbd08e4e..92e213655 100644
--- a/core/src/main/java/com/opensymphony/xwork2/util/finder/ClassFinder.java
+++ b/core/src/main/java/com/opensymphony/xwork2/util/finder/ClassFinder.java
@@ -29,11 +29,11 @@ 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.
@@ -67,32 +67,32 @@ public interface ClassFinder {
List findAnnotatedPackages(Class extends Annotation> annotation);
- List findAnnotatedClasses(Class extends Annotation> annotation);
+ List> findAnnotatedClasses(Class extends Annotation> annotation);
List findAnnotatedMethods(Class extends Annotation> annotation);
- List findAnnotatedConstructors(Class extends Annotation> annotation);
+ List> findAnnotatedConstructors(Class extends Annotation> annotation);
List findAnnotatedFields(Class extends Annotation> annotation);
- List findClassesInPackage(String packageName, boolean recursive);
+ List> findClassesInPackage(String packageName, boolean recursive);
- List findClasses(Test test);
+ List> findClasses(Test test);
- List findClasses();
+ List> findClasses();
ClassLoaderInterface getClassLoaderInterface();
- public static interface Info {
+ interface Info {
String getName();
List getAnnotations();
}
- public class AnnotationInfo extends Annotatable implements Info {
+ class AnnotationInfo extends Annotatable implements Info {
private final String name;
- public AnnotationInfo(Annotation annotation){
+ public AnnotationInfo(Annotation annotation) {
this(annotation.getClass().getName());
}
@@ -116,7 +116,7 @@ public interface ClassFinder {
}
}
- public class Annotatable {
+ class Annotatable {
private final List annotations = new ArrayList<>();
public Annotatable(AnnotatedElement element) {
@@ -134,12 +134,12 @@ public interface ClassFinder {
}
- public class PackageInfo extends Annotatable implements Info {
+ class PackageInfo extends Annotatable implements Info {
private final String name;
private final ClassInfo info;
private final Package pkg;
- public PackageInfo(Package pkg){
+ public PackageInfo(Package pkg) {
super(pkg);
this.pkg = pkg;
this.name = pkg.getName();
@@ -157,11 +157,11 @@ public interface ClassFinder {
}
public Package get() throws ClassNotFoundException {
- return (pkg != null)?pkg:info.get().getPackage();
+ return (pkg != null) ? pkg : info.get().getPackage();
}
}
- public class ClassInfo extends Annotatable implements Info {
+ class ClassInfo extends Annotatable implements Info {
private final String name;
private final List methods = new ArrayList<>();
private final List constructors = new ArrayList<>();
@@ -169,17 +169,18 @@ public interface ClassFinder {
private final List interfaces = new ArrayList<>();
private final List superInterfaces = new ArrayList<>();
private final List fields = new ArrayList<>();
+ private final ClassFinder classFinder;
+
private Class> clazz;
- private ClassFinder classFinder;
private ClassNotFoundException notFound;
- public ClassInfo(Class clazz, ClassFinder classFinder) {
+ 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;
+ Class> superclass = clazz.getSuperclass();
+ this.superType = superclass != null ? superclass.getName() : null;
}
public ClassInfo(String name, String superType, ClassFinder classFinder) {
@@ -188,8 +189,8 @@ public interface ClassFinder {
this.classFinder = classFinder;
}
- public String getPackageName(){
- return name.indexOf('.') > 0 ? name.substring(0, name.lastIndexOf('.')) : "" ;
+ public String getPackageName() {
+ return name.indexOf('.') > 0 ? name.substring(0, name.lastIndexOf('.')) : "";
}
public List getConstructors() {
@@ -220,7 +221,7 @@ public interface ClassFinder {
return superType;
}
- public Class get() throws ClassNotFoundException {
+ public Class> get() throws ClassNotFoundException {
if (clazz != null) return clazz;
if (notFound != null) throw notFound;
try {
@@ -239,20 +240,20 @@ public interface ClassFinder {
}
}
- public class MethodInfo extends Annotatable implements Info {
+ 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){
+ public MethodInfo(ClassInfo info, Constructor> constructor) {
super(constructor);
this.declaringClass = info;
this.name = "";
this.returnType = Void.TYPE.getName();
}
- public MethodInfo(ClassInfo info, Method method){
+ public MethodInfo(ClassInfo info, Method method) {
super(method);
this.declaringClass = info;
this.name = method.getName();
@@ -297,12 +298,12 @@ public interface ClassFinder {
}
}
- public class FieldInfo extends Annotatable implements Info {
+ class FieldInfo extends Annotatable implements Info {
private final String name;
private final String type;
private final ClassInfo declaringClass;
- public FieldInfo(ClassInfo info, Field field){
+ public FieldInfo(ClassInfo info, Field field) {
super(field);
this.declaringClass = info;
this.name = field.getName();
diff --git a/plugins/convention/src/main/java/org/apache/struts2/convention/DefaultClassFinder.java b/plugins/convention/src/main/java/org/apache/struts2/convention/DefaultClassFinder.java
index 54d535811..9b6fdb86d 100644
--- a/plugins/convention/src/main/java/org/apache/struts2/convention/DefaultClassFinder.java
+++ b/plugins/convention/src/main/java/org/apache/struts2/convention/DefaultClassFinder.java
@@ -38,6 +38,7 @@ import org.objectweb.asm.Opcodes;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
@@ -45,7 +46,15 @@ import java.lang.reflect.Method;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLDecoder;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarInputStream;
@@ -57,9 +66,9 @@ public class DefaultClassFinder implements ClassFinder {
private final List classesNotLoaded = new ArrayList<>();
- private boolean extractBaseInterfaces;
- private ClassLoaderInterface classLoaderInterface;
- private FileManager fileManager;
+ private final ClassLoaderInterface classLoaderInterface;
+ private final boolean extractBaseInterfaces;
+ private final FileManager fileManager;
public DefaultClassFinder(ClassLoaderInterface classLoaderInterface, Collection urls, boolean extractBaseInterfaces, Set protocols, Test classNameFilter) {
this.classLoaderInterface = classLoaderInterface;
@@ -97,46 +106,6 @@ public class DefaultClassFinder implements ClassFinder {
}
}
- public DefaultClassFinder(Class... classes){
- this(Arrays.asList(classes));
- }
-
- public DefaultClassFinder(List classes){
- this.classLoaderInterface = null;
- List infos = new ArrayList<>();
- List packages = new ArrayList<>();
- for (Class clazz : classes) {
-
- Package aPackage = clazz.getPackage();
- if (aPackage != null && !packages.contains(aPackage)){
- infos.add(new PackageInfo(aPackage));
- packages.add(aPackage);
- }
-
- ClassInfo classInfo = new ClassInfo(clazz, this);
- infos.add(classInfo);
- classInfos.put(classInfo.getName(), classInfo);
- for (Method method : clazz.getDeclaredMethods()) {
- infos.add(new MethodInfo(classInfo, method));
- }
-
- for (Constructor constructor : clazz.getConstructors()) {
- infos.add(new MethodInfo(classInfo, constructor));
- }
-
- for (Field field : clazz.getDeclaredFields()) {
- infos.add(new FieldInfo(classInfo, field));
- }
- }
-
- for (Info info : infos) {
- for (AnnotationInfo annotation : info.getAnnotations()) {
- List annotationInfos = getAnnotationInfos(annotation.getName());
- annotationInfos.add(info);
- }
- }
- }
-
public ClassLoaderInterface getClassLoaderInterface() {
return classLoaderInterface;
}
@@ -171,15 +140,15 @@ public class DefaultClassFinder implements ClassFinder {
return packages;
}
- public List findAnnotatedClasses(Class extends Annotation> annotation) {
+ public List> findAnnotatedClasses(Class extends Annotation> annotation) {
classesNotLoaded.clear();
- List classes = new ArrayList<>();
+ List> classes = new ArrayList<>();
List infos = getAnnotationInfos(annotation.getName());
for (Info info : infos) {
if (info instanceof ClassInfo) {
ClassInfo classInfo = (ClassInfo) info;
try {
- Class clazz = classInfo.get();
+ Class> clazz = classInfo.get();
// double check via proper reflection
if (clazz.isAnnotationPresent(annotation)) {
classes.add(clazz);
@@ -208,7 +177,7 @@ public class DefaultClassFinder implements ClassFinder {
seen.add(classInfo);
try {
- Class clazz = classInfo.get();
+ Class> clazz = classInfo.get();
for (Method method : clazz.getDeclaredMethods()) {
if (method.isAnnotationPresent(annotation)) {
methods.add(method);
@@ -223,10 +192,10 @@ public class DefaultClassFinder implements ClassFinder {
return methods;
}
- public List findAnnotatedConstructors(Class extends Annotation> annotation) {
+ public List> findAnnotatedConstructors(Class extends Annotation> annotation) {
classesNotLoaded.clear();
List seen = new ArrayList<>();
- List constructors = new ArrayList<>();
+ List> constructors = new ArrayList<>();
List infos = getAnnotationInfos(annotation.getName());
for (Info info : infos) {
if (info instanceof MethodInfo && "".equals(info.getName())) {
@@ -238,8 +207,8 @@ public class DefaultClassFinder implements ClassFinder {
seen.add(classInfo);
try {
- Class clazz = classInfo.get();
- for (Constructor constructor : clazz.getConstructors()) {
+ Class> clazz = classInfo.get();
+ for (Constructor> constructor : clazz.getConstructors()) {
if (constructor.isAnnotationPresent(annotation)) {
constructors.add(constructor);
}
@@ -270,7 +239,7 @@ public class DefaultClassFinder implements ClassFinder {
seen.add(classInfo);
try {
- Class clazz = classInfo.get();
+ Class> clazz = classInfo.get();
for (Field field : clazz.getDeclaredFields()) {
if (field.isAnnotationPresent(annotation)) {
fields.add(field);
@@ -285,14 +254,14 @@ public class DefaultClassFinder implements ClassFinder {
return fields;
}
- public List findClassesInPackage(String packageName, boolean recursive) {
+ public List> findClassesInPackage(String packageName, boolean recursive) {
classesNotLoaded.clear();
- List classes = new ArrayList<>();
+ List> classes = new ArrayList<>();
for (ClassInfo classInfo : classInfos.values()) {
try {
- if (recursive && classInfo.getPackageName().startsWith(packageName)){
+ if (recursive && classInfo.getPackageName().startsWith(packageName)) {
classes.add(classInfo.get());
- } else if (classInfo.getPackageName().equals(packageName)){
+ } else if (classInfo.getPackageName().equals(packageName)) {
classes.add(classInfo.get());
}
} catch (Throwable e) {
@@ -303,9 +272,9 @@ public class DefaultClassFinder implements ClassFinder {
return classes;
}
- public List findClasses(Test test) {
+ public List> findClasses(Test test) {
classesNotLoaded.clear();
- List classes = new ArrayList<>();
+ List> classes = new ArrayList<>();
for (ClassInfo classInfo : classInfos.values()) {
try {
if (test.test(classInfo)) {
@@ -319,9 +288,9 @@ public class DefaultClassFinder implements ClassFinder {
return classes;
}
- public List findClasses() {
+ public List> findClasses() {
classesNotLoaded.clear();
- List classes = new ArrayList<>();
+ List> classes = new ArrayList<>();
for (ClassInfo classInfo : classInfos.values()) {
try {
classes.add(classInfo.get());
@@ -333,9 +302,9 @@ public class DefaultClassFinder implements ClassFinder {
return classes;
}
- private List file(URL location) {
+ private List file(URL location) throws UnsupportedEncodingException {
List classNames = new ArrayList<>();
- File dir = new File(URLDecoder.decode(location.getPath()));
+ File dir = new File(URLDecoder.decode(location.getPath(), "UTF-8"));
if ("META-INF".equals(dir.getName())) {
dir = dir.getParentFile(); // Scrape "META-INF" off
}
@@ -347,15 +316,17 @@ public class DefaultClassFinder implements ClassFinder {
private void scanDir(File dir, List classNames, String packageName) {
File[] files = dir.listFiles();
- for (File file : files) {
- if (file.isDirectory()) {
- scanDir(file, classNames, packageName + file.getName() + ".");
- } else if (file.getName().endsWith(".class")) {
- String name = file.getName();
- name = name.replaceFirst(".class$", "");
- // Classes packaged in an exploded .war (e.g. in a VFS file system) should not
- // have WEB-INF.classes in their package name.
- classNames.add(StringUtils.removeStart(packageName, "WEB-INF.classes.") + name);
+ if (files != null) {
+ for (File file : files) {
+ if (file.isDirectory()) {
+ scanDir(file, classNames, packageName + file.getName() + ".");
+ } else if (file.getName().endsWith(".class")) {
+ String name = file.getName();
+ name = name.replaceFirst(".class$", "");
+ // Classes packaged in an exploded .war (e.g. in a VFS file system) should not
+ // have WEB-INF.classes in their package name.
+ classNames.add(StringUtils.removeStart(packageName, "WEB-INF.classes.") + name);
+ }
}
}
}
@@ -363,12 +334,9 @@ public class DefaultClassFinder implements ClassFinder {
private List jar(URL location) throws IOException {
URL url = fileManager.normalizeToFileProtocol(location);
if (url != null) {
- InputStream in = url.openStream();
- try {
+ try (InputStream in = url.openStream()) {
JarInputStream jarStream = new JarInputStream(in);
return jar(jarStream);
- } finally {
- in.close();
}
} else {
LOG.debug("Unable to read [{}]", location.toExternalForm());
@@ -388,7 +356,7 @@ public class DefaultClassFinder implements ClassFinder {
className = className.replaceFirst(".class$", "");
//war files are treated as .jar files, so takeout WEB-INF/classes
- className = StringUtils.removeStart(className, "WEB-INF/classes/");
+ className = StringUtils.removeStart(className, "WEB-INF/classes/");
className = className.replace('/', '.');
classNames.add(className);
@@ -397,40 +365,8 @@ public class DefaultClassFinder implements ClassFinder {
return classNames;
}
- 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();
- }
- }
-
private List getAnnotationInfos(String name) {
- List infos = annotated.get(name);
- if (infos == null) {
- infos = new ArrayList<>();
- annotated.put(name, infos);
- }
- return infos;
+ return annotated.computeIfAbsent(name, k -> new ArrayList<>());
}
private void readClassDef(String className) {
@@ -454,19 +390,16 @@ public class DefaultClassFinder implements ClassFinder {
}
public class InfoBuildingVisitor extends ClassVisitor {
+
+ private final ClassFinder classFinder;
+
private Info info;
- private ClassFinder classFinder;
public InfoBuildingVisitor(ClassFinder classFinder) {
- super(Opcodes.ASM7);
+ super(Opcodes.ASM9);
this.classFinder = classFinder;
}
- public InfoBuildingVisitor(Info info, ClassFinder classFinder) {
- this(classFinder);
- this.info = info;
- }
-
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
if (name.endsWith("package-info")) {
@@ -480,8 +413,9 @@ public class DefaultClassFinder implements ClassFinder {
info = classInfo;
classInfos.put(classInfo.getName(), classInfo);
- if (extractBaseInterfaces)
+ if (extractBaseInterfaces) {
extractSuperInterfaces(classInfo);
+ }
}
}