From 6f5da891d1b6f55e26ab7ca9fbfd3ce71ae7b8c7 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Thu, 24 Oct 2024 15:13:35 +0200 Subject: [PATCH 1/6] Merge docgen And make it support both, maven and resolver. --- maven-resolver-tools/pom.xml | 89 ++++- .../aether/tools/CollectConfiguration.java | 346 +++++++++++++----- .../{props.vm => configuration.properties.vm} | 2 + .../{yaml.vm => configuration.yaml.vm} | 2 + .../src/main/resources/page-maven.md.vm | 55 +++ .../{page.vm => page-resolver.md.vm} | 0 pom.xml | 5 + 7 files changed, 404 insertions(+), 95 deletions(-) rename maven-resolver-tools/src/main/resources/{props.vm => configuration.properties.vm} (97%) rename maven-resolver-tools/src/main/resources/{yaml.vm => configuration.yaml.vm} (97%) create mode 100644 maven-resolver-tools/src/main/resources/page-maven.md.vm rename maven-resolver-tools/src/main/resources/{page.vm => page-resolver.md.vm} (100%) diff --git a/maven-resolver-tools/pom.xml b/maven-resolver-tools/pom.xml index 67a176e34..cab99d5e7 100644 --- a/maven-resolver-tools/pom.xml +++ b/maven-resolver-tools/pom.xml @@ -33,7 +33,6 @@ 17 - true @@ -41,62 +40,82 @@ org.apache.maven.resolver maven-resolver-api + provided org.apache.maven.resolver maven-resolver-spi + provided org.apache.maven.resolver maven-resolver-util + provided org.apache.maven.resolver maven-resolver-impl + provided org.apache.maven.resolver maven-resolver-named-locks + provided org.apache.maven.resolver maven-resolver-named-locks-hazelcast + provided org.apache.maven.resolver maven-resolver-named-locks-redisson + provided org.apache.maven.resolver maven-resolver-connector-basic + provided org.apache.maven.resolver maven-resolver-transport-apache + provided org.apache.maven.resolver maven-resolver-transport-classpath + provided org.apache.maven.resolver maven-resolver-transport-file + provided org.apache.maven.resolver maven-resolver-transport-jdk + provided org.apache.maven.resolver maven-resolver-transport-jetty + provided org.apache.maven.resolver maven-resolver-transport-wagon + provided org.apache.maven.resolver maven-resolver-generator-gnupg + provided + + + org.apache.maven.resolver + maven-resolver-generator-sigstore + provided @@ -113,11 +132,25 @@ roaster-jdt 2.29.0.Final + + org.ow2.asm + asm + 9.7.1 + org.apache.velocity velocity-engine-core 2.4.1 + + org.codehaus.plexus + plexus-utils + + + info.picocli + picocli + 4.7.6 + @@ -135,6 +168,50 @@ + + org.apache.maven.plugins + maven-shade-plugin + + + cli + + shade + + package + + false + true + cli + + + + org.eclipse.aether.tools.CollectConfiguration + ${project.artifactId} + ${project.version} + ${project.artifactId} + ${project.version} + ${project.groupId} + + + + + + *:* + + META-INF/MANIFEST.MF + META-INF/LICENSE + META-INF/LICENSE.txt + META-INF/DEPENDENCIES + META-INF/NOTICE + META-INF/NOTICE.txt + **/module-info.class + + + + + + + org.codehaus.mojo exec-maven-plugin @@ -149,10 +226,10 @@ org.eclipse.aether.tools.CollectConfiguration + --mode=resolver + --templates=page-resolver.md,configuration.properties,configuration.yaml ${basedir}/.. - ${basedir}/../src/site/markdown/configuration.md - ${basedir}/target/maven-resolver.properties - ${basedir}/target/maven-resolver.yaml + ${basedir}/target/ @@ -173,11 +250,11 @@ properties - ${basedir}/target/maven-resolver.properties + ${basedir}/target/configuration.properties yaml - ${basedir}/target/maven-resolver.yaml + ${basedir}/target/configuration.yaml diff --git a/maven-resolver-tools/src/main/java/org/eclipse/aether/tools/CollectConfiguration.java b/maven-resolver-tools/src/main/java/org/eclipse/aether/tools/CollectConfiguration.java index 746e17cdf..5c898616b 100644 --- a/maven-resolver-tools/src/main/java/org/eclipse/aether/tools/CollectConfiguration.java +++ b/maven-resolver-tools/src/main/java/org/eclipse/aether/tools/CollectConfiguration.java @@ -18,115 +18,283 @@ */ package org.eclipse.aether.tools; -import java.io.BufferedWriter; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; import java.io.UncheckedIOException; +import java.io.Writer; +import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; -import java.util.TreeMap; +import java.util.concurrent.Callable; import java.util.regex.Matcher; import java.util.regex.Pattern; import java.util.spi.ToolProvider; +import java.util.stream.Stream; import org.apache.velocity.VelocityContext; import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader; +import org.codehaus.plexus.util.io.CachingWriter; import org.jboss.forge.roaster.Roaster; +import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.AST; +import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.ASTNode; +import org.jboss.forge.roaster._shade.org.eclipse.jdt.core.dom.Javadoc; import org.jboss.forge.roaster.model.JavaDoc; import org.jboss.forge.roaster.model.JavaDocCapable; import org.jboss.forge.roaster.model.JavaDocTag; import org.jboss.forge.roaster.model.JavaType; +import org.jboss.forge.roaster.model.impl.JavaDocImpl; import org.jboss.forge.roaster.model.source.FieldSource; import org.jboss.forge.roaster.model.source.JavaClassSource; +import org.jboss.forge.roaster.model.source.JavaDocSource; +import org.objectweb.asm.AnnotationVisitor; +import org.objectweb.asm.ClassReader; +import org.objectweb.asm.ClassVisitor; +import org.objectweb.asm.FieldVisitor; +import org.objectweb.asm.Opcodes; +import picocli.CommandLine; -public class CollectConfiguration { - public static void main(String[] args) throws Exception { - Path start = Paths.get(args.length > 0 ? args[0] : "."); - Path output = Paths.get(args.length > 1 ? args[1] : "output"); - Path props = Paths.get(args.length > 2 ? args[2] : "props"); - Path yaml = Paths.get(args.length > 3 ? args[3] : "yaml"); - - TreeMap discoveredKeys = new TreeMap<>(); - Files.walk(start) - .map(Path::toAbsolutePath) - .filter(p -> p.getFileName().toString().endsWith(".java")) - .filter(p -> p.toString().contains("/src/main/java/")) - .filter(p -> !p.toString().endsWith("/module-info.java")) - .forEach(p -> { - JavaType type = parse(p); - if (type instanceof JavaClassSource javaClassSource) { - javaClassSource.getFields().stream() - .filter(CollectConfiguration::hasConfigurationSource) - .forEach(f -> { - Map constants = extractConstants(Paths.get(p.toString() - .replace("/src/main/java/", "/target/classes/") - .replace(".java", ".class"))); - - String name = f.getName(); - String key = constants.get(name); - String fqName = f.getOrigin().getCanonicalName() + "." + name; - String configurationType = getConfigurationType(f); - String defValue = getTag(f, "@configurationDefaultValue"); - if (defValue != null && defValue.startsWith("{@link #") && defValue.endsWith("}")) { - // constant "lookup" - String lookupValue = - constants.get(defValue.substring(8, defValue.length() - 1)); - if (lookupValue == null) { - // currently we hard fail if javadoc cannot be looked up - // workaround: at cost of redundancy, but declare constants in situ for now - // (in same class) - throw new IllegalArgumentException( - "Could not look up " + defValue + " for configuration " + fqName); - } - defValue = lookupValue; - } - if ("java.lang.Long".equals(configurationType) - && (defValue.endsWith("l") || defValue.endsWith("L"))) { - defValue = defValue.substring(0, defValue.length() - 1); - } - discoveredKeys.put( - key, - new ConfigurationKey( - key, - defValue, - fqName, - cleanseJavadoc(f), - nvl(getSince(f), ""), - getConfigurationSource(f), - configurationType, - toBoolean(getTag(f, "@configurationRepoIdSuffix")))); - }); - } - }); - - VelocityEngine velocityEngine = new VelocityEngine(); - Properties properties = new Properties(); - properties.setProperty("resource.loaders", "classpath"); - properties.setProperty("resource.loader.classpath.class", ClasspathResourceLoader.class.getName()); - velocityEngine.init(properties); - - VelocityContext context = new VelocityContext(); - context.put("keys", discoveredKeys.values()); - - try (BufferedWriter fileWriter = Files.newBufferedWriter(output)) { - velocityEngine.getTemplate("page.vm").merge(context, fileWriter); +@CommandLine.Command(name = "docgen", description = "Maven Documentation Generator") +public class CollectConfiguration implements Callable { + public static void main(String[] args) { + new CommandLine(new CollectConfiguration()).execute(args); + } + + enum Mode { + maven, + resolver + } + + private static final Map> MODE_TEMPLATES = Map.of( + Mode.maven, List.of("page-maven.md", "configuration.properties", "configuration.yaml"), + Mode.resolver, List.of("page-resolver.md", "configuration.properties", "configuration.yaml")); + + @CommandLine.Option( + names = {"-m", "--mode"}, + arity = "1", + paramLabel = "mode", + description = "The mode of generator (what is being scanned?), supported modes are 'maven', 'resolver'") + private Mode mode; + + @CommandLine.Option( + names = {"-t", "--templates"}, + arity = "1", + split = ",", + paramLabel = "template", + description = "The template names to write content out without '.vm' extension") + private List templates; + + @CommandLine.Parameters(index = "0", description = "The root directory to process sources from") + private Path rootDirectory; + + @CommandLine.Parameters(index = "1", description = "The directory to generate output(s) to") + private Path outputDirectory; + + @Override + public Integer call() { + try { + ArrayList> discoveredKeys = new ArrayList<>(); + try (Stream stream = Files.walk(rootDirectory)) { + if (mode == Mode.maven) { + stream.map(Path::toAbsolutePath) + .filter(p -> p.getFileName().toString().endsWith(".class")) + .filter(p -> p.toString().contains("/target/classes/")) + .forEach(p -> { + processMavenClass(p, discoveredKeys); + }); + } else if (mode == Mode.resolver) { + stream.map(Path::toAbsolutePath) + .filter(p -> p.getFileName().toString().endsWith(".java")) + .filter(p -> p.toString().contains("/src/main/java/")) + .filter(p -> !p.toString().endsWith("/module-info.java")) + .forEach(p -> processResolverClass(p, discoveredKeys)); + } else { + throw new IllegalStateException("Unsupported mode " + mode); + } + } + + VelocityEngine velocityEngine = new VelocityEngine(); + Properties properties = new Properties(); + properties.setProperty("resource.loaders", "classpath"); + properties.setProperty("resource.loader.classpath.class", ClasspathResourceLoader.class.getName()); + velocityEngine.init(properties); + + VelocityContext context = new VelocityContext(); + context.put("keys", discoveredKeys); + + for (String template : MODE_TEMPLATES.get(mode)) { + // output name: remove ".vm" + try (Writer fileWriter = new CachingWriter(outputDirectory.resolve(template), StandardCharsets.UTF_8)) { + velocityEngine.getTemplate(template + ".vm").merge(context, fileWriter); + } + } + return 0; + } catch (Exception e) { + e.printStackTrace(System.err); + return 1; } - try (BufferedWriter fileWriter = Files.newBufferedWriter(props)) { - velocityEngine.getTemplate("props.vm").merge(context, fileWriter); + } + + private void processMavenClass(Path path, List> discoveredKeys) { + try { + ClassReader classReader = new ClassReader(Files.newInputStream(path)); + classReader.accept( + new ClassVisitor(Opcodes.ASM9) { + @Override + public FieldVisitor visitField( + int fieldAccess, + String fieldName, + String fieldDescriptor, + String fieldSignature, + Object fieldValue) { + return new FieldVisitor(Opcodes.ASM9) { + @Override + public AnnotationVisitor visitAnnotation( + String annotationDescriptor, boolean annotationVisible) { + if (annotationDescriptor.equals("Lorg/apache/maven/api/annotations/Config;")) { + return new AnnotationVisitor(Opcodes.ASM9) { + final Map values = new HashMap<>(); + + @Override + public void visit(String name, Object value) { + values.put(name, value); + } + + @Override + public void visitEnum(String name, String descriptor, String value) { + values.put(name, value); + } + + @Override + public void visitEnd() { + JavaType jtype = parse(Paths.get(path.toString() + .replace("/target/classes/", "/src/main/java/") + .replace(".class", ".java"))); + FieldSource f = + ((JavaClassSource) jtype).getField(fieldName); + + String fqName = null; + String desc = cloneJavadoc(f.getJavaDoc()) + .removeAllTags() + .getFullText() + .replace("*", "\\*"); + String since = getSince(f); + String source = + switch ((values.get("source") != null + ? (String) values.get("source") + : "USER_PROPERTIES") // TODO: enum + .toLowerCase()) { + case "model" -> "Model properties"; + case "user_properties" -> "User properties"; + default -> throw new IllegalStateException(); + }; + String type = + switch ((values.get("type") != null + ? (String) values.get("type") + : "java.lang.String")) { + case "java.lang.String" -> "String"; + case "java.lang.Integer" -> "Integer"; + case "java.lang.Boolean" -> "Boolean"; + default -> throw new IllegalStateException(); + }; + discoveredKeys.add(Map.of( + "key", + fieldValue.toString(), + "defaultValue", + values.get("defaultValue") != null + ? values.get("defaultValue") + .toString() + : "-", + "fqName", + nvl(fqName, "-"), + "description", + desc, + "since", + since, + "configurationSource", + source, + "configurationType", + type)); + } + }; + } + return null; + } + }; + } + }, + 0); + } catch (IOException e) { + throw new RuntimeException(e); } - try (BufferedWriter fileWriter = Files.newBufferedWriter(yaml)) { - velocityEngine.getTemplate("yaml.vm").merge(context, fileWriter); + } + + private void processResolverClass(Path path, List> discoveredKeys) { + JavaType type = parse(path); + if (type instanceof JavaClassSource javaClassSource) { + javaClassSource.getFields().stream() + .filter(this::hasConfigurationSource) + .forEach(f -> { + Map constants = extractConstants(Paths.get(path.toString() + .replace("/src/main/java/", "/target/classes/") + .replace(".java", ".class"))); + + String name = f.getName(); + String key = constants.get(name); + String fqName = f.getOrigin().getCanonicalName() + "." + name; + String configurationType = getConfigurationType(f); + String defValue = getTag(f, "@configurationDefaultValue"); + if (defValue != null && defValue.startsWith("{@link #") && defValue.endsWith("}")) { + // constant "lookup" + String lookupValue = constants.get(defValue.substring(8, defValue.length() - 1)); + if (lookupValue == null) { + // currently we hard fail if javadoc cannot be looked up + // workaround: at cost of redundancy, but declare constants in situ for now + // (in same class) + throw new IllegalArgumentException( + "Could not look up " + defValue + " for configuration " + fqName); + } + defValue = lookupValue; + if ("java.lang.Long".equals(configurationType) + && (defValue.endsWith("l") || defValue.endsWith("L"))) { + defValue = defValue.substring(0, defValue.length() - 1); + } + } + discoveredKeys.add(Map.of( + "key", + key, + "defaultValue", + nvl(defValue, "-"), + "fqName", + fqName, + "description", + cleanseJavadoc(f), + "since", + nvl(getSince(f), ""), + "configurationSource", + getConfigurationSource(f), + "configurationType", + configurationType, + "supportRepoIdSuffix", + toBoolean(getTag(f, "@configurationRepoIdSuffix")))); + }); } } - private static String cleanseJavadoc(FieldSource javaClassSource) { + private JavaDocSource cloneJavadoc(JavaDocSource javaDoc) { + Javadoc jd = (Javadoc) javaDoc.getInternal(); + return new JavaDocImpl<>(javaDoc.getOrigin(), (Javadoc) + ASTNode.copySubtree(AST.newAST(jd.getAST().apiLevel(), false), jd)); + } + + private String cleanseJavadoc(FieldSource javaClassSource) { JavaDoc> javaDoc = javaClassSource.getJavaDoc(); String[] text = javaDoc.getFullText().split("\n"); StringBuilder result = new StringBuilder(); @@ -138,7 +306,7 @@ private static String cleanseJavadoc(FieldSource javaClassSourc return cleanseTags(result.toString()); } - private static String cleanseTags(String text) { + private String cleanseTags(String text) { // {@code XXX} ->
XXX
// {@link XXX} -> ??? pre for now Pattern pattern = Pattern.compile("(\\{@\\w\\w\\w\\w (.+?)})"); @@ -159,7 +327,7 @@ private static String cleanseTags(String text) { return result.toString(); } - private static JavaType parse(Path path) { + private JavaType parse(Path path) { try { return Roaster.parse(path.toFile()); } catch (IOException e) { @@ -167,8 +335,8 @@ private static JavaType parse(Path path) { } } - private static boolean toBoolean(String value) { - return ("yes".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value)); + private String toBoolean(String value) { + return Boolean.toString("yes".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value)); } /** @@ -237,15 +405,15 @@ public boolean isSupportRepoIdSuffix() { } } - private static String nvl(String string, String def) { + private String nvl(String string, String def) { return string == null ? def : string; } - private static boolean hasConfigurationSource(JavaDocCapable javaDocCapable) { + private boolean hasConfigurationSource(JavaDocCapable javaDocCapable) { return getTag(javaDocCapable, "@configurationSource") != null; } - private static String getConfigurationType(JavaDocCapable javaDocCapable) { + private String getConfigurationType(JavaDocCapable javaDocCapable) { String type = getTag(javaDocCapable, "@configurationType"); if (type != null) { String linkPrefix = "{@link "; @@ -261,7 +429,7 @@ private static String getConfigurationType(JavaDocCapable javaDocCapable) { return nvl(type, "n/a"); } - private static String getConfigurationSource(JavaDocCapable javaDocCapable) { + private String getConfigurationSource(JavaDocCapable javaDocCapable) { String source = getTag(javaDocCapable, "@configurationSource"); if ("{@link RepositorySystemSession#getConfigProperties()}".equals(source)) { return "Session Configuration"; @@ -272,7 +440,7 @@ private static String getConfigurationSource(JavaDocCapable javaDocCapable) { } } - private static String getSince(JavaDocCapable javaDocCapable) { + private String getSince(JavaDocCapable javaDocCapable) { List tags; if (javaDocCapable != null) { if (javaDocCapable instanceof FieldSource fieldSource) { @@ -292,7 +460,7 @@ private static String getSince(JavaDocCapable javaDocCapable) { return null; } - private static String getTag(JavaDocCapable javaDocCapable, String tagName) { + private String getTag(JavaDocCapable javaDocCapable, String tagName) { List tags; if (javaDocCapable != null) { if (javaDocCapable instanceof FieldSource fieldSource) { @@ -313,7 +481,7 @@ private static String getTag(JavaDocCapable javaDocCapable, String tagName) { /** * Builds "constant table" for one single class. - * + *

* Limitations: * - works only for single class (no inherited constants) * - does not work for fields that are Enum.name() diff --git a/maven-resolver-tools/src/main/resources/props.vm b/maven-resolver-tools/src/main/resources/configuration.properties.vm similarity index 97% rename from maven-resolver-tools/src/main/resources/props.vm rename to maven-resolver-tools/src/main/resources/configuration.properties.vm index dfa5a2b1a..a94ea40bc 100644 --- a/maven-resolver-tools/src/main/resources/props.vm +++ b/maven-resolver-tools/src/main/resources/configuration.properties.vm @@ -43,6 +43,8 @@ props.${foreach.count}.defaultValue = ${key.defaultValue} #if( !${key.since.empty} ) props.${foreach.count}.since = ${key.since} #end +#if( !${key.supportRepoIdSuffix.empty} ) props.${foreach.count}.supportRepoIdSuffix = ${key.supportRepoIdSuffix} +#end props.${foreach.count}.configurationSource = ${key.configurationSource} #end diff --git a/maven-resolver-tools/src/main/resources/yaml.vm b/maven-resolver-tools/src/main/resources/configuration.yaml.vm similarity index 97% rename from maven-resolver-tools/src/main/resources/yaml.vm rename to maven-resolver-tools/src/main/resources/configuration.yaml.vm index 6c97d8722..eaf71be19 100644 --- a/maven-resolver-tools/src/main/resources/yaml.vm +++ b/maven-resolver-tools/src/main/resources/configuration.yaml.vm @@ -43,6 +43,8 @@ props: #if( !${key.since.empty} ) since: ${key.since} #end + #if( !${key.supportRepoIdSuffix.empty} ) supportRepoIdSuffix: ${key.supportRepoIdSuffix} + #end configurationSource: ${key.configurationSource} #end diff --git a/maven-resolver-tools/src/main/resources/page-maven.md.vm b/maven-resolver-tools/src/main/resources/page-maven.md.vm new file mode 100644 index 000000000..8cd78064a --- /dev/null +++ b/maven-resolver-tools/src/main/resources/page-maven.md.vm @@ -0,0 +1,55 @@ +## +## Licensed to the Apache Software Foundation (ASF) under one +## or more contributor license agreements. See the NOTICE file +## distributed with this work for additional information +## regarding copyright ownership. The ASF licenses this file +## to you 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 +## +## http://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. +## +#[[ +# Configuration Options + + +]]# + +#macro(yesno $val) + #if ($val) Yes #else No #end +#end + +#macro(value $val) +#if ($val) `$val` #else - #end +#end + +| No | Key | Type | Description | Default Value | Since | Source | +| --- | --- | --- | --- | --- | --- | --- | +#foreach($key in $keys) +| $foreach.count. | `$key.key` | `$key.configurationType` | $key.description | #value( $key.defaultValue ) | $key.since | $key.configurationSource | +#end + diff --git a/maven-resolver-tools/src/main/resources/page.vm b/maven-resolver-tools/src/main/resources/page-resolver.md.vm similarity index 100% rename from maven-resolver-tools/src/main/resources/page.vm rename to maven-resolver-tools/src/main/resources/page-resolver.md.vm diff --git a/pom.xml b/pom.xml index f325acee8..2d35f82b5 100644 --- a/pom.xml +++ b/pom.xml @@ -201,6 +201,11 @@ maven-resolver-generator-gnupg ${project.version} + + org.apache.maven.resolver + maven-resolver-generator-sigstore + ${project.version} + org.apache.maven.resolver maven-resolver-supplier-mvn3 From 9bf051d8d4f5e17428717b9cb017591ca1c81b21 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Thu, 24 Oct 2024 15:18:43 +0200 Subject: [PATCH 2/6] Remove unused --- .../org/eclipse/aether/tools/CollectConfiguration.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/maven-resolver-tools/src/main/java/org/eclipse/aether/tools/CollectConfiguration.java b/maven-resolver-tools/src/main/java/org/eclipse/aether/tools/CollectConfiguration.java index 5c898616b..e311e8827 100644 --- a/maven-resolver-tools/src/main/java/org/eclipse/aether/tools/CollectConfiguration.java +++ b/maven-resolver-tools/src/main/java/org/eclipse/aether/tools/CollectConfiguration.java @@ -72,10 +72,6 @@ enum Mode { resolver } - private static final Map> MODE_TEMPLATES = Map.of( - Mode.maven, List.of("page-maven.md", "configuration.properties", "configuration.yaml"), - Mode.resolver, List.of("page-resolver.md", "configuration.properties", "configuration.yaml")); - @CommandLine.Option( names = {"-m", "--mode"}, arity = "1", @@ -129,8 +125,7 @@ public Integer call() { VelocityContext context = new VelocityContext(); context.put("keys", discoveredKeys); - for (String template : MODE_TEMPLATES.get(mode)) { - // output name: remove ".vm" + for (String template : templates) { try (Writer fileWriter = new CachingWriter(outputDirectory.resolve(template), StandardCharsets.UTF_8)) { velocityEngine.getTemplate(template + ".vm").merge(context, fileWriter); } From c34325a504c0fce098286904e19d8139a5d94f9d Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Thu, 24 Oct 2024 15:49:57 +0200 Subject: [PATCH 3/6] Updates --- maven-resolver-tools/pom.xml | 60 ++------- .../aether/tools/CollectConfiguration.java | 125 +++++------------- .../resources/configuration.properties.vm | 2 +- .../src/main/resources/configuration.yaml.vm | 2 +- .../src/main/resources/page-maven.md.vm | 55 -------- pom.xml | 6 + 6 files changed, 49 insertions(+), 201 deletions(-) delete mode 100644 maven-resolver-tools/src/main/resources/page-maven.md.vm diff --git a/maven-resolver-tools/pom.xml b/maven-resolver-tools/pom.xml index cab99d5e7..e488d1fa1 100644 --- a/maven-resolver-tools/pom.xml +++ b/maven-resolver-tools/pom.xml @@ -118,10 +118,6 @@ provided - - org.slf4j - slf4j-api - org.jboss.forge.roaster roaster-api @@ -151,67 +147,27 @@ picocli 4.7.6 - - org.slf4j - slf4j-simple - runtime + slf4j-api + + org.apache.commons commons-lang3 3.17.0 runtime + + org.slf4j + slf4j-nop + runtime + - - org.apache.maven.plugins - maven-shade-plugin - - - cli - - shade - - package - - false - true - cli - - - - org.eclipse.aether.tools.CollectConfiguration - ${project.artifactId} - ${project.version} - ${project.artifactId} - ${project.version} - ${project.groupId} - - - - - - *:* - - META-INF/MANIFEST.MF - META-INF/LICENSE - META-INF/LICENSE.txt - META-INF/DEPENDENCIES - META-INF/NOTICE - META-INF/NOTICE.txt - **/module-info.class - - - - - - - org.codehaus.mojo exec-maven-plugin diff --git a/maven-resolver-tools/src/main/java/org/eclipse/aether/tools/CollectConfiguration.java b/maven-resolver-tools/src/main/java/org/eclipse/aether/tools/CollectConfiguration.java index e311e8827..83c8abaec 100644 --- a/maven-resolver-tools/src/main/java/org/eclipse/aether/tools/CollectConfiguration.java +++ b/maven-resolver-tools/src/main/java/org/eclipse/aether/tools/CollectConfiguration.java @@ -77,7 +77,7 @@ enum Mode { arity = "1", paramLabel = "mode", description = "The mode of generator (what is being scanned?), supported modes are 'maven', 'resolver'") - private Mode mode; + protected Mode mode; @CommandLine.Option( names = {"-t", "--templates"}, @@ -85,20 +85,24 @@ enum Mode { split = ",", paramLabel = "template", description = "The template names to write content out without '.vm' extension") - private List templates; + protected List templates; @CommandLine.Parameters(index = "0", description = "The root directory to process sources from") - private Path rootDirectory; + protected Path rootDirectory; @CommandLine.Parameters(index = "1", description = "The directory to generate output(s) to") - private Path outputDirectory; + protected Path outputDirectory; @Override public Integer call() { try { + rootDirectory = rootDirectory.toAbsolutePath().normalize(); + outputDirectory = outputDirectory.toAbsolutePath().normalize(); + ArrayList> discoveredKeys = new ArrayList<>(); try (Stream stream = Files.walk(rootDirectory)) { if (mode == Mode.maven) { + System.out.println("Processing Maven sources from " + rootDirectory); stream.map(Path::toAbsolutePath) .filter(p -> p.getFileName().toString().endsWith(".class")) .filter(p -> p.toString().contains("/target/classes/")) @@ -106,6 +110,7 @@ public Integer call() { processMavenClass(p, discoveredKeys); }); } else if (mode == Mode.resolver) { + System.out.println("Processing Resolver sources from " + rootDirectory); stream.map(Path::toAbsolutePath) .filter(p -> p.getFileName().toString().endsWith(".java")) .filter(p -> p.toString().contains("/src/main/java/")) @@ -116,17 +121,19 @@ public Integer call() { } } - VelocityEngine velocityEngine = new VelocityEngine(); Properties properties = new Properties(); properties.setProperty("resource.loaders", "classpath"); properties.setProperty("resource.loader.classpath.class", ClasspathResourceLoader.class.getName()); + VelocityEngine velocityEngine = new VelocityEngine(); velocityEngine.init(properties); VelocityContext context = new VelocityContext(); context.put("keys", discoveredKeys); for (String template : templates) { - try (Writer fileWriter = new CachingWriter(outputDirectory.resolve(template), StandardCharsets.UTF_8)) { + Path output = outputDirectory.resolve(template); + System.out.println("Writing out to " + output); + try (Writer fileWriter = new CachingWriter(output, StandardCharsets.UTF_8)) { velocityEngine.getTemplate(template + ".vm").merge(context, fileWriter); } } @@ -137,7 +144,7 @@ public Integer call() { } } - private void processMavenClass(Path path, List> discoveredKeys) { + protected void processMavenClass(Path path, List> discoveredKeys) { try { ClassReader classReader = new ClassReader(Files.newInputStream(path)); classReader.accept( @@ -206,13 +213,13 @@ public void visitEnd() { values.get("defaultValue") != null ? values.get("defaultValue") .toString() - : "-", + : "", "fqName", - nvl(fqName, "-"), + nvl(fqName, ""), "description", desc, "since", - since, + nvl(since, ""), "configurationSource", source, "configurationType", @@ -231,7 +238,7 @@ public void visitEnd() { } } - private void processResolverClass(Path path, List> discoveredKeys) { + protected void processResolverClass(Path path, List> discoveredKeys) { JavaType type = parse(path); if (type instanceof JavaClassSource javaClassSource) { javaClassSource.getFields().stream() @@ -266,7 +273,7 @@ private void processResolverClass(Path path, List> discovere "key", key, "defaultValue", - nvl(defValue, "-"), + nvl(defValue, ""), "fqName", fqName, "description", @@ -283,13 +290,13 @@ private void processResolverClass(Path path, List> discovere } } - private JavaDocSource cloneJavadoc(JavaDocSource javaDoc) { + protected JavaDocSource cloneJavadoc(JavaDocSource javaDoc) { Javadoc jd = (Javadoc) javaDoc.getInternal(); return new JavaDocImpl<>(javaDoc.getOrigin(), (Javadoc) ASTNode.copySubtree(AST.newAST(jd.getAST().apiLevel(), false), jd)); } - private String cleanseJavadoc(FieldSource javaClassSource) { + protected String cleanseJavadoc(FieldSource javaClassSource) { JavaDoc> javaDoc = javaClassSource.getJavaDoc(); String[] text = javaDoc.getFullText().split("\n"); StringBuilder result = new StringBuilder(); @@ -301,7 +308,7 @@ private String cleanseJavadoc(FieldSource javaClassSource) { return cleanseTags(result.toString()); } - private String cleanseTags(String text) { + protected String cleanseTags(String text) { // {@code XXX} ->
XXX
// {@link XXX} -> ??? pre for now Pattern pattern = Pattern.compile("(\\{@\\w\\w\\w\\w (.+?)})"); @@ -322,7 +329,7 @@ private String cleanseTags(String text) { return result.toString(); } - private JavaType parse(Path path) { + protected JavaType parse(Path path) { try { return Roaster.parse(path.toFile()); } catch (IOException e) { @@ -330,85 +337,19 @@ private JavaType parse(Path path) { } } - private String toBoolean(String value) { + protected String toBoolean(String value) { return Boolean.toString("yes".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value)); } - /** - * Would be record, but... Velocity have no idea what it is nor how to handle it. - */ - public static class ConfigurationKey { - private final String key; - private final String defaultValue; - private final String fqName; - private final String description; - private final String since; - private final String configurationSource; - private final String configurationType; - private final boolean supportRepoIdSuffix; - - @SuppressWarnings("checkstyle:parameternumber") - public ConfigurationKey( - String key, - String defaultValue, - String fqName, - String description, - String since, - String configurationSource, - String configurationType, - boolean supportRepoIdSuffix) { - this.key = key; - this.defaultValue = defaultValue; - this.fqName = fqName; - this.description = description; - this.since = since; - this.configurationSource = configurationSource; - this.configurationType = configurationType; - this.supportRepoIdSuffix = supportRepoIdSuffix; - } - - public String getKey() { - return key; - } - - public String getDefaultValue() { - return defaultValue; - } - - public String getFqName() { - return fqName; - } - - public String getDescription() { - return description; - } - - public String getSince() { - return since; - } - - public String getConfigurationSource() { - return configurationSource; - } - - public String getConfigurationType() { - return configurationType; - } - - public boolean isSupportRepoIdSuffix() { - return supportRepoIdSuffix; - } - } - - private String nvl(String string, String def) { + protected String nvl(String string, String def) { return string == null ? def : string; } - private boolean hasConfigurationSource(JavaDocCapable javaDocCapable) { + protected boolean hasConfigurationSource(JavaDocCapable javaDocCapable) { return getTag(javaDocCapable, "@configurationSource") != null; } - private String getConfigurationType(JavaDocCapable javaDocCapable) { + protected String getConfigurationType(JavaDocCapable javaDocCapable) { String type = getTag(javaDocCapable, "@configurationType"); if (type != null) { String linkPrefix = "{@link "; @@ -424,7 +365,7 @@ private String getConfigurationType(JavaDocCapable javaDocCapable) { return nvl(type, "n/a"); } - private String getConfigurationSource(JavaDocCapable javaDocCapable) { + protected String getConfigurationSource(JavaDocCapable javaDocCapable) { String source = getTag(javaDocCapable, "@configurationSource"); if ("{@link RepositorySystemSession#getConfigProperties()}".equals(source)) { return "Session Configuration"; @@ -435,7 +376,7 @@ private String getConfigurationSource(JavaDocCapable javaDocCapable) { } } - private String getSince(JavaDocCapable javaDocCapable) { + protected String getSince(JavaDocCapable javaDocCapable) { List tags; if (javaDocCapable != null) { if (javaDocCapable instanceof FieldSource fieldSource) { @@ -455,7 +396,7 @@ private String getSince(JavaDocCapable javaDocCapable) { return null; } - private String getTag(JavaDocCapable javaDocCapable, String tagName) { + protected String getTag(JavaDocCapable javaDocCapable, String tagName) { List tags; if (javaDocCapable != null) { if (javaDocCapable instanceof FieldSource fieldSource) { @@ -470,9 +411,9 @@ private String getTag(JavaDocCapable javaDocCapable, String tagName) { return null; } - private static final Pattern CONSTANT_PATTERN = Pattern.compile(".*static final.* ([A-Z_]+) = (.*);"); + protected static final Pattern CONSTANT_PATTERN = Pattern.compile(".*static final.* ([A-Z_]+) = (.*);"); - private static final ToolProvider JAVAP = ToolProvider.findFirst("javap").orElseThrow(); + protected static final ToolProvider JAVAP = ToolProvider.findFirst("javap").orElseThrow(); /** * Builds "constant table" for one single class. @@ -482,7 +423,7 @@ private String getTag(JavaDocCapable javaDocCapable, String tagName) { * - does not work for fields that are Enum.name() * - more to come */ - private static Map extractConstants(Path file) { + protected static Map extractConstants(Path file) { StringWriter out = new StringWriter(); JAVAP.run(new PrintWriter(out), new PrintWriter(System.err), "-constants", file.toString()); Map result = new HashMap<>(); diff --git a/maven-resolver-tools/src/main/resources/configuration.properties.vm b/maven-resolver-tools/src/main/resources/configuration.properties.vm index a94ea40bc..33f2a5530 100644 --- a/maven-resolver-tools/src/main/resources/configuration.properties.vm +++ b/maven-resolver-tools/src/main/resources/configuration.properties.vm @@ -43,7 +43,7 @@ props.${foreach.count}.defaultValue = ${key.defaultValue} #if( !${key.since.empty} ) props.${foreach.count}.since = ${key.since} #end -#if( !${key.supportRepoIdSuffix.empty} ) +#if(${key.supportRepoIdSuffix}) props.${foreach.count}.supportRepoIdSuffix = ${key.supportRepoIdSuffix} #end props.${foreach.count}.configurationSource = ${key.configurationSource} diff --git a/maven-resolver-tools/src/main/resources/configuration.yaml.vm b/maven-resolver-tools/src/main/resources/configuration.yaml.vm index eaf71be19..079330684 100644 --- a/maven-resolver-tools/src/main/resources/configuration.yaml.vm +++ b/maven-resolver-tools/src/main/resources/configuration.yaml.vm @@ -43,7 +43,7 @@ props: #if( !${key.since.empty} ) since: ${key.since} #end - #if( !${key.supportRepoIdSuffix.empty} ) + #if(${key.supportRepoIdSuffix}) supportRepoIdSuffix: ${key.supportRepoIdSuffix} #end configurationSource: ${key.configurationSource} diff --git a/maven-resolver-tools/src/main/resources/page-maven.md.vm b/maven-resolver-tools/src/main/resources/page-maven.md.vm deleted file mode 100644 index 8cd78064a..000000000 --- a/maven-resolver-tools/src/main/resources/page-maven.md.vm +++ /dev/null @@ -1,55 +0,0 @@ -## -## Licensed to the Apache Software Foundation (ASF) under one -## or more contributor license agreements. See the NOTICE file -## distributed with this work for additional information -## regarding copyright ownership. The ASF licenses this file -## to you 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 -## -## http://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. -## -#[[ -# Configuration Options - - -]]# - -#macro(yesno $val) - #if ($val) Yes #else No #end -#end - -#macro(value $val) -#if ($val) `$val` #else - #end -#end - -| No | Key | Type | Description | Default Value | Since | Source | -| --- | --- | --- | --- | --- | --- | --- | -#foreach($key in $keys) -| $foreach.count. | `$key.key` | `$key.configurationType` | $key.description | #value( $key.defaultValue ) | $key.since | $key.configurationSource | -#end - diff --git a/pom.xml b/pom.xml index 2d35f82b5..ce36f4396 100644 --- a/pom.xml +++ b/pom.xml @@ -296,6 +296,12 @@ ${slf4jVersion} test + + org.slf4j + slf4j-nop + ${slf4jVersion} + test + com.google.jimfs From 1a08cb9c0d4db6e03808e57d5d2a5543a0173bcc Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Thu, 24 Oct 2024 16:17:54 +0200 Subject: [PATCH 4/6] Tidy up --- maven-resolver-tools/pom.xml | 2 +- .../main/resources/{page-resolver.md.vm => configuration.md.vm} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename maven-resolver-tools/src/main/resources/{page-resolver.md.vm => configuration.md.vm} (100%) diff --git a/maven-resolver-tools/pom.xml b/maven-resolver-tools/pom.xml index e488d1fa1..ad426eca4 100644 --- a/maven-resolver-tools/pom.xml +++ b/maven-resolver-tools/pom.xml @@ -183,7 +183,7 @@ org.eclipse.aether.tools.CollectConfiguration --mode=resolver - --templates=page-resolver.md,configuration.properties,configuration.yaml + --templates=configuration.md,configuration.properties,configuration.yaml ${basedir}/.. ${basedir}/target/ diff --git a/maven-resolver-tools/src/main/resources/page-resolver.md.vm b/maven-resolver-tools/src/main/resources/configuration.md.vm similarity index 100% rename from maven-resolver-tools/src/main/resources/page-resolver.md.vm rename to maven-resolver-tools/src/main/resources/configuration.md.vm From e97fd76d2c80383d217d3ea8f759079d61040fcd Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Thu, 24 Oct 2024 16:29:02 +0200 Subject: [PATCH 5/6] Tidy up more, return same output --- maven-resolver-tools/pom.xml | 20 +++++++++++++++++-- .../aether/tools/CollectConfiguration.java | 16 ++++++++++----- .../src/main/resources/configuration.md.vm | 6 +----- src/site/markdown/configuration.md | 1 - src/site/markdown/configuration.mdl | 0 5 files changed, 30 insertions(+), 13 deletions(-) create mode 100644 src/site/markdown/configuration.mdl diff --git a/maven-resolver-tools/pom.xml b/maven-resolver-tools/pom.xml index ad426eca4..85725fb65 100644 --- a/maven-resolver-tools/pom.xml +++ b/maven-resolver-tools/pom.xml @@ -183,7 +183,23 @@ org.eclipse.aether.tools.CollectConfiguration --mode=resolver - --templates=configuration.md,configuration.properties,configuration.yaml + --templates=configuration.md + ${basedir}/.. + ${basedir}/../src/site/markdown/ + + + + + render-configuration-artifacts + + java + + verify + + org.eclipse.aether.tools.CollectConfiguration + + --mode=resolver + --templates=configuration.properties,configuration.yaml ${basedir}/.. ${basedir}/target/ @@ -197,7 +213,7 @@ 3.6.0 - attach + attach-configuration-artifacts attach-artifact diff --git a/maven-resolver-tools/src/main/java/org/eclipse/aether/tools/CollectConfiguration.java b/maven-resolver-tools/src/main/java/org/eclipse/aether/tools/CollectConfiguration.java index 83c8abaec..f6d73415d 100644 --- a/maven-resolver-tools/src/main/java/org/eclipse/aether/tools/CollectConfiguration.java +++ b/maven-resolver-tools/src/main/java/org/eclipse/aether/tools/CollectConfiguration.java @@ -28,6 +28,8 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -67,6 +69,8 @@ public static void main(String[] args) { new CommandLine(new CollectConfiguration()).execute(args); } + protected static final String KEY = "key"; + enum Mode { maven, resolver @@ -121,6 +125,8 @@ public Integer call() { } } + Collections.sort(discoveredKeys, Comparator.comparing(e -> e.get(KEY))); + Properties properties = new Properties(); properties.setProperty("resource.loaders", "classpath"); properties.setProperty("resource.loader.classpath.class", ClasspathResourceLoader.class.getName()); @@ -207,7 +213,7 @@ public void visitEnd() { default -> throw new IllegalStateException(); }; discoveredKeys.add(Map.of( - "key", + KEY, fieldValue.toString(), "defaultValue", values.get("defaultValue") != null @@ -270,7 +276,7 @@ protected void processResolverClass(Path path, List> discove } } discoveredKeys.add(Map.of( - "key", + KEY, key, "defaultValue", nvl(defValue, ""), @@ -285,7 +291,7 @@ protected void processResolverClass(Path path, List> discove "configurationType", configurationType, "supportRepoIdSuffix", - toBoolean(getTag(f, "@configurationRepoIdSuffix")))); + toYesNo(getTag(f, "@configurationRepoIdSuffix")))); }); } } @@ -337,8 +343,8 @@ protected JavaType parse(Path path) { } } - protected String toBoolean(String value) { - return Boolean.toString("yes".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value)); + protected String toYesNo(String value) { + return "yes".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value) ? "Yes" : "No"; } protected String nvl(String string, String def) { diff --git a/maven-resolver-tools/src/main/resources/configuration.md.vm b/maven-resolver-tools/src/main/resources/configuration.md.vm index 46c565de2..60e6e8112 100644 --- a/maven-resolver-tools/src/main/resources/configuration.md.vm +++ b/maven-resolver-tools/src/main/resources/configuration.md.vm @@ -39,10 +39,6 @@ under the License. ]]# -#macro(yesno $val) - #if ($val) Yes #else No #end -#end - #macro(value $val) #if ($val) `$val` #else - #end #end @@ -50,7 +46,7 @@ under the License. | No | Key | Type | Description | Default Value | Since | Supports Repo ID suffix | Source | | --- | --- | --- | --- | --- | --- | --- | --- | #foreach($key in $keys) -| $foreach.count. | `$key.key` | `$key.configurationType` | $key.description | #value( $key.defaultValue ) | $key.since | #yesno( $key.supportRepoIdSuffix ) | $key.configurationSource | +| $foreach.count. | `$key.key` | `$key.configurationType` | $key.description | #value( $key.defaultValue ) | $key.since | $key.supportRepoIdSuffix | $key.configurationSource | #end #[[ diff --git a/src/site/markdown/configuration.md b/src/site/markdown/configuration.md index 5ffc45674..51cc4f45c 100644 --- a/src/site/markdown/configuration.md +++ b/src/site/markdown/configuration.md @@ -22,7 +22,6 @@ under the License. - | No | Key | Type | Description | Default Value | Since | Supports Repo ID suffix | Source | | --- | --- | --- | --- | --- | --- | --- | --- | | 1. | `"aether.artifactResolver.postProcessor.trustedChecksums"` | `Boolean` | Is post processor enabled. | `false` | 1.9.0 | No | Session Configuration | diff --git a/src/site/markdown/configuration.mdl b/src/site/markdown/configuration.mdl new file mode 100644 index 000000000..e69de29bb From e5abdaeff0821b24b6a6360b376198889de8287d Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Thu, 24 Oct 2024 16:29:42 +0200 Subject: [PATCH 6/6] Remove error --- src/site/markdown/configuration.mdl | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 src/site/markdown/configuration.mdl diff --git a/src/site/markdown/configuration.mdl b/src/site/markdown/configuration.mdl deleted file mode 100644 index e69de29bb..000000000