Skip to content

Commit 4e77fdd

Browse files
committed
partial compile stuff
1 parent c18e798 commit 4e77fdd

File tree

12 files changed

+282
-39
lines changed

12 files changed

+282
-39
lines changed
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package io.avaje.http.api.spi;
2+
3+
import static java.lang.annotation.ElementType.TYPE;
4+
import static java.lang.annotation.RetentionPolicy.CLASS;
5+
6+
import java.lang.annotation.*;
7+
8+
/**
9+
* For internal use, holds metadata on generated client interfaces for use by code generation (Java
10+
* annotation processing).
11+
*/
12+
@Target(TYPE)
13+
@Retention(CLASS)
14+
public @interface MetaData {
15+
16+
/** The generated HttpClient interfaces. */
17+
Class<?>[] value();
18+
}

http-api/src/main/java/module-info.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,5 @@
22

33
exports io.avaje.http.api;
44
exports io.avaje.http.api.context;
5+
exports io.avaje.http.api.spi;
56
}

http-generator-client/pom.xml

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,16 @@
1111

1212
<properties>
1313
<java.version>11</java.version>
14+
<avaje.prisms.version>1.9</avaje.prisms.version>
1415
</properties>
15-
1616
<dependencies>
17-
17+
<dependency>
18+
<groupId>io.avaje</groupId>
19+
<artifactId>avaje-prisms</artifactId>
20+
<version>${avaje.prisms.version}</version>
21+
<optional>true</optional>
22+
<scope>provided</scope>
23+
</dependency>
1824
<dependency>
1925
<groupId>io.avaje</groupId>
2026
<artifactId>avaje-http-generator-core</artifactId>
@@ -30,8 +36,9 @@
3036
<dependency>
3137
<groupId>io.avaje</groupId>
3238
<artifactId>avaje-http-api</artifactId>
33-
<scope>test</scope>
3439
<version>${project.version}</version>
40+
<optional>true</optional>
41+
<scope>provided</scope>
3542
</dependency>
3643

3744
</dependencies>
@@ -41,12 +48,14 @@
4148
<plugin>
4249
<groupId>org.apache.maven.plugins</groupId>
4350
<artifactId>maven-compiler-plugin</artifactId>
44-
<version>3.10.1</version>
4551
<configuration>
46-
<source>11</source>
47-
<target>11</target>
48-
<!-- Turn off annotation processing for building -->
49-
<compilerArgument>-proc:none</compilerArgument>
52+
<annotationProcessorPaths>
53+
<path>
54+
<groupId>io.avaje</groupId>
55+
<artifactId>avaje-prisms</artifactId>
56+
<version>${avaje.prisms.version}</version>
57+
</path>
58+
</annotationProcessorPaths>
5059
</configuration>
5160
</plugin>
5261
<plugin>

http-generator-client/src/main/java/io/avaje/http/generator/client/ClientProcessor.java

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
package io.avaje.http.generator.client;
22

3-
import static io.avaje.http.generator.core.ProcessingContext.*;
3+
import static io.avaje.http.generator.core.ProcessingContext.logError;
44
import static io.avaje.http.generator.core.ProcessingContext.platform;
55
import static io.avaje.http.generator.core.ProcessingContext.setPlatform;
66
import static io.avaje.http.generator.core.ProcessingContext.typeElement;
77

88
import java.io.IOException;
9-
import java.util.LinkedHashSet;
109
import java.util.Objects;
1110
import java.util.Set;
1211

