Configure CLI with repositories from active profiles in settings.xml
This commit enhances the CLI to use the repositories configured in the profiles declared in a user's Maven settings.xml file during dependency resolution. A profile must be active for its repositories to be used. Closes gh-2703 Closes gh-3483
This commit is contained in:
parent
eafee1ecb6
commit
8493755178
|
@ -0,0 +1,283 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2015 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
|
||||||
|
*
|
||||||
|
* 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.springframework.boot.cli.compiler;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.PrintWriter;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.maven.model.ActivationFile;
|
||||||
|
import org.apache.maven.model.ActivationOS;
|
||||||
|
import org.apache.maven.model.ActivationProperty;
|
||||||
|
import org.apache.maven.model.building.ModelProblemCollector;
|
||||||
|
import org.apache.maven.model.building.ModelProblemCollectorRequest;
|
||||||
|
import org.apache.maven.model.profile.DefaultProfileSelector;
|
||||||
|
import org.apache.maven.model.profile.ProfileActivationContext;
|
||||||
|
import org.apache.maven.model.profile.activation.FileProfileActivator;
|
||||||
|
import org.apache.maven.model.profile.activation.JdkVersionProfileActivator;
|
||||||
|
import org.apache.maven.model.profile.activation.OperatingSystemProfileActivator;
|
||||||
|
import org.apache.maven.model.profile.activation.PropertyProfileActivator;
|
||||||
|
import org.apache.maven.settings.Activation;
|
||||||
|
import org.apache.maven.settings.Mirror;
|
||||||
|
import org.apache.maven.settings.Profile;
|
||||||
|
import org.apache.maven.settings.Proxy;
|
||||||
|
import org.apache.maven.settings.Server;
|
||||||
|
import org.apache.maven.settings.Settings;
|
||||||
|
import org.apache.maven.settings.crypto.SettingsDecryptionResult;
|
||||||
|
import org.eclipse.aether.repository.Authentication;
|
||||||
|
import org.eclipse.aether.repository.AuthenticationSelector;
|
||||||
|
import org.eclipse.aether.repository.MirrorSelector;
|
||||||
|
import org.eclipse.aether.repository.ProxySelector;
|
||||||
|
import org.eclipse.aether.util.repository.AuthenticationBuilder;
|
||||||
|
import org.eclipse.aether.util.repository.ConservativeAuthenticationSelector;
|
||||||
|
import org.eclipse.aether.util.repository.DefaultAuthenticationSelector;
|
||||||
|
import org.eclipse.aether.util.repository.DefaultMirrorSelector;
|
||||||
|
import org.eclipse.aether.util.repository.DefaultProxySelector;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An encapsulation of settings read from a user's Maven settings.xml.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
* @since 1.3.0
|
||||||
|
* @see MavenSettingsReader
|
||||||
|
*/
|
||||||
|
public class MavenSettings {
|
||||||
|
|
||||||
|
private final boolean offline;
|
||||||
|
|
||||||
|
private final MirrorSelector mirrorSelector;
|
||||||
|
|
||||||
|
private final AuthenticationSelector authenticationSelector;
|
||||||
|
|
||||||
|
private final ProxySelector proxySelector;
|
||||||
|
|
||||||
|
private final String localRepository;
|
||||||
|
|
||||||
|
private final List<Profile> activeProfiles;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param settings
|
||||||
|
* @param decryptedSettings
|
||||||
|
*/
|
||||||
|
public MavenSettings(Settings settings, SettingsDecryptionResult decryptedSettings) {
|
||||||
|
this.offline = settings.isOffline();
|
||||||
|
this.mirrorSelector = createMirrorSelector(settings);
|
||||||
|
this.authenticationSelector = createAuthenticationSelector(decryptedSettings);
|
||||||
|
this.proxySelector = createProxySelector(decryptedSettings);
|
||||||
|
this.localRepository = settings.getLocalRepository();
|
||||||
|
this.activeProfiles = determineActiveProfiles(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
private MirrorSelector createMirrorSelector(Settings settings) {
|
||||||
|
DefaultMirrorSelector selector = new DefaultMirrorSelector();
|
||||||
|
for (Mirror mirror : settings.getMirrors()) {
|
||||||
|
selector.add(mirror.getId(), mirror.getUrl(), mirror.getLayout(), false,
|
||||||
|
mirror.getMirrorOf(), mirror.getMirrorOfLayouts());
|
||||||
|
}
|
||||||
|
return selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AuthenticationSelector createAuthenticationSelector(
|
||||||
|
SettingsDecryptionResult decryptedSettings) {
|
||||||
|
DefaultAuthenticationSelector selector = new DefaultAuthenticationSelector();
|
||||||
|
for (Server server : decryptedSettings.getServers()) {
|
||||||
|
AuthenticationBuilder auth = new AuthenticationBuilder();
|
||||||
|
auth.addUsername(server.getUsername()).addPassword(server.getPassword());
|
||||||
|
auth.addPrivateKey(server.getPrivateKey(), server.getPassphrase());
|
||||||
|
selector.add(server.getId(), auth.build());
|
||||||
|
}
|
||||||
|
return new ConservativeAuthenticationSelector(selector);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ProxySelector createProxySelector(SettingsDecryptionResult decryptedSettings) {
|
||||||
|
DefaultProxySelector selector = new DefaultProxySelector();
|
||||||
|
for (Proxy proxy : decryptedSettings.getProxies()) {
|
||||||
|
Authentication authentication = new AuthenticationBuilder()
|
||||||
|
.addUsername(proxy.getUsername()).addPassword(proxy.getPassword())
|
||||||
|
.build();
|
||||||
|
selector.add(new org.eclipse.aether.repository.Proxy(proxy.getProtocol(),
|
||||||
|
proxy.getHost(), proxy.getPort(), authentication), proxy
|
||||||
|
.getNonProxyHosts());
|
||||||
|
}
|
||||||
|
return selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Profile> determineActiveProfiles(Settings settings) {
|
||||||
|
SpringBootCliModelProblemCollector problemCollector = new SpringBootCliModelProblemCollector();
|
||||||
|
List<org.apache.maven.model.Profile> activeModelProfiles = createProfileSelector()
|
||||||
|
.getActiveProfiles(
|
||||||
|
createModelProfiles(settings.getProfiles()),
|
||||||
|
new SpringBootCliProfileActivationContext(settings
|
||||||
|
.getActiveProfiles()), problemCollector);
|
||||||
|
if (!problemCollector.getProblems().isEmpty()) {
|
||||||
|
throw new IllegalStateException(createFailureMessage(problemCollector));
|
||||||
|
}
|
||||||
|
List<Profile> activeProfiles = new ArrayList<Profile>();
|
||||||
|
Map<String, Profile> profiles = settings.getProfilesAsMap();
|
||||||
|
for (org.apache.maven.model.Profile modelProfile : activeModelProfiles) {
|
||||||
|
activeProfiles.add(profiles.get(modelProfile.getId()));
|
||||||
|
}
|
||||||
|
return activeProfiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String createFailureMessage(
|
||||||
|
SpringBootCliModelProblemCollector problemCollector) {
|
||||||
|
StringWriter message = new StringWriter();
|
||||||
|
PrintWriter printer = new PrintWriter(message);
|
||||||
|
printer.println("Failed to determine active profiles:");
|
||||||
|
for (ModelProblemCollectorRequest problem : problemCollector.getProblems()) {
|
||||||
|
printer.println(" " + problem.getMessage() + " at "
|
||||||
|
+ problem.getLocation());
|
||||||
|
}
|
||||||
|
return message.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private DefaultProfileSelector createProfileSelector() {
|
||||||
|
DefaultProfileSelector selector = new DefaultProfileSelector();
|
||||||
|
selector.addProfileActivator(new FileProfileActivator());
|
||||||
|
selector.addProfileActivator(new JdkVersionProfileActivator());
|
||||||
|
selector.addProfileActivator(new PropertyProfileActivator());
|
||||||
|
selector.addProfileActivator(new OperatingSystemProfileActivator());
|
||||||
|
return selector;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<org.apache.maven.model.Profile> createModelProfiles(
|
||||||
|
List<Profile> profiles) {
|
||||||
|
List<org.apache.maven.model.Profile> modelProfiles = new ArrayList<org.apache.maven.model.Profile>();
|
||||||
|
for (Profile profile : profiles) {
|
||||||
|
org.apache.maven.model.Profile modelProfile = new org.apache.maven.model.Profile();
|
||||||
|
modelProfile.setId(profile.getId());
|
||||||
|
modelProfile.setActivation(createModelActivation(profile.getActivation()));
|
||||||
|
modelProfiles.add(modelProfile);
|
||||||
|
}
|
||||||
|
return modelProfiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
private org.apache.maven.model.Activation createModelActivation(Activation activation) {
|
||||||
|
org.apache.maven.model.Activation modelActivation = new org.apache.maven.model.Activation();
|
||||||
|
modelActivation.setActiveByDefault(activation.isActiveByDefault());
|
||||||
|
if (activation.getFile() != null) {
|
||||||
|
ActivationFile activationFile = new ActivationFile();
|
||||||
|
activationFile.setExists(activation.getFile().getExists());
|
||||||
|
activationFile.setMissing(activation.getFile().getMissing());
|
||||||
|
modelActivation.setFile(activationFile);
|
||||||
|
}
|
||||||
|
modelActivation.setJdk(activation.getJdk());
|
||||||
|
if (activation.getOs() != null) {
|
||||||
|
ActivationOS os = new ActivationOS();
|
||||||
|
os.setArch(activation.getOs().getArch());
|
||||||
|
os.setFamily(activation.getOs().getFamily());
|
||||||
|
os.setName(activation.getOs().getName());
|
||||||
|
os.setVersion(activation.getOs().getVersion());
|
||||||
|
modelActivation.setOs(os);
|
||||||
|
}
|
||||||
|
if (activation.getProperty() != null) {
|
||||||
|
ActivationProperty property = new ActivationProperty();
|
||||||
|
property.setName(activation.getProperty().getName());
|
||||||
|
property.setValue(activation.getProperty().getValue());
|
||||||
|
modelActivation.setProperty(property);
|
||||||
|
}
|
||||||
|
return modelActivation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getOffline() {
|
||||||
|
return this.offline;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MirrorSelector getMirrorSelector() {
|
||||||
|
return this.mirrorSelector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AuthenticationSelector getAuthenticationSelector() {
|
||||||
|
return this.authenticationSelector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProxySelector getProxySelector() {
|
||||||
|
return this.proxySelector;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLocalRepository() {
|
||||||
|
return this.localRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Profile> getActiveProfiles() {
|
||||||
|
return this.activeProfiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class SpringBootCliProfileActivationContext implements
|
||||||
|
ProfileActivationContext {
|
||||||
|
|
||||||
|
private final List<String> activeProfiles;
|
||||||
|
|
||||||
|
SpringBootCliProfileActivationContext(List<String> activeProfiles) {
|
||||||
|
this.activeProfiles = activeProfiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getActiveProfileIds() {
|
||||||
|
return this.activeProfiles;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<String> getInactiveProfileIds() {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getSystemProperties() {
|
||||||
|
return (Map) System.getProperties();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getUserProperties() {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public File getProjectDirectory() {
|
||||||
|
return new File(".");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getProjectProperties() {
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final class SpringBootCliModelProblemCollector implements
|
||||||
|
ModelProblemCollector {
|
||||||
|
|
||||||
|
private final List<ModelProblemCollectorRequest> problems = new ArrayList<ModelProblemCollectorRequest>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void add(ModelProblemCollectorRequest req) {
|
||||||
|
this.problems.add(req);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<ModelProblemCollectorRequest> getProblems() {
|
||||||
|
return this.problems;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,120 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2015 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
|
||||||
|
*
|
||||||
|
* 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.springframework.boot.cli.compiler;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.lang.reflect.Field;
|
||||||
|
|
||||||
|
import org.apache.maven.settings.Settings;
|
||||||
|
import org.apache.maven.settings.building.DefaultSettingsBuilderFactory;
|
||||||
|
import org.apache.maven.settings.building.DefaultSettingsBuildingRequest;
|
||||||
|
import org.apache.maven.settings.building.SettingsBuildingException;
|
||||||
|
import org.apache.maven.settings.building.SettingsBuildingRequest;
|
||||||
|
import org.apache.maven.settings.crypto.DefaultSettingsDecrypter;
|
||||||
|
import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest;
|
||||||
|
import org.apache.maven.settings.crypto.SettingsDecrypter;
|
||||||
|
import org.apache.maven.settings.crypto.SettingsDecryptionResult;
|
||||||
|
import org.sonatype.plexus.components.cipher.DefaultPlexusCipher;
|
||||||
|
import org.sonatype.plexus.components.cipher.PlexusCipherException;
|
||||||
|
import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher;
|
||||||
|
import org.springframework.boot.cli.util.Log;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@code MavenSettingsReader} reads settings from a user's Maven settings.xml file,
|
||||||
|
* decrypting them if necessary using settings-security.xml.
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
* @since 1.3.0
|
||||||
|
*/
|
||||||
|
public class MavenSettingsReader {
|
||||||
|
|
||||||
|
private final String homeDir;
|
||||||
|
|
||||||
|
public MavenSettingsReader() {
|
||||||
|
this(System.getProperty("user.home"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public MavenSettingsReader(String homeDir) {
|
||||||
|
this.homeDir = homeDir;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MavenSettings readSettings() {
|
||||||
|
Settings settings = loadSettings();
|
||||||
|
SettingsDecryptionResult decrypted = decryptSettings(settings);
|
||||||
|
if (!decrypted.getProblems().isEmpty()) {
|
||||||
|
Log.error("Maven settings decryption failed. Some Maven repositories may be inaccessible");
|
||||||
|
// Continue - the encrypted credentials may not be used
|
||||||
|
}
|
||||||
|
return new MavenSettings(settings, decrypted);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Settings loadSettings() {
|
||||||
|
File settingsFile = new File(this.homeDir, ".m2/settings.xml");
|
||||||
|
SettingsBuildingRequest request = new DefaultSettingsBuildingRequest();
|
||||||
|
request.setUserSettingsFile(settingsFile);
|
||||||
|
request.setSystemProperties(System.getProperties());
|
||||||
|
try {
|
||||||
|
return new DefaultSettingsBuilderFactory().newInstance().build(request)
|
||||||
|
.getEffectiveSettings();
|
||||||
|
}
|
||||||
|
catch (SettingsBuildingException ex) {
|
||||||
|
throw new IllegalStateException("Failed to build settings from "
|
||||||
|
+ settingsFile, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private SettingsDecryptionResult decryptSettings(Settings settings) {
|
||||||
|
DefaultSettingsDecryptionRequest request = new DefaultSettingsDecryptionRequest(
|
||||||
|
settings);
|
||||||
|
|
||||||
|
return createSettingsDecrypter().decrypt(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private SettingsDecrypter createSettingsDecrypter() {
|
||||||
|
SettingsDecrypter settingsDecrypter = new DefaultSettingsDecrypter();
|
||||||
|
setField(DefaultSettingsDecrypter.class, "securityDispatcher", settingsDecrypter,
|
||||||
|
new SpringBootSecDispatcher());
|
||||||
|
return settingsDecrypter;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setField(Class<?> clazz, String fieldName, Object target, Object value) {
|
||||||
|
try {
|
||||||
|
Field field = clazz.getDeclaredField(fieldName);
|
||||||
|
field.setAccessible(true);
|
||||||
|
field.set(target, value);
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
throw new IllegalStateException("Failed to set field '" + fieldName
|
||||||
|
+ "' on '" + target + "'", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SpringBootSecDispatcher extends DefaultSecDispatcher {
|
||||||
|
|
||||||
|
public SpringBootSecDispatcher() {
|
||||||
|
this._configurationFile = new File(MavenSettingsReader.this.homeDir,
|
||||||
|
".m2/settings-security.xml").getAbsolutePath();
|
||||||
|
try {
|
||||||
|
this._cipher = new DefaultPlexusCipher();
|
||||||
|
}
|
||||||
|
catch (PlexusCipherException e) {
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -21,11 +21,8 @@ import java.net.URI;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.maven.settings.Settings;
|
import org.apache.maven.settings.Profile;
|
||||||
import org.apache.maven.settings.building.DefaultSettingsBuilderFactory;
|
import org.apache.maven.settings.Repository;
|
||||||
import org.apache.maven.settings.building.DefaultSettingsBuildingRequest;
|
|
||||||
import org.apache.maven.settings.building.SettingsBuildingException;
|
|
||||||
import org.apache.maven.settings.building.SettingsBuildingRequest;
|
|
||||||
import org.springframework.boot.cli.compiler.grape.RepositoryConfiguration;
|
import org.springframework.boot.cli.compiler.grape.RepositoryConfiguration;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
@ -46,60 +43,56 @@ public final class RepositoryConfigurationFactory {
|
||||||
private static final RepositoryConfiguration SPRING_SNAPSHOT = new RepositoryConfiguration(
|
private static final RepositoryConfiguration SPRING_SNAPSHOT = new RepositoryConfiguration(
|
||||||
"spring-snapshot", URI.create("http://repo.spring.io/snapshot"), true);
|
"spring-snapshot", URI.create("http://repo.spring.io/snapshot"), true);
|
||||||
|
|
||||||
|
private RepositoryConfigurationFactory() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the newly-created default repository configuration
|
* @return the newly-created default repository configuration
|
||||||
*/
|
*/
|
||||||
public static List<RepositoryConfiguration> createDefaultRepositoryConfiguration() {
|
public static List<RepositoryConfiguration> createDefaultRepositoryConfiguration() {
|
||||||
|
MavenSettings mavenSettings = new MavenSettingsReader().readSettings();
|
||||||
List<RepositoryConfiguration> repositoryConfiguration = new ArrayList<RepositoryConfiguration>();
|
List<RepositoryConfiguration> repositoryConfiguration = new ArrayList<RepositoryConfiguration>();
|
||||||
|
|
||||||
repositoryConfiguration.add(MAVEN_CENTRAL);
|
repositoryConfiguration.add(MAVEN_CENTRAL);
|
||||||
|
|
||||||
if (!Boolean.getBoolean("disableSpringSnapshotRepos")) {
|
if (!Boolean.getBoolean("disableSpringSnapshotRepos")) {
|
||||||
repositoryConfiguration.add(SPRING_MILESTONE);
|
repositoryConfiguration.add(SPRING_MILESTONE);
|
||||||
repositoryConfiguration.add(SPRING_SNAPSHOT);
|
repositoryConfiguration.add(SPRING_SNAPSHOT);
|
||||||
}
|
}
|
||||||
|
addDefaultCacheAsRepository(mavenSettings.getLocalRepository(),
|
||||||
addDefaultCacheAsRepository(repositoryConfiguration);
|
repositoryConfiguration);
|
||||||
|
addActiveProfileRepositories(mavenSettings.getActiveProfiles(),
|
||||||
|
repositoryConfiguration);
|
||||||
return repositoryConfiguration;
|
return repositoryConfiguration;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private static void addDefaultCacheAsRepository(String localRepository,
|
||||||
* Add the default local M2 cache directory as a remote repository. Only do this if
|
|
||||||
* the local cache location has been changed from the default.
|
|
||||||
* @param repositoryConfiguration
|
|
||||||
*/
|
|
||||||
public static void addDefaultCacheAsRepository(
|
|
||||||
List<RepositoryConfiguration> repositoryConfiguration) {
|
List<RepositoryConfiguration> repositoryConfiguration) {
|
||||||
RepositoryConfiguration repository = new RepositoryConfiguration("local",
|
RepositoryConfiguration repository = new RepositoryConfiguration("local",
|
||||||
getLocalRepositoryDirectory().toURI(), true);
|
getLocalRepositoryDirectory(localRepository).toURI(), true);
|
||||||
if (!repositoryConfiguration.contains(repository)) {
|
if (!repositoryConfiguration.contains(repository)) {
|
||||||
repositoryConfiguration.add(0, repository);
|
repositoryConfiguration.add(0, repository);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static File getLocalRepositoryDirectory() {
|
private static void addActiveProfileRepositories(List<Profile> activeProfiles,
|
||||||
String localRepository = loadSettings().getLocalRepository();
|
List<RepositoryConfiguration> repositoryConfiguration) {
|
||||||
|
for (Profile activeProfile : activeProfiles) {
|
||||||
|
for (Repository repository : activeProfile.getRepositories()) {
|
||||||
|
repositoryConfiguration.add(new RepositoryConfiguration(repository
|
||||||
|
.getId(), URI.create(repository.getUrl()), repository
|
||||||
|
.getSnapshots() != null ? repository.getSnapshots().isEnabled()
|
||||||
|
: false));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static File getLocalRepositoryDirectory(String localRepository) {
|
||||||
if (StringUtils.hasText(localRepository)) {
|
if (StringUtils.hasText(localRepository)) {
|
||||||
return new File(localRepository);
|
return new File(localRepository);
|
||||||
}
|
}
|
||||||
return new File(getM2HomeDirectory(), "repository");
|
return new File(getM2HomeDirectory(), "repository");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Settings loadSettings() {
|
|
||||||
File settingsFile = new File(System.getProperty("user.home"), ".m2/settings.xml");
|
|
||||||
SettingsBuildingRequest request = new DefaultSettingsBuildingRequest();
|
|
||||||
request.setUserSettingsFile(settingsFile);
|
|
||||||
request.setSystemProperties(System.getProperties());
|
|
||||||
try {
|
|
||||||
return new DefaultSettingsBuilderFactory().newInstance().build(request)
|
|
||||||
.getEffectiveSettings();
|
|
||||||
}
|
|
||||||
catch (SettingsBuildingException ex) {
|
|
||||||
throw new IllegalStateException("Failed to build settings from "
|
|
||||||
+ settingsFile, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static File getM2HomeDirectory() {
|
private static File getM2HomeDirectory() {
|
||||||
String mavenRoot = System.getProperty("maven.home");
|
String mavenRoot = System.getProperty("maven.home");
|
||||||
if (StringUtils.hasLength(mavenRoot)) {
|
if (StringUtils.hasLength(mavenRoot)) {
|
||||||
|
|
|
@ -16,38 +16,11 @@
|
||||||
|
|
||||||
package org.springframework.boot.cli.compiler.grape;
|
package org.springframework.boot.cli.compiler.grape;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.lang.reflect.Field;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.apache.maven.settings.Mirror;
|
|
||||||
import org.apache.maven.settings.Proxy;
|
|
||||||
import org.apache.maven.settings.Server;
|
|
||||||
import org.apache.maven.settings.Settings;
|
|
||||||
import org.apache.maven.settings.building.DefaultSettingsBuilderFactory;
|
|
||||||
import org.apache.maven.settings.building.DefaultSettingsBuildingRequest;
|
|
||||||
import org.apache.maven.settings.building.SettingsBuildingException;
|
|
||||||
import org.apache.maven.settings.building.SettingsBuildingRequest;
|
|
||||||
import org.apache.maven.settings.crypto.DefaultSettingsDecrypter;
|
|
||||||
import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest;
|
|
||||||
import org.apache.maven.settings.crypto.SettingsDecrypter;
|
|
||||||
import org.apache.maven.settings.crypto.SettingsDecryptionResult;
|
|
||||||
import org.eclipse.aether.DefaultRepositorySystemSession;
|
import org.eclipse.aether.DefaultRepositorySystemSession;
|
||||||
import org.eclipse.aether.RepositorySystem;
|
import org.eclipse.aether.RepositorySystem;
|
||||||
import org.eclipse.aether.repository.Authentication;
|
|
||||||
import org.eclipse.aether.repository.AuthenticationSelector;
|
|
||||||
import org.eclipse.aether.repository.LocalRepository;
|
import org.eclipse.aether.repository.LocalRepository;
|
||||||
import org.eclipse.aether.repository.MirrorSelector;
|
import org.springframework.boot.cli.compiler.MavenSettings;
|
||||||
import org.eclipse.aether.repository.ProxySelector;
|
import org.springframework.boot.cli.compiler.MavenSettingsReader;
|
||||||
import org.eclipse.aether.util.repository.AuthenticationBuilder;
|
|
||||||
import org.eclipse.aether.util.repository.ConservativeAuthenticationSelector;
|
|
||||||
import org.eclipse.aether.util.repository.DefaultAuthenticationSelector;
|
|
||||||
import org.eclipse.aether.util.repository.DefaultMirrorSelector;
|
|
||||||
import org.eclipse.aether.util.repository.DefaultProxySelector;
|
|
||||||
import org.sonatype.plexus.components.cipher.DefaultPlexusCipher;
|
|
||||||
import org.sonatype.plexus.components.cipher.PlexusCipherException;
|
|
||||||
import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher;
|
|
||||||
import org.springframework.boot.cli.util.Log;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Auto-configuration for a RepositorySystemSession that uses Maven's settings.xml to
|
* Auto-configuration for a RepositorySystemSession that uses Maven's settings.xml to
|
||||||
|
@ -58,32 +31,16 @@ import org.springframework.boot.cli.util.Log;
|
||||||
public class SettingsXmlRepositorySystemSessionAutoConfiguration implements
|
public class SettingsXmlRepositorySystemSessionAutoConfiguration implements
|
||||||
RepositorySystemSessionAutoConfiguration {
|
RepositorySystemSessionAutoConfiguration {
|
||||||
|
|
||||||
private final String homeDir;
|
|
||||||
|
|
||||||
public SettingsXmlRepositorySystemSessionAutoConfiguration() {
|
|
||||||
this(System.getProperty("user.home"));
|
|
||||||
}
|
|
||||||
|
|
||||||
SettingsXmlRepositorySystemSessionAutoConfiguration(String homeDir) {
|
|
||||||
this.homeDir = homeDir;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void apply(DefaultRepositorySystemSession session,
|
public void apply(DefaultRepositorySystemSession session,
|
||||||
RepositorySystem repositorySystem) {
|
RepositorySystem repositorySystem) {
|
||||||
|
|
||||||
Settings settings = loadSettings();
|
MavenSettings settings = new MavenSettingsReader().readSettings();
|
||||||
SettingsDecryptionResult decryptionResult = decryptSettings(settings);
|
|
||||||
if (!decryptionResult.getProblems().isEmpty()) {
|
|
||||||
Log.error("Maven settings decryption failed. Some Maven repositories may be inaccessible");
|
|
||||||
// Continue - the encrypted credentials may not be used
|
|
||||||
}
|
|
||||||
|
|
||||||
session.setOffline(settings.isOffline());
|
session.setOffline(settings.getOffline());
|
||||||
session.setMirrorSelector(createMirrorSelector(settings));
|
session.setMirrorSelector(settings.getMirrorSelector());
|
||||||
session.setAuthenticationSelector(createAuthenticationSelector(decryptionResult
|
session.setAuthenticationSelector(settings.getAuthenticationSelector());
|
||||||
.getServers()));
|
session.setProxySelector(settings.getProxySelector());
|
||||||
session.setProxySelector(createProxySelector(decryptionResult.getProxies()));
|
|
||||||
|
|
||||||
String localRepository = settings.getLocalRepository();
|
String localRepository = settings.getLocalRepository();
|
||||||
if (localRepository != null) {
|
if (localRepository != null) {
|
||||||
|
@ -92,92 +49,4 @@ public class SettingsXmlRepositorySystemSessionAutoConfiguration implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Settings loadSettings() {
|
|
||||||
File settingsFile = new File(this.homeDir, ".m2/settings.xml");
|
|
||||||
SettingsBuildingRequest request = new DefaultSettingsBuildingRequest();
|
|
||||||
request.setUserSettingsFile(settingsFile);
|
|
||||||
request.setSystemProperties(System.getProperties());
|
|
||||||
try {
|
|
||||||
return new DefaultSettingsBuilderFactory().newInstance().build(request)
|
|
||||||
.getEffectiveSettings();
|
|
||||||
}
|
|
||||||
catch (SettingsBuildingException ex) {
|
|
||||||
throw new IllegalStateException("Failed to build settings from "
|
|
||||||
+ settingsFile, ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private SettingsDecryptionResult decryptSettings(Settings settings) {
|
|
||||||
DefaultSettingsDecryptionRequest request = new DefaultSettingsDecryptionRequest(
|
|
||||||
settings);
|
|
||||||
|
|
||||||
return createSettingsDecrypter().decrypt(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
private SettingsDecrypter createSettingsDecrypter() {
|
|
||||||
SettingsDecrypter settingsDecrypter = new DefaultSettingsDecrypter();
|
|
||||||
setField(DefaultSettingsDecrypter.class, "securityDispatcher", settingsDecrypter,
|
|
||||||
new SpringBootSecDispatcher());
|
|
||||||
return settingsDecrypter;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setField(Class<?> clazz, String fieldName, Object target, Object value) {
|
|
||||||
try {
|
|
||||||
Field field = clazz.getDeclaredField(fieldName);
|
|
||||||
field.setAccessible(true);
|
|
||||||
field.set(target, value);
|
|
||||||
}
|
|
||||||
catch (Exception e) {
|
|
||||||
throw new IllegalStateException("Failed to set field '" + fieldName
|
|
||||||
+ "' on '" + target + "'", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private MirrorSelector createMirrorSelector(Settings settings) {
|
|
||||||
DefaultMirrorSelector selector = new DefaultMirrorSelector();
|
|
||||||
for (Mirror mirror : settings.getMirrors()) {
|
|
||||||
selector.add(mirror.getId(), mirror.getUrl(), mirror.getLayout(), false,
|
|
||||||
mirror.getMirrorOf(), mirror.getMirrorOfLayouts());
|
|
||||||
}
|
|
||||||
return selector;
|
|
||||||
}
|
|
||||||
|
|
||||||
private AuthenticationSelector createAuthenticationSelector(List<Server> servers) {
|
|
||||||
DefaultAuthenticationSelector selector = new DefaultAuthenticationSelector();
|
|
||||||
for (Server server : servers) {
|
|
||||||
AuthenticationBuilder auth = new AuthenticationBuilder();
|
|
||||||
auth.addUsername(server.getUsername()).addPassword(server.getPassword());
|
|
||||||
auth.addPrivateKey(server.getPrivateKey(), server.getPassphrase());
|
|
||||||
selector.add(server.getId(), auth.build());
|
|
||||||
}
|
|
||||||
return new ConservativeAuthenticationSelector(selector);
|
|
||||||
}
|
|
||||||
|
|
||||||
private ProxySelector createProxySelector(List<Proxy> proxies) {
|
|
||||||
DefaultProxySelector selector = new DefaultProxySelector();
|
|
||||||
for (Proxy proxy : proxies) {
|
|
||||||
Authentication authentication = new AuthenticationBuilder()
|
|
||||||
.addUsername(proxy.getUsername()).addPassword(proxy.getPassword())
|
|
||||||
.build();
|
|
||||||
selector.add(new org.eclipse.aether.repository.Proxy(proxy.getProtocol(),
|
|
||||||
proxy.getHost(), proxy.getPort(), authentication), proxy
|
|
||||||
.getNonProxyHosts());
|
|
||||||
}
|
|
||||||
return selector;
|
|
||||||
}
|
|
||||||
|
|
||||||
private class SpringBootSecDispatcher extends DefaultSecDispatcher {
|
|
||||||
|
|
||||||
public SpringBootSecDispatcher() {
|
|
||||||
this._configurationFile = new File(
|
|
||||||
SettingsXmlRepositorySystemSessionAutoConfiguration.this.homeDir,
|
|
||||||
".m2/settings-security.xml").getAbsolutePath();
|
|
||||||
try {
|
|
||||||
this._cipher = new DefaultPlexusCipher();
|
|
||||||
}
|
|
||||||
catch (PlexusCipherException e) {
|
|
||||||
throw new IllegalStateException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,106 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2015 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
|
||||||
|
*
|
||||||
|
* 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.springframework.boot.cli.compiler;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.boot.cli.compiler.grape.RepositoryConfiguration;
|
||||||
|
import org.springframework.boot.cli.util.SystemProperties;
|
||||||
|
|
||||||
|
import static org.hamcrest.Matchers.hasItems;
|
||||||
|
import static org.hamcrest.Matchers.hasSize;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests for {@link RepositoryConfigurationFactory}
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
public class RepositoryConfigurationFactoryTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void defaultRepositories() {
|
||||||
|
SystemProperties.doWithSystemProperties(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
List<RepositoryConfiguration> repositoryConfiguration = RepositoryConfigurationFactory
|
||||||
|
.createDefaultRepositoryConfiguration();
|
||||||
|
assertRepositoryConfiguration(repositoryConfiguration, "central",
|
||||||
|
"local", "spring-snapshot", "spring-milestone");
|
||||||
|
}
|
||||||
|
}, "user.home:src/test/resources/maven-settings/basic");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void snapshotRepositoriesDisabled() {
|
||||||
|
SystemProperties.doWithSystemProperties(
|
||||||
|
new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
List<RepositoryConfiguration> repositoryConfiguration = RepositoryConfigurationFactory
|
||||||
|
.createDefaultRepositoryConfiguration();
|
||||||
|
assertRepositoryConfiguration(repositoryConfiguration, "central",
|
||||||
|
"local");
|
||||||
|
}
|
||||||
|
}, "user.home:src/test/resources/maven-settings/basic",
|
||||||
|
"disableSpringSnapshotRepos:true");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void activeByDefaultProfileRepositories() {
|
||||||
|
SystemProperties.doWithSystemProperties(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
List<RepositoryConfiguration> repositoryConfiguration = RepositoryConfigurationFactory
|
||||||
|
.createDefaultRepositoryConfiguration();
|
||||||
|
assertRepositoryConfiguration(repositoryConfiguration, "central",
|
||||||
|
"local", "spring-snapshot", "spring-milestone",
|
||||||
|
"active-by-default");
|
||||||
|
}
|
||||||
|
}, "user.home:src/test/resources/maven-settings/active-profile-repositories");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void activeByPropertyProfileRepositories() {
|
||||||
|
SystemProperties.doWithSystemProperties(
|
||||||
|
new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
List<RepositoryConfiguration> repositoryConfiguration = RepositoryConfigurationFactory
|
||||||
|
.createDefaultRepositoryConfiguration();
|
||||||
|
assertRepositoryConfiguration(repositoryConfiguration, "central",
|
||||||
|
"local", "spring-snapshot", "spring-milestone",
|
||||||
|
"active-by-property");
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"user.home:src/test/resources/maven-settings/active-profile-repositories",
|
||||||
|
"foo:bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertRepositoryConfiguration(
|
||||||
|
List<RepositoryConfiguration> configurations, String... expectedNames) {
|
||||||
|
assertThat(configurations, hasSize(expectedNames.length));
|
||||||
|
Set<String> actualNames = new HashSet<String>();
|
||||||
|
for (RepositoryConfiguration configuration : configurations) {
|
||||||
|
actualNames.add(configuration.getName());
|
||||||
|
}
|
||||||
|
assertThat(actualNames, hasItems(expectedNames));
|
||||||
|
}
|
||||||
|
}
|
|
@ -37,6 +37,7 @@ import org.mockito.Mock;
|
||||||
import org.mockito.invocation.InvocationOnMock;
|
import org.mockito.invocation.InvocationOnMock;
|
||||||
import org.mockito.runners.MockitoJUnitRunner;
|
import org.mockito.runners.MockitoJUnitRunner;
|
||||||
import org.mockito.stubbing.Answer;
|
import org.mockito.stubbing.Answer;
|
||||||
|
import org.springframework.boot.cli.util.SystemProperties;
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.endsWith;
|
import static org.hamcrest.Matchers.endsWith;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
|
@ -89,25 +90,33 @@ public class SettingsXmlRepositorySystemSessionAutoConfigurationTests {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
System.setProperty("foo", "bar");
|
SystemProperties.doWithSystemProperties(
|
||||||
try {
|
new Runnable() {
|
||||||
new SettingsXmlRepositorySystemSessionAutoConfiguration(
|
@Override
|
||||||
"src/test/resources/maven-settings/property-interpolation").apply(
|
public void run() {
|
||||||
session, this.repositorySystem);
|
new SettingsXmlRepositorySystemSessionAutoConfiguration()
|
||||||
}
|
.apply(session,
|
||||||
finally {
|
SettingsXmlRepositorySystemSessionAutoConfigurationTests.this.repositorySystem);
|
||||||
System.clearProperty("foo");
|
|
||||||
}
|
}
|
||||||
|
}, "user.home:src/test/resources/maven-settings/property-interpolation",
|
||||||
|
"foo:bar");
|
||||||
|
|
||||||
assertThat(session.getLocalRepository().getBasedir().getAbsolutePath(),
|
assertThat(session.getLocalRepository().getBasedir().getAbsolutePath(),
|
||||||
endsWith(File.separatorChar + "bar" + File.separatorChar + "repository"));
|
endsWith(File.separatorChar + "bar" + File.separatorChar + "repository"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertSessionCustomization(String userHome) {
|
private void assertSessionCustomization(String userHome) {
|
||||||
DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();
|
final DefaultRepositorySystemSession session = MavenRepositorySystemUtils
|
||||||
|
.newSession();
|
||||||
|
|
||||||
new SettingsXmlRepositorySystemSessionAutoConfiguration(userHome).apply(session,
|
SystemProperties.doWithSystemProperties(new Runnable() {
|
||||||
this.repositorySystem);
|
@Override
|
||||||
|
public void run() {
|
||||||
|
new SettingsXmlRepositorySystemSessionAutoConfiguration()
|
||||||
|
.apply(session,
|
||||||
|
SettingsXmlRepositorySystemSessionAutoConfigurationTests.this.repositorySystem);
|
||||||
|
}
|
||||||
|
}, "user.home:" + userHome);
|
||||||
|
|
||||||
RemoteRepository repository = new RemoteRepository.Builder("my-server",
|
RemoteRepository repository = new RemoteRepository.Builder("my-server",
|
||||||
"default", "http://maven.example.com").build();
|
"default", "http://maven.example.com").build();
|
||||||
|
@ -151,4 +160,5 @@ public class SettingsXmlRepositorySystemSessionAutoConfigurationTests {
|
||||||
assertEquals("tester", authenticationContext.get(AuthenticationContext.USERNAME));
|
assertEquals("tester", authenticationContext.get(AuthenticationContext.USERNAME));
|
||||||
assertEquals("secret", authenticationContext.get(AuthenticationContext.PASSWORD));
|
assertEquals("secret", authenticationContext.get(AuthenticationContext.PASSWORD));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2012-2015 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
|
||||||
|
*
|
||||||
|
* 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.springframework.boot.cli.util;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utilities for working with System properties in unit tests
|
||||||
|
*
|
||||||
|
* @author Andy Wilkinson
|
||||||
|
*/
|
||||||
|
public class SystemProperties {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the given {@code action} with the given system properties set. System
|
||||||
|
* properties are restored to their previous values once the action has run.
|
||||||
|
*
|
||||||
|
* @param action The action to perform
|
||||||
|
* @param systemPropertyPairs The system properties, each in the form
|
||||||
|
* {@code key:value}
|
||||||
|
*/
|
||||||
|
public static void doWithSystemProperties(Runnable action,
|
||||||
|
String... systemPropertyPairs) {
|
||||||
|
Map<String, String> originalValues = new HashMap<String, String>();
|
||||||
|
for (String pair : systemPropertyPairs) {
|
||||||
|
String[] components = pair.split(":");
|
||||||
|
String key = components[0];
|
||||||
|
String value = components[1];
|
||||||
|
originalValues.put(key, System.setProperty(key, value));
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
action.run();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
for (Entry<String, String> entry : originalValues.entrySet()) {
|
||||||
|
if (entry.getValue() == null) {
|
||||||
|
System.clearProperty(entry.getKey());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
System.setProperty(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -490,6 +490,24 @@ the top level, or you can put the beans DSL in a separate file if you prefer.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[[cli-maven-settings]]
|
||||||
|
== Configuring the CLI with settings.xml
|
||||||
|
The Spring Boot CLI uses Aether, Maven's dependency resolution engine, to resolve
|
||||||
|
dependencies. The CLI makes use of the Maven configuration found in `~/.m2/settings.xml`
|
||||||
|
to configure Aether. The following configuration settings are honored by the CLI:
|
||||||
|
|
||||||
|
* Offline
|
||||||
|
* Mirrors
|
||||||
|
* Servers
|
||||||
|
* Proxies
|
||||||
|
* Profiles
|
||||||
|
** Activation
|
||||||
|
** Repositories
|
||||||
|
* Active profiles
|
||||||
|
|
||||||
|
Please refer to https://maven.apache.org/settings.html[Maven's settings documentation] for
|
||||||
|
further information.
|
||||||
|
|
||||||
[[cli-whats-next]]
|
[[cli-whats-next]]
|
||||||
== What to read next
|
== What to read next
|
||||||
There are some {github-code}/spring-boot-cli/samples[sample groovy
|
There are some {github-code}/spring-boot-cli/samples[sample groovy
|
||||||
|
|
Loading…
Reference in New Issue