Add support for configuring Aether via settings.xml
Previously, Aether's configuration was largely hard-coded making it impossible to configure a mirror, provide credentials for accessing a repository, etc. This commit adds support for configuring Aether via Maven's settings.xml file. The support is optional and must be enabled by grabbing spring-boot-maven-settings in an init script. The Aether instance that's used when running the application will then be configured using settings.xml. The settings file is expected to be found in ${user.home}/.m2/settings.xml. The configuration of the following items is currently supported: - Offline - Proxies - Mirrors - Server authentication - Local repository location If the support is not enabled, settings.xml does not exist, or settings.xml does not configure certain things then sensible defaults are applied.pull/208/head
parent
2e81b1d0d0
commit
a58e4cbb1f
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright 2012-2013 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.grape;
|
||||
|
||||
import groovy.lang.GroovyClassLoader;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
|
||||
import org.eclipse.aether.DefaultRepositorySystemSession;
|
||||
import org.eclipse.aether.RepositorySystem;
|
||||
import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory;
|
||||
import org.eclipse.aether.impl.DefaultServiceLocator;
|
||||
import org.eclipse.aether.internal.impl.DefaultRepositorySystem;
|
||||
import org.eclipse.aether.repository.RemoteRepository;
|
||||
import org.eclipse.aether.repository.RepositoryPolicy;
|
||||
import org.eclipse.aether.spi.connector.RepositoryConnectorFactory;
|
||||
import org.eclipse.aether.spi.connector.transport.TransporterFactory;
|
||||
import org.eclipse.aether.spi.locator.ServiceLocator;
|
||||
import org.eclipse.aether.transport.file.FileTransporterFactory;
|
||||
import org.eclipse.aether.transport.http.HttpTransporterFactory;
|
||||
|
||||
/**
|
||||
* Utility class to create a pre-configured {@link AetherGrapeEngine}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public abstract class AetherGrapeEngineFactory {
|
||||
|
||||
public static AetherGrapeEngine create(GroovyClassLoader classLoader,
|
||||
List<RepositoryConfiguration> repositoryConfigurations) {
|
||||
|
||||
RepositorySystem repositorySystem = createServiceLocator().getService(
|
||||
RepositorySystem.class);
|
||||
|
||||
DefaultRepositorySystemSession repositorySystemSession = MavenRepositorySystemUtils
|
||||
.newSession();
|
||||
|
||||
ServiceLoader<RepositorySystemSessionAutoConfiguration> autoConfigurations = ServiceLoader
|
||||
.load(RepositorySystemSessionAutoConfiguration.class);
|
||||
|
||||
for (RepositorySystemSessionAutoConfiguration autoConfiguration : autoConfigurations) {
|
||||
autoConfiguration.apply(repositorySystemSession, repositorySystem);
|
||||
}
|
||||
|
||||
new DefaultRepositorySystemSessionAutoConfiguration().apply(
|
||||
repositorySystemSession, repositorySystem);
|
||||
|
||||
return new AetherGrapeEngine(classLoader, repositorySystem,
|
||||
repositorySystemSession, createRepositories(repositoryConfigurations));
|
||||
}
|
||||
|
||||
private static ServiceLocator createServiceLocator() {
|
||||
DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator();
|
||||
locator.addService(RepositorySystem.class, DefaultRepositorySystem.class);
|
||||
locator.addService(RepositoryConnectorFactory.class,
|
||||
BasicRepositoryConnectorFactory.class);
|
||||
locator.addService(TransporterFactory.class, HttpTransporterFactory.class);
|
||||
locator.addService(TransporterFactory.class, FileTransporterFactory.class);
|
||||
return locator;
|
||||
}
|
||||
|
||||
private static List<RemoteRepository> createRepositories(
|
||||
List<RepositoryConfiguration> repositoryConfigurations) {
|
||||
List<RemoteRepository> repositories = new ArrayList<RemoteRepository>(
|
||||
repositoryConfigurations.size());
|
||||
for (RepositoryConfiguration repositoryConfiguration : repositoryConfigurations) {
|
||||
RemoteRepository.Builder builder = new RemoteRepository.Builder(
|
||||
repositoryConfiguration.getName(), "default", repositoryConfiguration
|
||||
.getUri().toASCIIString());
|
||||
|
||||
if (!repositoryConfiguration.getSnapshotsEnabled()) {
|
||||
builder.setSnapshotPolicy(new RepositoryPolicy(false,
|
||||
RepositoryPolicy.UPDATE_POLICY_NEVER,
|
||||
RepositoryPolicy.CHECKSUM_POLICY_IGNORE));
|
||||
}
|
||||
repositories.add(builder.build());
|
||||
}
|
||||
return repositories;
|
||||
}
|
||||
}
|
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 2012-2013 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.grape;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.eclipse.aether.DefaultRepositorySystemSession;
|
||||
import org.eclipse.aether.RepositorySystem;
|
||||
import org.eclipse.aether.repository.LocalRepository;
|
||||
import org.eclipse.aether.repository.LocalRepositoryManager;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A {@link RepositorySystemSessionAutoConfiguration} that, in the absence of any
|
||||
* configuration, applies sensible defaults.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class DefaultRepositorySystemSessionAutoConfiguration implements
|
||||
RepositorySystemSessionAutoConfiguration {
|
||||
|
||||
@Override
|
||||
public void apply(DefaultRepositorySystemSession session,
|
||||
RepositorySystem repositorySystem) {
|
||||
|
||||
if (session.getLocalRepositoryManager() == null) {
|
||||
LocalRepository localRepository = new LocalRepository(getM2RepoDirectory());
|
||||
LocalRepositoryManager localRepositoryManager = repositorySystem
|
||||
.newLocalRepositoryManager(session, localRepository);
|
||||
session.setLocalRepositoryManager(localRepositoryManager);
|
||||
}
|
||||
|
||||
if (session.getProxySelector() == null) {
|
||||
session.setProxySelector(new JreProxySelector());
|
||||
}
|
||||
}
|
||||
|
||||
private File getM2RepoDirectory() {
|
||||
return new File(getM2HomeDirectory(), "repository");
|
||||
}
|
||||
|
||||
private File getM2HomeDirectory() {
|
||||
String grapeRoot = System.getProperty("grape.root");
|
||||
if (StringUtils.hasLength(grapeRoot)) {
|
||||
return new File(grapeRoot);
|
||||
}
|
||||
return getDefaultM2HomeDirectory();
|
||||
}
|
||||
|
||||
private File getDefaultM2HomeDirectory() {
|
||||
String mavenRoot = System.getProperty("maven.home");
|
||||
if (StringUtils.hasLength(mavenRoot)) {
|
||||
return new File(mavenRoot);
|
||||
}
|
||||
return new File(System.getProperty("user.home"), ".m2");
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2012-2013 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.grape;
|
||||
|
||||
import org.eclipse.aether.DefaultRepositorySystemSession;
|
||||
import org.eclipse.aether.RepositorySystem;
|
||||
|
||||
/**
|
||||
* Strategy that can be used to apply some auto-configuration during the installation of
|
||||
* an {@link AetherGrapeEngine}.
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public interface RepositorySystemSessionAutoConfiguration {
|
||||
|
||||
/**
|
||||
* Apply the configuration
|
||||
*/
|
||||
void apply(DefaultRepositorySystemSession session, RepositorySystem repositorySystem);
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-parent</artifactId>
|
||||
<version>0.5.0.BUILD-SNAPSHOT</version>
|
||||
<relativePath>../spring-boot-parent</relativePath>
|
||||
</parent>
|
||||
<artifactId>spring-boot-maven-settings</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<dependencies>
|
||||
<!-- Compile -->
|
||||
<dependency>
|
||||
<groupId>org.apache.maven</groupId>
|
||||
<artifactId>maven-settings-builder</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.aether</groupId>
|
||||
<artifactId>aether-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.aether</groupId>
|
||||
<artifactId>aether-util</artifactId>
|
||||
</dependency>
|
||||
<!-- Provided -->
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>spring-boot-cli</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -0,0 +1,113 @@
|
||||
package org.springframework.boot.maven.settings;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
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.building.SettingsBuildingResult;
|
||||
import org.eclipse.aether.DefaultRepositorySystemSession;
|
||||
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.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;
|
||||
import org.springframework.boot.cli.compiler.grape.RepositorySystemSessionAutoConfiguration;
|
||||
|
||||
/**
|
||||
* Auto-configuration for a RepositorySystemSession that uses Maven's settings.xml to
|
||||
* determine the configuration settings
|
||||
*
|
||||
* @author Andy Wilkinson
|
||||
*/
|
||||
public class SettingsXmlRepositorySystemSessionAutoConfiguration implements
|
||||
RepositorySystemSessionAutoConfiguration {
|
||||
|
||||
@Override
|
||||
public void apply(DefaultRepositorySystemSession session,
|
||||
RepositorySystem repositorySystem) {
|
||||
Settings settings = loadSettings();
|
||||
|
||||
session.setOffline(settings.isOffline());
|
||||
session.setMirrorSelector(createMirrorSelector(settings));
|
||||
session.setAuthenticationSelector(createAuthenticationSelector(settings));
|
||||
session.setProxySelector(createProxySelector(settings));
|
||||
|
||||
String localRepository = settings.getLocalRepository();
|
||||
|
||||
if (localRepository != null) {
|
||||
session.setLocalRepositoryManager(repositorySystem.newLocalRepositoryManager(
|
||||
session, new LocalRepository(localRepository)));
|
||||
}
|
||||
}
|
||||
|
||||
private Settings loadSettings() {
|
||||
SettingsBuildingRequest request = new DefaultSettingsBuildingRequest();
|
||||
|
||||
File userSettingsFile = new File(System.getProperty("user.home"),
|
||||
".m2/settings.xml");
|
||||
|
||||
request.setUserSettingsFile(userSettingsFile);
|
||||
|
||||
SettingsBuildingResult result;
|
||||
try {
|
||||
result = new DefaultSettingsBuilderFactory().newInstance().build(request);
|
||||
}
|
||||
catch (SettingsBuildingException e) {
|
||||
throw new IllegalStateException("Failed to build settings from "
|
||||
+ userSettingsFile, e);
|
||||
}
|
||||
|
||||
return result.getEffectiveSettings();
|
||||
}
|
||||
|
||||
private MirrorSelector createMirrorSelector(Settings settings) {
|
||||
DefaultMirrorSelector mirrorSelector = new DefaultMirrorSelector();
|
||||
for (Mirror mirror : settings.getMirrors()) {
|
||||
mirrorSelector.add(mirror.getId(), mirror.getUrl(), mirror.getLayout(),
|
||||
false, mirror.getMirrorOf(), mirror.getMirrorOfLayouts());
|
||||
}
|
||||
return mirrorSelector;
|
||||
}
|
||||
|
||||
private AuthenticationSelector createAuthenticationSelector(Settings settings) {
|
||||
DefaultAuthenticationSelector authenticationSelector = new DefaultAuthenticationSelector();
|
||||
|
||||
for (Server server : settings.getServers()) {
|
||||
AuthenticationBuilder auth = new AuthenticationBuilder();
|
||||
auth.addUsername(server.getUsername()).addPassword(server.getPassword());
|
||||
auth.addPrivateKey(server.getPrivateKey(), server.getPassphrase());
|
||||
authenticationSelector.add(server.getId(), auth.build());
|
||||
}
|
||||
|
||||
return new ConservativeAuthenticationSelector(authenticationSelector);
|
||||
}
|
||||
|
||||
private ProxySelector createProxySelector(Settings settings) {
|
||||
DefaultProxySelector proxySelector = new DefaultProxySelector();
|
||||
|
||||
for (Proxy proxy : settings.getProxies()) {
|
||||
Authentication authentication = new AuthenticationBuilder()
|
||||
.addUsername(proxy.getUsername()).addPassword(proxy.getPassword())
|
||||
.build();
|
||||
|
||||
proxySelector.add(
|
||||
new org.eclipse.aether.repository.Proxy(proxy.getProtocol(), proxy
|
||||
.getHost(), proxy.getPort(), authentication), proxy
|
||||
.getNonProxyHosts());
|
||||
}
|
||||
|
||||
return proxySelector;
|
||||
}
|
||||
}
|
@ -0,0 +1 @@
|
||||
org.springframework.boot.maven.settings.SettingsXmlRepositorySystemSessionAutoConfiguration
|
@ -0,0 +1,39 @@
|
||||
package org.springframework.boot.maven.settings;
|
||||
|
||||
import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
|
||||
import org.apache.maven.settings.building.SettingsBuildingException;
|
||||
import org.eclipse.aether.DefaultRepositorySystemSession;
|
||||
import org.eclipse.aether.RepositorySystem;
|
||||
import org.eclipse.aether.repository.LocalRepositoryManager;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class SettingsXmlRepositorySystemSessionAutoConfigurationTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
|
||||
@Mock
|
||||
private RepositorySystem repositorySystem;
|
||||
|
||||
@Mock
|
||||
LocalRepositoryManager localRepositoryManager;
|
||||
|
||||
@Test
|
||||
public void basicSessionCustomization() throws SettingsBuildingException {
|
||||
DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();
|
||||
|
||||
new SettingsXmlRepositorySystemSessionAutoConfiguration().apply(session,
|
||||
this.repositorySystem);
|
||||
|
||||
assertNotNull(session.getMirrorSelector());
|
||||
assertNotNull(session.getProxySelector());
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue