Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: #2470 Use mirror to download dependencies if applicable #2617

Merged
merged 1 commit into from
May 29, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
import org.eclipse.aether.repository.Authentication;
import org.eclipse.aether.repository.LocalRepository;
import org.eclipse.aether.repository.Proxy;
import org.eclipse.aether.repository.ProxySelector;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.repository.RepositoryPolicy;
import org.eclipse.aether.spi.connector.RepositoryConnectorFactory;
Expand All @@ -68,8 +69,9 @@
import io.quarkus.bootstrap.resolver.AppModelResolverException;
import io.quarkus.bootstrap.util.PropertyUtils;

import static java.util.stream.Collectors.toList;

/**
*
* @author Alexey Loubyansky
*/
public class MavenRepoInitializer {
Expand Down Expand Up @@ -216,7 +218,7 @@ public static DefaultRepositorySystemSession newSession(RepositorySystem system,
}

public static List<RemoteRepository> getRemoteRepos() throws AppModelResolverException {
if(remoteRepos != null) {
if (remoteRepos != null) {
return remoteRepos;
}
return remoteRepos = Collections.unmodifiableList(getRemoteRepos(getSettings()));
Expand All @@ -225,8 +227,6 @@ public static List<RemoteRepository> getRemoteRepos() throws AppModelResolverExc
public static List<RemoteRepository> getRemoteRepos(Settings settings) throws AppModelResolverException {
final List<RemoteRepository> remotes = new ArrayList<>();

final Proxy proxy = toAetherProxy(settings.getActiveProxy());

final int profilesTotal = settings.getProfiles().size();
if(profilesTotal > 0) {
List<org.apache.maven.model.Profile> modelProfiles = new ArrayList<>(profilesTotal);
Expand Down Expand Up @@ -276,7 +276,7 @@ public void add(ModelProblemCollectorRequest req) {
}
});
for(org.apache.maven.model.Profile modelProfile : modelProfiles) {
addProfileRepos(modelProfile, remotes, proxy);
addProfileRepos(modelProfile, remotes);
}
}

Expand All @@ -286,7 +286,7 @@ public void add(ModelProblemCollectorRequest req) {
for (String profileName : activeProfiles) {
final Profile profile = getProfile(profileName, settings);
if(profile != null) {
addProfileRepos(profile, remotes, proxy);
addProfileRepos(profile, remotes);
}
}
}
Expand All @@ -295,15 +295,41 @@ public void add(ModelProblemCollectorRequest req) {
remotes.add(new RemoteRepository.Builder(DEFAULT_REMOTE_REPO_ID, "default", DEFAULT_REMOTE_REPO_URL)
.setReleasePolicy(new RepositoryPolicy(true, RepositoryPolicy.UPDATE_POLICY_DAILY, RepositoryPolicy.CHECKSUM_POLICY_WARN))
.setSnapshotPolicy(new RepositoryPolicy(false, RepositoryPolicy.UPDATE_POLICY_DAILY, RepositoryPolicy.CHECKSUM_POLICY_WARN))
.setProxy(proxy)
.build());
}
final ProxyAwareMirrorSelector proxyAwareMirrorSelector = new ProxyAwareMirrorSelector(
settings.getMirrors(),
getProxySelector(settings)
);
return remotes.stream()
.map(proxyAwareMirrorSelector::getMirror)
// remove duplicates
.distinct()
.collect(toList());
}

return remotes;
private static ProxySelector getProxySelector(Settings settings) {
final org.apache.maven.settings.Proxy settingsProxy = settings.getActiveProxy();
if (settingsProxy == null) {
return null;
}
return new DefaultProxySelector().add(
new Proxy(
settingsProxy.getProtocol(),
settingsProxy.getHost(),
settingsProxy.getPort(),
settingsProxy.getUsername() == null ? null : new AuthenticationBuilder()
.addUsername(settingsProxy.getUsername())
.addPassword(settingsProxy.getPassword())
.build()
),
settingsProxy.getNonProxyHosts()
);
}

/**
* Convert a {@link org.apache.maven.settings.Proxy} to a {@link Proxy}.
*
* @param proxy Maven proxy settings, may be {@code null}.
* @return Aether repository proxy or {@code null} if given {@link org.apache.maven.settings.Proxy} is {@code null}.
*/
Expand Down Expand Up @@ -339,7 +365,7 @@ private static void unrecognizedProfile(String name, boolean activate) {
log.warn(buf.toString());
}

private static void addProfileRepos(final org.apache.maven.model.Profile profile, final List<RemoteRepository> all, final Proxy proxy) {
private static void addProfileRepos(final org.apache.maven.model.Profile profile, final List<RemoteRepository> all) {
final List<org.apache.maven.model.Repository> repositories = profile.getRepositories();
for (org.apache.maven.model.Repository repo : repositories) {
final RemoteRepository.Builder repoBuilder = new RemoteRepository.Builder(repo.getId(), repo.getLayout(), repo.getUrl());
Expand All @@ -351,12 +377,11 @@ private static void addProfileRepos(final org.apache.maven.model.Profile profile
if (policy != null) {
repoBuilder.setSnapshotPolicy(toAetherRepoPolicy(policy));
}
repoBuilder.setProxy(proxy);
all.add(repoBuilder.build());
}
}

private static void addProfileRepos(final Profile profile, final List<RemoteRepository> all, final Proxy proxy) {
private static void addProfileRepos(final Profile profile, final List<RemoteRepository> all) {
final List<Repository> repositories = profile.getRepositories();
for (Repository repo : repositories) {
final RemoteRepository.Builder repoBuilder = new RemoteRepository.Builder(repo.getId(), repo.getLayout(), repo.getUrl());
Expand All @@ -368,7 +393,6 @@ private static void addProfileRepos(final Profile profile, final List<RemoteRepo
if (policy != null) {
repoBuilder.setSnapshotPolicy(toAetherRepoPolicy(policy));
}
repoBuilder.setProxy(proxy);
all.add(repoBuilder.build());
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package io.quarkus.bootstrap.resolver.maven;

import org.apache.maven.settings.Mirror;
import org.eclipse.aether.repository.MirrorSelector;
import org.eclipse.aether.repository.Proxy;
import org.eclipse.aether.repository.ProxySelector;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.util.repository.DefaultMirrorSelector;

import java.util.List;

/**
* Retrieve mirror for a {@link RemoteRepository} if applicable, and setup proxy if applicable.
*/
class ProxyAwareMirrorSelector implements MirrorSelector {
private final ProxySelector proxySelector;
private final MirrorSelector wrappedMirrorSelector;
private static final ProxySelector NULL_PROXY_SELECTOR = new ProxySelector() {
@Override
public Proxy getProxy(RemoteRepository repository) {
return null;
}
};


private static MirrorSelector createMirrorSelector(List<Mirror> mirrors) {
DefaultMirrorSelector ms = new DefaultMirrorSelector();
if (mirrors != null) {
for (Mirror m : mirrors) {
ms.add(
m.getId(),
m.getUrl(),
m.getLayout(),
false,
m.getMirrorOf(),
m.getMirrorOfLayouts()
);
}
}
return ms;
}

ProxyAwareMirrorSelector(List<Mirror> mirrors, ProxySelector proxySelector) {
this.wrappedMirrorSelector = createMirrorSelector(mirrors);
this.proxySelector = proxySelector == null ? NULL_PROXY_SELECTOR : proxySelector;
}

/**
* Replace repo with it's mirror if applicable, and ensure proxy is set-up if needed.
*
* @param remoteRepository Remote repository to enhance
* @return Mirror or RemoteRepository (if no mirror is applicable) but add proxy on this mirror or RemoteRepository if needed
*/
@Override
public RemoteRepository getMirror(final RemoteRepository remoteRepository) {
RemoteRepository remoteRepositoryResult = wrappedMirrorSelector.getMirror(remoteRepository);
if (remoteRepositoryResult == null) {
// No Mirror, take remoteRepository it-self
remoteRepositoryResult = remoteRepository;
}

final Proxy proxy = proxySelector.getProxy(remoteRepositoryResult);
if (proxy == null) {
// No Proxy, return remoteRepositoryMirror
return remoteRepositoryResult;
}

// Available proxy, use it
return new RemoteRepository.Builder(remoteRepositoryResult)
.setProxy(proxy)
.build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
package io.quarkus.bootstrap.resolver.maven.test;

import io.quarkus.bootstrap.resolver.AppModelResolverException;
import io.quarkus.bootstrap.resolver.maven.MavenRepoInitializer;
import org.apache.maven.settings.*;
import org.eclipse.aether.repository.RemoteRepository;
import org.junit.BeforeClass;
import org.junit.Test;

import java.util.List;

import static org.eclipse.aether.repository.RepositoryPolicy.CHECKSUM_POLICY_WARN;
import static org.eclipse.aether.repository.RepositoryPolicy.UPDATE_POLICY_DAILY;
import static org.junit.Assert.*;

public class MavenRepoInitializerTest {
private static Mirror mirrorA;
private static Proxy localProxy;
private static Settings baseSettings;

@BeforeClass
public static void init() {
baseSettings = new Settings();

baseSettings.setInteractiveMode(true);
baseSettings.setUsePluginRegistry(false);
baseSettings.setOffline(false);

final Profile profile = new Profile();
profile.setId("foo-profile");

final RepositoryPolicy releasesPolicy = new RepositoryPolicy();
releasesPolicy.setEnabled(true);
releasesPolicy.setUpdatePolicy(null);
releasesPolicy.setChecksumPolicy(CHECKSUM_POLICY_WARN);

final RepositoryPolicy snapshotsPolicy = new RepositoryPolicy();
snapshotsPolicy.setEnabled(true);
snapshotsPolicy.setUpdatePolicy(UPDATE_POLICY_DAILY);
snapshotsPolicy.setChecksumPolicy(CHECKSUM_POLICY_WARN);

final RepositoryPolicy noSnapshotsPolicy = new RepositoryPolicy();
noSnapshotsPolicy.setEnabled(false);

final Repository customRepository = new Repository();
customRepository.setId("custom-repo");
customRepository.setUrl("https://foo.repo/artifact/content/groups/foo/");
customRepository.setReleases(releasesPolicy);
customRepository.setSnapshots(snapshotsPolicy);
profile.addRepository(customRepository);

final Repository jbossRepository = new Repository();
jbossRepository.setId("jboss-public-repository");
jbossRepository.setUrl("https://repository.jboss.org/nexus/content/repositories/releases/");
jbossRepository.setReleases(releasesPolicy);
jbossRepository.setSnapshots(noSnapshotsPolicy);
profile.addRepository(jbossRepository);

final Repository springRepository = new Repository();
springRepository.setId("spring-public-repository");
springRepository.setUrl("http://repo.spring.io/libs-release/");
springRepository.setReleases(releasesPolicy);
springRepository.setSnapshots(noSnapshotsPolicy);
profile.addRepository(springRepository);

baseSettings.addProfile(profile);
baseSettings.addActiveProfile("foo-profile");

localProxy = new Proxy();
localProxy.setActive(true);
localProxy.setProtocol("http");
localProxy.setUsername(null);
localProxy.setPassword(null);
localProxy.setPort(8888);
localProxy.setHost("localhost");
localProxy.setNonProxyHosts("localhost");
localProxy.setId("local-proxy-http");

mirrorA = new Mirror();
mirrorA.setMirrorOf("central,jboss-public-repository,spring-public-repository");
mirrorA.setUrl("https://mirror.com/artifact/content/groups/public/");
mirrorA.setId("mirror-A");
}

@Test
public void getRemoteRepoFromSettingsWithNeitherProxyNorMirror() throws AppModelResolverException {
final Settings settings = baseSettings.clone();

List<RemoteRepository> repos = MavenRepoInitializer.getRemoteRepos(settings);
assertEquals(4, repos.size());

assertEquals("custom-repo", repos.get(0).getId());
assertNull(repos.get(0).getProxy());
assertTrue(repos.get(0).getMirroredRepositories().isEmpty());

final RemoteRepository centralRepo = repos.get(repos.size() - 1);
assertEquals("central", centralRepo.getId());
assertNull(centralRepo.getProxy());
assertTrue(centralRepo.getMirroredRepositories().isEmpty());
}

@Test
public void getRemoteRepoFromSettingsWithProxyButWithoutMirror() throws AppModelResolverException {
final Settings settings = baseSettings.clone();
settings.addProxy(localProxy);

List<RemoteRepository> repos = MavenRepoInitializer.getRemoteRepos(settings);
assertEquals(4, repos.size());

assertEquals("custom-repo", repos.get(0).getId());
assertNotNull(repos.get(0).getProxy());
assertNotNull(repos.get(0).getMirroredRepositories());

final RemoteRepository centralRepo = repos.get(repos.size() - 1);
assertEquals("central repo must be added as default repository", "central", centralRepo.getId());
assertNotNull(centralRepo.getProxy());
assertTrue(centralRepo.getMirroredRepositories().isEmpty());
}

@Test
public void getRemoteRepoFromSettingsWithProxyAndMirror() throws AppModelResolverException {
final Settings settings = baseSettings.clone();
settings.addProxy(localProxy);
settings.addMirror(mirrorA);

List<RemoteRepository> repos = MavenRepoInitializer.getRemoteRepos(settings);
assertEquals(4, repos.size());

assertEquals("custom-repo", repos.get(0).getId());
assertNotNull(repos.get(0).getProxy());
assertNotNull(repos.get(0).getMirroredRepositories());

final RemoteRepository centralRepo = repos.get(repos.size() - 1);
assertEquals("Central repo must be substitute by mirror", "mirror-A", centralRepo.getId());
assertNotNull(centralRepo.getProxy());
assertEquals(1, centralRepo.getMirroredRepositories().size());
assertEquals("central", centralRepo.getMirroredRepositories().get(0).getId());
}
}