diff --git a/.checkstyle b/.checkstyle
deleted file mode 100644
index 98225a4..0000000
--- a/.checkstyle
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
deleted file mode 100644
index ecf1325..0000000
--- a/.github/dependabot.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-version: 2
-updates:
-- package-ecosystem: maven
- directory: "/"
- schedule:
- interval: monthly
- time: "04:00"
- open-pull-requests-limit: 10
-
diff --git a/README.md b/README.md
index 9496c95..906a0ac 100644
--- a/README.md
+++ b/README.md
@@ -9,7 +9,8 @@ A small Java library that contains several helpful utility classes.
[](https://openjdk.java.net/projects/jdk/17/)
## Versions
-- 0.14.0 = See [release-notes](release-notes.md)
+- [0.15.0](release-notes.md#0150)
+- [0.14.0](release-notes.md#0140)
- 0.13.x (or later) = **Java 17**
- 0.12.0 = **Java 11** with new **jakarta** namespace
- 0.11.x = **Java 11** before namespace change from 'javax' to 'jakarta'
diff --git a/pom.xml b/pom.xml
index d49d910..51b328f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -12,7 +12,7 @@
utils4j
bundle
- 0.14.0
+ 0.15.0-SNAPSHOT
A small Java library that contains several helpful utility classes.
http://www.fuin.org/utils4j/
diff --git a/release-notes.md b/release-notes.md
index d8ed268..c67ac46 100644
--- a/release-notes.md
+++ b/release-notes.md
@@ -1,5 +1,9 @@
# Release Notes
+## 0.15.0
+- Added new [JandexUtils](src/main/java/org/fuin/utils4j/jandex/JandexUtils.java) methods
+- Added new [TechnicalId](src/main/java/org/fuin/utils4j/TechnicalId.java) tag interface.
+
## 0.14.0
### General
diff --git a/src/main/java/org/fuin/utils4j/TechnicalId.java b/src/main/java/org/fuin/utils4j/TechnicalId.java
new file mode 100644
index 0000000..79999ed
--- /dev/null
+++ b/src/main/java/org/fuin/utils4j/TechnicalId.java
@@ -0,0 +1,25 @@
+/**
+ * Copyright (C) 2015 Michael Schnell. All rights reserved.
+ * http://www.fuin.org/
+ *
+ * This library is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License as published by the Free
+ * Software Foundation; either version 3 of the License, or (at your option) any
+ * later version.
+ *
+ * This library is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this library. If not, see http://www.gnu.org/licenses/.
+ */
+package org.fuin.utils4j;
+
+/**
+ * Technical identifier that is only used internally and never shown to a user.
+ */
+public interface TechnicalId {
+
+}
diff --git a/src/main/java/org/fuin/utils4j/jandex/JandexUtils.java b/src/main/java/org/fuin/utils4j/jandex/JandexUtils.java
index 125ccbf..e2a1cc2 100644
--- a/src/main/java/org/fuin/utils4j/jandex/JandexUtils.java
+++ b/src/main/java/org/fuin/utils4j/jandex/JandexUtils.java
@@ -18,14 +18,21 @@
package org.fuin.utils4j.jandex;
import org.fuin.utils4j.Utils4J;
+import org.jboss.jandex.ClassInfo;
+import org.jboss.jandex.CompositeIndex;
import org.jboss.jandex.DotName;
import org.jboss.jandex.Index;
+import org.jboss.jandex.IndexView;
import org.jboss.jandex.Indexer;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Modifier;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
@@ -84,6 +91,21 @@ public static Index indexDir(final File dir) {
return indexer.complete();
}
+ /**
+ * Indexes all classes in multiple directories and their subdirectories.
+ *
+ * @param dirs Classes directories to analyze.
+ * @return Index of all classes in the directories.
+ */
+ public static Index indexDirs(final File... dirs) {
+ final Indexer indexer = new Indexer();
+ final List knownClassFiles = new ArrayList<>();
+ for (final File dir : dirs) {
+ indexDir(indexer, knownClassFiles, dir);
+ }
+ return indexer.complete();
+ }
+
/**
* Indexes all classes in a directory or it's subdirectories.
*
@@ -194,5 +216,43 @@ public static Class> loadClass(DotName name) {
return Utils4J.loadClass(name.toString());
}
+ /**
+ * Locates (non-abstract, non-interface) classes that implement a given interface in directories.
+ *
+ * @param intf Interface to find implementors for.
+ * @param classesDirs Directories with class files to scan.
+ * @return List of classes.
+ *
+ * @param Expected interface type.
+ */
+ @SuppressWarnings("unchecked")
+ public static List> findImplementors(final Class intf, final File... classesDirs) {
+ final List indexes = new ArrayList<>();
+ indexes.add(new JandexIndexFileReader.Builder().addDefaultResource().build().loadR());
+ indexes.add(indexDirs(classesDirs));
+ return findImplementors(intf, CompositeIndex.create(indexes));
+ }
+
+ /**
+ * Locates (non-abstract, non-interface) classes that implement a given interface in an index.
+ *
+ * @param intf Interface to find implementors for.
+ * @param index Index with known classes.
+ * @return List of classes.
+ *
+ * @param Expected interface type.
+ */
+ @SuppressWarnings("unchecked")
+ public static List> findImplementors(final Class intf, final IndexView index) {
+ List> implementors = new ArrayList<>();
+ final Collection implementingClasses = index.getAllKnownImplementors(DotName.createSimple(intf));
+ for (final ClassInfo classInfo : implementingClasses) {
+ if (!Modifier.isAbstract(classInfo.flags()) && !Modifier.isInterface(classInfo.flags())) {
+ final Class extends T> implementor = (Class extends T>) JandexUtils.loadClass(classInfo.name());
+ implementors.add(implementor);
+ }
+ }
+ return implementors;
+ }
}
diff --git a/src/test/java/org/fuin/utils4j/jandex/JandexUtilsTest.java b/src/test/java/org/fuin/utils4j/jandex/JandexUtilsTest.java
index 86e5e6e..e9edbe1 100644
--- a/src/test/java/org/fuin/utils4j/jandex/JandexUtilsTest.java
+++ b/src/test/java/org/fuin/utils4j/jandex/JandexUtilsTest.java
@@ -18,7 +18,10 @@
package org.fuin.utils4j.jandex;
import org.fuin.utils4j.Utils4J;
+import org.fuin.utils4j.filter.AndFilter;
+import org.fuin.utils4j.filter.Filter;
import org.fuin.utils4j.jandex.JandexUtils;
+import org.fuin.utils4j.jaxb.CDataXmlAdapter;
import org.jboss.jandex.DotName;
import org.jboss.jandex.Index;
import org.jboss.jandex.Indexer;
@@ -73,6 +76,22 @@ public final void testIndexDirSimple() {
}
+ @Test
+ public final void testIndexDirs() {
+
+ // PREPEARE
+ final File filterDir = new File(TARGET_DIR, "classes/org/fuin/utils4j/filter");
+ final File jaxbDir = new File(TARGET_DIR, "classes/org/fuin/utils4j/jaxb");
+
+ // TEST
+ final Index index = JandexUtils.indexDirs(filterDir, jaxbDir);
+
+ // VERIFY
+ assertThat(index.getClassByName(DotName.createSimple(AndFilter.class.getName()))).isNotNull();
+ assertThat(index.getClassByName(DotName.createSimple(CDataXmlAdapter.class.getName()))).isNotNull();
+
+ }
+
@Test
public final void testIndexDir() {
@@ -145,5 +164,20 @@ public final void loadClassFailure() {
.hasMessageContaining("Failed to load class");
}
+ @Test
+ public final void findImplementors() {
+
+ // PREPEARE
+ final File filterDir = new File(TARGET_DIR, "classes/org/fuin/utils4j/filter");
+
+ // TEST
+ final List> classes = JandexUtils.findImplementors(Filter.class, filterDir);
+
+ // VERIFY
+ assertThat(classes).isNotEmpty();
+ assertThat(classes).contains(AndFilter.class);
+
+ }
+
}
// CHECKSTYLE:ON