Skip to content

Commit 65a8e1e

Browse files
Improvements in classpath scanning (refs #142)
- fast-classpath-scanner updated to version 2.2.1 - limit classpath scanning to provided classpath - `debug` option for verbose output - continue when class cannot be loaded
1 parent 9cbdc78 commit 65a8e1e

File tree

6 files changed

+78
-35
lines changed

6 files changed

+78
-35
lines changed

typescript-generator-core/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
<dependency>
4242
<groupId>io.github.lukehutch</groupId>
4343
<artifactId>fast-classpath-scanner</artifactId>
44-
<version>2.0.17</version>
44+
<version>2.2.1</version>
4545
</dependency>
4646
<!--test dependencies-->
4747
<dependency>

typescript-generator-core/src/main/java/cz/habarta/typescript/generator/Input.java

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import io.github.lukehutch.fastclasspathscanner.FastClasspathScanner;
77
import io.github.lukehutch.fastclasspathscanner.scanner.ScanResult;
88
import java.lang.reflect.*;
9+
import java.net.URLClassLoader;
910
import java.util.*;
1011
import java.util.regex.Matcher;
1112
import java.util.regex.Pattern;
@@ -31,20 +32,20 @@ public static Input from(Type... types) {
3132
return new Input(sourceTypes);
3233
}
3334

34-
public static Input fromClassNamesAndJaxrsApplication(List<String> classNames, List<String> classNamePatterns, String jaxrsApplicationClassName, boolean automaticJaxrsApplication, Predicate<String> isClassNameExcluded, ClassLoader classLoader) {
35+
public static Input fromClassNamesAndJaxrsApplication(List<String> classNames, List<String> classNamePatterns, String jaxrsApplicationClassName, boolean automaticJaxrsApplication, Predicate<String> isClassNameExcluded, URLClassLoader classLoader, boolean debug) {
3536
final ClassLoader originalContextClassLoader = Thread.currentThread().getContextClassLoader();
3637
try {
3738
Thread.currentThread().setContextClassLoader(classLoader);
38-
final ClasspathScanner classpathScanner = new ClasspathScanner();
39+
final ClasspathScanner classpathScanner = new ClasspathScanner(classLoader, debug);
3940
final List<SourceType<Type>> types = new ArrayList<>();
4041
if (classNames != null) {
41-
types.addAll(fromClassNames(classNames).getSourceTypes());
42+
types.addAll(fromClassNames(classNames));
4243
}
4344
if (classNamePatterns != null) {
44-
types.addAll(fromClassNamePatterns(classpathScanner.scanClasspath(), classNamePatterns).getSourceTypes());
45+
types.addAll(fromClassNamePatterns(classpathScanner.scanClasspath(), classNamePatterns));
4546
}
4647
if (jaxrsApplicationClassName != null) {
47-
types.addAll(fromClassNames(Arrays.asList(jaxrsApplicationClassName)).sourceTypes);
48+
types.addAll(fromClassNames(Arrays.asList(jaxrsApplicationClassName)));
4849
}
4950
if (automaticJaxrsApplication) {
5051
types.addAll(JaxrsApplicationScanner.scanAutomaticJaxrsApplication(classpathScanner.scanClasspath(), isClassNameExcluded));
@@ -62,13 +63,23 @@ public static Input fromClassNamesAndJaxrsApplication(List<String> classNames, L
6263

6364
private static class ClasspathScanner {
6465

66+
private final URLClassLoader classLoader;
67+
private final boolean verbose;
6568
private ScanResult scanResult = null;
6669

70+
public ClasspathScanner(URLClassLoader classLoader, boolean verbose) {
71+
this.classLoader = classLoader;
72+
this.verbose = verbose;
73+
}
74+
6775
public ScanResult scanClasspath() {
6876
if (scanResult == null) {
6977
System.out.println("Scanning classpath");
7078
final Date scanStart = new Date();
71-
final ScanResult result = new FastClasspathScanner().scan();
79+
final ScanResult result = new FastClasspathScanner()
80+
.overrideClasspath(classLoader.getURLs())
81+
.verbose(verbose)
82+
.scan();
7283
final int count = result.getNamesOfAllClasses().size();
7384
final Date scanEnd = new Date();
7485
final double timeInSeconds = (scanEnd.getTime() - scanStart.getTime()) / 1000.0;
@@ -80,7 +91,7 @@ public ScanResult scanClasspath() {
8091

8192
}
8293

83-
private static Input fromClassNamePatterns(ScanResult scanResult, List<String> classNamePatterns) {
94+
private static List<SourceType<Type>> fromClassNamePatterns(ScanResult scanResult, List<String> classNamePatterns) {
8495
final List<String> allClassNames = new ArrayList<>();
8596
allClassNames.addAll(scanResult.getNamesOfAllStandardClasses());
8697
allClassNames.addAll(scanResult.getNamesOfAllInterfaceClasses());
@@ -90,21 +101,30 @@ private static Input fromClassNamePatterns(ScanResult scanResult, List<String> c
90101
return fromClassNames(classNames);
91102
}
92103

93-
private static Input fromClassNames(List<String> classNames) {
94-
try {
95-
final List<SourceType<Type>> types = new ArrayList<>();
96-
for (String className : classNames) {
104+
private static List<SourceType<Type>> fromClassNames(List<String> classNames) {
105+
final List<SourceType<Type>> types = new ArrayList<>();
106+
for (Class<?> cls : loadClasses(classNames)) {
107+
// skip synthetic classes (as those generated by java compiler for switch with enum)
108+
// and anonymous classes (should not be processed and they do not have SimpleName)
109+
if (!cls.isSynthetic() && !cls.isAnonymousClass()) {
110+
types.add(new SourceType<Type>(cls, null, null));
111+
}
112+
}
113+
return types;
114+
}
115+
116+
static List<Class<?>> loadClasses(List<String> classNames) {
117+
final List<Class<?>> classes = new ArrayList<>();
118+
for (String className : classNames) {
119+
try {
97120
final Class<?> cls = Thread.currentThread().getContextClassLoader().loadClass(className);
98-
// skip synthetic classes (as those generated by java compiler for switch with enum)
99-
// and anonymous classes (should not be processed and they do not have SimpleName)
100-
if (!cls.isSynthetic() && !cls.isAnonymousClass()) {
101-
types.add(new SourceType<Type>(cls, null, null));
102-
}
121+
classes.add(cls);
122+
} catch (ReflectiveOperationException e) {
123+
System.out.println(String.format("Error: Cannot load class '%s'", className));
124+
e.printStackTrace(System.out);
103125
}
104-
return new Input(types);
105-
} catch (ReflectiveOperationException e) {
106-
throw new RuntimeException(e);
107126
}
127+
return classes;
108128
}
109129

110130
static List<String> filterClassNames(List<String> classNames, List<String> globs) {

typescript-generator-core/src/main/java/cz/habarta/typescript/generator/JaxrsApplicationScanner.java

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,17 +31,10 @@ public static List<SourceType<Type>> scanJaxrsApplication(Class<?> jaxrsApplicat
3131
}
3232

3333
public static List<SourceType<Type>> scanAutomaticJaxrsApplication(ScanResult scanResult, Predicate<String> isClassNameExcluded) {
34-
try {
35-
final List<String> namesOfResourceClasses = scanResult.getNamesOfClassesWithAnnotation(Path.class);
36-
final List<Class<?>> resourceClasses = new ArrayList<>();
37-
for (String className : namesOfResourceClasses) {
38-
resourceClasses.add(Thread.currentThread().getContextClassLoader().loadClass(className));
39-
}
40-
System.out.println(String.format("Found %d root resources.", resourceClasses.size()));
41-
return new JaxrsApplicationScanner().scanJaxrsApplication(null, resourceClasses, isClassNameExcluded);
42-
} catch (ReflectiveOperationException e) {
43-
throw reportError(e);
44-
}
34+
final List<String> namesOfResourceClasses = scanResult.getNamesOfClassesWithAnnotation(Path.class);
35+
final List<Class<?>> resourceClasses = Input.loadClasses(namesOfResourceClasses);
36+
System.out.println(String.format("Found %d root resources.", resourceClasses.size()));
37+
return new JaxrsApplicationScanner().scanJaxrsApplication(null, resourceClasses, isClassNameExcluded);
4538
}
4639

4740
private static RuntimeException reportError(ReflectiveOperationException e) {

typescript-generator-core/src/main/java/cz/habarta/typescript/generator/Settings.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
import cz.habarta.typescript.generator.util.Predicate;
88
import java.io.File;
99
import java.lang.annotation.Annotation;
10+
import java.net.URL;
11+
import java.net.URLClassLoader;
1012
import java.util.*;
1113
import java.util.regex.Pattern;
1214

@@ -72,6 +74,26 @@ public class Settings {
7274
private boolean defaultStringEnumsOverriddenByExtension = false;
7375

7476

77+
private static class TypeScriptGeneratorURLClassLoader extends URLClassLoader {
78+
79+
private final String name;
80+
81+
public TypeScriptGeneratorURLClassLoader(String name, URL[] urls, ClassLoader parent) {
82+
super(urls, parent);
83+
this.name = name;
84+
}
85+
86+
@Override
87+
public String toString() {
88+
return "TsGenURLClassLoader{" + name + ", parent: " + getParent() + "}";
89+
}
90+
91+
}
92+
93+
public static URLClassLoader createClassLoader(String name, URL[] urls, ClassLoader parent) {
94+
return new TypeScriptGeneratorURLClassLoader(name, urls, parent);
95+
}
96+
7597
public void setStringQuotes(StringQuotes quotes) {
7698
this.quotes = quotes == StringQuotes.singleQuotes ? "'" : "\"";
7799
}

typescript-generator-gradle-plugin/src/main/java/cz/habarta/typescript/generator/gradle/GenerateTask.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ public class GenerateTask extends DefaultTask {
6262
public StringQuotes stringQuotes;
6363
public boolean displaySerializerWarning = true;
6464
public boolean disableJackson2ModuleDiscovery;
65+
public boolean debug;
6566

6667
@TaskAction
6768
public void generate() throws Exception {
@@ -84,7 +85,7 @@ public void generate() throws Exception {
8485
for (File file : getProject().getConfigurations().getAt("compile").getFiles()) {
8586
urls.add(file.toURI().toURL());
8687
}
87-
final URLClassLoader classLoader = new URLClassLoader(urls.toArray(new URL[0]), Thread.currentThread().getContextClassLoader());
88+
final URLClassLoader classLoader = Settings.createClassLoader(getProject().getName(), urls.toArray(new URL[0]), Thread.currentThread().getContextClassLoader());
8889

8990
// Settings
9091
final Settings settings = new Settings();
@@ -142,7 +143,7 @@ public void generate() throws Exception {
142143

143144
// TypeScriptGenerator
144145
new TypeScriptGenerator(settings).generateTypeScript(
145-
Input.fromClassNamesAndJaxrsApplication(classes, classPatterns, classesFromJaxrsApplication, classesFromAutomaticJaxrsApplication, settings.getExcludeFilter(), classLoader),
146+
Input.fromClassNamesAndJaxrsApplication(classes, classPatterns, classesFromJaxrsApplication, classesFromAutomaticJaxrsApplication, settings.getExcludeFilter(), classLoader, debug),
146147
Output.to(output)
147148
);
148149
}

typescript-generator-maven-plugin/src/main/java/cz/habarta/typescript/generator/maven/GenerateMojo.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -401,6 +401,13 @@ public class GenerateMojo extends AbstractMojo {
401401
@Parameter
402402
private boolean disableJackson2ModuleDiscovery;
403403

404+
/**
405+
* Turns on verbose output for debugging purposes.
406+
*/
407+
@Parameter
408+
private boolean debug;
409+
410+
404411
@Parameter(defaultValue = "${project}", readonly = true, required = true)
405412
private MavenProject project;
406413

@@ -417,7 +424,7 @@ public void execute() {
417424
for (String element : project.getCompileClasspathElements()) {
418425
urls.add(new File(element).toURI().toURL());
419426
}
420-
final URLClassLoader classLoader = new URLClassLoader(urls.toArray(new URL[0]), Thread.currentThread().getContextClassLoader());
427+
final URLClassLoader classLoader = Settings.createClassLoader(project.getArtifactId(), urls.toArray(new URL[0]), Thread.currentThread().getContextClassLoader());
421428

422429
// Settings
423430
final Settings settings = new Settings();
@@ -475,7 +482,7 @@ public void execute() {
475482

476483
// TypeScriptGenerator
477484
new TypeScriptGenerator(settings).generateTypeScript(
478-
Input.fromClassNamesAndJaxrsApplication(classes, classPatterns, classesFromJaxrsApplication, classesFromAutomaticJaxrsApplication, settings.getExcludeFilter(), classLoader),
485+
Input.fromClassNamesAndJaxrsApplication(classes, classPatterns, classesFromJaxrsApplication, classesFromAutomaticJaxrsApplication, settings.getExcludeFilter(), classLoader, debug),
479486
Output.to(output)
480487
);
481488

0 commit comments

Comments
 (0)