From c4a0633569e6000fe79a6a4be2d2a640c9a4737f Mon Sep 17 00:00:00 2001
From: aserkes
Date: Thu, 13 Apr 2023 19:04:25 +0200
Subject: [PATCH 1/2] check of compatibility archetype version and cli (draft)
helidon init compatibility support fix check compatibility in
ArchetypeEngineV2.java add logs to test add logs to test, fix copyright fix
check compatibility in ArchetypeEngineV2 use maven-remote-resources-plugin to
share resources between modules refactoring refactoring code change after
review fix IT test
Signed-off-by: aserkes
---
archetype/engine-v2/pom.xml | 38 +-
.../engine/v2/ArchetypeEngineV2.java | 35 +
.../engine-v2/src/main/java/module-info.java | 3 +-
.../src/main/schema/archetype-2.0.xsd | 1375 +++++++++++++++++
.../helidon-archetype-maven-plugin/pom.xml | 26 +-
.../src/it/projects/test7/expected.log | 1 +
.../src/it/projects/test7/pom.xml | 51 +
.../src/it/projects/test7/postbuild.groovy | 29 +
.../test7/src/main/archetype/circle.xml | 28 +
.../src/main/archetype/files/pom.xml.mustache | 35 +
.../src/main/java/__pkg__/Shape.java.mustache | 26 +
.../test7/src/main/archetype/main.xml | 59 +
.../build/maven/archetype/Converter.java | 30 +-
.../build/maven/archetype/JarMojo.java | 94 +-
.../helidon/build/maven/archetype/Schema.java | 62 +-
.../build/maven/archetype/Validator.java | 53 +-
.../build/maven/archetype/SchemaTest.java | 4 +-
.../resources/simple/META-INF/MANIFEST.MF | 1 +
pom.xml | 6 +
19 files changed, 1898 insertions(+), 58 deletions(-)
create mode 100644 archetype/engine-v2/src/main/schema/archetype-2.0.xsd
create mode 100644 maven-plugins/helidon-archetype-maven-plugin/src/it/projects/test7/expected.log
create mode 100644 maven-plugins/helidon-archetype-maven-plugin/src/it/projects/test7/pom.xml
create mode 100644 maven-plugins/helidon-archetype-maven-plugin/src/it/projects/test7/postbuild.groovy
create mode 100644 maven-plugins/helidon-archetype-maven-plugin/src/it/projects/test7/src/main/archetype/circle.xml
create mode 100644 maven-plugins/helidon-archetype-maven-plugin/src/it/projects/test7/src/main/archetype/files/pom.xml.mustache
create mode 100644 maven-plugins/helidon-archetype-maven-plugin/src/it/projects/test7/src/main/archetype/files/src/main/java/__pkg__/Shape.java.mustache
create mode 100644 maven-plugins/helidon-archetype-maven-plugin/src/it/projects/test7/src/main/archetype/main.xml
create mode 100644 maven-plugins/helidon-archetype-maven-plugin/src/test/resources/simple/META-INF/MANIFEST.MF
diff --git a/archetype/engine-v2/pom.xml b/archetype/engine-v2/pom.xml
index 00ac9e273..fe64cbcbb 100644
--- a/archetype/engine-v2/pom.xml
+++ b/archetype/engine-v2/pom.xml
@@ -49,6 +49,11 @@
helidon-build-common-xml${project.version}
+
+ io.helidon.build-tools.common
+ helidon-build-common-maven
+ ${project.version}
+ com.github.spullara.mustache.javacompiler
@@ -77,25 +82,34 @@
+
+
+ ${project.basedir}/src/main/resources
+
+
+ ${project.basedir}/src/main/schema
+ ${project.build.outputDirectory}/schemas
+
+ *.xsd
+
+
+
- org.codehaus.mojo
- build-helper-maven-plugin
+ org.apache.maven.plugins
+ maven-remote-resources-plugin
- attach-artifacts
- package
+ bundle-resources
+ process-resources
- attach-artifact
+ bundle
-
-
- src/main/schema/archetype.xsd
- xsd
- schema-2.0
-
-
+ ${project.build.outputDirectory}
+
+ **/schemas/**/*.xsd
+
diff --git a/archetype/engine-v2/src/main/java/io/helidon/build/archetype/engine/v2/ArchetypeEngineV2.java b/archetype/engine-v2/src/main/java/io/helidon/build/archetype/engine/v2/ArchetypeEngineV2.java
index c7f2dfcaf..c2a105cfe 100644
--- a/archetype/engine-v2/src/main/java/io/helidon/build/archetype/engine/v2/ArchetypeEngineV2.java
+++ b/archetype/engine-v2/src/main/java/io/helidon/build/archetype/engine/v2/ArchetypeEngineV2.java
@@ -17,15 +17,21 @@
package io.helidon.build.archetype.engine.v2;
import java.io.File;
+import java.io.IOException;
import java.nio.file.FileSystem;
+import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import java.util.function.Function;
+import java.util.jar.Manifest;
import io.helidon.build.archetype.engine.v2.ast.Script;
import io.helidon.build.archetype.engine.v2.context.Context;
import io.helidon.build.archetype.engine.v2.context.ContextSerializer;
import io.helidon.build.common.FileUtils;
+import io.helidon.build.common.RequirementFailure;
+import io.helidon.build.common.maven.MavenVersion;
+import io.helidon.build.common.maven.VersionRange;
import static java.util.Objects.requireNonNull;
@@ -37,6 +43,8 @@ public class ArchetypeEngineV2 {
private static final String ENTRYPOINT = "main.xml";
private static final String ARTIFACT_ID = "artifactId";
+ private static final VersionRange COMPATIBLE_SCHEMA_RANGE = VersionRange.createFromVersionSpec("[2.0.0,3.0.0)");
+
private final Path cwd;
private final InputResolver inputResolver;
private final Map externalValues;
@@ -46,6 +54,7 @@ public class ArchetypeEngineV2 {
private final File outputPropsFile;
private ArchetypeEngineV2(Builder builder) {
+ checkCompatability(builder.cwd);
this.cwd = builder.cwd;
this.inputResolver = builder.inputResolver;
this.externalValues = builder.externalValues;
@@ -55,6 +64,32 @@ private ArchetypeEngineV2(Builder builder) {
this.outputPropsFile = builder.outputPropsFile;
}
+ private void checkCompatability(Path cwd) {
+ Path manifestPath = cwd.resolve("META-INF/MANIFEST.MF");
+ if (!Files.exists(manifestPath)) {
+ //it is not an archetype archive
+ return;
+ }
+ try {
+ Manifest manifest = new Manifest(Files.newInputStream(manifestPath));
+ String maxVersion = manifest.getMainAttributes().getValue("archetype-schema-version");
+ if (maxVersion == null) {
+ //it is a some previous version of archetype archive
+ return;
+ }
+ MavenVersion mavenVersion = MavenVersion.toMavenVersion(maxVersion);
+ if (!COMPATIBLE_SCHEMA_RANGE.containsVersion(mavenVersion)) {
+ throw new RequirementFailure(
+ String.format("Version of schema %s is not compatible with the current version of "
+ + "the Archetype engine (v2). The version of schema must be in range %s",
+ maxVersion,
+ COMPATIBLE_SCHEMA_RANGE));
+ }
+ } catch (IOException e) {
+ throw new RequirementFailure(e.getMessage());
+ }
+ }
+
/**
* Generate a project.
*
diff --git a/archetype/engine-v2/src/main/java/module-info.java b/archetype/engine-v2/src/main/java/module-info.java
index c09f37632..40786ae5a 100644
--- a/archetype/engine-v2/src/main/java/module-info.java
+++ b/archetype/engine-v2/src/main/java/module-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2022 Oracle and/or its affiliates.
+ * Copyright (c) 2021, 2023 Oracle and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -26,6 +26,7 @@
requires io.helidon.build.common.ansi;
requires io.helidon.build.common.xml;
requires com.github.mustachejava;
+ requires io.helidon.build.common.maven;
exports io.helidon.build.archetype.engine.v2;
exports io.helidon.build.archetype.engine.v2.ast;
diff --git a/archetype/engine-v2/src/main/schema/archetype-2.0.xsd b/archetype/engine-v2/src/main/schema/archetype-2.0.xsd
new file mode 100644
index 000000000..0a891607f
--- /dev/null
+++ b/archetype/engine-v2/src/main/schema/archetype-2.0.xsd
@@ -0,0 +1,1375 @@
+
+
+
+
+
+
+
+ 2.0
+
+ File path of a script relative to the current script directory ; a leading / can be
+ used to
+ refer to the archetype root directory.
+
+
+
+
+
+ 2.0
+ URL of a script.
+
+
+
+
+
+
+
+ 2.0
+
+ Directive that executes a script in its respective directory.
+
+
+
+
+
+
+
+ 2.0
+
+ Directive that executes a script in the current script directory.
+
+
+ NOTE:
+ Relative file path will be resolved in the current script directory, thus files that
+ are co-located with the script to be executed won't be resolved.
+
+
+
+
+
+
+
+ 2.0
+
+ Directive that executes a method.
+
+
+
+
+ 2.0
+
+ Name of the method to invoke.
+
+
+
+
+
+
+
+ 2.0
+
+ Ant glob pattern.
+
+
+
+ Use * to wildcard file and directory names and
+ **
+ to wildcard any depth of directory structure.
+
+
+ E.g.
+ <include>**/*.java</include>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2.0
+
+ File path of a base directory that contains the files to be included. Relative file path
+ are resolved relative to the current script directory. A leading / can be used to
+ refer to the archetype root directory.
+
+
+ By default everything is included, unless includes or excludes patterns are set.
+
+
+
+
+
+ 2.0
+
+ Set of include patterns.
+
+
+
+
+
+
+
+
+
+
+ 2.0
+
+ Set of exclude patterns.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2.0
+
+ Define the set of path transformations to apply.
+
+
+ Multiple transformations can be specified, separated by a comma (,) character.
+
+
+
+
+
+
+
+
+ 2.0
+
+ Expression to guard this element.
+
+
+
+ Expressions are boolean expressions that can be used to query the context.
+
+
+ Values can be either context values (${path}) or literal, and are only of the
+ following types:
+
+ The template data model is shared. The key identifies the data to set.
+
+ The key is the identifier used when resolving data from a template. The syntax for
+ resolving data from a template is template specific. E.g. in mustache: {{my-key}}.
+
+
+
+
+
+
+
+
+
+ 2.0
+
+ Data model order.
+
+
+
+ The order is used to affect how the data for the same keys are merged. The value is an integer
+ with a default value of 100.
+
+
+ Data is sorted by comparing order, data with higher order is inserted before data with lower
+ order. When the order is equal, the distance to the root input node and the declaration order
+ is used.
+
+
+
+
+
+
+
+
+ 2.0
+
+ Value data type.
+
+
+
+ The value for the data can be declared as a literal, or it can also use a property like syntax
+ to resolve the value of an input.
+
+
+ E.g.
+
+
+ <value>${media-support.json.provider}</value>
+
+
+ <value>foo</value>
+
+
+ Inline search and replace regular expressions are also supported:
+
+
+ <value>${package/\./\/}</value>
+
+
+
+
+
+
+
+
+
+ 2.0
+
+ File path to a file containing the content for this value.
+
+
+
+
+
+ 2.0
+
+ URL point at a file containing the content for this value.
+
+
+
+
+
+ 2.0
+
+ Pre-process the value with the given template engine. The value must match
+ a template engine registered with the archetype engine.
+
+
+
+
+
+
+
+
+
+
+
+ 2.0
+
+ Value data type.
+
+
+
+ The value for the data can be declared as a literal, or it can also use a property like syntax
+ to resolve the value of an input.
+
+
+ E.g.
+
+
+ <value>${media-support.json.provider}</value>
+
+
+ <value>foo</value>
+
+
+ Inline search and replace regular expressions are also supported:
+
+
+ <value>${package/\./\/}</value>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2.0
+
+ Map data type.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2.0
+
+ List data type. Nested elements do not require a key attribute.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2.0
+
+ Indicate if a variable should be serialized to a client.
+
+
+
+
+
+
+
+
+ 2.0
+
+ The path of an input whose value is to be set in the context.
+
+
+
A path contains segments separated by "." characters
+
Segments are ids of the parents for a given input
+
Segments can contain only letters, digits and separator "-"
+
The segment separator "-" must be used between valid characters ;
+ ("--" is prohibited
+
+
Two reference operators are available, root scope: "~" ; parent scope: ".."
+
+
A path that starts with "~" is absolute. I.e. relative to the root scope
+
A path that starts with a segment is relative, or a parent reference is relative
+
+
+
+ Inputs can be declared as global in order to shorten the external path of an input.
+
+ The external path is the control visible to end-users.
+
+
+ An input can be declared global if:
+
+
the input has no parent input
+
the input is nested under a global input
+
+
+ There are effectively two kinds of path:
+
+
+
internal: all inputs are included in the path
+
external: global parents are excluded
+
+
+ Example:
+
+ "foo.bar.bob" is equivalent to "bob" if:
+
+
all inputs are global
+
"foo" and "bar" are global
+
+
+ "foo.bar.bob" is equivalent to "bar.bob" if:
+
+ When enclosed by <archetype-script> in the entry-point script, it defines
+ the help text for the entire archetype
+
+
+ When enclosed by <archetype-script> in a script that is invoked, it defines
+ the help text for the enclosing element of the directive used to invoke the script
+
+
+
+ The rich text format is a limited Markdown format:
+
+
+
+ **bold text**
+ _italic_
+ paragraphs
+ `code`
+ [Links](https://example.com)
+ {::color-primary}text in primary color{:/}
+ {::color-secondary}text in secondary color{:/}
+ {::color-accent}text in accent color{:/}
+ {::color-error}text in error color{:/}
+ {::color-info}text in info color{:/}
+ {::color-success}text in success color{:/}
+ {::color-warning}text in warning color{:/}
+
+
+
+ Example:
+
+
+
+ <help><![CDATA[
+ This is a rich help text. **THIS IS BOLD** ; **THIS IS ITALIC**.
+
+ This is a paragraph
+
+ This is a Java code snippet:
+ ```java
+ request.content()
+ .as(JsonObject.class)
+ .thenAccept(json -> {
+
+ System.output.println(json);
+ response.send("OK");
+ });
+ ```
+ ]]></help>
+
+
+
+
+
+
+
+
+
+
+
+ 2.0
+
+ Human readable name for step or input components.
+
+
+
+
+
+
+
+
+ 2.0
+
+ Input description (single line).
+
+
+
+
+
+
+
+
+ 2.0
+
+ Indicate if the step or input is optional.
+
+
+
+
+
+
+
+
+ 2.0
+
+ Indicate if the step or input is global.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2.0
+
+ The input id. Must be unique among siblings.
+
+
+
+
+
+ 2.0
+
+ The prompt for this input. Defaults to the name if not defined.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2.0
+
+ Default text input value.
+
+
+
+
+
+ 2.0
+
+ List of validation id.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2.0
+
+ Default boolean input value.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2.0
+
+ Enum constant value.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2.0
+
+ Default enum input value.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2.0
+
+ List constant value.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2.0
+
+ Default list input value.
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2.0
+
+ Configuration of validation.
+
+
+
+
+
+
+
+ 2.0
+
+ The id of the validation. The id must be unique across all the descriptors
+ of an archetype.
+
+
+
+
+
+ 2.0
+
+ The validation description.
+
+
+
+
+
+
+
+ 2.0
+
+ Regular expression to apply during pattern validation.
+
+
+
+
+
+
+
+
+
+ 2.0
+
+ A user input.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2.0
+
+ Step. A logical group of inputs to be presented together like a pane or a window.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ 2.0
+
+ Define data for the template model. The data-model is global unless it is scoped under <template>
+ or <templates>.
+
+
+
+
+
+
+
+
+
+
+
+
+ 2.0
+
+ Configuration of files, template and data model for the current scope.
+
+
+
+
+
+
+ 2.0
+
+ Define a set of replacements to be applied on the path of created files.
+
+
+
+ Replacements are search and replace regular expressions declared using
+ <replace>. They form a chain where the first input is the included file
+ path,
+ the result is passed to the next replacement and the last result is used as the final
+ file
+ path.
+
+ A property like syntax can be used to resolve the value of an input.
+
+
+ E.g.
+
+
+ ${media-support.json.provider}
+
+
+ ${security.authentication.provider}
+
+
+ ${security}
+
+
+ Inline search and replace regular expressions are also supported:
+
+
+ ${package/\./\/}
+
+
+
+
+
+
+
+
+
+
+
+ 2.0
+
+ The id of the path transformation. The id must be unique across all the descriptors
+ of an archetype.
+
+
+
+
+
+
+
+ 2.0
+
+ Defines a static file.
+
+
+
+ The path of the file is relative to the configured directory.
+
+
+
+
+
+
+
+ 2.0
+
+ The file source.
+
+
+
+
+
+ 2.0
+
+ The file target.
+
+
+
+
+
+
+
+
+ 2.0
+
+ Defines a set of static files.
+
+
+
+ The path of the files included are relative to the configured directory.
+
+
Transformations can be used to modify the final path of the files to be created