diff --git a/pom.xml b/pom.xml
index 9d760f2..be01e29 100644
--- a/pom.xml
+++ b/pom.xml
@@ -55,6 +55,7 @@
1.8.0
2.7.0-01
2.0.4-04
+ 4.8.149
1.0.8
2.1.7
2.3.0
@@ -64,7 +65,6 @@
3.6.0
3.3.0
3.2.0
- 0.9.12
1.7.29
@@ -105,9 +105,9 @@
${org.apache.maven.version}
- org.reflections
- reflections
- ${org.reflections.version}
+ io.github.classgraph
+ classgraph
+ ${io.github.classgraph.version}
javax.xml.bind
diff --git a/src/main/java/io/openapitools/swagger/GenerateMojo.java b/src/main/java/io/openapitools/swagger/GenerateMojo.java
index fab7629..5cc5643 100644
--- a/src/main/java/io/openapitools/swagger/GenerateMojo.java
+++ b/src/main/java/io/openapitools/swagger/GenerateMojo.java
@@ -110,40 +110,29 @@ public void execute() throws MojoExecutionException, MojoFailureException {
return;
}
- ClassLoader origClzLoader = Thread.currentThread().getContextClassLoader();
- ClassLoader clzLoader = createClassLoader(origClzLoader);
+ Reader reader = new Reader(swaggerConfig == null ? new OpenAPI() : swaggerConfig.createSwaggerModel());
- try {
- // set the TCCL before everything else
- Thread.currentThread().setContextClassLoader(clzLoader);
-
- Reader reader = new Reader(swaggerConfig == null ? new OpenAPI() : swaggerConfig.createSwaggerModel());
+ JaxRSScanner reflectiveScanner = new JaxRSScanner(getLog(), createClassLoader(), resourcePackages, useResourcePackagesChildren);
- JaxRSScanner reflectiveScanner = new JaxRSScanner(getLog(), resourcePackages, useResourcePackagesChildren);
+ Application application = resolveApplication(reflectiveScanner);
+ reader.setApplication(application);
- Application application = resolveApplication(reflectiveScanner);
- reader.setApplication(application);
+ OpenAPI swagger = OpenAPISorter.sort(reader.read(reflectiveScanner.classes()));
- OpenAPI swagger = OpenAPISorter.sort(reader.read(reflectiveScanner.classes()));
-
- if (outputDirectory.mkdirs()) {
- getLog().debug("Created output directory " + outputDirectory);
- }
+ if (outputDirectory.mkdirs()) {
+ getLog().debug("Created output directory " + outputDirectory);
+ }
- outputFormats.forEach(format -> {
- try {
- File outputFile = new File(outputDirectory, outputFilename + "." + format.name().toLowerCase());
- format.write(swagger, outputFile, prettyPrint);
- if (attachSwaggerArtifact) {
- projectHelper.attachArtifact(project, format.name().toLowerCase(), "swagger", outputFile);
- }
- } catch (IOException e) {
- throw new RuntimeException("Unable write " + outputFilename + " document", e);
+ try {
+ for (OutputFormat format : outputFormats) {
+ File outputFile = new File(outputDirectory, outputFilename + "." + format.name().toLowerCase());
+ format.write(swagger, outputFile, prettyPrint);
+ if (attachSwaggerArtifact) {
+ projectHelper.attachArtifact(project, format.name().toLowerCase(), "swagger", outputFile);
}
- });
- } finally {
- // reset the TCCL back to the original class loader
- Thread.currentThread().setContextClassLoader(origClzLoader);
+ }
+ } catch (IOException e) {
+ throw new RuntimeException("Unable write " + outputFilename + " document", e);
}
}
@@ -164,7 +153,7 @@ private Application resolveApplication(JaxRSScanner reflectiveScanner) {
return ClassUtils.createInstance(appClazz);
}
- private URLClassLoader createClassLoader(ClassLoader parent) {
+ private URLClassLoader createClassLoader() {
try {
Collection dependencies = getDependentClasspathElements();
URL[] urls = new URL[dependencies.size()];
@@ -172,7 +161,7 @@ private URLClassLoader createClassLoader(ClassLoader parent) {
for (String dependency : dependencies) {
urls[index++] = Paths.get(dependency).toUri().toURL();
}
- return new URLClassLoader(urls, parent);
+ return new URLClassLoader(urls, Thread.currentThread().getContextClassLoader());
} catch (MalformedURLException e) {
throw new RuntimeException("Unable to create class loader with compiled classes", e);
} catch (DependencyResolutionRequiredException e) {
diff --git a/src/main/java/io/openapitools/swagger/JaxRSScanner.java b/src/main/java/io/openapitools/swagger/JaxRSScanner.java
index 2c9c6d7..9f5982c 100644
--- a/src/main/java/io/openapitools/swagger/JaxRSScanner.java
+++ b/src/main/java/io/openapitools/swagger/JaxRSScanner.java
@@ -10,12 +10,11 @@
import javax.ws.rs.core.Application;
import org.apache.maven.plugin.logging.Log;
-import org.reflections.Reflections;
-import org.reflections.scanners.ResourcesScanner;
-import org.reflections.scanners.SubTypesScanner;
-import org.reflections.scanners.TypeAnnotationsScanner;
-import org.reflections.util.ConfigurationBuilder;
+import io.github.classgraph.ClassGraph;
+import io.github.classgraph.ClassInfo;
+import io.github.classgraph.ClassInfoList;
+import io.github.classgraph.ScanResult;
import io.swagger.v3.oas.annotations.OpenAPIDefinition;
/**
@@ -26,53 +25,54 @@ class JaxRSScanner {
private final Log log;
+ private final ClassGraph classGraph;
+
private final Set resourcePackages;
private final boolean useResourcePackagesChildren;
- public JaxRSScanner(Log log, Set resourcePackages, Boolean useResourcePackagesChildren) {
+ public JaxRSScanner(Log log, ClassLoader clzLoader, Set resourcePackages, Boolean useResourcePackagesChildren) {
this.log = log;
+ this.classGraph = new ClassGraph().enableClassInfo().enableAnnotationInfo()
+ .addClassLoader(clzLoader);
this.resourcePackages = resourcePackages == null ? Collections.emptySet() : new HashSet<>(resourcePackages);
- this.useResourcePackagesChildren = useResourcePackagesChildren != null && useResourcePackagesChildren;
+ this.useResourcePackagesChildren = Boolean.TRUE.equals(useResourcePackagesChildren);
}
Application applicationInstance() {
- ConfigurationBuilder config = ConfigurationBuilder
- .build(resourcePackages)
- .setScanners(new ResourcesScanner(), new TypeAnnotationsScanner(), new SubTypesScanner());
- Reflections reflections = new Reflections(config);
- Set> applicationClasses = reflections.getSubTypesOf(Application.class)
- .stream()
- .filter(this::filterClassByResourcePackages)
- .collect(Collectors.toSet());
- if (applicationClasses.isEmpty()) {
- return null;
- }
- if (applicationClasses.size() > 1) {
- log.warn("More than one javax.ws.rs.core.Application classes found on the classpath, skipping");
- return null;
+ Application applicationInstance = null;
+ try (ScanResult scanResult = classGraph.scan()) {
+ ClassInfoList applicationClasses = scanResult.getSubclasses(Application.class.getName())
+ .filter(this::filterClassByResourcePackages);
+ if (applicationClasses.size() == 1) {
+ applicationInstance = ClassUtils.createInstance(applicationClasses.get(0).loadClass(Application.class));
+ } else if (applicationClasses.size() > 1) {
+ log.warn("More than one javax.ws.rs.core.Application classes found on the classpath, skipping");
+ }
}
- return ClassUtils.createInstance(applicationClasses.iterator().next());
+ return applicationInstance;
}
Set> classes() {
- ConfigurationBuilder config = ConfigurationBuilder
- .build(resourcePackages)
- .setScanners(new ResourcesScanner(), new TypeAnnotationsScanner(), new SubTypesScanner());
- Reflections reflections = new Reflections(config);
- Stream> apiClasses = reflections.getTypesAnnotatedWith(Path.class)
- .stream()
- .filter(this::filterClassByResourcePackages);
- Stream> defClasses = reflections.getTypesAnnotatedWith(OpenAPIDefinition.class)
- .stream()
- .filter(this::filterClassByResourcePackages);
- return Stream.concat(apiClasses, defClasses).collect(Collectors.toSet());
+ Set> classes;
+ try (ScanResult scanResult = classGraph.scan()) {
+ ClassInfoList apiClasses = scanResult.getClassesWithAnnotation(Path.class.getName());
+ ClassInfoList defClasses = scanResult.getClassesWithAnnotation(OpenAPIDefinition.class.getName());
+ classes = Stream.of(apiClasses, defClasses)
+ .flatMap(classList -> classList.filter(this::filterClassByResourcePackages).stream())
+ .map(ClassInfo::loadClass)
+ .collect(Collectors.toSet());
+ }
+ if (classes.isEmpty()) {
+ log.warn("No @Path or @OpenAPIDefinition annotated classes found in given resource packages: " + resourcePackages);
+ }
+ return classes;
}
- private boolean filterClassByResourcePackages(Class> cls) {
+ private boolean filterClassByResourcePackages(ClassInfo cls) {
return resourcePackages.isEmpty()
- || resourcePackages.contains(cls.getPackage().getName())
- || (useResourcePackagesChildren && resourcePackages.stream().anyMatch(p -> cls.getPackage().getName().startsWith(p)));
+ || resourcePackages.contains(cls.getPackageName())
+ || (useResourcePackagesChildren && resourcePackages.stream().anyMatch(p -> cls.getPackageName().startsWith(p)));
}
}