Skip to content

Commit

Permalink
fix(citrusframework#477): Support custom Maven plugin repository
Browse files Browse the repository at this point in the history
Enable users to define custom Maven plugin repositories
  • Loading branch information
christophd committed Aug 31, 2023
1 parent d28cc83 commit cc4f660
Show file tree
Hide file tree
Showing 29 changed files with 524 additions and 72 deletions.
47 changes: 45 additions & 2 deletions java/docs/configuration.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,10 @@ yaks run --settings yaks.settings.yaml camel-route.feature
----

[[configuration-repositories]]
== Maven repositories
== Maven repositories and pluginRepositories

When adding custom runtime dependencies those artifacts might not be available on the public central Maven repository.
Instead you may need to add a custom repository that holds your artifacts.
Instead you may need to add a custom Maven repository that holds your artifacts.

You can do this with several configuration options:

Expand All @@ -183,6 +183,11 @@ You can add repositories also by specifying the repositories as command line par
yaks run --maven-repository jboss-ea=https://repository.jboss.org/nexus/content/groups/ea/ my.feature
----

[source,shell script]
----
yaks run --maven-plugin-repository jboss-ea=https://repository.jboss.org/nexus/content/groups/ea/ my.feature
----

This will add a environment setting in the YAKS runtime container and the repository will be added to the Maven runtime project model.

[[configuration-repository-file]]
Expand All @@ -196,6 +201,10 @@ Maven repository id and url in the property file using a common property key pre
# Maven repositories
yaks.repository.central=https://repo.maven.apache.org/maven2/
yaks.repository.jboss-ea=https://repository.jboss.org/nexus/content/groups/ea/
# Maven plugin repositories
yaks.pluginRepository.central=https://repo.maven.apache.org/maven2/
yaks.pluginRepository.jboss-ea=https://repository.jboss.org/nexus/content/groups/ea/
----

You can add the property file when running the test via `yaks` CLI like follows:
Expand Down Expand Up @@ -227,6 +236,20 @@ repositories:
name: "JBoss Community Early Access Release Repository"
url: "https://repository.jboss.org/nexus/content/groups/ea/"
layout: "default"
pluginRepositories:
- id: "central"
name: "Maven Central"
url: "https://repo.maven.apache.org/maven2/"
releases:
enabled: "true"
updatePolicy: "daily"
snapshots:
enabled: "false"
- id: "jboss-ea"
name: "JBoss Community Early Access Release Repository"
url: "https://repository.jboss.org/nexus/content/groups/ea/"
layout: "default"
----

[source,json]
Expand All @@ -251,6 +274,26 @@ repositories:
"url": "https://repository.jboss.org/nexus/content/groups/ea/",
"layout": "default"
}
],
"pluginRepositories": [
{
"id": "central",
"name": "Maven Central",
"url": "https://repo.maven.apache.org/maven2/",
"releases": {
"enabled": "true",
"updatePolicy": "daily"
},
"snapshots": {
"enabled": "false"
}
},
{
"id": "jboss-ea",
"name": "JBoss Community Early Access Release Repository",
"url": "https://repository.jboss.org/nexus/content/groups/ea/",
"layout": "default"
}
]
}
----
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ public final class ExtensionSettings {
public static final String REPOSITORIES_SETTING_KEY = "yaks.repositories";
public static final String REPOSITORIES_SETTING_ENV = "YAKS_REPOSITORIES";

public static final String PLUGIN_REPOSITORIES_SETTING_KEY = "yaks.plugin.repositories";
public static final String PLUGIN_REPOSITORIES_SETTING_ENV = "YAKS_PLUGIN_REPOSITORIES";

public static final String LOGGERS_SETTING_KEY = "yaks.loggers";
public static final String LOGGERS_SETTING_ENV = "YAKS_LOGGERS";
public static final String LOGGING_LEVEL_PREFIX = "logging.level.";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@

package org.citrusframework.yaks.maven.extension;

import javax.inject.Singleton;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.inject.Singleton;

import org.apache.maven.lifecycle.LifecycleExecutionException;
import org.apache.maven.model.Model;
Expand Down Expand Up @@ -50,32 +50,55 @@ public class ProjectModelReader extends DefaultModelReader {
private Logger logger;

private List<Repository> repositoryList;
private List<Repository> pluginRepositoryList;

@Override
public Model read(InputStream input, Map<String, ?> options) throws IOException {
Model projectModel = super.read(input, options);
projectModel.getRepositories().addAll(loadDynamicRepositories());
projectModel.getPluginRepositories().addAll(loadDynamicPluginRepositories());
return projectModel;
}

/**
* Dynamically add project repositories based on different configuration sources such as environment variables,
* system properties configuration files.
* system properties and configuration files.
*/
private List<Repository> loadDynamicRepositories() {
if (repositoryList == null) {
repositoryList = new ArrayList<>();
logger.info("Add dynamic project repositories ...");

try {
repositoryList.addAll(new FileBasedRepositoryLoader().load(logger));
repositoryList.addAll(new SystemPropertyRepositoryLoader().load(logger));
repositoryList.addAll(new EnvironmentSettingRepositoryLoader().load(logger));
repositoryList.addAll(new FileBasedRepositoryLoader().load(logger, false));
repositoryList.addAll(new SystemPropertyRepositoryLoader().load(logger, false));
repositoryList.addAll(new EnvironmentSettingRepositoryLoader().load(logger, false));
} catch (LifecycleExecutionException e) {
throw new RuntimeException(e);
}
}

return repositoryList;
}

/**
* Dynamically add plugin repositories based on different configuration sources such as environment variables,
* system properties and configuration files.
*/
private List<Repository> loadDynamicPluginRepositories() {
if (pluginRepositoryList == null) {
pluginRepositoryList = new ArrayList<>();
logger.info("Add dynamic plugin repositories ...");

try {
pluginRepositoryList.addAll(new FileBasedRepositoryLoader().load(logger, true));
pluginRepositoryList.addAll(new SystemPropertyRepositoryLoader().load(logger, true));
pluginRepositoryList.addAll(new EnvironmentSettingRepositoryLoader().load(logger, true));
} catch (LifecycleExecutionException e) {
throw new RuntimeException(e);
}
}

return pluginRepositoryList;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,17 @@
public abstract class AbstractConfigFileRepositoryLoader implements RepositoryLoader {

@Override
public List<Repository> load(Logger logger) {
public List<Repository> load(Logger logger, boolean asPluginRepository) {
return Collections.emptyList();
}

/**
* Load repositories from given file.
* @param filePath
* @param logger
* @param asPluginRepository
* @return
* @throws LifecycleExecutionException
*/
protected abstract List<Repository> load(Path filePath, Logger logger) throws LifecycleExecutionException;
protected abstract List<Repository> load(Path filePath, Logger logger, boolean asPluginRepository) throws LifecycleExecutionException;
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,14 @@ public FileBasedRepositoryLoader() {
}

@Override
public List<Repository> load(Logger logger) throws LifecycleExecutionException {
public List<Repository> load(Logger logger, boolean asPluginRepository) throws LifecycleExecutionException {
Path settingsFile = getSettingsFile();

if (Files.exists(settingsFile)) {
Optional<String> fileExtension = getFileNameExtension(settingsFile.getFileName().toString());
return fileExtension.flatMap(this::getFileConfigLoader)
.orElse(new PropertyFileRepositoryLoader())
.load(settingsFile, logger);
.load(settingsFile, logger, asPluginRepository);
}

return Collections.emptyList();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,10 @@ public interface RepositoryLoader {
/**
* Load Maven repositories from configuration source.
* @param logger
* @param asPluginRepository
* @return
*/
List<Repository> load(Logger logger) throws LifecycleExecutionException;
List<Repository> load(Logger logger, boolean asPluginRepository) throws LifecycleExecutionException;

/**
* Construct repository instance from given url. Query parameters are translated to fields on the target repository.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@
public class EnvironmentSettingRepositoryLoader implements RepositoryLoader, EnvironmentSettingLoader {

@Override
public List<Repository> load(Logger logger) throws LifecycleExecutionException {
public List<Repository> load(Logger logger, boolean asPluginRepository) throws LifecycleExecutionException {
List<Repository> repositoryList = new ArrayList<>();

String settings = getEnvSetting(ExtensionSettings.REPOSITORIES_SETTING_ENV);
String settings = getEnvSetting(asPluginRepository ?
ExtensionSettings.PLUGIN_REPOSITORIES_SETTING_ENV : ExtensionSettings.REPOSITORIES_SETTING_ENV);

if (settings.length() > 0) {
for (String scalar : settings.split(",")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,13 +69,13 @@
public class JsonFileRepositoryLoader extends AbstractConfigFileRepositoryLoader {

@Override
protected List<Repository> load(Path filePath, Logger logger) throws LifecycleExecutionException {
protected List<Repository> load(Path filePath, Logger logger, boolean asPluginRepository) throws LifecycleExecutionException {
List<Repository> repositoryList = new ArrayList<>();

ObjectMapper mapper = new ObjectMapper();
try {
JsonNode root = mapper.readTree(new StringReader(new String(Files.readAllBytes(filePath), StandardCharsets.UTF_8)));
ArrayNode repositories = (ArrayNode) root.get("repositories");
ArrayNode repositories = (ArrayNode) root.get(asPluginRepository ? "pluginRepositories" : "repositories");
for (Object o : repositories) {
ObjectNode model = (ObjectNode) o;
Repository repository = new Repository();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
public class PropertyFileRepositoryLoader extends AbstractConfigFileRepositoryLoader {

@Override
protected List<Repository> load(Path filePath, Logger logger) throws LifecycleExecutionException {
protected List<Repository> load(Path filePath, Logger logger, boolean asPluginRepository) throws LifecycleExecutionException {
List<Repository> repositoryList = new ArrayList<>();

try {
Expand All @@ -54,7 +54,9 @@ protected List<Repository> load(Path filePath, Logger logger) throws LifecycleEx

for (Enumeration<?> e = props.propertyNames(); e.hasMoreElements(); ) {
String name = (String) e.nextElement();
if (name.startsWith("yaks.repository.")) {
if (asPluginRepository && name.startsWith("yaks.pluginRepository.")) {
repositoryList.add(build(name.substring("yaks.pluginRepository.".length()), props.getProperty(name), logger));
} else if (!asPluginRepository && name.startsWith("yaks.repository.")) {
repositoryList.add(build(name.substring("yaks.repository.".length()), props.getProperty(name), logger));
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@
public class SystemPropertyRepositoryLoader implements RepositoryLoader {

@Override
public List<Repository> load(Logger logger) throws LifecycleExecutionException {
public List<Repository> load(Logger logger, boolean asPluginRepository) throws LifecycleExecutionException {
List<Repository> repositoryList = new ArrayList<>();

String coordinates = System.getProperty(ExtensionSettings.REPOSITORIES_SETTING_KEY, "");
String coordinates = System.getProperty(asPluginRepository ?
ExtensionSettings.PLUGIN_REPOSITORIES_SETTING_KEY : ExtensionSettings.REPOSITORIES_SETTING_KEY, "");

if (coordinates.length() > 0) {
for (String scalar : coordinates.split(",")) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,14 @@
public class YamlFileRepositoryLoader extends AbstractConfigFileRepositoryLoader {

@Override
protected List<Repository> load(Path filePath, Logger logger) throws LifecycleExecutionException {
protected List<Repository> load(Path filePath, Logger logger, boolean asPluginRepository) throws LifecycleExecutionException {
try {
List<Repository> repositoryList = new ArrayList<>();
Yaml yaml = new Yaml();

HashMap<String, List<Map<String, Object>>> root = yaml.load(new StringReader(new String(Files.readAllBytes(filePath), StandardCharsets.UTF_8)));
if (root.containsKey("repositories")) {
for (Map<String, Object> model : root.get("repositories")) {
for (Map<String, Object> model : root.get(asPluginRepository ? "pluginRepositories" : "repositories")) {
Repository repository = new Repository();

repository.setId(Objects.toString(model.get("id")));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/*
* 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.
*/

package org.citrusframework.yaks.maven.extension.configuration;

import java.util.List;

import org.apache.maven.lifecycle.LifecycleExecutionException;
import org.apache.maven.model.Repository;
import org.assertj.core.api.Assertions;
import org.citrusframework.yaks.maven.extension.ExtensionSettings;
import org.codehaus.plexus.logging.console.ConsoleLogger;
import org.junit.Test;

/**
* @author Christoph Deppisch
*/
public class FileBasedPluginRepositoryLoaderTest {

private final FileBasedRepositoryLoader loader = new FileBasedRepositoryLoader();

private final ConsoleLogger logger = new ConsoleLogger();

@Test
public void shouldLoadFromPropertyFile() throws LifecycleExecutionException {
System.setProperty(ExtensionSettings.SETTINGS_FILE_KEY, "classpath:yaks.properties");
List<Repository> repositoryList = loader.load(logger, true);
TestHelper.verifyRepositories(repositoryList);

System.setProperty(ExtensionSettings.SETTINGS_FILE_KEY, "classpath:yaks.settings.yaml");
repositoryList = loader.load(logger, true);
TestHelper.verifyRepositories(repositoryList);

System.setProperty(ExtensionSettings.SETTINGS_FILE_KEY, "classpath:yaks.settings.json");
repositoryList = loader.load(logger, true);
TestHelper.verifyRepositories(repositoryList);
}

@Test
public void shouldHandleNonExistingFile() throws LifecycleExecutionException {
System.setProperty(ExtensionSettings.SETTINGS_FILE_KEY, "doesNotExist");
List<Repository> repositoryList = loader.load(logger, true);
Assertions.assertThat(repositoryList).isEmpty();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -38,22 +38,22 @@ public class FileBasedRepositoryLoaderTest {
@Test
public void shouldLoadFromPropertyFile() throws LifecycleExecutionException {
System.setProperty(ExtensionSettings.SETTINGS_FILE_KEY, "classpath:yaks.properties");
List<Repository> repositoryList = loader.load(logger);
List<Repository> repositoryList = loader.load(logger, false);
TestHelper.verifyRepositories(repositoryList);

System.setProperty(ExtensionSettings.SETTINGS_FILE_KEY, "classpath:yaks.settings.yaml");
repositoryList = loader.load(logger);
repositoryList = loader.load(logger, false);
TestHelper.verifyRepositories(repositoryList);

System.setProperty(ExtensionSettings.SETTINGS_FILE_KEY, "classpath:yaks.settings.json");
repositoryList = loader.load(logger);
repositoryList = loader.load(logger, false);
TestHelper.verifyRepositories(repositoryList);
}

@Test
public void shouldHandleNonExistingFile() throws LifecycleExecutionException {
System.setProperty(ExtensionSettings.SETTINGS_FILE_KEY, "doesNotExist");
List<Repository> repositoryList = loader.load(logger);
List<Repository> repositoryList = loader.load(logger, false);
Assertions.assertThat(repositoryList).isEmpty();
}

Expand Down
Loading

0 comments on commit cc4f660

Please sign in to comment.