Support proxy settings for Aether Module resolver
- Add `AetherProxyProperties` as a ConfigurationProperties for the proxy settings needed for the ProxySelector in Aether system - Update proxy settings in two places: 1) Where the remote repositories are setup 2) WHere the repository system session is created to resolve the artifacts This resolves #272 Set authentication only for proxy settings Set port type to `int`
This commit is contained in:
committed by
Marius Bogoevici
parent
9c3eef49da
commit
b98d91da39
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2016 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.
|
||||
@@ -34,7 +34,11 @@ import org.eclipse.aether.collection.CollectRequest;
|
||||
import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory;
|
||||
import org.eclipse.aether.graph.Dependency;
|
||||
import org.eclipse.aether.impl.DefaultServiceLocator;
|
||||
import org.eclipse.aether.repository.Authentication;
|
||||
import org.eclipse.aether.repository.AuthenticationContext;
|
||||
import org.eclipse.aether.repository.AuthenticationDigest;
|
||||
import org.eclipse.aether.repository.LocalRepository;
|
||||
import org.eclipse.aether.repository.Proxy;
|
||||
import org.eclipse.aether.repository.RemoteRepository;
|
||||
import org.eclipse.aether.resolution.ArtifactRequest;
|
||||
import org.eclipse.aether.resolution.ArtifactResolutionException;
|
||||
@@ -47,6 +51,7 @@ import org.eclipse.aether.spi.connector.transport.TransporterFactory;
|
||||
import org.eclipse.aether.transport.file.FileTransporterFactory;
|
||||
import org.eclipse.aether.transport.http.HttpTransporterFactory;
|
||||
import org.eclipse.aether.util.artifact.JavaScopes;
|
||||
import org.eclipse.aether.util.repository.DefaultProxySelector;
|
||||
|
||||
import org.springframework.core.io.FileSystemResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
@@ -63,6 +68,7 @@ import org.springframework.util.StringUtils;
|
||||
* @author David Turanski
|
||||
* @author Mark Fisher
|
||||
* @author Marius Bogoevici
|
||||
* @author Ilayaperumal Gopinathan
|
||||
*/
|
||||
public class AetherModuleResolver implements ModuleResolver {
|
||||
|
||||
@@ -78,13 +84,19 @@ public class AetherModuleResolver implements ModuleResolver {
|
||||
|
||||
private volatile boolean offline = false;
|
||||
|
||||
private final AetherProxyProperties proxyProperties;
|
||||
|
||||
private Authentication authentication;
|
||||
|
||||
/**
|
||||
* Create an instance specifying the locations of the local and remote repositories.
|
||||
* @param localRepository the root path of the local maven repository
|
||||
* @param remoteRepositories a Map containing pairs of (repository ID,repository URL). This
|
||||
* may be null or empty if the local repository is off line.
|
||||
* @param proxyProperties the proxy properties for the maven proxy settings.
|
||||
*/
|
||||
public AetherModuleResolver(File localRepository, Map<String, String> remoteRepositories) {
|
||||
public AetherModuleResolver(File localRepository, Map<String, String> remoteRepositories,
|
||||
final AetherProxyProperties proxyProperties) {
|
||||
Assert.notNull(localRepository, "Local repository path cannot be null");
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Local repository: " + localRepository);
|
||||
@@ -93,6 +105,22 @@ public class AetherModuleResolver implements ModuleResolver {
|
||||
log.debug("Remote repositories: " + StringUtils.collectionToCommaDelimitedString(remoteRepositories.values()));
|
||||
}
|
||||
}
|
||||
this.proxyProperties = proxyProperties;
|
||||
if (isProxyEnabled() && proxyHasCredentials()) {
|
||||
this.authentication = new Authentication() {
|
||||
@Override
|
||||
public void fill(AuthenticationContext context, String key, Map<String, String> data) {
|
||||
context.put(context.USERNAME, proxyProperties.getAuth().getUsername());
|
||||
context.put(context.PASSWORD, proxyProperties.getAuth().getPassword());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void digest(AuthenticationDigest digest) {
|
||||
digest.update(AuthenticationContext.USERNAME, proxyProperties.getAuth().getUsername(),
|
||||
AuthenticationContext.PASSWORD, proxyProperties.getAuth().getPassword());
|
||||
}
|
||||
};
|
||||
}
|
||||
if (!localRepository.exists()) {
|
||||
Assert.isTrue(localRepository.mkdirs(),
|
||||
"Unable to create directory for local repository: " + localRepository);
|
||||
@@ -101,14 +129,38 @@ public class AetherModuleResolver implements ModuleResolver {
|
||||
this.remoteRepositories = new LinkedList<>();
|
||||
if (!CollectionUtils.isEmpty(remoteRepositories)) {
|
||||
for (Map.Entry<String, String> remoteRepo : remoteRepositories.entrySet()) {
|
||||
RemoteRepository remoteRepository = new RemoteRepository.Builder(remoteRepo.getKey(),
|
||||
DEFAULT_CONTENT_TYPE, remoteRepo.getValue()).build();
|
||||
this.remoteRepositories.add(remoteRepository);
|
||||
RemoteRepository.Builder remoteRepositoryBuilder = new RemoteRepository.Builder(remoteRepo.getKey(),
|
||||
DEFAULT_CONTENT_TYPE, remoteRepo.getValue());
|
||||
if (this.authentication != null) {
|
||||
//todo: Set direct authentication for the remote repositories
|
||||
remoteRepositoryBuilder.setProxy(new Proxy(proxyProperties.getProtocol(), proxyProperties.getHost(),
|
||||
proxyProperties.getPort(), authentication));
|
||||
}
|
||||
this.remoteRepositories.add(remoteRepositoryBuilder.build());
|
||||
}
|
||||
}
|
||||
repositorySystem = newRepositorySystem();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the proxy settings are provided.
|
||||
*
|
||||
* @return boolean true if the proxy settings are provided.
|
||||
*/
|
||||
private boolean isProxyEnabled() {
|
||||
return (this.proxyProperties != null && this.proxyProperties.getHost() != null && proxyProperties.getPort() > 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the proxy setting has username/password set.
|
||||
*
|
||||
* @return boolean true if both the username/password are set
|
||||
*/
|
||||
private boolean proxyHasCredentials() {
|
||||
return (this.proxyProperties != null && this.proxyProperties.getAuth() != null &&
|
||||
this.proxyProperties.getAuth().getUsername() != null && this.proxyProperties.getAuth().getPassword() != null);
|
||||
}
|
||||
|
||||
public void setOffline(boolean offline) {
|
||||
this.offline = offline;
|
||||
}
|
||||
@@ -133,6 +185,13 @@ public class AetherModuleResolver implements ModuleResolver {
|
||||
LocalRepository localRepo = new LocalRepository(localRepoPath);
|
||||
session.setLocalRepositoryManager(system.newLocalRepositoryManager(session, localRepo));
|
||||
session.setOffline(this.offline);
|
||||
if (isProxyEnabled()) {
|
||||
DefaultProxySelector proxySelector = new DefaultProxySelector();
|
||||
Proxy proxy = new Proxy(proxyProperties.getProtocol(), proxyProperties.getHost(), proxyProperties.getPort(),
|
||||
authentication);
|
||||
proxySelector.add(proxy, proxyProperties.getNonProxyHosts());
|
||||
session.setProxySelector(proxySelector);
|
||||
}
|
||||
return session;
|
||||
}
|
||||
|
||||
@@ -214,7 +273,8 @@ public class AetherModuleResolver implements ModuleResolver {
|
||||
result.add(toResource(artifactResult));
|
||||
}
|
||||
}
|
||||
} catch (DependencyResolutionException e) {
|
||||
}
|
||||
catch (DependencyResolutionException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 2016 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.cloud.stream.module.resolver;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
|
||||
/**
|
||||
* Proxy properties for the Aether Module Resolver.
|
||||
*
|
||||
* @author Ilayaperumal Gopinathan
|
||||
*/
|
||||
@ConfigurationProperties(prefix = "aether.proxy")
|
||||
public class AetherProxyProperties {
|
||||
/**
|
||||
* Protocol to use for proxy settings.
|
||||
*/
|
||||
private String protocol = "http";
|
||||
|
||||
/**
|
||||
* Host for the proxy.
|
||||
*/
|
||||
private String host;
|
||||
|
||||
/**
|
||||
* Port for the proxy.
|
||||
*/
|
||||
private int port;
|
||||
|
||||
/**
|
||||
* List of non proxy hosts.
|
||||
*/
|
||||
private String nonProxyHosts;
|
||||
|
||||
private Authentication auth;
|
||||
|
||||
public String getProtocol() {
|
||||
return this.protocol;
|
||||
}
|
||||
|
||||
public void setProtocol(String protocol) {
|
||||
this.protocol = protocol;
|
||||
}
|
||||
|
||||
public String getHost() {
|
||||
return this.host;
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return this.port;
|
||||
}
|
||||
|
||||
public void setPort(int port) {
|
||||
this.port = port;
|
||||
}
|
||||
|
||||
public String getNonProxyHosts() {
|
||||
return this.nonProxyHosts;
|
||||
}
|
||||
|
||||
public void setNonProxyHosts(String nonProxyHosts) {
|
||||
this.nonProxyHosts = nonProxyHosts;
|
||||
}
|
||||
|
||||
public Authentication getAuth() {
|
||||
return this.auth;
|
||||
}
|
||||
|
||||
public void setAuth(Authentication auth) {
|
||||
this.auth = auth;
|
||||
}
|
||||
|
||||
public static class Authentication {
|
||||
|
||||
/**
|
||||
* Username for the proxy.
|
||||
*/
|
||||
private String username;
|
||||
|
||||
/**
|
||||
* Password for the proxy.
|
||||
*/
|
||||
private String password;
|
||||
|
||||
public String getUsername() {
|
||||
return this.username;
|
||||
}
|
||||
|
||||
public void setUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
|
||||
public String getPassword() {
|
||||
return this.password;
|
||||
}
|
||||
|
||||
public void setPassword(String password) {
|
||||
this.password = password;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-2016 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.
|
||||
@@ -28,22 +28,27 @@ import org.springframework.context.annotation.Bean;
|
||||
* Sets up the default Aether-based module resolver, unless overridden.
|
||||
*
|
||||
* @author Eric Bottard
|
||||
* @author Ilayaperumal Gopinathan
|
||||
*/
|
||||
@EnableConfigurationProperties(ModuleResolverProperties.class)
|
||||
@EnableConfigurationProperties({ModuleResolverProperties.class, AetherProxyProperties.class})
|
||||
public class ModuleResolverConfiguration {
|
||||
|
||||
@Autowired
|
||||
private ModuleResolverProperties properties;
|
||||
|
||||
@Autowired
|
||||
private AetherProxyProperties proxyProperties;
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean(ModuleResolver.class)
|
||||
public ModuleResolver moduleResolver() {
|
||||
int i = 1;
|
||||
Map<String, String> repositoriesMap = new HashMap<>();
|
||||
for (String repository: properties.getRemoteRepositories()) {
|
||||
for (String repository : properties.getRemoteRepositories()) {
|
||||
repositoriesMap.put("repository " + i++, repository);
|
||||
}
|
||||
AetherModuleResolver aetherModuleResolver = new AetherModuleResolver(properties.getLocalRepository(), repositoriesMap);
|
||||
AetherModuleResolver aetherModuleResolver = new AetherModuleResolver(properties.getLocalRepository(),
|
||||
repositoriesMap, proxyProperties);
|
||||
aetherModuleResolver.setOffline(properties.isOffline());
|
||||
return aetherModuleResolver;
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ public class ModuleResolverProperties {
|
||||
public String[] getRemoteRepositories() {
|
||||
return remoteRepositories;
|
||||
}
|
||||
|
||||
public void setLocalRepository(File localRepository) {
|
||||
this.localRepository = localRepository;
|
||||
}
|
||||
|
||||
@@ -20,14 +20,10 @@ import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.get;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
|
||||
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
|
||||
import static org.hamcrest.Matchers.arrayContaining;
|
||||
import static org.hamcrest.Matchers.arrayContainingInAnyOrder;
|
||||
import static org.hamcrest.Matchers.arrayWithSize;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.instanceOf;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.beans.HasPropertyWithValue.hasProperty;
|
||||
import static org.hamcrest.object.HasToString.hasToString;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
@@ -65,7 +61,7 @@ public class AetherModuleResolverTests {
|
||||
public void testResolveLocal() throws IOException {
|
||||
ClassPathResource cpr = new ClassPathResource("local-repo");
|
||||
File localRepository = cpr.getFile();
|
||||
AetherModuleResolver defaultModuleResolver = new AetherModuleResolver(localRepository, null);
|
||||
AetherModuleResolver defaultModuleResolver = new AetherModuleResolver(localRepository, null, null);
|
||||
Resource resource = defaultModuleResolver.resolve(new Coordinates("foo.bar", "foo-bar", "jar", "", "1.0.0"));
|
||||
assertTrue(resource.exists());
|
||||
assertEquals(resource.getFile().getName(), "foo-bar-1.0.0.jar");
|
||||
@@ -75,7 +71,7 @@ public class AetherModuleResolverTests {
|
||||
public void testResolveLocalWithIncludes() throws IOException {
|
||||
ClassPathResource cpr = new ClassPathResource("local-repo");
|
||||
File localRepository = cpr.getFile();
|
||||
AetherModuleResolver defaultModuleResolver = new AetherModuleResolver(localRepository, null);
|
||||
AetherModuleResolver defaultModuleResolver = new AetherModuleResolver(localRepository, null, null);
|
||||
Resource[] resources = defaultModuleResolver.resolve(
|
||||
new Coordinates("foo.bar", "foo-bar", "jar", "", "1.0.0"),
|
||||
new Coordinates[]{new Coordinates("qux.bar", "qux-bar", "jar", "", "1.0.0")},new String[]{});
|
||||
@@ -92,7 +88,7 @@ public class AetherModuleResolverTests {
|
||||
public void testResolveDoesNotExist() throws IOException {
|
||||
ClassPathResource cpr = new ClassPathResource("local-repo");
|
||||
File localRepository = cpr.getFile();
|
||||
AetherModuleResolver defaultModuleResolver = new AetherModuleResolver(localRepository, null);
|
||||
AetherModuleResolver defaultModuleResolver = new AetherModuleResolver(localRepository, null, null);
|
||||
defaultModuleResolver.resolve(new Coordinates("niente", "nada", "jar", "", "zilch"));
|
||||
}
|
||||
|
||||
@@ -103,7 +99,7 @@ public class AetherModuleResolverTests {
|
||||
localRepository.deleteOnExit();
|
||||
Map<String, String> remoteRepos = new HashMap<>();
|
||||
remoteRepos.put("modules", "http://repo.spring.io/libs-snapshot");
|
||||
AetherModuleResolver defaultModuleResolver = new AetherModuleResolver(localRepository, remoteRepos);
|
||||
AetherModuleResolver defaultModuleResolver = new AetherModuleResolver(localRepository, remoteRepos, null);
|
||||
Resource resource = defaultModuleResolver.resolve(
|
||||
new Coordinates("org.springframework.cloud.stream.module", "time-source", "jar", "exec", "1.0.0.BUILD-SNAPSHOT"));
|
||||
assertTrue(resource.exists());
|
||||
@@ -123,7 +119,7 @@ public class AetherModuleResolverTests {
|
||||
.willReturn(aResponse()
|
||||
.withStatus(200)
|
||||
.withBodyFile(stubFileName)));
|
||||
AetherModuleResolver defaultModuleResolver = new AetherModuleResolver(localRepository, remoteRepos);
|
||||
AetherModuleResolver defaultModuleResolver = new AetherModuleResolver(localRepository, remoteRepos, null);
|
||||
Resource resource = defaultModuleResolver.resolve(new Coordinates("org.bar", "foo", "jar", "", "1.0.0"));
|
||||
assertTrue(resource.exists());
|
||||
assertEquals(resource.getFile().getName(), "foo-1.0.0.jar");
|
||||
@@ -143,7 +139,7 @@ public class AetherModuleResolverTests {
|
||||
.willReturn(aResponse()
|
||||
.withStatus(200)
|
||||
.withBodyFile(stubFileName)));
|
||||
AetherModuleResolver defaultModuleResolver = new AetherModuleResolver(localRepository, remoteRepos);
|
||||
AetherModuleResolver defaultModuleResolver = new AetherModuleResolver(localRepository, remoteRepos, null);
|
||||
defaultModuleResolver.setOffline(true);
|
||||
defaultModuleResolver.resolve(new Coordinates("org.bar", "foo", "jar", "", "1.0.0"));
|
||||
} catch (RuntimeException e) {
|
||||
|
||||
Reference in New Issue
Block a user