diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 0193db3..8ab492e 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -4,7 +4,7 @@ import com.uwyn.rife2.gradle.TemplateType.* plugins { application - id("com.uwyn.rife2") + id("com.uwyn.rife2") version "1.0.0" `maven-publish` id("org.graalvm.buildtools.native") version "0.9.20" } diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts deleted file mode 100644 index c7fabff..0000000 --- a/build-logic/build.gradle.kts +++ /dev/null @@ -1,31 +0,0 @@ -plugins { - `java-gradle-plugin` - groovy -} - -repositories { - mavenCentral() -} - -dependencies { - gradleApi() - testImplementation(libs.spock.core) - testImplementation(gradleTestKit()) -} - -gradlePlugin { - plugins { - create("rife2") { - id = "com.uwyn.rife2" - implementationClass = "com.uwyn.rife2.gradle.Rife2Plugin" - } - } -} - -tasks.withType().configureEach { - useJUnitPlatform() - testLogging { - exceptionFormat = org.gradle.api.tasks.testing.logging.TestExceptionFormat.FULL - events = setOf(org.gradle.api.tasks.testing.logging.TestLogEvent.PASSED, org.gradle.api.tasks.testing.logging.TestLogEvent.SKIPPED, org.gradle.api.tasks.testing.logging.TestLogEvent.FAILED) - } -} diff --git a/build-logic/settings.gradle.kts b/build-logic/settings.gradle.kts deleted file mode 100644 index 9ac59bd..0000000 --- a/build-logic/settings.gradle.kts +++ /dev/null @@ -1,9 +0,0 @@ -rootProject.name = "build-logic" - -dependencyResolutionManagement { - versionCatalogs { - create("libs") { - from(files("../gradle/libs.versions.toml")) - } - } -} diff --git a/build-logic/src/main/java/com/uwyn/rife2/gradle/PrecompileTemplates.java b/build-logic/src/main/java/com/uwyn/rife2/gradle/PrecompileTemplates.java deleted file mode 100644 index e739026..0000000 --- a/build-logic/src/main/java/com/uwyn/rife2/gradle/PrecompileTemplates.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2003-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.uwyn.rife2.gradle; - -import org.gradle.api.DefaultTask; -import org.gradle.api.file.ConfigurableFileCollection; -import org.gradle.api.file.DirectoryProperty; -import org.gradle.api.provider.ListProperty; -import org.gradle.api.provider.Property; -import org.gradle.api.tasks.CacheableTask; -import org.gradle.api.tasks.Classpath; -import org.gradle.api.tasks.Input; -import org.gradle.api.tasks.InputFiles; -import org.gradle.api.tasks.Optional; -import org.gradle.api.tasks.OutputDirectory; -import org.gradle.api.tasks.PathSensitive; -import org.gradle.api.tasks.PathSensitivity; -import org.gradle.api.tasks.TaskAction; -import org.gradle.process.ExecOperations; - -import javax.inject.Inject; -import java.nio.file.Files; -import java.util.ArrayList; -import java.util.List; - -/** - * Gradle task to pre-compile RIFE2 templates - */ -@CacheableTask -public abstract class PrecompileTemplates extends DefaultTask { - /** - * The directories where template files can be found. - * - * @return the directories with template files - */ - @InputFiles - @PathSensitive(PathSensitivity.RELATIVE) - public abstract ConfigurableFileCollection getTemplatesDirectories(); - - /** - * The template types to pre-compile. - * - * @return a list of template types - */ - @Input - public abstract ListProperty getTypes(); - - /** - * The encoding to use when reading the template files. - * Defaults to {@code UTF-8}. - * - * @return the encoding of the template files - */ - @Input - @Optional - public abstract Property getEncoding(); - - /** - * Indicates whether the pre-compilation should be verbose or not. - * - * @return {@code true} when the pre-compilation should be verbose; or - * {@code false} otherwise - */ - @Input - @Optional - public abstract Property getVerbose(); - - /** - * Provides the directory into which pre-compiled template class files should be stored. - * - * @return the output directory for the template pre-compilation - */ - @OutputDirectory - public abstract DirectoryProperty getOutputDirectory(); - - @Classpath - public abstract ConfigurableFileCollection getClasspath(); - - @Inject - protected abstract ExecOperations getExecOperations(); - - /** - * Perform the template pre-compilation - */ - @TaskAction - public void precompileTemplates() { - for (var type : getTypes().get()) { - getTemplatesDirectories().getFiles().forEach(dir -> { - if (Files.exists(dir.toPath())) { - getExecOperations().javaexec(javaexec -> { - javaexec.setClasspath(getClasspath()); - javaexec.getMainClass().set("rife.template.TemplateDeployer"); - List args = new ArrayList<>(); - if (getVerbose().isPresent() && Boolean.TRUE.equals(getVerbose().get())) { - args.add("-verbose"); - } - args.add("-t"); - args.add(type.identifier()); - args.add("-d"); - args.add(getOutputDirectory().get().getAsFile().getPath()); - args.add("-encoding"); - args.add(getEncoding().orElse("UTF-8").get()); - args.add(dir.getPath()); - javaexec.args(args); - }); - } - }); - - } - } -} diff --git a/build-logic/src/main/java/com/uwyn/rife2/gradle/Rife2Extension.java b/build-logic/src/main/java/com/uwyn/rife2/gradle/Rife2Extension.java deleted file mode 100644 index 5919e05..0000000 --- a/build-logic/src/main/java/com/uwyn/rife2/gradle/Rife2Extension.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2003-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.uwyn.rife2.gradle; - -import org.gradle.api.file.ConfigurableFileCollection; -import org.gradle.api.provider.ListProperty; -import org.gradle.api.provider.Property; - -/** - * The Gradle RIFE2 extension - */ -public abstract class Rife2Extension { - /** - * The RIFE2 version that should be used by the project. - * - * @return the RIFE2 version as a string - */ - public abstract Property getVersion(); - - /** - * Indicates whether the project should be launched with the RIFE2 agent or not. - * - * @return {@code true} when the project should be launched with the RIFE2 agent; - * {@code false} otherwise - */ - public abstract Property getUseAgent(); - - /** - * Specifies the main Java class to use when building the uber jar. - * - * @return the fully qualified name of the main class to use when launching the uber jar. - */ - public abstract Property getUberMainClass(); - - /** - * Specifies the template types that should be precompiled. - * By default, none are precompiled. - * - * @return a list of template types to precompile - */ - public abstract ListProperty getPrecompiledTemplateTypes(); - - /** - * Specifies the directories where the template files can be found. - * By default, this includes {@code "src/main/resources/templates"}. - * - * @return the collection of directories to look for template files - */ - public abstract ConfigurableFileCollection getTemplateDirectories(); -} diff --git a/build-logic/src/main/java/com/uwyn/rife2/gradle/Rife2Plugin.java b/build-logic/src/main/java/com/uwyn/rife2/gradle/Rife2Plugin.java deleted file mode 100644 index 608faa6..0000000 --- a/build-logic/src/main/java/com/uwyn/rife2/gradle/Rife2Plugin.java +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright 2003-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.uwyn.rife2.gradle; - -import org.gradle.api.Plugin; -import org.gradle.api.Project; -import org.gradle.api.artifacts.Configuration; -import org.gradle.api.artifacts.ConfigurationContainer; -import org.gradle.api.artifacts.dsl.DependencyHandler; -import org.gradle.api.attributes.Attribute; -import org.gradle.api.attributes.Bundling; -import org.gradle.api.component.AdhocComponentWithVariants; -import org.gradle.api.component.ConfigurationVariantDetails; -import org.gradle.api.file.ConfigurableFileCollection; -import org.gradle.api.file.DuplicatesStrategy; -import org.gradle.api.plugins.BasePluginExtension; -import org.gradle.api.plugins.JavaApplication; -import org.gradle.api.plugins.JavaPlugin; -import org.gradle.api.plugins.JavaPluginExtension; -import org.gradle.api.plugins.PluginContainer; -import org.gradle.api.tasks.JavaExec; -import org.gradle.api.tasks.SourceSet; -import org.gradle.api.tasks.TaskContainer; -import org.gradle.api.tasks.TaskProvider; -import org.gradle.api.tasks.bundling.Jar; -import org.gradle.api.tasks.testing.Test; -import org.gradle.process.CommandLineArgumentProvider; - -import java.util.Collections; -import java.util.List; -import java.util.Locale; -import java.util.stream.Collectors; - -public class Rife2Plugin implements Plugin { - static final List DEFAULT_TEMPLATES_DIRS = List.of("src/main/resources/templates"); - static final String DEFAULT_GENERATED_RIFE2_CLASSES_DIR = "generated/classes/rife2"; - static final String RIFE2_GROUP = "rife2"; - static final String WEBAPP_SRCDIR = "src/main/webapp"; - static final String PRECOMPILE_TEMPLATES_TASK_NAME = "precompileTemplates"; - - @Override - public void apply(Project project) { - var plugins = project.getPlugins(); - plugins.apply("java"); - var javaPluginExtension = project.getExtensions().getByType(JavaPluginExtension.class); - var rife2Extension = createRife2Extension(project); - var configurations = project.getConfigurations(); - var dependencyHandler = project.getDependencies(); - var tasks = project.getTasks(); - - var rife2Configuration = createRife2Configuration(configurations, dependencyHandler, rife2Extension); - var rife2CompilerClasspath = createRife2CompilerClasspathConfiguration(configurations, rife2Configuration); - var rife2AgentClasspath = createRife2AgentConfiguration(configurations, dependencyHandler, rife2Extension); - configurations.getByName(JavaPlugin.IMPLEMENTATION_CONFIGURATION_NAME).extendsFrom(rife2Configuration); - - var precompileTemplates = registerPrecompileTemplateTask(project, rife2CompilerClasspath, rife2Extension); - createRife2DevelopmentOnlyConfiguration(project, configurations, dependencyHandler, rife2Extension.getTemplateDirectories()); - exposePrecompiledTemplatesToTestTask(project, configurations, dependencyHandler, precompileTemplates); - configureAgent(project, plugins, rife2Extension, rife2AgentClasspath); - TaskProvider uberJarTask = registerUberJarTask(project, plugins, javaPluginExtension, rife2Extension, tasks, precompileTemplates); - bundlePrecompiledTemplatesIntoJarFile(tasks, precompileTemplates, rife2Extension); - - configureMavenPublishing(project, plugins, configurations, uberJarTask); - } - - @SuppressWarnings("unchecked") - private static void configureMavenPublishing(Project project, - PluginContainer plugins, - ConfigurationContainer configurations, - TaskProvider uberJarTask) { - plugins.withId("maven-publish", unused -> { - var rife2UberJarElements = configurations.create("rife2UberJarElements", conf -> { - conf.setDescription("Exposes the uber jar archive of the RIFE2 web application."); - conf.setCanBeResolved(false); - conf.setCanBeConsumed(true); - conf.getOutgoing().artifact(uberJarTask, artifact -> artifact.setClassifier("uber")); - - var runtimeAttributes = configurations.getByName(JavaPlugin.RUNTIME_ELEMENTS_CONFIGURATION_NAME).getAttributes(); - conf.attributes(attrs -> { - for (Attribute attribute : runtimeAttributes.keySet()) { - Object value = runtimeAttributes.getAttribute(attribute); - //noinspection unchecked - if (Bundling.class.equals(attribute.getType())) { - attrs.attribute(Bundling.BUNDLING_ATTRIBUTE, project.getObjects().named(Bundling.class, Bundling.SHADOWED)); - } else { - attrs.attribute((Attribute) attribute, value); - } - } - }); - }); - - var component = (AdhocComponentWithVariants) project.getComponents().getByName("java"); - component.addVariantsFromConfiguration(rife2UberJarElements, ConfigurationVariantDetails::mapToOptional); - }); - } - - private static void exposePrecompiledTemplatesToTestTask(Project project, - ConfigurationContainer configurations, - DependencyHandler dependencyHandler, - TaskProvider precompileTemplatesTask) { - configurations.getByName(JavaPlugin.TEST_RUNTIME_ONLY_CONFIGURATION_NAME) - .getDependencies() - .add(dependencyHandler.create(project.files(precompileTemplatesTask))); - } - - private static void bundlePrecompiledTemplatesIntoJarFile(TaskContainer tasks, - TaskProvider precompileTemplatesTask, - Rife2Extension rife2Extension) { - tasks.named("jar", Jar.class, jar -> { - jar.from(precompileTemplatesTask); - excludeTemplateSourcesInClassPath(jar, precompileTemplatesTask, rife2Extension); - }); - } - - private static void excludeTemplateSourcesInClassPath(Jar jar, TaskProvider precompileTemplatesTask, Rife2Extension rife2Extension) { - // This isn't great because it needs to be partially hardcoded, in order to avoid the templates - // declared in `src/main/resources/templates` to be included in the jar file. - precompileTemplatesTask.get().getTemplatesDirectories().forEach(dir -> { - if (dir.getAbsolutePath().contains("/src/main/resources/")) { - rife2Extension.getPrecompiledTemplateTypes().get().forEach(templateType -> - jar.exclude("/" + dir.getName() + "/**." + templateType.identifier().toLowerCase())); - } - }); - } - - private void createRife2DevelopmentOnlyConfiguration(Project project, - ConfigurationContainer configurations, - DependencyHandler dependencies, - ConfigurableFileCollection templateDirectories) { - var rife2DevelopmentOnly = configurations.create("rife2DevelopmentOnly", conf -> { - conf.setDescription("Dependencies which should only be visible when running the application in development mode (and not in tests)."); - conf.setCanBeConsumed(false); - conf.setCanBeResolved(false); - }); - rife2DevelopmentOnly.getDependencies().addAllLater(templateDirectories.getElements().map(locations -> - locations.stream().map(fs -> dependencies.create(project.files(fs))).collect(Collectors.toList())) - ); - configurations.getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME).extendsFrom(rife2DevelopmentOnly); - } - - private static TaskProvider registerUberJarTask(Project project, - PluginContainer plugins, - JavaPluginExtension javaPluginExtension, - Rife2Extension rife2Extension, - TaskContainer tasks, - TaskProvider precompileTemplatesTask) { - return tasks.register("uberJar", Jar.class, jar -> { - jar.setGroup(RIFE2_GROUP); - jar.setDescription("Assembles the web application and all dependencies into a single jar archive."); - var base = project.getExtensions().getByType(BasePluginExtension.class); - jar.getArchiveBaseName().convention(project.provider(() -> base.getArchivesName().get() + "-uber")); - jar.setDuplicatesStrategy(DuplicatesStrategy.EXCLUDE); - jar.from(javaPluginExtension.getSourceSets().getByName(SourceSet.MAIN_SOURCE_SET_NAME).getOutput()); - jar.from(precompileTemplatesTask); - jar.into("webapp", spec -> spec.from(WEBAPP_SRCDIR)); - var runtimeClasspath = project.getConfigurations().getByName(JavaPlugin.RUNTIME_CLASSPATH_CONFIGURATION_NAME); - jar.from(runtimeClasspath.getElements().map(e -> e.stream() - .filter(f -> f.getAsFile().getName().toLowerCase(Locale.ENGLISH).endsWith(".jar")) - .map(project::zipTree) - .toList())); - excludeTemplateSourcesInClassPath(jar, precompileTemplatesTask, rife2Extension); - plugins.withId("application", unused -> jar.manifest(manifest -> - manifest.getAttributes().put("Main-Class", rife2Extension.getUberMainClass().get())) - ); - }); - } - - private static void configureAgent(Project project, - PluginContainer plugins, - Rife2Extension rife2Extension, - Configuration rife2AgentClasspath) { - CommandLineArgumentProvider agentProvider = () -> { - if (Boolean.TRUE.equals(rife2Extension.getUseAgent().get())) { - return Collections.singleton("-javaagent:" + rife2AgentClasspath.getAsPath()); - } - return Collections.emptyList(); - }; - project.getTasks().named("test", Test.class, test -> test.getJvmArgumentProviders().add(agentProvider)); - plugins.withId("application", unused -> project.getTasks().named("run", JavaExec.class, run -> run.getArgumentProviders().add(agentProvider))); - } - - private static Rife2Extension createRife2Extension(Project project) { - var rife2 = project.getExtensions().create("rife2", Rife2Extension.class); - rife2.getUseAgent().convention(false); - rife2.getUberMainClass().convention(project.getExtensions().getByType(JavaApplication.class).getMainClass() - .map(mainClass -> mainClass + "Uber")); - DEFAULT_TEMPLATES_DIRS.stream().forEachOrdered(dir -> rife2.getTemplateDirectories().from(project.files(dir))); - return rife2; - } - - private static Configuration createRife2CompilerClasspathConfiguration(ConfigurationContainer configurations, - Configuration rife2Configuration) { - return configurations.create("rife2CompilerClasspath", conf -> { - conf.setDescription("The RIFE2 compiler classpath"); - conf.setCanBeConsumed(false); - conf.setCanBeResolved(true); - conf.extendsFrom(rife2Configuration); - }); - } - - private static Configuration createRife2AgentConfiguration(ConfigurationContainer configurations, - DependencyHandler dependencyHandler, - Rife2Extension rife2Extension) { - return configurations.create("rife2Agent", conf -> { - conf.setDescription("The RIFE2 agent classpath"); - conf.setCanBeConsumed(false); - conf.setCanBeResolved(true); - conf.setTransitive(false); - conf.getDependencies().addLater(rife2Extension.getVersion() - .map(version -> dependencyHandler.create("com.uwyn.rife2:rife2:" + version + ":agent"))); - }); - } - - private static Configuration createRife2Configuration(ConfigurationContainer configurations, - DependencyHandler dependencyHandler, - Rife2Extension rife2Extension) { - var config = configurations.create("rife2", conf -> { - conf.setDescription("The RIFE2 framework dependencies"); - conf.setCanBeConsumed(false); - conf.setCanBeResolved(false); - }); - config.getDependencies().addLater(rife2Extension.getVersion() - .map(version -> dependencyHandler.create("com.uwyn.rife2:rife2:" + version))); - return config; - } - - private static TaskProvider registerPrecompileTemplateTask(Project project, - Configuration rife2CompilerClasspath, - Rife2Extension rife2Extension) { - return project.getTasks().register(PRECOMPILE_TEMPLATES_TASK_NAME, PrecompileTemplates.class, task -> { - task.setGroup(RIFE2_GROUP); - task.setDescription("Pre-compiles the templates."); - task.getVerbose().convention(true); - task.getClasspath().from(rife2CompilerClasspath); - task.getTypes().convention(rife2Extension.getPrecompiledTemplateTypes()); - task.getTemplatesDirectories().from(rife2Extension.getTemplateDirectories()); - task.getOutputDirectory().set(project.getLayout().getBuildDirectory().dir(DEFAULT_GENERATED_RIFE2_CLASSES_DIR)); - }); - } -} \ No newline at end of file diff --git a/build-logic/src/main/java/com/uwyn/rife2/gradle/TemplateType.java b/build-logic/src/main/java/com/uwyn/rife2/gradle/TemplateType.java deleted file mode 100644 index 96a4bc6..0000000 --- a/build-logic/src/main/java/com/uwyn/rife2/gradle/TemplateType.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2003-2021 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.uwyn.rife2.gradle; - -import java.io.Serial; -import java.io.Serializable; - -/** - * Allows template types to be specified for pre-compilation. - */ -public class TemplateType implements Serializable { - @Serial private static final long serialVersionUID = -2736320275307140837L; - - /** - * The {@code html} template type. - */ - public static TemplateType HTML = new TemplateType("html"); - /** - * The {@code json} template type. - */ - public static TemplateType JSON = new TemplateType("json"); - /** - * The {@code svg} template type. - */ - public static TemplateType SVG = new TemplateType("svg"); - /** - * The {@code xml} template type. - */ - public static TemplateType XML = new TemplateType("xml"); - /** - * The {@code txt} template type. - */ - public static TemplateType TXT = new TemplateType("txt"); - /** - * The {@code sql} template type. - */ - public static TemplateType SQL = new TemplateType("sql"); - - private final String identifier_; - - /** - * Creates a new template type instance. - * - * @param identifier the identifier of this template type - */ - public TemplateType(String identifier) { - identifier_ = identifier; - } - - /** - * Retrieves the identifier for this template type - * @return the template type identifier as a string - */ - public String identifier() { - return identifier_; - } -} \ No newline at end of file diff --git a/build-logic/src/test-projects/minimal/build.gradle b/build-logic/src/test-projects/minimal/build.gradle deleted file mode 100644 index 2212c0f..0000000 --- a/build-logic/src/test-projects/minimal/build.gradle +++ /dev/null @@ -1,42 +0,0 @@ -import com.uwyn.rife2.gradle.TemplateType - -plugins { - id("application") - id("com.uwyn.rife2") -} - -base { - archivesName = "hello" - version = 1.0 - group = "com.example" -} - -application { - mainClass = "hello.App" -} - -java { - toolchain { - languageVersion = JavaLanguageVersion.of(17) - } -} - -repositories { - mavenCentral() -} - -rife2 { - version = "1.4.0" - useAgent = true - precompiledTemplateTypes.add(TemplateType.HTML) - templateDirectories.from(file("src/main/templates")) -} - -dependencies { - runtimeOnly("org.eclipse.jetty:jetty-server:11.0.13") - runtimeOnly("org.eclipse.jetty:jetty-servlet:11.0.13") - runtimeOnly("org.slf4j:slf4j-simple:2.0.5") - - testImplementation("org.jsoup:jsoup:1.15.3") - testImplementation("org.junit.jupiter:junit-jupiter:5.9.1") -} diff --git a/build-logic/src/test-projects/minimal/settings.gradle b/build-logic/src/test-projects/minimal/settings.gradle deleted file mode 100644 index e87ab3c..0000000 --- a/build-logic/src/test-projects/minimal/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -rootProject.name = 'minimal' diff --git a/build-logic/src/test-projects/minimal/src/main/java/hello/App.java b/build-logic/src/test-projects/minimal/src/main/java/hello/App.java deleted file mode 100644 index 43a1870..0000000 --- a/build-logic/src/test-projects/minimal/src/main/java/hello/App.java +++ /dev/null @@ -1,16 +0,0 @@ -package hello; - -import rife.engine.*; - -public class App extends Site { - public void setup() { - var hello = get("/hello", c -> c.print(c.template("hello"))); - get("/", c -> c.redirect(hello)); - } - - public static void main(String[] args) { - new Server() - .staticResourceBase("src/main/webapp") - .start(new App()); - } -} diff --git a/build-logic/src/test-projects/minimal/src/main/resources/templates/world.html b/build-logic/src/test-projects/minimal/src/main/resources/templates/world.html deleted file mode 100644 index 59ff81b..0000000 --- a/build-logic/src/test-projects/minimal/src/main/resources/templates/world.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - <!--v title-->Hello<!--/v--> - - - -

Hello World

- - diff --git a/build-logic/src/test-projects/minimal/src/main/templates/hello.html b/build-logic/src/test-projects/minimal/src/main/templates/hello.html deleted file mode 100644 index 59ff81b..0000000 --- a/build-logic/src/test-projects/minimal/src/main/templates/hello.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - - <!--v title-->Hello<!--/v--> - - - -

Hello World

- - diff --git a/build-logic/src/test-projects/minimal/src/main/webapp/css/style.css b/build-logic/src/test-projects/minimal/src/main/webapp/css/style.css deleted file mode 100644 index 52bf6c7..0000000 --- a/build-logic/src/test-projects/minimal/src/main/webapp/css/style.css +++ /dev/null @@ -1,21 +0,0 @@ -:root { - /* fonts */ - --main-font: sans-serif; - - /* font sizes */ - --main-font-size: 18px; - - /* colors */ - --main-background-color: #0d0d0d; - --main-text-color: #d0d0d0; - - /* margins and padding */ - --content-padding: 2em; -} -body { - background: var(--main-background-color); - font-family: var(--main-font); - font-style: var(--main-font-size); - color: var(--main-text-color); - padding: var(--content-padding); -} \ No newline at end of file diff --git a/build-logic/src/test-projects/minimal/src/test/java/hello/AppTest.java b/build-logic/src/test-projects/minimal/src/test/java/hello/AppTest.java deleted file mode 100644 index 45a0763..0000000 --- a/build-logic/src/test-projects/minimal/src/test/java/hello/AppTest.java +++ /dev/null @@ -1,24 +0,0 @@ -/* - * This Java source file was generated by the Gradle 'init' task. - */ -package hello; - -import org.junit.jupiter.api.Test; -import rife.test.MockConversation; - -import static org.junit.jupiter.api.Assertions.*; - -public class AppTest { - @Test - void verifyRoot() { - var m = new MockConversation(new App()); - assertEquals(m.doRequest("/").getStatus(), 302); - } - - @Test - void verifyHello() { - var m = new MockConversation(new App()); - assertEquals("Hello", m.doRequest("/hello") - .getTemplate().getValue("title")); - } -} diff --git a/build-logic/src/test/groovy/com/uwyn/rife2/gradle/AbstractFunctionalTest.groovy b/build-logic/src/test/groovy/com/uwyn/rife2/gradle/AbstractFunctionalTest.groovy deleted file mode 100644 index 7629d3f..0000000 --- a/build-logic/src/test/groovy/com/uwyn/rife2/gradle/AbstractFunctionalTest.groovy +++ /dev/null @@ -1,184 +0,0 @@ -package com.uwyn.rife2.gradle - -import org.gradle.testkit.runner.BuildResult -import org.gradle.testkit.runner.GradleRunner -import org.gradle.testkit.runner.TaskOutcome -import org.gradle.util.GFileUtils -import org.gradle.util.GradleVersion -import spock.lang.Specification -import spock.lang.TempDir - -import java.nio.file.Path - -abstract class AbstractFunctionalTest extends Specification { - - private final String gradleVersion = System.getProperty("gradleVersion", GradleVersion.current().version) - - @TempDir - Path testDirectory - - boolean debug - - private StringWriter outputWriter - private StringWriter errorOutputWriter - private String output - private String errorOutput - - BuildResult result - - Path path(String... pathElements) { - Path cur = testDirectory - pathElements.each { - cur = cur.resolve(it) - } - cur - } - - File file(String... pathElements) { - path(pathElements).toFile() - } - - File getGroovyBuildFile() { - file("build.gradle") - } - - File getBuildFile() { - groovyBuildFile - } - - File getKotlinBuildFile() { - file("build.gradle.kts") - } - - File getGroovySettingsFile() { - file("settings.gradle") - } - - File getKotlinSettingsFile() { - file("settings.gradle.kts") - } - - File getSettingsFile() { - groovySettingsFile - } - - void run(String... args) { - try { - result = newRunner(args) - .build() - } finally { - recordOutputs() - } - } - - void outputContains(String text) { - assert output.normalize().contains(text.normalize()) - } - - void outputDoesNotContain(String text) { - assert !output.normalize().contains(text.normalize()) - } - - void errorOutputContains(String text) { - assert errorOutput.normalize().contains(text.normalize()) - } - - void tasks(@DelegatesTo(value = TaskExecutionGraph, strategy = Closure.DELEGATE_FIRST) Closure spec) { - def graph = new TaskExecutionGraph() - spec.delegate = graph - spec.resolveStrategy = Closure.DELEGATE_FIRST - spec() - } - - private void recordOutputs() { - output = outputWriter.toString() - errorOutput = errorOutputWriter.toString() - } - - private GradleRunner newRunner(String... args) { - outputWriter = new StringWriter() - errorOutputWriter = new StringWriter() - ArrayList autoArgs = computeAutoArgs() - def runner = GradleRunner.create() - .forwardStdOutput(tee(new OutputStreamWriter(System.out), outputWriter)) - .forwardStdError(tee(new OutputStreamWriter(System.err), errorOutputWriter)) - .withPluginClasspath() - .withProjectDir(testDirectory.toFile()) - .withArguments([*autoArgs, *args]) - if (gradleVersion) { - runner.withGradleVersion(gradleVersion) - } - if (debug) { - runner.withDebug(true) - } - runner - } - - private ArrayList computeAutoArgs() { - List autoArgs = [ - "-s", - "--console=verbose" - ] - if (Boolean.getBoolean("config.cache")) { - autoArgs << '--configuration-cache' - } - autoArgs - } - - private static Writer tee(Writer one, Writer two) { - return TeeWriter.of(one, two) - } - - void fails(String... args) { - try { - result = newRunner(args) - .buildAndFail() - } finally { - recordOutputs() - } - } - - private class TaskExecutionGraph { - void succeeded(String... tasks) { - tasks.each { task -> - contains(task) - assert result.task(task).outcome == TaskOutcome.SUCCESS - } - } - - void failed(String... tasks) { - tasks.each { task -> - contains(task) - assert result.task(task).outcome == TaskOutcome.FAILED - } - } - - void skipped(String... tasks) { - tasks.each { task -> - contains(task) - assert result.task(task).outcome == TaskOutcome.SKIPPED - } - } - - void contains(String... tasks) { - tasks.each { task -> - assert result.task(task) != null: "Expected to find task $task in the graph but it was missing" - } - } - - void doesNotContain(String... tasks) { - tasks.each { task -> - assert result.task(task) == null: "Task $task should be missing from the task graph but it was found with an outcome of ${result.task(task).outcome}" - } - } - } - - void usesProject(String name) { - File sampleDir = new File("src/test-projects/$name") - GFileUtils.copyDirectory(sampleDir, testDirectory.toFile()) - } - - File file(String path) { - new File(testDirectory.toFile(), path) - } -} diff --git a/build-logic/src/test/groovy/com/uwyn/rife2/gradle/PackagingTest.groovy b/build-logic/src/test/groovy/com/uwyn/rife2/gradle/PackagingTest.groovy deleted file mode 100644 index e3aeb36..0000000 --- a/build-logic/src/test/groovy/com/uwyn/rife2/gradle/PackagingTest.groovy +++ /dev/null @@ -1,38 +0,0 @@ -package com.uwyn.rife2.gradle - -import java.nio.file.FileSystems -import java.nio.file.Files - -class PackagingTest extends AbstractFunctionalTest { - def setup() { - usesProject("minimal") - } - - def "#archive contains compiled resources"() { - def jarFile = file(archive).toPath() - when: - run task - - then: "compiles templates are found in the archive" - tasks { - succeeded ":${Rife2Plugin.PRECOMPILE_TEMPLATES_TASK_NAME}" - } - Files.exists(jarFile) - try (def fs = FileSystems.newFileSystem(jarFile, [:])) { - fs.getRootDirectories().each { - Files.walk(it).forEach { path -> - println path - } - } - assert Files.exists(fs.getPath("/rife/template/html/hello.class")) - assert Files.exists(fs.getPath("/rife/template/html/world.class")) - assert !Files.exists(fs.getPath("/templates/hello.html")) - assert !Files.exists(fs.getPath("/templates/world.html")) - } - - where: - task | archive - 'jar' | 'build/libs/hello-1.0.jar' - 'uberJar' | 'build/libs/hello-uber-1.0.jar' - } -} diff --git a/build-logic/src/test/groovy/com/uwyn/rife2/gradle/TeeWriter.groovy b/build-logic/src/test/groovy/com/uwyn/rife2/gradle/TeeWriter.groovy deleted file mode 100644 index 89f60c1..0000000 --- a/build-logic/src/test/groovy/com/uwyn/rife2/gradle/TeeWriter.groovy +++ /dev/null @@ -1,81 +0,0 @@ -package com.uwyn.rife2.gradle - -import groovy.transform.CompileStatic - -@CompileStatic -class TeeWriter extends Writer { - private final Writer one - private final Writer two - - static TeeWriter of(Writer one, Writer two) { - new TeeWriter(one, two) - } - - private TeeWriter(Writer one, Writer two) { - this.one = one - this.two = two - } - - @Override - void write(int c) throws IOException { - try { - one.write(c) - } finally { - two.write(c) - } - } - - @Override - void write(char[] cbuf) throws IOException { - try { - one.write(cbuf) - } finally { - two.write(cbuf) - } - } - - @Override - void write(char[] cbuf, int off, int len) throws IOException { - try { - one.write(cbuf, off, len) - } finally { - two.write(cbuf, off, len) - } - } - - @Override - void write(String str) throws IOException { - try { - one.write(str) - } finally { - two.write(str) - } - } - - @Override - void write(String str, int off, int len) throws IOException { - try { - one.write(str, off, len) - } finally { - two.write(str, off, len) - } - } - - @Override - void flush() throws IOException { - try { - one.flush() - } finally { - two.flush() - } - } - - @Override - void close() throws IOException { - try { - one.close() - } finally { - two.close() - } - } -} diff --git a/build-logic/src/test/groovy/com/uwyn/rife2/gradle/TemplateCompilationTest.groovy b/build-logic/src/test/groovy/com/uwyn/rife2/gradle/TemplateCompilationTest.groovy deleted file mode 100644 index b935f04..0000000 --- a/build-logic/src/test/groovy/com/uwyn/rife2/gradle/TemplateCompilationTest.groovy +++ /dev/null @@ -1,60 +0,0 @@ -package com.uwyn.rife2.gradle - -class TemplateCompilationTest extends AbstractFunctionalTest { - def setup() { - usesProject("minimal") - } - - def "doesn't precompile templates when calling `run`"() { - given: - buildFile << """ - tasks.named("run") { - doFirst { - throw new RuntimeException("force stop") - } - } - """ - when: - fails 'run' - - then: "precompile templates task must not be present in task graph" - errorOutputContains("force stop") - tasks { - doesNotContain ":${Rife2Plugin.PRECOMPILE_TEMPLATES_TASK_NAME}" - } - } - - def "`run` task classpath includes template sources"() { - given: - buildFile << """ - tasks.register("dumpRunClasspath") { - doLast { - def rootPath = rootProject.projectDir.toPath() - tasks.named("run").get().classpath.files.each { - println "Classpath entry: \${rootPath.relativize(it.toPath())}" - } - } - } - """ - - when: - run("dumpRunClasspath") - - then: "template sources must be present in the classpath" - outputContains("Classpath entry: src/main/templates") - outputContains("Classpath entry: src/main/resources/templates") - } - - def "compiles templates when running #task"() { - when: - run task - - then: "precompile templates task must be present in task graph" - tasks { - succeeded ":${Rife2Plugin.PRECOMPILE_TEMPLATES_TASK_NAME}" - } - - where: - task << ['jar', 'test', 'uberJar'] - } -} diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml deleted file mode 100644 index 3a8c200..0000000 --- a/gradle/libs.versions.toml +++ /dev/null @@ -1,17 +0,0 @@ -[versions] -jetty = "11.0.13" -jsoup = "1.15.3" -junit-jupiter = "5.9.1" -slf4j = "2.0.5" -spock = "2.3-groovy-3.0" - -[libraries] -jetty-server = { module = "org.eclipse.jetty:jetty-server", version.ref = "jetty" } -jetty-servlet = { module = "org.eclipse.jetty:jetty-servlet", version.ref = "jetty" } -jsoup = { module = "org.jsoup:jsoup", version.ref = "jsoup" } -junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit-jupiter" } -slf4j-simple = { module = "org.slf4j:slf4j-simple", version.ref = "slf4j" } -spock-core = { module = "org.spockframework:spock-core", version.ref = "spock" } - -[bundles] -jetty = [ "jetty-server", "jetty-servlet" ] diff --git a/settings.gradle.kts b/settings.gradle.kts index b4af770..2e879a5 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -1,9 +1,9 @@ pluginManagement { repositories { + mavenLocal() mavenCentral() gradlePluginPortal() } - includeBuild("build-logic") } rootProject.name = "hello"