diff --git a/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusGenerateCode.java b/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusGenerateCode.java index 6f6a72d104394..0b1dbb5537e35 100644 --- a/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusGenerateCode.java +++ b/devtools/gradle/src/main/java/io/quarkus/gradle/tasks/QuarkusGenerateCode.java @@ -32,7 +32,7 @@ public class QuarkusGenerateCode extends QuarkusTask { public static final String QUARKUS_GENERATED_SOURCES = "quarkus-generated-sources"; public static final String QUARKUS_TEST_GENERATED_SOURCES = "quarkus-test-generated-sources"; // TODO dynamically load generation provider, or make them write code directly in quarkus-generated-sources - public static final String[] CODE_GENERATION_PROVIDER = new String[] { "grpc", "avpr", "avsc" }; + public static final String[] CODE_GENERATION_PROVIDER = new String[] { "grpc", "avdl", "avpr", "avsc" }; public static final String INIT_AND_RUN = "initAndRun"; private Set sourcesDirectories; diff --git a/extensions/avro/deployment/src/main/java/io/quarkus/avro/deployment/AvroIDLCodeGenProvider.java b/extensions/avro/deployment/src/main/java/io/quarkus/avro/deployment/AvroIDLCodeGenProvider.java new file mode 100644 index 0000000000000..fd89cec14c1a9 --- /dev/null +++ b/extensions/avro/deployment/src/main/java/io/quarkus/avro/deployment/AvroIDLCodeGenProvider.java @@ -0,0 +1,52 @@ +package io.quarkus.avro.deployment; + +import java.io.IOException; +import java.nio.file.Path; + +import org.apache.avro.Protocol; +import org.apache.avro.compiler.idl.Idl; +import org.apache.avro.compiler.idl.ParseException; +import org.apache.avro.compiler.specific.SpecificCompiler; + +import io.quarkus.bootstrap.prebuild.CodeGenException; +import io.quarkus.deployment.CodeGenProvider; + +public class AvroIDLCodeGenProvider extends AvroCodeGenProviderBase implements CodeGenProvider { + @Override + public String providerId() { + return "avdl"; + } + + @Override + public String inputExtension() { + return "avdl"; + } + + @Override + void init() { + + } + + @Override + void compileSingleFile(Path filePath, Path outputDir, AvroOptions options) throws CodeGenException { + try (Idl parser = new Idl(filePath.toFile())) { + Protocol idlProtocol = parser.CompilationUnit(); + String json = idlProtocol.toString(false); + Protocol protocol = Protocol.parse(json); + final SpecificCompiler compiler = new SpecificCompiler(protocol); + compiler.setTemplateDir(templateDirectory); + compiler.setStringType(options.stringType); + compiler.setFieldVisibility(SpecificCompiler.FieldVisibility.PRIVATE); + compiler.setCreateOptionalGetters(options.createOptionalGetters); + compiler.setGettersReturnOptional(options.gettersReturnOptional); + compiler.setOptionalGettersForNullableFieldsOnly(options.optionalGettersForNullableFieldsOnly); + compiler.setCreateSetters(options.createSetters); + compiler.setEnableDecimalLogicalType(options.enableDecimalLogicalType); + + compiler.setOutputCharacterEncoding("UTF-8"); + compiler.compileToDestination(filePath.toFile(), outputDir.toFile()); + } catch (IOException | ParseException e) { + throw new CodeGenException("Failed to compile avro IDL file: " + filePath.toString() + " to Java", e); + } + } +} diff --git a/extensions/avro/deployment/src/main/resources/META-INF/services/io.quarkus.deployment.CodeGenProvider b/extensions/avro/deployment/src/main/resources/META-INF/services/io.quarkus.deployment.CodeGenProvider index d27d31cd4e5f8..5703fd1fcd487 100644 --- a/extensions/avro/deployment/src/main/resources/META-INF/services/io.quarkus.deployment.CodeGenProvider +++ b/extensions/avro/deployment/src/main/resources/META-INF/services/io.quarkus.deployment.CodeGenProvider @@ -1,2 +1,3 @@ +io.quarkus.avro.deployment.AvroIDLCodeGenProvider io.quarkus.avro.deployment.AvroSchemaCodeGenProvider io.quarkus.avro.deployment.AvroProtocolCodeGenProvider \ No newline at end of file diff --git a/integration-tests/avro-reload/src/test/avro/Hello.avdl b/integration-tests/avro-reload/src/test/avro/Hello.avdl new file mode 100644 index 0000000000000..b73c3a35262a0 --- /dev/null +++ b/integration-tests/avro-reload/src/test/avro/Hello.avdl @@ -0,0 +1,13 @@ +@namespace("test") +protocol Hello { + + enum Level{ + LOW, MEDIUM, HIGH + } + + record Message { + string name; + string desc; + Level priority; + } +} \ No newline at end of file diff --git a/integration-tests/avro-reload/src/test/java/io/quarkus/avro/deployment/AvroCodeReloadTest.java b/integration-tests/avro-reload/src/test/java/io/quarkus/avro/deployment/AvroCodeReloadTest.java index c4dcc9a90c4df..e818de39344b2 100644 --- a/integration-tests/avro-reload/src/test/java/io/quarkus/avro/deployment/AvroCodeReloadTest.java +++ b/integration-tests/avro-reload/src/test/java/io/quarkus/avro/deployment/AvroCodeReloadTest.java @@ -43,4 +43,15 @@ void shouldAlterProtocol() throws InterruptedException { assertThat(when().get("/protocol").body().print().split(",")).containsExactlyInAnyOrder("Public", "Private", "Default"); } + @Test + void shouldAlterAvdl() throws InterruptedException { + assertThat(when().get("/avdl").body().print().split(",")).containsExactlyInAnyOrder("LOW", "MEDIUM", "HIGH"); + + test.modifyFile("avro/Hello.avdl", + text -> text.replaceAll(Pattern.quote("LOW, MEDIUM, HIGH"), + "LOWER, MEDIUM, HIGHEST")); + Thread.sleep(5000); // to wait for eager reload for code gen sources to happen + assertThat(when().get("/avdl").body().print().split(",")).containsExactlyInAnyOrder("LOWER", "MEDIUM", "HIGHEST"); + } + } diff --git a/integration-tests/avro-reload/src/test/java/io/quarkus/avro/deployment/AvroReloadResource.java b/integration-tests/avro-reload/src/test/java/io/quarkus/avro/deployment/AvroReloadResource.java index f93e7744b0ef1..810c2bc7d6ae0 100644 --- a/integration-tests/avro-reload/src/test/java/io/quarkus/avro/deployment/AvroReloadResource.java +++ b/integration-tests/avro-reload/src/test/java/io/quarkus/avro/deployment/AvroReloadResource.java @@ -7,6 +7,7 @@ import javax.ws.rs.GET; import javax.ws.rs.Path; +import test.Level; import test.PrivacyImport; import test.ProtocolPrivacy; @@ -23,4 +24,10 @@ public String getAvailableProtocolPrivacies() { return Arrays.stream(ProtocolPrivacy.values()).map(String::valueOf).collect(joining(",")); } + @GET + @Path("/avdl") + public String getAvailableLevel() { + return Arrays.stream(Level.values()).map(String::valueOf).collect(joining(",")); + } + }