Browse Source
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
13 changed files with 437 additions and 84 deletions
@ -0,0 +1,97 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -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 @@
@@ -0,0 +1 @@
|
||||
org.springframework.boot.maven.settings.SettingsXmlRepositorySystemSessionAutoConfiguration |
||||
@ -0,0 +1,39 @@
@@ -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