/* * Copyright (c) 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017 David Berkman * * This file is part of the SmallMind Code Project. * * The SmallMind Code Project is free software, you can redistribute * it and/or modify it under either, at your discretion... * * 1) The terms of GNU Affero General Public License as published by the * Free Software Foundation, either version 3 of the License, or (at * your option) any later version. * * ...or... * * 2) The terms of the Apache License, Version 2.0. * * The SmallMind Code Project is distributed in the hope that it will * be useful, but WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License or Apache License for more details. * * You should have received a copy of the GNU Affero General Public License * and the Apache License along with the SmallMind Code Project. If not, see * <http://www.gnu.org/licenses/> or <http://www.apache.org/licenses/LICENSE-2.0>. * * Additional permission under the GNU Affero GPL version 3 section 7 * ------------------------------------------------------------------ * If you modify this Program, or any covered work, by linking or * combining it with other code, such other code is not for that reason * alone subject to any of the requirements of the GNU Affero GPL * version 3. */ package org.smallmind.artifact.maven; import java.io.File; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.apache.maven.model.building.DefaultModelBuilderFactory; import org.apache.maven.model.building.ModelBuilder; import org.apache.maven.repository.internal.MavenRepositorySystemUtils; import org.apache.maven.settings.Mirror; import org.apache.maven.settings.Profile; import org.apache.maven.settings.Proxy; import org.apache.maven.settings.Repository; 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.eclipse.aether.ConfigurationProperties; import org.eclipse.aether.DefaultRepositoryCache; import org.eclipse.aether.DefaultRepositorySystemSession; import org.eclipse.aether.RepositorySystem; import org.eclipse.aether.RepositorySystemSession; import org.eclipse.aether.artifact.Artifact; import org.eclipse.aether.artifact.DefaultArtifact; import org.eclipse.aether.collection.CollectRequest; import org.eclipse.aether.collection.DependencyCollectionException; import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory; import org.eclipse.aether.graph.Dependency; import org.eclipse.aether.graph.DependencyNode; import org.eclipse.aether.graph.DependencyVisitor; import org.eclipse.aether.impl.DefaultServiceLocator; import org.eclipse.aether.repository.AuthenticationSelector; import org.eclipse.aether.repository.LocalRepository; import org.eclipse.aether.repository.LocalRepositoryManager; import org.eclipse.aether.repository.MirrorSelector; import org.eclipse.aether.repository.ProxySelector; import org.eclipse.aether.repository.RemoteRepository; import org.eclipse.aether.repository.RepositoryPolicy; import org.eclipse.aether.resolution.ArtifactRequest; import org.eclipse.aether.resolution.ArtifactResolutionException; import org.eclipse.aether.resolution.DependencyRequest; import org.eclipse.aether.resolution.DependencyResolutionException; import org.eclipse.aether.spi.connector.RepositoryConnectorFactory; 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.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; public class MavenRepository { private static final RepositorySystem REPOSITORY_SYSTEM; private final Settings settings; private final ProxySelector proxySelector; private final MirrorSelector mirrorSelector; private final AuthenticationSelector authenticationSelector; private final Map<Object, Object> configProps = new HashMap<>(); private final List<Profile> profileList; private final List<RemoteRepository> remoteRepositoryList; private boolean offline; static { DefaultServiceLocator locator = MavenRepositorySystemUtils.newServiceLocator(); locator.setServices(ModelBuilder.class, new DefaultModelBuilderFactory().newInstance()); locator.addService(RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class); locator.addService(TransporterFactory.class, FileTransporterFactory.class); locator.addService(TransporterFactory.class, HttpTransporterFactory.class); REPOSITORY_SYSTEM = locator.getService(RepositorySystem.class); } public MavenRepository (String repositoryId, boolean offline) throws SettingsBuildingException { this(System.getProperty("user.home") + "/.m2", repositoryId, offline); } public MavenRepository (String settingsDirectory, String repositoryId, boolean offline) throws SettingsBuildingException { DefaultSettingsBuildingRequest request = new DefaultSettingsBuildingRequest(); this.offline = offline; request.setGlobalSettingsFile(new File((((settingsDirectory == null) || settingsDirectory.isEmpty()) ? System.getProperty("user.home") + "/.m2" : settingsDirectory) + "/settings.xml")); settings = new DefaultSettingsBuilderFactory().newInstance().build(request).getEffectiveSettings(); profileList = settings.getProfiles(); configProps.put(ConfigurationProperties.USER_AGENT, getUserAgent(repositoryId)); proxySelector = getProxySelector(settings); mirrorSelector = getMirrorSelector(settings); authenticationSelector = getAuthenticationSelector(settings); remoteRepositoryList = initRepositories(authenticationSelector, mirrorSelector, settings); } public DefaultRepositorySystemSession generateSession () { DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession(); session.setOffline(offline); session.setCache(new DefaultRepositoryCache()); session.setConfigProperties(configProps); if ((profileList != null) && (!profileList.isEmpty())) { for (Profile profile : settings.getProfiles()) { session.setUserProperties(profile.getProperties()); } } session.setProxySelector(proxySelector); session.setMirrorSelector(mirrorSelector); session.setAuthenticationSelector(authenticationSelector); session.setLocalRepositoryManager(getLocalRepoMan(settings, REPOSITORY_SYSTEM, session)); return session; } public Artifact acquireArtifact (DefaultRepositorySystemSession session, MavenCoordinate mavenCoordinate) throws ArtifactResolutionException { return acquireArtifact(session, new DefaultArtifact(mavenCoordinate.getGroupId(), mavenCoordinate.getArtifactId(), mavenCoordinate.getClassifier(), mavenCoordinate.getExtension(), mavenCoordinate.getVersion())); } public Artifact acquireArtifact (DefaultRepositorySystemSession session, Artifact artifact) throws ArtifactResolutionException { ArtifactRequest artifactRequest = new ArtifactRequest(); artifactRequest.setArtifact(artifact); artifactRequest.setRepositories(remoteRepositoryList); return REPOSITORY_SYSTEM.resolveArtifact(session, artifactRequest).getArtifact(); } public Artifact[] resolve (final DefaultRepositorySystemSession session, Artifact artifact) throws DependencyCollectionException, DependencyResolutionException { final HashSet<DependencyNode> visitedSet = new HashSet<>(); final HashSet<Artifact> artifactSet = new HashSet<>(); Artifact[] artifacts; DependencyNode dependencyNode; dependencyNode = REPOSITORY_SYSTEM.collectDependencies(session, new CollectRequest().setRoot(new Dependency(artifact, "compile"))).getRoot(); dependencyNode.accept(new DependencyVisitor() { @Override public boolean visitEnter (DependencyNode node) { if (visitedSet.add(node)) { Dependency dependency; if (((dependency = node.getDependency()) != null) && (!dependency.isOptional())) { Artifact artifact; if ((artifact = dependency.getArtifact()).getFile() == null) { try { artifact = acquireArtifact(session, artifact); } catch (ArtifactResolutionException artifactResolutionException) { throw new RuntimeException(artifactResolutionException); } } artifactSet.add(artifact); } return true; } return false; } @Override public boolean visitLeave (DependencyNode node) { return true; } }); REPOSITORY_SYSTEM.resolveDependencies(session, new DependencyRequest().setRoot(dependencyNode)); artifacts = new Artifact[artifactSet.size()]; artifactSet.toArray(artifacts); return artifacts; } private String getUserAgent (String repositoryId) { StringBuilder buffer = new StringBuilder(); buffer.append("Maven-Repository/").append(repositoryId); buffer.append(" ("); buffer.append("Java ").append(System.getProperty("java.version")); buffer.append("; "); buffer.append(System.getProperty("os.name")).append(" ").append(System.getProperty("os.version")); buffer.append(")"); buffer.append(" Aether"); return buffer.toString(); } private List<RemoteRepository> initRepositories (AuthenticationSelector authenticationSelector, MirrorSelector mirrorSelector, Settings settings) { LinkedList<RemoteRepository> remoteRepositoryList = new LinkedList<>(); for (Profile profile : settings.getProfiles()) { if (isProfileActive(settings, profile)) { for (Repository repository : profile.getRepositories()) { constructRemoteRepository(authenticationSelector, mirrorSelector, remoteRepositoryList, repository); } for (Repository repository : profile.getPluginRepositories()) { constructRemoteRepository(authenticationSelector, mirrorSelector, remoteRepositoryList, repository); } } } return remoteRepositoryList; } private boolean isProfileActive (Settings settings, Profile profile) { return settings.getActiveProfiles().contains(profile.getId()) || (profile.getActivation() != null && profile.getActivation().isActiveByDefault()); } private void constructRemoteRepository (AuthenticationSelector authenticationSelector, MirrorSelector mirrorSelector, List<RemoteRepository> remoteRepositoryList, Repository repository) { RemoteRepository remoteRepository = new RemoteRepository.Builder(repository.getId(), repository.getLayout(), repository.getUrl()) .setReleasePolicy(new RepositoryPolicy(true, RepositoryPolicy.UPDATE_POLICY_ALWAYS, RepositoryPolicy.CHECKSUM_POLICY_WARN)) .setSnapshotPolicy(new RepositoryPolicy(true, RepositoryPolicy.UPDATE_POLICY_ALWAYS, RepositoryPolicy.CHECKSUM_POLICY_WARN)) .build(); RemoteRepository mirrorRepository = mirrorSelector.getMirror(remoteRepository); RemoteRepository coercedRepository = (mirrorRepository != null) ? mirrorRepository : remoteRepository; remoteRepositoryList.add(new RemoteRepository.Builder(coercedRepository).setAuthentication(authenticationSelector.getAuthentication(coercedRepository)).build()); } private ProxySelector getProxySelector (Settings settings) { DefaultProxySelector selector = new DefaultProxySelector(); for (Proxy proxy : settings.getProxies()) { AuthenticationBuilder auth = new AuthenticationBuilder(); auth.addUsername(proxy.getUsername()).addPassword(proxy.getPassword()); selector.add(new org.eclipse.aether.repository.Proxy(proxy.getProtocol(), proxy.getHost(), proxy.getPort(), auth.build()), proxy.getNonProxyHosts()); } return selector; } private MirrorSelector getMirrorSelector (Settings settings) { DefaultMirrorSelector selector = new DefaultMirrorSelector(); for (Mirror mirror : settings.getMirrors()) { selector.add(String.valueOf(mirror.getId()), mirror.getUrl(), mirror.getLayout(), false, mirror.getMirrorOf(), mirror.getMirrorOfLayouts()); } return selector; } private AuthenticationSelector getAuthenticationSelector (Settings settings) { DefaultAuthenticationSelector selector = new DefaultAuthenticationSelector(); for (Server server : settings.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 LocalRepositoryManager getLocalRepoMan (Settings settings, RepositorySystem repositorySystem, RepositorySystemSession repositorySystemSession) { LocalRepository repo = new LocalRepository(getDefaultLocalRepoDir(settings)); return repositorySystem.newLocalRepositoryManager(repositorySystemSession, repo); } private File getDefaultLocalRepoDir (Settings settings) { if (settings.getLocalRepository() != null) { return new File(settings.getLocalRepository()); } return new File(System.getProperty("user.home") + "/.m2/repository"); } }