@@ -27,10 +26,14 @@
2726
@SupportedAnnotationTypes({ClientPrism.PRISM_TYPE, ImportPrism.PRISM_TYPE})
2827
public class ClientProcessor extends AbstractProcessor {
2928

30-
private final Set<String> generatedClients = new LinkedHashSet<>();
29+
private final ComponentMetaData metaData = new ComponentMetaData();
3130

3231
private final boolean useJsonB;
3332

33+
private SimpleComponentWriter componentWriter;
34+
35+
private boolean readModuleInfo;
36+
3437
public ClientProcessor() {
3538
useJsonB = JsonBUtil.detectJsonb();
3639
}
@@ -49,6 +52,8 @@ public synchronized void init(ProcessingEnvironment processingEnv) {
4952
super.init(processingEnv);
5053
this.processingEnv = processingEnv;
5154
ProcessingContext.init(processingEnv, new ClientPlatformAdapter(), false);
55+
56+
this.componentWriter = new SimpleComponentWriter(metaData);
5257
}
5358

5459
@Override
@@ -57,11 +62,13 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
5762
if (!(platform instanceof ClientPlatformAdapter)) {
5863
setPlatform(new ClientPlatformAdapter());
5964
}
60-
61-
for (final Element controller : round.getElementsAnnotatedWith(typeElement(ClientPrism.PRISM_TYPE))) {
65+
readModule();
66+
for (final Element controller :
67+
round.getElementsAnnotatedWith(typeElement(ClientPrism.PRISM_TYPE))) {
6268
writeClient(controller);
6369
}
64-
for (final var importedElement : round.getElementsAnnotatedWith(typeElement(ImportPrism.PRISM_TYPE))) {
70+
for (final var importedElement :
71+
round.getElementsAnnotatedWith(typeElement(ImportPrism.PRISM_TYPE))) {
6572
writeForImported(importedElement);
6673
}
6774

@@ -70,6 +77,14 @@ public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment
7077
setPlatform(platform);
7178
return false;
7279
}
80+
/** Read the existing metadata from the generated component (if exists). */
81+
private void readModule() {
82+
if (readModuleInfo) {
83+
return;
84+
}
85+
readModuleInfo = true;
86+
new ComponentReader(metaData).read();
87+
}
7388

7489
private void writeForImported(Element importedElement) {
7590
ImportPrism.getInstanceOn(importedElement).types().stream()
@@ -83,7 +98,7 @@ private void writeClient(Element controller) {
8398
final ControllerReader reader = new ControllerReader((TypeElement) controller);
8499
reader.read(false);
85100
try {
86-
generatedClients.add(writeClientAdapter(reader));
101+
metaData.add(writeClientAdapter(reader));
87102
} catch (final Throwable e) {
88103
e.printStackTrace();
89104
logError(reader.beanType(), "Failed to write client class " + e);
@@ -95,10 +110,20 @@ protected String writeClientAdapter(ControllerReader reader) throws IOException
95110
return new ClientWriter(reader, useJsonB).write();
96111
}
97112

113+
private void initialiseComponent() {
114+
metaData.initialiseFullName();
115+
try {
116+
componentWriter.init();
117+
} catch (final IOException e) {
118+
logError("Error creating writer for JsonbComponent", e);
119+
}
120+
}
121+
98122
private void writeComponent(boolean processingOver) {
123+
initialiseComponent();
99124
if (processingOver) {
100125
try {
101-
new SimpleComponentWriter(generatedClients).write();
126+
componentWriter.write();
102127
} catch (final IOException e) {
103128
logError("Error writing component", e);
104129
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package io.avaje.http.generator.client;
2+
3+
import java.util.*;
4+
5+
final class ComponentMetaData {
6+
7+
private final List<String> generatedClients = new ArrayList<>();
8+
private String fullName;
9+
10+
@Override
11+
public String toString() {
12+
return generatedClients.toString();
13+
}
14+
15+
/** Ensure the component name has been initialised. */
16+
void initialiseFullName() {
17+
fullName();
18+
}
19+
20+
boolean contains(String type) {
21+
return generatedClients.contains(type);
22+
}
23+
24+
void add(String type) {
25+
generatedClients.add(type);
26+
}
27+
28+
void setFullName(String fullName) {
29+
this.fullName = fullName;
30+
}
31+
32+
String fullName() {
33+
if (fullName == null) {
34+
35+
String topPackage = TopPackage.of(generatedClients);
36+
if (!topPackage.endsWith(".httpclient")) {
37+
topPackage += ".httpclient";
38+
}
39+
fullName = topPackage + ".GeneratedHttpComponent";
40+
}
41+
return fullName;
42+
}
43+
44+
String packageName() {
45+
return TopPackage.packageOf(fullName());
46+
}
47+
48+
List<String> all() {
49+
return generatedClients;
50+
}
51+
52+
/** Return the package imports for the JsonAdapters and related types. */
53+
Collection<String> allImports() {
54+
final Set<String> packageImports = new TreeSet<>(generatedClients);
55+
generatedClients.stream()
56+
.map(s -> removeLast(removeLast(s, ".httpclient"), "HttpClient"))
57+
.forEach(packageImports::add);
58+
59+
return packageImports;
60+
}
61+
62+
public static String removeLast(String s, String search) {
63+
final int pos = s.lastIndexOf(search);
64+
65+
if (pos > -1) {
66+
return s.substring(0, pos) + s.substring(pos + search.length());
67+
}
68+
69+
return s;
70+
}
71+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
package io.avaje.http.generator.client;
2+
import static io.avaje.http.generator.core.ProcessingContext.filer;
3+
import static io.avaje.http.generator.core.ProcessingContext.logDebug;
4+
import static io.avaje.http.generator.core.ProcessingContext.logWarn;
5+
import static io.avaje.http.generator.core.ProcessingContext.typeElement;
6+
7+
import java.io.FileNotFoundException;
8+
import java.io.LineNumberReader;
9+
import java.io.Reader;
10+
import java.nio.file.NoSuchFileException;
11+
import java.util.ArrayList;
12+
import java.util.Collections;
13+
import java.util.List;
14+
15+
import javax.annotation.processing.FilerException;
16+
import javax.lang.model.element.AnnotationMirror;
17+
import javax.lang.model.element.TypeElement;
18+
import javax.lang.model.type.TypeMirror;
19+
import javax.tools.FileObject;
20+
import javax.tools.StandardLocation;
21+
22+
import io.avaje.http.generator.core.Constants;
23+
import io.avaje.prism.GeneratePrism;
24+
25+
@GeneratePrism(io.avaje.http.api.spi.MetaData.class)
26+
final class ComponentReader {
27+
28+
private final ComponentMetaData componentMetaData;
29+
30+
ComponentReader(ComponentMetaData metaData) {
31+
this.componentMetaData = metaData;
32+
}
33+
34+
void read() {
35+
final String componentFullName = loadMetaInfServices();
36+
if (componentFullName != null) {
37+
final TypeElement moduleType = typeElement(componentFullName);
38+
if (moduleType != null) {
39+
componentMetaData.setFullName(componentFullName);
40+
readMetaData(moduleType);
41+
}
42+
}
43+
}
44+
45+
/** Read the existing JsonAdapters from the MetaData annotation of the generated component. */
46+
private void readMetaData(TypeElement moduleType) {
47+
for (final AnnotationMirror annotationMirror : moduleType.getAnnotationMirrors()) {
48+
MetaDataPrism.getOptional(annotationMirror).map(MetaDataPrism::value).stream()
49+
.flatMap(List::stream)
50+
.map(TypeMirror::toString)
51+
.forEach(componentMetaData::add);
52+
}
53+
}
54+
55+
private String loadMetaInfServices() {
56+
final List<String> lines = loadMetaInf();
57+
return lines.isEmpty() ? null : lines.get(0);
58+
}
59+
60+
private List<String> loadMetaInf() {
61+
try {
62+
final FileObject fileObject = filer()
63+
.getResource(StandardLocation.CLASS_OUTPUT, "", Constants.META_INF_COMPONENT);
64+
65+
if (fileObject != null) {
66+
final List<String> lines = new ArrayList<>();
67+
final Reader reader = fileObject.openReader(true);
68+
final LineNumberReader lineReader = new LineNumberReader(reader);
69+
String line;
70+
while ((line = lineReader.readLine()) != null) {
71+
line = line.trim();
72+
if (!line.isEmpty()) {
73+
lines.add(line);
74+
}
75+
}
76+
return lines;
77+
}
78+
79+
} catch (FileNotFoundException | NoSuchFileException e) {
80+
// logDebug("no services file yet");
81+
82+
} catch (final FilerException e) {
83+
logDebug("FilerException reading services file");
84+
85+
} catch (final Exception e) {
86+
e.printStackTrace();
87+
logWarn("Error reading services file: " + e.getMessage());
88+
}
89+
return Collections.emptyList();
90+
}
91+
}

0 commit comments

Comments
 (0)