Skip to content

Commit

Permalink
initial commit - add sources from closed source repository
Browse files Browse the repository at this point in the history
  • Loading branch information
jschwarz-eitco-de committed Jul 22, 2024
1 parent e2490ca commit cafd8f4
Show file tree
Hide file tree
Showing 10 changed files with 530 additions and 50 deletions.
46 changes: 6 additions & 40 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,11 @@

[![License](https://img.shields.io/github/license/eitco/bom-maven-plugin.svg?style=for-the-badge)](https://opensource.org/license/mit)
[![License](https://img.shields.io/github/license/eitco/spring-config-collector-maven-plugin.svg?style=for-the-badge)](https://opensource.org/license/mit)


<!-- TODO: this is the documentation for the eitco github maven project template - it will however be generated with
a project if used. In your project simply replace the content of this file with the documentation of your project.
consider the following additional badges (and adapt them for your project):
[![Build status](https://img.shields.io/github/actions/workflow/status/eitco/spring-config-collector-maven-plugin/deploy.yaml?branch=main&style=for-the-badge&logo=github)](https://github.com/eitco/spring-config-collector-maven-plugin/actions/workflows/deploy.yaml)
[![Maven Central Version](https://img.shields.io/maven-central/v/de.eitco.cicd/spring-config-collector-maven-plugin?style=for-the-badge&logo=apachemaven)](https://central.sonatype.com/artifact/de.eitco.cicd/spring-config-collector-maven-plugin)

[![Build status](https://img.shields.io/github/actions/workflow/status/eitco/<your github project name>/deploy.yaml?branch=main&style=for-the-badge&logo=github)](https://github.com/eitco/<your github project name>/actions/workflows/deploy.yaml)
[![Maven Central Version](https://img.shields.io/maven-central/v/<groupId>/<artifactId>?style=for-the-badge&logo=apachemaven)](https://central.sonatype.com/artifact/<groupId>/<artifactId>)
# spring config collector maven plugin

also check whether the license badge link points to the correct license.
-->

# eitco maven project template

This [github template repository](https://docs.github.com/en/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template)
contains a basic maven project ready for the eitco open source ci. It contains:

# README.md

This readme, you are currently viewing. In a generated project it needs to be replaced. See the TODO-commentary for
some ideas.

# LICENSE

By default, eitco open source software is licensed under the [MIT license](https://opensource.org/license/mit).
To change this, simply replace this file

# continuous integration

The directories `.github` and `deployment` contain the CI. While the directory `.github` contains actions that build
each commit and release the project on demand, the directory `deployment` contains configuration for the release.
A lot of the build however is configured by the project object model (pom.xml).

# pom.xml

This file specifies the build for your project. Make sure to adapt it according to the TODOs. A lot of the
CI is inherited from the [`eitco-oss-parent`](https://github.com/eitco/eitco-oss-parent) pom.

# .mvn

The `.mvn` directory activates and configures the `maven-git-versioning-extension`. This extension changes the
projects version depending on the current branch. This way every branch can be deployed without their artifacts
overriding each other.
This maven plugin collects all spring configuration properties of the project and its dependencies and creates
documentation for them. Either in plain html or in asciidoc.
74 changes: 64 additions & 10 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,76 @@
<parent>
<groupId>de.eitco.cicd</groupId>
<artifactId>eitco-oss-parent</artifactId>
<version>0.0.12</version>
<version>0.0.14-SNAPSHOT</version>
</parent>


<!-- TODO: replace with your coordinates -->
<groupId>de.eitco</groupId>
<artifactId>eitco-maven-template</artifactId>
<version>0.0.1-SNAPSHOT</version>
<groupId>de.eitco.cicd</groupId>
<artifactId>spring-config-collector-maven-plugin</artifactId>
<version>4.0.1-SNAPSHOT</version>
<packaging>maven-plugin</packaging>

<developers>
<!-- TODO: add developers concerned -->
<developer>
<name>Christopher Merkel</name>
<email>[email protected]</email>
</developer>
</developers>

<scm>
<!-- TODO: replace with your repository url -->
<url>https://github.com/eitco/maven-template.git</url>
<connection>scm:git:https://github.com/eitco/maven-template.git</connection>
<developerConnection>scm:git:https://github.com/eitco/maven-template.git</developerConnection>
<url>https://github.com/eitco/spring-config-collector-maven-plugin.git</url>
<connection>scm:git:https://github.com/eitco/spring-config-collector-maven-plugin.git</connection>
<developerConnection>scm:git:https://github.com/eitco/spring-config-collector-maven-plugin.git</developerConnection>
</scm>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.fasterxml.jackson</groupId>
<artifactId>jackson-bom</artifactId>
<version>${jackson.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>


<dependencies>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
</dependency>
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-project</artifactId>
<version>2.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.j2html</groupId>
<artifactId>j2html</artifactId>
<version>1.6.0</version>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
Expand All @@ -34,6 +84,10 @@
<plugin>
<artifactId>maven-resources-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
</plugin>
</plugins>
</build>

Expand Down
131 changes: 131 additions & 0 deletions src/main/java/de/eitco/cicd/sccmp/AbstractConfigCollectorMojo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package de.eitco.cicd.sccmp;

import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import de.eitco.cicd.sccmp.model.ConfigurationMetadata;
import de.eitco.cicd.sccmp.model.Group;
import de.eitco.cicd.sccmp.model.Property;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public abstract class AbstractConfigCollectorMojo extends AbstractMojo {

public static final String CONFIG_METADATA_JSON_FILE = "META-INF/spring-configuration-metadata.json";
@Parameter(defaultValue = "${project}", required = true, readonly = true)
MavenProject project;

@Parameter(defaultValue = ".*")
String filteringRegex;

protected CollectedProperties loadConfigurationMetadata() throws IOException, MojoExecutionException {

Enumeration<URL> systemResources = getProjectDependencyClassLoader().getResources(CONFIG_METADATA_JSON_FILE);
List<URL> urls = new ArrayList<>();

while (systemResources.hasMoreElements()) {

URL url = systemResources.nextElement();
urls.add(url);
}

getLog().info("Found " + urls.size() + " configuration metadata files in the classpath.");

ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

List<String> groupNames = new ArrayList<>();
Map<String, List<Property>> propertiesByGroupName = new HashMap<>();

Pattern pattern = Pattern.compile(filteringRegex);

for (URL url : urls) {

try (InputStream stream = url.openStream()) {

getLog().info("Processing " + url);

ConfigurationMetadata configurationMetadata = mapper.readValue(stream, ConfigurationMetadata.class);

Objects.requireNonNullElse(configurationMetadata.getGroups(), List.<Group>of()).forEach(group -> {

boolean matches = pattern.matcher(group.getName()).matches();

if (group.getSourceMethod() == null && matches) {

groupNames.add(group.getName());
getLog().info("Group " + group.getName() + " added.");
} else if (!matches) {
getLog().info("Group " + group.getName() + " ignored.");
}
});

groupNames.forEach(name ->
configurationMetadata.getProperties().stream().filter(p -> p.getName().startsWith(name)).forEach(p -> {

List<Property> list = propertiesByGroupName.computeIfAbsent(name, n -> new ArrayList<>());
list.add(p);
}));
}
}

List<String> sortedGroupNames = groupNames.stream().sorted().collect(Collectors.toList());

Map<String, List<Property>> sortedPropertiesByGroupName = propertiesByGroupName.entrySet().stream()
.collect(Collectors.toMap(
Map.Entry::getKey,
entry -> entry.getValue().stream().sorted().collect(Collectors.toList())
)
);

return new CollectedProperties(sortedGroupNames, sortedPropertiesByGroupName);
}

private ClassLoader getProjectDependencyClassLoader() throws MojoExecutionException {

try {
List<?> classpathElements = project.getRuntimeClasspathElements();

URL[] urls = new URL[classpathElements.size()];

for (int i = 0; i < classpathElements.size(); ++i) {
urls[i] = new File((String) classpathElements.get(i)).toURI().toURL();
}

return new URLClassLoader(urls);

} catch (Exception e) {
throw new MojoExecutionException("Failed to initialize class loader.");
}
}

protected String getOutputPath(String outputDirectory) throws MojoExecutionException {

String out = outputDirectory != null ? outputDirectory : project.getBuild().getDirectory();
boolean mkdirs = Path.of(out).toFile().mkdirs();

if (!mkdirs && !Files.exists(Path.of(out))) {

throw new MojoExecutionException("Failed to create output directory " + out);
}

return out;
}

protected String getPropertyName(Property property, String groupName) {

return property.getName().substring(groupName.length() + 1);
}
}
77 changes: 77 additions & 0 deletions src/main/java/de/eitco/cicd/sccmp/AdocConfigCollectorMojo.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package de.eitco.cicd.sccmp;

import de.eitco.cicd.sccmp.model.Property;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

/**
* This mojo collects all spring-configuration-metadata.json files in the classpath and creates an asciidoc overview page
* containing the available properties.
*/
@Mojo(name = "adoc-overview", defaultPhase = LifecyclePhase.PROCESS_CLASSES, requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME)
public class AdocConfigCollectorMojo extends AbstractConfigCollectorMojo {

@Parameter
String outputDirectory;

@Parameter(defaultValue = "3")
int titleLevel = 3;

@Override
public void execute() throws MojoExecutionException {

try {

CollectedProperties collectedProperties = loadConfigurationMetadata();
generateAdoc(collectedProperties);

} catch (IOException e) {
throw new MojoExecutionException("Failed to load configuration metadata from classpath.", e);
}
}

private void generateAdoc(CollectedProperties collectedProperties) throws MojoExecutionException, IOException {

StringBuilder adoc = new StringBuilder();
String titlePrefix = "=".repeat(titleLevel);
String groupPrefix = "=".repeat(titleLevel + 1);

adoc.append(titlePrefix).append(" Configuration Properties\n\n");

for (String groupName : collectedProperties.getGroupNames()) {

adoc.append("[#_").append(groupName.replace('.', '_')).append("]\n");
adoc.append(groupPrefix).append(" ").append(groupName).append("\n\n");

adoc.append("[%autowidth]\n|===\n|Property |Type |Description |Default value\n\n");

List<Property> properties = collectedProperties.getPropertiesByGroupName().get(groupName);

for (Property property : properties) {

adoc
.append("|").append(getPropertyName(property, groupName)).append("\n")
.append("|").append(property.getType()).append("\n")
.append("|").append(property.getDescription()).append("\n")
.append("|").append(property.getDefaultValue() != null ? property.getDefaultValue() : "").append("\n\n");
}

adoc.append("|===\n\n");
}

String out = getOutputPath(outputDirectory);

Path outputPath = Path.of(out, "configuration-properties.adoc");
getLog().info("Writing adoc file " + outputPath);

Files.writeString(outputPath, adoc.toString());
}
}
25 changes: 25 additions & 0 deletions src/main/java/de/eitco/cicd/sccmp/CollectedProperties.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package de.eitco.cicd.sccmp;

import de.eitco.cicd.sccmp.model.Property;

import java.util.List;
import java.util.Map;

public class CollectedProperties {

private final List<String> groupNames;
private final Map<String, List<Property>> propertiesByGroupName;

public CollectedProperties(List<String> groupNames, Map<String, List<Property>> propertiesByGroupName) {
this.groupNames = groupNames;
this.propertiesByGroupName = propertiesByGroupName;
}

public List<String> getGroupNames() {
return groupNames;
}

public Map<String, List<Property>> getPropertiesByGroupName() {
return propertiesByGroupName;
}
}
Loading

0 comments on commit cafd8f4

Please sign in to comment.