Skip to content

Commit 467181a

Browse files
committed
Java 17: more changes for 3.x
- Redo how annotation processor generates byte code. Now generates on first round (avoid annoying warning) - Fix some missing dependencies from jooby-cli - upgrade graddle usage from jooby-cli - upgrade generates files to use Java 17 for maven/gradle
1 parent f4ba3e0 commit 467181a

File tree

9 files changed

+129
-90
lines changed

9 files changed

+129
-90
lines changed

modules/jooby-apt/src/main/java/io/jooby/apt/JoobyProcessor.java

Lines changed: 91 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.util.List;
1717
import java.util.Map;
1818
import java.util.Set;
19+
import java.util.function.Predicate;
1920
import java.util.stream.Collectors;
2021
import java.util.stream.Stream;
2122

@@ -59,20 +60,14 @@ public class JoobyProcessor extends AbstractProcessor {
5960

6061
private ProcessingEnvironment processingEnv;
6162

62-
/**
63-
* Route Data.
64-
* {
65-
* HTTP_METHOD: [method1, ..., methodN]
66-
* }
67-
*/
68-
private Map<TypeElement, Map<TypeElement, List<ExecutableElement>>> routeMap = new LinkedHashMap<>();
69-
7063
private boolean debug;
7164
private boolean incremental;
7265
private boolean services;
73-
private boolean extendedLooupOfSuperTypes;
66+
private boolean extendedLookupOfSuperTypes;
7467

7568
private int round;
69+
private Map<TypeElement, String> modules = new LinkedHashMap<>();
70+
private Set<String> alreadyProcessed = new HashSet<>();
7671

7772
@Override
7873
public Set<String> getSupportedOptions() {
@@ -110,73 +105,89 @@ public synchronized void init(ProcessingEnvironment processingEnvironment) {
110105
debug = Opts.boolOpt(processingEnv, Opts.OPT_DEBUG, false);
111106
incremental = Opts.boolOpt(processingEnv, Opts.OPT_INCREMENTAL, true);
112107
services = Opts.boolOpt(processingEnv, Opts.OPT_SERVICES, true);
113-
extendedLooupOfSuperTypes = Opts.boolOpt(processingEnv, Opts.OPT_EXTENDED_LOOKUP_OF_SUPERTYPES, false);
108+
extendedLookupOfSuperTypes = Opts.boolOpt(processingEnv, Opts.OPT_EXTENDED_LOOKUP_OF_SUPERTYPES,
109+
true);
114110

115111
debug("Incremental annotation processing is turned %s.", incremental ? "ON" : "OFF");
116112
debug("Generation of service provider configuration is turned %s.", services ? "ON" : "OFF");
117-
debug("Extended lookup of superTypes %s.", extendedLooupOfSuperTypes ? "ON" : "OFF");
113+
debug("Extended lookup of superTypes %s.", extendedLookupOfSuperTypes ? "ON" : "OFF");
118114
}
119115

120116
@Override
121117
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
122118
try {
123119
debug("Round #%s", round++);
124120
if (roundEnv.processingOver()) {
121+
if (services) {
122+
doServices(processingEnv.getFiler(), modules);
123+
}
124+
return false;
125+
} else {
126+
Map<TypeElement, Map<TypeElement, List<ExecutableElement>>> routeMap = collectRoutes(
127+
annotations, roundEnv);
125128

126-
build(processingEnv.getFiler());
129+
Map<TypeElement, String> modules = build(processingEnv.getFiler(), classes(routeMap), alreadyProcessed::add);
130+
alreadyProcessed.addAll(modules.values());
131+
this.modules.putAll(modules);
127132

128-
return false;
133+
return true;
129134
}
135+
} catch (Exception x) {
136+
throw SneakyThrows.propagate(x);
137+
}
138+
}
139+
140+
private Map<TypeElement, Map<TypeElement, List<ExecutableElement>>> collectRoutes(
141+
Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
142+
Map<TypeElement, Map<TypeElement, List<ExecutableElement>>> routeMap = new LinkedHashMap<>();
143+
144+
for (TypeElement annotation : annotations) {
145+
Set<? extends Element> elements = roundEnv
146+
.getElementsAnnotatedWith(annotation);
130147

131148
/**
132-
* Do MVC handler: per each mvc method we create a Route.Handler.
149+
* Add empty-subclass (edge case where you mark something with @Path and didn't add any
150+
* HTTP annotation.
133151
*/
134-
for (TypeElement annotation : annotations) {
135-
Set<? extends Element> elements = roundEnv
136-
.getElementsAnnotatedWith(annotation);
137-
138-
/**
139-
* Add empty-subclass (edge case where you mark something with @Path and didn't add any
140-
* HTTP annotation.
141-
*/
142-
elements.stream()
143-
.filter(TypeElement.class::isInstance)
144-
.map(TypeElement.class::cast)
145-
.filter(type -> !type.getModifiers().contains(Modifier.ABSTRACT))
146-
.forEach(e -> routeMap.computeIfAbsent(e, k -> new LinkedHashMap<>()));
147-
148-
if (Annotations.HTTP_METHODS.contains(annotation.asType().toString())) {
149-
Set<ExecutableElement> methods = elements.stream()
150-
.filter(ExecutableElement.class::isInstance)
151-
.map(ExecutableElement.class::cast)
152-
.collect(Collectors.toCollection(LinkedHashSet::new));
153-
for (ExecutableElement method : methods) {
154-
Map<TypeElement, List<ExecutableElement>> mapping = routeMap
155-
.computeIfAbsent((TypeElement) method.getEnclosingElement(),
156-
k -> new LinkedHashMap<>());
157-
mapping.computeIfAbsent(annotation, k -> new ArrayList<>()).add(method);
158-
}
159-
} else {
160-
if (extendedLooupOfSuperTypes) {
161-
elements.stream()
162-
.filter(TypeElement.class::isInstance)
163-
.map(TypeElement.class::cast)
164-
.forEach(parentTypeElement -> extendedLookupOfSuperTypes(parentTypeElement));
165-
}
152+
elements.stream()
153+
.filter(TypeElement.class::isInstance)
154+
.map(TypeElement.class::cast)
155+
.filter(type -> !type.getModifiers().contains(Modifier.ABSTRACT))
156+
.forEach(e -> routeMap.computeIfAbsent(e, k -> new LinkedHashMap<>()));
157+
158+
if (Annotations.HTTP_METHODS.contains(annotation.asType().toString())) {
159+
Set<ExecutableElement> methods = elements.stream()
160+
.filter(ExecutableElement.class::isInstance)
161+
.map(ExecutableElement.class::cast)
162+
.collect(Collectors.toCollection(LinkedHashSet::new));
163+
for (ExecutableElement method : methods) {
164+
Map<TypeElement, List<ExecutableElement>> mapping = routeMap
165+
.computeIfAbsent((TypeElement) method.getEnclosingElement(),
166+
k -> new LinkedHashMap<>());
167+
mapping.computeIfAbsent(annotation, k -> new ArrayList<>()).add(method);
168+
}
169+
} else {
170+
if (extendedLookupOfSuperTypes) {
171+
elements.stream()
172+
.filter(TypeElement.class::isInstance)
173+
.map(TypeElement.class::cast)
174+
.forEach(
175+
parentTypeElement -> extendedLookupOfSuperTypes(routeMap, parentTypeElement));
166176
}
167177
}
168-
return true;
169-
} catch (Exception x) {
170-
throw SneakyThrows.propagate(x);
171178
}
179+
return routeMap;
172180
}
173181

174182
/**
175183
* Crawls through the sub-classes. Inspects them for HTTP Method annotated entries
176184
*
185+
* @param routeMap
177186
* @param parentTypeElement
178187
*/
179-
private void extendedLookupOfSuperTypes(TypeElement parentTypeElement) {
188+
private void extendedLookupOfSuperTypes(
189+
Map<TypeElement, Map<TypeElement, List<ExecutableElement>>> routeMap,
190+
TypeElement parentTypeElement) {
180191
for (TypeElement superType : superTypes(parentTypeElement)) {
181192
//collect all declared methods
182193
Set<ExecutableElement> methods = superType.getEnclosedElements().stream()
@@ -198,7 +209,8 @@ private void extendedLookupOfSuperTypes(TypeElement parentTypeElement) {
198209
Map<TypeElement, List<ExecutableElement>> mapping = routeMap
199210
.computeIfAbsent(parentTypeElement,
200211
k -> new LinkedHashMap<>());
201-
List<ExecutableElement> list = mapping.computeIfAbsent(annotationType, k -> new ArrayList<>());
212+
List<ExecutableElement> list = mapping.computeIfAbsent(annotationType,
213+
k -> new ArrayList<>());
202214
//ensure that the same method wasnt already defined in parent
203215
if (list.stream().map(this::signature).noneMatch(signature(method)::equals)) {
204216
list.add(method);
@@ -209,8 +221,30 @@ private void extendedLookupOfSuperTypes(TypeElement parentTypeElement) {
209221
}
210222
}
211223

212-
private void build(Filer filer) throws Exception {
224+
private Map<TypeElement, String> build(Filer filer,
225+
Map<TypeElement, List<HandlerCompiler>> classes, Predicate<String> includes) throws Exception {
213226
Types typeUtils = processingEnv.getTypeUtils();
227+
228+
Map<TypeElement, String> modules = new LinkedHashMap<>();
229+
for (Map.Entry<TypeElement, List<HandlerCompiler>> entry : classes.entrySet()) {
230+
TypeElement type = entry.getKey();
231+
String typeName = typeUtils.erasure(type.asType()).toString();
232+
if (includes.test(typeName)) {
233+
List<HandlerCompiler> handlers = entry.getValue();
234+
ModuleCompiler module = new ModuleCompiler(processingEnv, typeName);
235+
String moduleClass = module.getModuleClass();
236+
byte[] moduleBin = module.compile(handlers);
237+
onClass(moduleClass, moduleBin);
238+
writeClass(filer.createClassFile(moduleClass, type), moduleBin);
239+
modules.put(type, moduleClass);
240+
}
241+
}
242+
243+
return modules;
244+
}
245+
246+
private Map<TypeElement, List<HandlerCompiler>> classes(
247+
Map<TypeElement, Map<TypeElement, List<ExecutableElement>>> routeMap) {
214248
Map<TypeElement, List<HandlerCompiler>> classes = new LinkedHashMap<>();
215249
for (Map.Entry<TypeElement, Map<TypeElement, List<ExecutableElement>>> e : routeMap
216250
.entrySet()) {
@@ -255,24 +289,7 @@ private void build(Filer filer) throws Exception {
255289
}
256290
}
257291
}
258-
259-
Map<TypeElement, String> modules = new LinkedHashMap<>();
260-
for (Map.Entry<TypeElement, List<HandlerCompiler>> entry : classes.entrySet()) {
261-
TypeElement type = entry.getKey();
262-
String typeName = typeUtils.erasure(type.asType()).toString();
263-
List<HandlerCompiler> handlers = entry.getValue();
264-
ModuleCompiler module = new ModuleCompiler(processingEnv, typeName);
265-
String moduleClass = module.getModuleClass();
266-
byte[] moduleBin = module.compile(handlers);
267-
onClass(moduleClass, moduleBin);
268-
writeClass(filer.createClassFile(moduleClass, type), moduleBin);
269-
270-
modules.put(type, moduleClass);
271-
}
272-
273-
if (services) {
274-
doServices(filer, modules);
275-
}
292+
return classes;
276293
}
277294

278295
private String signature(ExecutableElement method) {
@@ -307,9 +324,11 @@ private void debug(String format, Object... args) {
307324

308325
private void doServices(Filer filer, Map<TypeElement, String> modules) throws IOException {
309326
String location = "META-INF/services/" + MvcFactory.class.getName();
310-
Element[] originatingElements = modules.keySet().toArray(new Element[0]);
311327
debug("%s", location);
312-
FileObject resource = filer.createResource(StandardLocation.CLASS_OUTPUT, "", location, originatingElements);
328+
329+
Element[] originatingElements = modules.keySet().toArray(new Element[0]);
330+
FileObject resource = filer.createResource(StandardLocation.CLASS_OUTPUT, "", location,
331+
originatingElements);
313332
StringBuilder content = new StringBuilder();
314333
for (Map.Entry<TypeElement, String> e : modules.entrySet()) {
315334
String classname = e.getValue();
Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,27 @@
11
package output;
22

33
import org.junit.jupiter.api.Test;
4-
import org.objectweb.asm.util.ASMifier;
54

65
public class ASMPrinter {
76

87
@Test
98
public void mvcExtension() throws Exception {
10-
ASMifier.main(new String[]{MvcExtension.class.getName()});
9+
// ASMifier.main(new String[]{MvcExtension.class.getName()});
1110
}
1211

1312
@Test
1413
public void mvcDispatch() throws Exception {
15-
ASMifier.main(new String[]{MvcDispatch.class.getName()});
14+
// ASMifier.main(new String[]{MvcDispatch.class.getName()});
1615
}
1716

1817
@Test
1918
public void myController() throws Exception {
20-
ASMifier.main(new String[]{MyControllerHandler.class.getName()});
19+
// ASMifier.main(new String[]{MyControllerHandler.class.getName()});
2120
}
2221

2322
@Test
2423
public void nullRoutes() throws Exception {
25-
ASMifier.main(new String[]{"source.SuspendRoute"});
24+
// ASMifier.main(new String[]{"source.SuspendRoute"});
2625
}
2726
}
2827

modules/jooby-bom/pom.xml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
<conscrypt.version>2.5.2</conscrypt.version>
3434
<cron-utils.version>9.1.6</cron-utils.version>
3535
<ebean.version>12.16.0</ebean.version>
36-
<exec-maven-plugin.version>3.0.0</exec-maven-plugin.version>
36+
<exec-maven-plugin.version>3.1.0</exec-maven-plugin.version>
3737
<flyway.version>7.5.1</flyway.version>
3838
<freemarker.version>2.3.31</freemarker.version>
3939
<frontend-maven-plugin.version>1.11.0</frontend-maven-plugin.version>
@@ -59,7 +59,7 @@
5959
<javax.inject.version>1</javax.inject.version>
6060
<jboss-modules.version>1.11.0.Final</jboss-modules.version>
6161
<jdbi.version>3.32.0</jdbi.version>
62-
<jetty.version>9.4.48.v20220622</jetty.version>
62+
<jetty.version>11.0.11</jetty.version>
6363
<jfiglet.version>0.0.9</jfiglet.version>
6464
<jmespath-java.version>1.12.230</jmespath-java.version>
6565
<jooby-maven-plugin.version>3.0.0-SNAPSHOT</jooby-maven-plugin.version>
@@ -86,13 +86,13 @@
8686
<maven-enforcer-plugin.version>3.0.0-M3</maven-enforcer-plugin.version>
8787
<maven-gpg-plugin.version>3.0.1</maven-gpg-plugin.version>
8888
<maven-jar-plugin.version>3.2.2</maven-jar-plugin.version>
89-
<maven-javadoc-plugin.version>3.3.0</maven-javadoc-plugin.version>
89+
<maven-javadoc-plugin.version>3.4.1</maven-javadoc-plugin.version>
9090
<maven-plugin-annotations.version>3.6.4</maven-plugin-annotations.version>
9191
<maven-plugin-api.version>3.8.5</maven-plugin-api.version>
92-
<maven-plugin-plugin.version>3.6.0</maven-plugin-plugin.version>
92+
<maven-plugin-plugin.version>3.6.4</maven-plugin-plugin.version>
9393
<maven-project.version>2.2.1</maven-project.version>
9494
<maven-resources-plugin.version>3.2.0</maven-resources-plugin.version>
95-
<maven-shade-plugin.version>3.2.4</maven-shade-plugin.version>
95+
<maven-shade-plugin.version>3.3.0</maven-shade-plugin.version>
9696
<maven-site-plugin.version>3.8.2</maven-site-plugin.version>
9797
<maven-source-plugin.version>3.2.1</maven-source-plugin.version>
9898
<maven-surefire-plugin.version>3.0.0-M6</maven-surefire-plugin.version>

modules/jooby-cli/src/main/resources/cli/build.gradle.hbs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,15 @@ plugins {
1717
id "io.jooby.openAPI" version "${joobyVersion}"
1818
{{/if}}
1919
id "io.jooby.run" version "${joobyVersion}"
20-
id "io.spring.dependency-management" version "1.0.11.RELEASE"
21-
id "com.google.osdetector" version "1.7.0"
22-
id "com.github.johnrengelman.shadow" version "7.0.0"
20+
id "io.spring.dependency-management" version "1.0.13.RELEASE"
21+
id "com.google.osdetector" version "1.7.1"
22+
id "com.github.johnrengelman.shadow" version "7.1.2"
2323
}
2424

2525
group "{{groupId}}"
2626
version "{{version}}"
2727
mainClassName = "{{package}}.App{{#if kotlin}}Kt{{/if}}"
28-
sourceCompatibility = 1.8
28+
sourceCompatibility = 17
2929

3030
repositories {
3131
mavenLocal()
Binary file not shown.

modules/jooby-cli/src/main/resources/cli/gradle/gradle/wrapper/gradle-wrapper.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
22
distributionPath=wrapper/dists
33
zipStoreBase=GRADLE_USER_HOME
44
zipStorePath=wrapper/dists
5-
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
5+
distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-bin.zip

modules/jooby-cli/src/main/resources/cli/pom.xml.hbs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@
2121
<kotlin.version>{{kotlinVersion}}</kotlin.version>
2222
<kotlin.compiler.incremental>true</kotlin.compiler.incremental>
2323
{{/if}}
24-
<maven.compiler.source>1.8</maven.compiler.source>
25-
<maven.compiler.target>1.8</maven.compiler.target>
24+
<maven.compiler.source>17</maven.compiler.source>
25+
<maven.compiler.target>17</maven.compiler.target>
2626
<maven.compiler.parameters>true</maven.compiler.parameters>
2727
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
2828
</properties>

modules/jooby-cli/src/test/java/io/jooby/internal/cli/CommandContextImplTest.java

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@
66

77
import java.io.IOException;
88
import java.io.PrintWriter;
9+
import java.nio.file.Files;
10+
import java.nio.file.Path;
11+
import java.nio.file.Paths;
912
import java.util.Map;
1013

1114
import static org.junit.jupiter.api.Assertions.assertNotNull;
15+
import static org.junit.jupiter.api.Assertions.assertTrue;
1216
import static org.mockito.Mockito.mock;
1317
import static org.mockito.Mockito.when;
1418

@@ -30,4 +34,21 @@ public void shouldLoadDependencyFile() throws IOException {
3034
assertNotNull(dependencyMap);
3135
assertNotNull(dependencyMap.get("mavenTilesPluginVersion"));
3236
}
37+
38+
@Test
39+
public void shouldCopyGradleJar() throws IOException {
40+
PrintWriter writer = mock(PrintWriter.class);
41+
42+
Terminal terminal = mock(Terminal.class);
43+
when(terminal.writer()).thenReturn(writer);
44+
45+
LineReader reader = mock(LineReader.class);
46+
when(reader.getTerminal()).thenReturn(terminal);
47+
48+
CommandContextImpl ctx = new CommandContextImpl(reader, "2.8.5");
49+
Path dest = Paths.get(System.getProperty("java.io.tmpdir"), "gradle-wrapper.jar");
50+
ctx.copyResource("/cli/gradle/gradle/wrapper/gradle-wrapper.jar", dest);
51+
assertTrue(Files.exists(dest));
52+
Files.delete(dest);
53+
}
3354
}

pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1559,7 +1559,7 @@
15591559
<dependency>
15601560
<groupId>org.codehaus.groovy</groupId>
15611561
<artifactId>groovy-all</artifactId>
1562-
<version>3.0.7</version>
1562+
<version>3.0.12</version>
15631563
<type>pom</type>
15641564
<exclusions>
15651565
<exclusion>

0 commit comments

Comments
 (0)