|
18 | 18 | package org.fuin.utils4j.jandex;
|
19 | 19 |
|
20 | 20 | import org.fuin.utils4j.Utils4J;
|
| 21 | +import org.jboss.jandex.ClassInfo; |
| 22 | +import org.jboss.jandex.CompositeIndex; |
21 | 23 | import org.jboss.jandex.DotName;
|
22 | 24 | import org.jboss.jandex.Index;
|
| 25 | +import org.jboss.jandex.IndexView; |
23 | 26 | import org.jboss.jandex.Indexer;
|
24 | 27 |
|
25 | 28 | import java.io.File;
|
26 | 29 | import java.io.IOException;
|
27 | 30 | import java.io.InputStream;
|
| 31 | +import java.lang.reflect.Constructor; |
| 32 | +import java.lang.reflect.InvocationTargetException; |
| 33 | +import java.lang.reflect.Modifier; |
28 | 34 | import java.util.ArrayList;
|
| 35 | +import java.util.Collection; |
29 | 36 | import java.util.Enumeration;
|
30 | 37 | import java.util.List;
|
31 | 38 | import java.util.jar.JarEntry;
|
@@ -84,6 +91,21 @@ public static Index indexDir(final File dir) {
|
84 | 91 | return indexer.complete();
|
85 | 92 | }
|
86 | 93 |
|
| 94 | + /** |
| 95 | + * Indexes all classes in multiple directories and their subdirectories. |
| 96 | + * |
| 97 | + * @param dirs Classes directories to analyze. |
| 98 | + * @return Index of all classes in the directories. |
| 99 | + */ |
| 100 | + public static Index indexDirs(final File... dirs) { |
| 101 | + final Indexer indexer = new Indexer(); |
| 102 | + final List<File> knownClassFiles = new ArrayList<>(); |
| 103 | + for (final File dir : dirs) { |
| 104 | + indexDir(indexer, knownClassFiles, dir); |
| 105 | + } |
| 106 | + return indexer.complete(); |
| 107 | + } |
| 108 | + |
87 | 109 | /**
|
88 | 110 | * Indexes all classes in a directory or it's subdirectories.
|
89 | 111 | *
|
@@ -194,5 +216,43 @@ public static Class<?> loadClass(DotName name) {
|
194 | 216 | return Utils4J.loadClass(name.toString());
|
195 | 217 | }
|
196 | 218 |
|
| 219 | + /** |
| 220 | + * Locates (non-abstract, non-interface) classes that implement a given interface in directories. |
| 221 | + * |
| 222 | + * @param intf Interface to find implementors for. |
| 223 | + * @param classesDirs Directories with class files to scan. |
| 224 | + * @return List of classes. |
| 225 | + * |
| 226 | + * @param <T> Expected interface type. |
| 227 | + */ |
| 228 | + @SuppressWarnings("unchecked") |
| 229 | + public static <T> List<Class<? extends T>> findImplementors(final Class<T> intf, final File... classesDirs) { |
| 230 | + final List<IndexView> indexes = new ArrayList<>(); |
| 231 | + indexes.add(new JandexIndexFileReader.Builder().addDefaultResource().build().loadR()); |
| 232 | + indexes.add(indexDirs(classesDirs)); |
| 233 | + return findImplementors(intf, CompositeIndex.create(indexes)); |
| 234 | + } |
| 235 | + |
| 236 | + /** |
| 237 | + * Locates (non-abstract, non-interface) classes that implement a given interface in an index. |
| 238 | + * |
| 239 | + * @param intf Interface to find implementors for. |
| 240 | + * @param index Index with known classes. |
| 241 | + * @return List of classes. |
| 242 | + * |
| 243 | + * @param <T> Expected interface type. |
| 244 | + */ |
| 245 | + @SuppressWarnings("unchecked") |
| 246 | + public static <T> List<Class<? extends T>> findImplementors(final Class<T> intf, final IndexView index) { |
| 247 | + List<Class<? extends T>> implementors = new ArrayList<>(); |
| 248 | + final Collection<ClassInfo> implementingClasses = index.getAllKnownImplementors(DotName.createSimple(intf)); |
| 249 | + for (final ClassInfo classInfo : implementingClasses) { |
| 250 | + if (!Modifier.isAbstract(classInfo.flags()) && !Modifier.isInterface(classInfo.flags())) { |
| 251 | + final Class<? extends T> implementor = (Class<? extends T>) JandexUtils.loadClass(classInfo.name()); |
| 252 | + implementors.add(implementor); |
| 253 | + } |
| 254 | + } |
| 255 | + return implementors; |
| 256 | + } |
197 | 257 |
|
198 | 258 | }
|
0 commit comments