Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@

import gg.jte.ContentType;
import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.provider.ListProperty;
import org.gradle.api.provider.MapProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Optional;
import org.gradle.workers.WorkParameters;

import java.util.Map;
Expand All @@ -18,12 +20,12 @@ public interface GenerateJteParams extends WorkParameters {
/**
* The directory where template files are located.
*/
RegularFileProperty getSourceDirectory();
DirectoryProperty getSourceDirectory();

/**
* Destination directory to store generated templates.
*/
RegularFileProperty getTargetDirectory();
DirectoryProperty getTargetDirectory();

/**
* The content type of all templates. Either Plain or Html.
Expand All @@ -44,7 +46,7 @@ public interface GenerateJteParams extends WorkParameters {
* Intercepts the given html tags during template compilation
* and calls the configured htmlInterceptor during template rendering.
*/
Property<String[]> getHtmlTags();
ListProperty<String> getHtmlTags();

/**
* By default, jte omits all HTML/CSS/JS comments, when compiling with {@link ContentType#Html}.
Expand All @@ -62,7 +64,8 @@ public interface GenerateJteParams extends WorkParameters {
* Directory in which to generate non-java files (resources). Typically, set by plugin rather than end user.
* Optional - if null, resources will not be generated
*/
RegularFileProperty getTargetResourceDirectory();
@Optional
DirectoryProperty getTargetResourceDirectory();

/**
* "group/artifact" of the project using jte. Typically, set by plugin rather than end user.
Expand Down
52 changes: 30 additions & 22 deletions jte-gradle-plugin/src/main/java/gg/jte/gradle/GenerateJteTask.java
Original file line number Diff line number Diff line change
@@ -1,61 +1,69 @@
package gg.jte.gradle;

import org.gradle.api.file.ConfigurableFileCollection;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.Property;
import org.gradle.api.provider.Provider;
import org.gradle.api.tasks.Classpath;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.TaskAction;
import org.gradle.workers.WorkQueue;
import org.gradle.workers.WorkerExecutor;

import javax.inject.Inject;
import java.nio.file.Path;
import java.util.List;

public abstract class GenerateJteTask extends JteTaskBase {
private final WorkerExecutor workerExecutor;

@Inject
public GenerateJteTask(JteExtension extension, WorkerExecutor workerExecutor) {
super(extension, JteStage.GENERATE);
public GenerateJteTask(WorkerExecutor workerExecutor, ObjectFactory objectFactory) {
super(JteStage.GENERATE, objectFactory);
this.workerExecutor = workerExecutor;
getOutputs().cacheIf(task -> true); // Enable caching based on outputs
getProjectNamespace().convention(getProject().getGroup() + "/" + getProject().getName());
}

@Override
public Path getTargetDirectory() {
if (!extension.getStage().isPresent()) {
extension.getStage().set(JteStage.GENERATE);
}
return super.getTargetDirectory();
}
@Input
public abstract Property<String> getProjectNamespace();

@InputFiles
@Classpath
public abstract ConfigurableFileCollection getClasspath();

@TaskAction
public void execute() {
getLogger().info("{} execute", getClass().getName());
// Use worker API with classloader isolation to avoid compiler symbol conflicts
WorkQueue workQueue = workerExecutor.classLoaderIsolation(spec -> {
// Include both application and compiler classpath in isolation
spec.getClasspath().from(getClasspath());
spec.getClasspath().from(extension.getCompilePath());
});

workQueue.submit(GenerateJteWorker.class, params -> {
params.getSourceDirectory().fileValue(getSourceDirectory().toFile());
params.getTargetDirectory().fileValue(getTargetDirectory().toFile());
params.getContentType().value(getContentType());
params.getPackageName().value(getPackageName());
params.getTrimControlStructures().value(getTrimControlStructures());
params.getHtmlTags().value(getHtmlTags());
params.getHtmlCommentsPreserved().value(getHtmlCommentsPreserved());
params.getBinaryStaticContent().value(getBinaryStaticContent());
params.getTargetResourceDirectory().fileValue(getTargetResourceDirectory().toFile());
params.getProjectNamespace().value(extension.getProjectNamespace());
params.getCompilerClasspath().from(extension.getCompilePath());
extension.getJteExtensions().get().forEach(e ->
params.getSourceDirectory().set(getSourceDirectory().get().toFile());
params.getTargetDirectory().set(getTargetDirectory().get().toFile());
params.getContentType().set(getContentType());
params.getPackageName().set(getPackageName());
params.getTrimControlStructures().set(getTrimControlStructures());
params.getHtmlTags().set(toListProvider(getHtmlTags()));
params.getHtmlCommentsPreserved().set(getHtmlCommentsPreserved());
params.getBinaryStaticContent().set(getBinaryStaticContent());
params.getTargetResourceDirectory().set(getTargetResourceDirectory().flatMap(path -> objectFactory.directoryProperty().fileValue(path.toFile())));
params.getProjectNamespace().set(getProjectNamespace());
params.getCompilerClasspath().from(getClasspath());
getJteExtensions().get().forEach(e ->
params.getJteExtensions().put(e.getClassName().get(), e.getProperties().get())
);
});
}

@Override
protected void wireExtension(JteExtension extension, Provider<Path> defaultTargetDirectory) {
super.wireExtension(extension, defaultTargetDirectory);
getProjectNamespace().set(extension.getProjectNamespace());
wiring = false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

import gg.jte.TemplateEngine;
import gg.jte.resolve.DirectoryCodeResolver;
import org.gradle.api.file.RegularFileProperty;
import org.gradle.workers.WorkAction;
import org.gradle.api.logging.Logger;
import org.gradle.api.logging.Logging;
Expand All @@ -21,11 +20,11 @@ public void execute() {

// Load compiler in isolated classloader
ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
try (URLClassLoader compilerClassLoader = ClassLoaderUtils.createCompilerClassLoader(params.getCompilerClasspath())) {
try (URLClassLoader compilerClassLoader = Utils.createCompilerClassLoader(params.getCompilerClasspath())) {
Thread.currentThread().setContextClassLoader(compilerClassLoader);

Path sourceDirectory = path(params.getSourceDirectory());
Path targetDirectory = path(params.getTargetDirectory());
Path sourceDirectory = Utils.toPathOrNull(params.getSourceDirectory());
Path targetDirectory = Utils.toPathOrNull(params.getTargetDirectory());

logger.info("Generating jte templates found in {}", sourceDirectory);

Expand All @@ -36,10 +35,10 @@ public void execute() {
null,
params.getPackageName().get());
templateEngine.setTrimControlStructures(params.getTrimControlStructures().getOrElse(false));
templateEngine.setHtmlTags(params.getHtmlTags().getOrNull());
templateEngine.setHtmlTags(Utils.toStringArrayOrNull(params.getHtmlTags()));
templateEngine.setHtmlCommentsPreserved(params.getHtmlCommentsPreserved().getOrElse(false));
templateEngine.setBinaryStaticContent(params.getBinaryStaticContent().getOrElse(false));
templateEngine.setTargetResourceDirectory(path(params.getTargetResourceDirectory()));
templateEngine.setTargetResourceDirectory(Utils.toPathOrNull(params.getTargetResourceDirectory()));
templateEngine.setProjectNamespace(params.getProjectNamespace().getOrNull());
templateEngine.setExtensions(params.getJteExtensions().get());

Expand All @@ -62,8 +61,4 @@ public void execute() {
}
}


private static Path path(RegularFileProperty property) {
return property.getAsFile().get().toPath();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.gradle.api.provider.ListProperty;
import org.gradle.api.provider.Property;

import javax.inject.Inject;
import java.nio.file.Path;


Expand All @@ -21,6 +22,7 @@ public abstract class JteExtension
{
private final ObjectFactory objectFactory;

@Inject
public JteExtension(ObjectFactory objectFactory) {
this.objectFactory = objectFactory;
}
Expand All @@ -29,7 +31,7 @@ public JteExtension(ObjectFactory objectFactory) {
public abstract Property<Path> getSourceDirectory();
public abstract Property<Path> getTargetDirectory();
public abstract Property<ContentType> getContentType();
public abstract Property<Boolean> getTrimControlStructures();
public abstract Property<Boolean> getTrimControlStructures();
public abstract Property<String[]> getHtmlTags();
public abstract Property<Boolean> getHtmlCommentsPreserved();
public abstract Property<Boolean> getBinaryStaticContent();
Expand All @@ -38,7 +40,9 @@ public JteExtension(ObjectFactory objectFactory) {
public abstract ConfigurableFileCollection getCompilePath();
public abstract Property<String> getHtmlPolicyClass();
public abstract Property<String[]> getCompileArgs();

public abstract Property<String[]> getKotlinCompileArgs();

public abstract Property<String> getProjectNamespace();
public abstract ListProperty<JteExtensionSettings> getJteExtensions();

Expand Down
29 changes: 11 additions & 18 deletions jte-gradle-plugin/src/main/java/gg/jte/gradle/JteGradle.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
import org.gradle.api.tasks.SourceSet;
import org.gradle.api.tasks.TaskProvider;

import java.io.File;

public class JteGradle implements Plugin<Project> {

@Override
Expand All @@ -21,11 +19,14 @@ public void apply(Project project) {
JteExtension extension = project.getExtensions().create("jte", JteExtension.class, project.getObjects());
defaults(project, extension, main);

TaskProvider<PrecompileJteTask> precompileJteTask = project.getTasks().register("precompileJte", PrecompileJteTask.class, extension);
precompileJteTask.configure(t -> t.dependsOn("compileJava"));
TaskProvider<PrecompileJteTask> precompileJteTask = project.getTasks().register("precompileJte", PrecompileJteTask.class);
precompileJteTask.configure(t -> {
t.dependsOn("compileJava");
t.wireExtension(extension, project.provider(() -> project.getLayout().getProjectDirectory().dir("jte-classes").getAsFile().toPath()));
});
project.getTasks().named("test").configure(t -> t.dependsOn(precompileJteTask));

TaskProvider<GenerateJteTask> generateJteTask = project.getTasks().register("generateJte", GenerateJteTask.class, extension);
TaskProvider<GenerateJteTask> generateJteTask = project.getTasks().register("generateJte", GenerateJteTask.class);
configureTask(project, "compileJava", t -> t.dependsOn(generateJteTask));
configureTask(project, "sourcesJar", t -> t.dependsOn(generateJteTask));
configureTask(project, "processResources", t -> t.dependsOn(generateJteTask));
Expand All @@ -36,7 +37,8 @@ public void apply(Project project) {
Configuration additionalClasspath = project.getConfigurations().create("jteGenerate");
generateJteTask.configure(t -> {
t.getClasspath().from(additionalClasspath);
if (extension.getStage().isPresent() && extension.getStage().get() == JteStage.GENERATE) {
t.wireExtension(extension, project.getLayout().getBuildDirectory().dir("generated-sources/jte").map(d -> d.getAsFile().toPath()));
if (t.getConfiguredStage().isPresent() && t.getConfiguredStage().get() == JteStage.GENERATE) {
main.getJava().srcDir(t.getTargetDirectory());
main.getResources().srcDir(t.getTargetResourceDirectory());
}
Expand All @@ -50,21 +52,12 @@ private SourceSet getMainSourceSet(Project project) {
}

private void defaults(Project project, JteExtension extension, SourceSet main) {
extension.getSourceDirectory().convention(project.file("src/main/jte").toPath()); // TODO can it use sourceset?
extension.getTargetDirectory().convention(extension.getStage().map(stage -> {
if (stage == JteStage.PRECOMPILE) {
return project.file("jte-classes").toPath();
} else if (stage == JteStage.GENERATE) {
return new File(project.getBuildDir(), "generated-sources/jte").toPath();
} else {
//noinspection ConstantConditions // according to https://docs.gradle.org/current/javadoc/org/gradle/api/provider/Provider.html#map-org.gradle.api.Transformer- it's ok to return null here
return null;
}
}));
extension.getStage().convention(JteStage.NONE);
extension.getSourceDirectory().convention(project.getLayout().getProjectDirectory().dir("src/main/jte").getAsFile().toPath()); // TODO can it use sourceset?
extension.getContentType().convention(ContentType.Html);
extension.getBinaryStaticContent().convention(false);
extension.getPackageName().convention(Constants.PACKAGE_NAME_PRECOMPILED);
extension.getTargetResourceDirectory().convention(new File(project.getBuildDir(), "generated-resources/jte").toPath());
extension.getTargetResourceDirectory().convention(project.getLayout().getBuildDirectory().dir("generated-resources/jte").map(d -> d.getAsFile().toPath()));

// Create configuration to include Kotlin Compiler isolated from user Kotlin version
String configurationName = "jteKotlinCompiler";
Expand Down
7 changes: 6 additions & 1 deletion jte-gradle-plugin/src/main/java/gg/jte/gradle/JteStage.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,10 @@ public enum JteStage
* "generate" means that jte files will be converted into Java source _before_ the main java code of your project
* is compiled, and will become part of your application jar during project build.
*/
GENERATE
GENERATE,

/**
* stage has not yet been configured
*/
NONE
}
Loading
Loading