From 5a7e497225bdd3bccad2f9f537875664b994cb9d Mon Sep 17 00:00:00 2001 From: Paul Kofmann Date: Mon, 30 Jan 2023 15:56:46 +0100 Subject: [PATCH 1/2] Support specifying classpath for additional velocity tool classes --- .../plugin/avro/GenerateAvroJavaTask.java | 43 +++++++++++++++---- 1 file changed, 35 insertions(+), 8 deletions(-) diff --git a/src/main/java/com/github/davidmc24/gradle/plugin/avro/GenerateAvroJavaTask.java b/src/main/java/com/github/davidmc24/gradle/plugin/avro/GenerateAvroJavaTask.java index 6415f09..878a4ac 100644 --- a/src/main/java/com/github/davidmc24/gradle/plugin/avro/GenerateAvroJavaTask.java +++ b/src/main/java/com/github/davidmc24/gradle/plugin/avro/GenerateAvroJavaTask.java @@ -18,11 +18,11 @@ import java.io.File; import java.io.IOException; import java.lang.reflect.InvocationTargetException; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLClassLoader; import java.nio.charset.Charset; -import java.util.Collections; -import java.util.List; -import java.util.Map; -import java.util.Set; +import java.util.*; import java.util.stream.Collectors; import javax.inject.Inject; import org.apache.avro.Conversion; @@ -42,10 +42,8 @@ import org.gradle.api.provider.Property; import org.gradle.api.provider.Provider; import org.gradle.api.specs.NotSpec; -import org.gradle.api.tasks.CacheableTask; -import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.*; import org.gradle.api.tasks.Optional; -import org.gradle.api.tasks.TaskAction; /** * Task to generate Java source files based on Avro protocol files and Avro schema files using {@link Protocol} and @@ -54,6 +52,7 @@ @SuppressWarnings("WeakerAccess") @CacheableTask public class GenerateAvroJavaTask extends OutputDirTask { + private FileCollection classpath; private static Set SUPPORTED_EXTENSIONS = new SetBuilder().add(Constants.PROTOCOL_EXTENSION).add(Constants.SCHEMA_EXTENSION).build(); @@ -79,6 +78,7 @@ public class GenerateAvroJavaTask extends OutputDirTask { @Inject public GenerateAvroJavaTask(ObjectFactory objects) { super(); + this.classpath = GradleCompatibility.createConfigurableFileCollection(getProject()); this.outputCharacterEncoding = objects.property(String.class); this.stringType = objects.property(String.class).convention(Constants.DEFAULT_STRING_TYPE); this.fieldVisibility = objects.property(String.class).convention(Constants.DEFAULT_FIELD_VISIBILITY); @@ -103,6 +103,19 @@ public GenerateAvroJavaTask(ObjectFactory objects) { this.resolver = new SchemaResolver(projectLayout, getLogger()); } + public void setClasspath(FileCollection classpath) { + this.classpath = classpath; + } + + public void classpath(Object... paths) { + this.classpath.plus(getProject().files(paths)); + } + + @Classpath + public FileCollection getClasspath() { + return this.classpath; + } + @Optional @Input public Property getOutputCharacterEncoding() { @@ -340,10 +353,11 @@ private void compile(SpecificCompiler compiler, File sourceFile) throws IOExcept compiler.setTemplateDir(getTemplateDirectory().get()); } if (getAdditionalVelocityToolClasses().isPresent()) { + ClassLoader loader = assembleClassLoader(); List tools = getAdditionalVelocityToolClasses().get().stream() .map(s -> { try { - return Class.forName(s); + return Class.forName(s, true, loader); } catch (ClassNotFoundException e) { throw new RuntimeException("unable to load velocity tool class " + s, e); } @@ -394,4 +408,17 @@ private void registerLogicalTypes() { private void registerCustomConversions(SpecificCompiler compiler) { customConversions.get().forEach(compiler::addCustomConversion); } + + private ClassLoader assembleClassLoader() { + getLogger().debug("Using additional classpath: {}", classpath.getFiles()); + List urls = new LinkedList<>(); + for (File file : classpath) { + try { + urls.add(file.toURI().toURL()); + } catch (MalformedURLException e) { + getLogger().debug(e.getMessage()); + } + } + return new URLClassLoader(urls.toArray(new URL[0]), Thread.currentThread().getContextClassLoader()); + } } From e4f1ede99f714808eb5998b1410857dc849258b5 Mon Sep 17 00:00:00 2001 From: Paul Kofmann Date: Tue, 31 Jan 2023 10:25:39 +0100 Subject: [PATCH 2/2] Add test for classpath property in GenerateAvroJavaTask --- .../avro/AvroBasePluginFunctionalSpec.groovy | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/src/test/groovy/com/github/davidmc24/gradle/plugin/avro/AvroBasePluginFunctionalSpec.groovy b/src/test/groovy/com/github/davidmc24/gradle/plugin/avro/AvroBasePluginFunctionalSpec.groovy index f6b44af..e726893 100644 --- a/src/test/groovy/com/github/davidmc24/gradle/plugin/avro/AvroBasePluginFunctionalSpec.groovy +++ b/src/test/groovy/com/github/davidmc24/gradle/plugin/avro/AvroBasePluginFunctionalSpec.groovy @@ -15,6 +15,9 @@ */ package com.github.davidmc24.gradle.plugin.avro +import com.github.davidmc24.gradle.plugin.avro.test.custom.CommentGenerator +import com.github.davidmc24.gradle.plugin.avro.test.custom.TimestampGenerator + import static org.gradle.testkit.runner.TaskOutcome.SUCCESS class AvroBasePluginFunctionalSpec extends FunctionalSpec { @@ -125,4 +128,50 @@ class AvroBasePluginFunctionalSpec extends FunctionalSpec { projectFile("build/generated-main-avro-avsc/org/apache/avro/Node.avsc").file projectFile("build/generated-main-avro-avsc/org/apache/avro/Interop.avsc").file } + + def "supports classpath property for instantiating of velocity tools"() { + given: + copyAvroTools("src/main/java") + def templatesDir = projectFolder("templates") + copyResource("user.avsc", avroDir) + copyResource("record-tools.vm", templatesDir, "record.vm") + applyPlugin("java") + buildFile << """ + |avro { + | templateDirectory = "${templatesDir.toString()}/" + | additionalVelocityToolClasses = ['com.github.davidmc24.gradle.plugin.avro.test.custom.TimestampGenerator', + | 'com.github.davidmc24.gradle.plugin.avro.test.custom.CommentGenerator'] + |} + |tasks.register("compileTools", JavaCompile) { + | source = sourceSets.main.java + | classpath = sourceSets.main.compileClasspath + | destinationDir = file("build/classes/java/main") + |} + |tasks.register("generateAvro", com.github.davidmc24.gradle.plugin.avro.GenerateAvroJavaTask) { + | dependsOn compileTools + | classpath = files("build/classes/java/main") + | source file("src/main/avro") + | include("**/*.avsc") + | outputDir = file("build/generated-main-avro-java") + |} + |""".stripMargin() + + when: + def result = run("generateAvro") + + then: "the task succeeds" + result.task(":generateAvro").outcome == SUCCESS + def content = projectFile("build/generated-main-avro-java/example/avro/User.java").text + + and: "the velocity tools have been applied" + content.contains(CommentGenerator.CUSTOM_COMMENT) + content.contains(TimestampGenerator.MESSAGE_PREFIX) + } + + private void copyAvroTools(String destDir) { + copyFile("src/test/java", destDir, + "com/github/davidmc24/gradle/plugin/avro/test/custom/CommentGenerator.java") + copyFile("src/test/java", destDir, + "com/github/davidmc24/gradle/plugin/avro/test/custom/TimestampGenerator.java") + } }