Java tutorial
/* * Copyright 2016 Red Hat, Inc. and/or its affiliates. * * 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.guvnor.common.services.project.backend.server; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.charset.StandardCharsets; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.Map; import java.util.Set; import javax.enterprise.context.ApplicationScoped; import javax.inject.Inject; import javax.inject.Named; import org.apache.maven.project.MavenProject; import org.apache.maven.settings.Server; import org.apache.maven.settings.Settings; import org.eclipse.aether.artifact.Artifact; import org.eclipse.aether.artifact.DefaultArtifact; import org.eclipse.aether.repository.ArtifactRepository; import org.eclipse.aether.repository.Authentication; import org.eclipse.aether.repository.LocalRepository; 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.ArtifactResult; import org.guvnor.common.services.project.backend.server.utils.POMContentHandler; import org.guvnor.common.services.project.model.GAV; import org.guvnor.common.services.project.model.MavenRepositoryMetadata; import org.guvnor.common.services.project.model.MavenRepositorySource; import org.guvnor.common.services.project.model.POM; import org.guvnor.common.services.project.model.Project; import org.guvnor.common.services.project.service.ProjectRepositoryResolver; import org.jboss.errai.bus.server.annotations.Service; import org.kie.scanner.Aether; import org.kie.scanner.embedder.MavenEmbedder; import org.kie.scanner.embedder.MavenProjectLoader; import org.kie.scanner.embedder.MavenSettings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.uberfire.backend.server.util.Paths; import org.uberfire.backend.vfs.Path; import org.uberfire.io.IOService; import org.uberfire.java.nio.file.NoSuchFileException; import static org.guvnor.common.services.project.backend.server.MavenLocalRepositoryUtils.*; @Service @ApplicationScoped public class ProjectRepositoryResolverImpl implements ProjectRepositoryResolver { private static final Logger log = LoggerFactory.getLogger(ProjectRepositoryResolverImpl.class); //Package protected for tests boolean isCheckConflictingGAVDisabled = false; private IOService ioService; private POMContentHandler pomContentHandler = new POMContentHandler(); public ProjectRepositoryResolverImpl() { //WELD proxy and setup this.isCheckConflictingGAVDisabled = Boolean.parseBoolean( System.getProperty(ProjectRepositoryResolver.CONFLICTING_GAV_CHECK_DISABLED, "false")); } @Inject public ProjectRepositoryResolverImpl(final @Named("ioStrategy") IOService ioService) { this(); this.ioService = ioService; } @Override public Set<MavenRepositoryMetadata> getRemoteRepositoriesMetaData() { final Set<MavenRepositoryMetadata> repositories = new HashSet<MavenRepositoryMetadata>(); final Aether aether = Aether.getAether(); final Map<MavenRepositorySource, Collection<ArtifactRepository>> remoteRepositories = getRemoteRepositories( aether.getSession().getLocalRepository()); if (remoteRepositories.isEmpty()) { return Collections.emptySet(); } for (Map.Entry<MavenRepositorySource, Collection<ArtifactRepository>> e : remoteRepositories.entrySet()) { repositories.addAll(makeRepositoriesMetaData(e.getValue(), e.getKey())); } return repositories; } @Override public Set<MavenRepositoryMetadata> getRemoteRepositoriesMetaData(final Project project) { if (project == null) { return Collections.emptySet(); } final Set<MavenRepositoryMetadata> repositories = new HashSet<MavenRepositoryMetadata>(); try { //Load Project's pom.xml final Path pomXMLPath = project.getPomXMLPath(); final org.uberfire.java.nio.file.Path nioPomXMLPath = Paths.convert(pomXMLPath); final String pomXML = ioService.readAllString(nioPomXMLPath); final InputStream pomStream = new ByteArrayInputStream(pomXML.getBytes(StandardCharsets.UTF_8)); final MavenProject mavenProject = MavenProjectLoader.parseMavenPom(pomStream); final Aether aether = new Aether(mavenProject); final Map<MavenRepositorySource, Collection<ArtifactRepository>> remoteRepositories = getRemoteRepositories( aether.getSession().getLocalRepository(), mavenProject); if (remoteRepositories.isEmpty()) { return Collections.emptySet(); } for (Map.Entry<MavenRepositorySource, Collection<ArtifactRepository>> e : remoteRepositories .entrySet()) { repositories.addAll(makeRepositoriesMetaData(e.getValue(), e.getKey())); } } catch (IllegalArgumentException iae) { log.error("Unable to get Remote Repositories for Project '%s'. Returning empty Collection. ", project.getProjectName(), iae); } catch (NoSuchFileException nsfe) { log.error("Unable to get Remote Repositories for Project '%s'. Returning empty Collection. ", project.getProjectName(), nsfe); } catch (org.uberfire.java.nio.IOException ioe) { log.error("Unable to get Remote Repositories for Project '%s'. Returning empty Collection. ", project.getProjectName(), ioe); } return repositories; } private Set<MavenRepositoryMetadata> makeRepositoriesMetaData(final Collection<ArtifactRepository> repositories, final MavenRepositorySource source) { final Set<MavenRepositoryMetadata> metadata = new HashSet<MavenRepositoryMetadata>(); for (ArtifactRepository repository : repositories) { final MavenRepositoryMetadata md = makeRepositoryMetaData(repository, source); if (md != null) { metadata.add(md); } } return metadata; } private MavenRepositoryMetadata makeRepositoryMetaData(final ArtifactRepository repository, final MavenRepositorySource source) { if (repository instanceof LocalRepository) { final LocalRepository localRepository = (LocalRepository) repository; return new MavenRepositoryMetadata(localRepository.getId(), MavenSettings.getSettings().getLocalRepository(), source); } else if (repository instanceof RemoteRepository) { final RemoteRepository remoteRepository = (RemoteRepository) repository; return new MavenRepositoryMetadata(remoteRepository.getId(), remoteRepository.getUrl(), source); } return null; } @Override public Set<MavenRepositoryMetadata> getRepositoriesResolvingArtifact(final GAV gav, final MavenRepositoryMetadata... filter) { if (isCheckConflictingGAVDisabled) { return Collections.EMPTY_SET; } final Set<MavenRepositoryMetadata> repositoriesResolvingArtifact = new HashSet<MavenRepositoryMetadata>(); try { //Construct the Project's pom.xml final String pomXML = pomContentHandler.toString(new POM(gav)); final InputStream pomStream = new ByteArrayInputStream(pomXML.getBytes(StandardCharsets.UTF_8)); final MavenProject mavenProject = MavenProjectLoader.parseMavenPom(pomStream); repositoriesResolvingArtifact.addAll(getRepositoriesResolvingArtifact(gav, mavenProject)); //Filter results if necessary if (filter != null && filter.length > 0) { repositoriesResolvingArtifact.retainAll(Arrays.asList(filter)); } } catch (IOException ioe) { log.error("Unable to get Remote Repositories for Project '" + gav.toString() + "'. Returning empty Collection. ", ioe); } return repositoriesResolvingArtifact; } @Override public Set<MavenRepositoryMetadata> getRepositoriesResolvingArtifact(final GAV gav, final Project project, final MavenRepositoryMetadata... filter) { if (isCheckConflictingGAVDisabled) { return Collections.EMPTY_SET; } final Set<MavenRepositoryMetadata> repositoriesResolvingArtifact = new HashSet<MavenRepositoryMetadata>(); try { //Load Project's pom.xml final Path pomXMLPath = project.getPomXMLPath(); final org.uberfire.java.nio.file.Path nioPomXMLPath = Paths.convert(pomXMLPath); final String pomXML = ioService.readAllString(nioPomXMLPath); final InputStream pomStream = new ByteArrayInputStream(pomXML.getBytes(StandardCharsets.UTF_8)); final MavenProject mavenProject = MavenProjectLoader.parseMavenPom(pomStream); repositoriesResolvingArtifact.addAll(getRepositoriesResolvingArtifact(gav, mavenProject)); //Filter results if necessary if (filter != null && filter.length > 0) { repositoriesResolvingArtifact.retainAll(Arrays.asList(filter)); } } catch (IllegalArgumentException iae) { log.error("Unable to get Remote Repositories for Project '" + project.getProjectName() + "'. Returning empty Collection. ", iae); } catch (NoSuchFileException nsfe) { log.error("Unable to get Remote Repositories for Project '" + project.getProjectName() + "'. Returning empty Collection. ", nsfe); } catch (org.uberfire.java.nio.IOException ioe) { log.error("Unable to get Remote Repositories for Project '" + project.getProjectName() + "'. Returning empty Collection. ", ioe); } return repositoriesResolvingArtifact; } @Override public Set<MavenRepositoryMetadata> getRepositoriesResolvingArtifact(final String pomXML, final MavenRepositoryMetadata... filter) { if (isCheckConflictingGAVDisabled) { return Collections.EMPTY_SET; } final InputStream pomStream = new ByteArrayInputStream(pomXML.getBytes(StandardCharsets.UTF_8)); final MavenProject mavenProject = MavenProjectLoader.parseMavenPom(pomStream); final GAV gav = new GAV(mavenProject.getGroupId(), mavenProject.getArtifactId(), mavenProject.getVersion()); final Set<MavenRepositoryMetadata> repositoriesResolvingArtifact = new HashSet<MavenRepositoryMetadata>(); repositoriesResolvingArtifact.addAll(getRepositoriesResolvingArtifact(gav, mavenProject)); //Filter results if necessary if (filter != null && filter.length > 0) { repositoriesResolvingArtifact.retainAll(Arrays.asList(filter)); } return repositoriesResolvingArtifact; } private Set<MavenRepositoryMetadata> getRepositoriesResolvingArtifact(final GAV gav, final MavenProject mavenProject) { final String artifactName = gav.toString(); final Artifact artifact = new DefaultArtifact(artifactName); final Aether aether = new Aether(mavenProject); final Set<MavenRepositoryMetadata> repositoriesResolvingArtifact = new HashSet<MavenRepositoryMetadata>(); final Map<MavenRepositorySource, Collection<ArtifactRepository>> repositories = getRemoteRepositories( aether.getSession().getLocalRepository(), mavenProject); try { for (Map.Entry<MavenRepositorySource, Collection<ArtifactRepository>> e : repositories.entrySet()) { for (ArtifactRepository repository : e.getValue()) { final ArtifactRequest artifactRequest = new ArtifactRequest(); artifactRequest.setArtifact(artifact); java.nio.file.Path tempLocalRepositoryBasePath = null; try { ArtifactResult result = null; if (repository instanceof LocalRepository) { result = aether.getSystem().resolveArtifact(aether.getSession(), artifactRequest); } else if (repository instanceof RemoteRepository) { // Maven always tries to resolve against LocalRepository first, which is not much use when we want to check // if the Artifact is available on a RemoteRepository. Therefore substitute the default RepositorySystemSession // with one that provides a LocalRepositoryManager that always uses an empty transient LocalRepository to ensure // Maven does not resolve Artifacts locally. artifactRequest.addRepository((RemoteRepository) repository); tempLocalRepositoryBasePath = getRepositoryPath(gav); result = aether.getSystem().resolveArtifact(new MavenRepositorySystemSessionWrapper( tempLocalRepositoryBasePath.toString(), aether.getSession()), artifactRequest); } if (result != null && result.isResolved()) { final MavenRepositoryMetadata artifactRepositoryMetaData = makeRepositoryMetaData( result.getRepository(), e.getKey()); if (artifactRepositoryMetaData != null) { repositoriesResolvingArtifact.add(artifactRepositoryMetaData); } } } catch (ArtifactResolutionException are) { //Ignore - this means the Artifact could not be resolved against the given RemoteRepository } finally { tearDownMavenRepository(tempLocalRepositoryBasePath); } } } } catch (IOException ioe) { log.error("Error resolving '" + gav.toString() + "' against Repositories. Returning empty Collection. ", ioe); } return repositoriesResolvingArtifact; } private Map<MavenRepositorySource, Collection<ArtifactRepository>> getRemoteRepositories( final LocalRepository localRepository) { final Map<MavenRepositorySource, Collection<ArtifactRepository>> repositories = new HashMap<MavenRepositorySource, Collection<ArtifactRepository>>(); //Local Repository repositories.put(MavenRepositorySource.LOCAL, new HashSet<ArtifactRepository>() { { add(localRepository); } }); //Settings.xml Repositories final Collection<ArtifactRepository> settingsRepositories = new HashSet<ArtifactRepository>( MavenSettings.getMavenRepositoryConfiguration().getRemoteRepositoriesForRequest()); if (settingsRepositories != null) { repositories.put(MavenRepositorySource.SETTINGS, settingsRepositories); } return repositories; } private Map<MavenRepositorySource, Collection<ArtifactRepository>> getRemoteRepositories( final LocalRepository localRepository, final MavenProject mavenProject) { //Get Local and Settings.xml Repositories final Map<MavenRepositorySource, Collection<ArtifactRepository>> repositories = new HashMap<MavenRepositorySource, Collection<ArtifactRepository>>(); repositories.putAll(getRemoteRepositories(localRepository)); //Project's Repositories, includes those in setting.xml final Collection<ArtifactRepository> projectRepositories = new HashSet<ArtifactRepository>( mavenProject.getRemoteProjectRepositories()); if (projectRepositories != null) { //Remove Project Repositories that are in settings.xml final Collection<ArtifactRepository> settingsRepositories = repositories .get(MavenRepositorySource.SETTINGS); removeProjectRepositoriesThatAreInSettings(projectRepositories, settingsRepositories); repositories.put(MavenRepositorySource.PROJECT, projectRepositories); } //Project's <distributionManagement> Repositories final org.apache.maven.artifact.repository.ArtifactRepository distributionManagementRepository = mavenProject .getDistributionManagementArtifactRepository(); if (distributionManagementRepository != null) { repositories.put(MavenRepositorySource.DISTRIBUTION_MANAGEMENT, new HashSet<ArtifactRepository>() { { add(convertToArtifactRepository(distributionManagementRepository)); } }); } return repositories; } private void removeProjectRepositoriesThatAreInSettings( final Collection<ArtifactRepository> projectRepositories, final Collection<ArtifactRepository> settingsRepositories) { final Iterator<ArtifactRepository> projectRepositoryItr = projectRepositories.iterator(); while (projectRepositoryItr.hasNext()) { final ArtifactRepository projectRepository = projectRepositoryItr.next(); for (ArtifactRepository settingsRepository : settingsRepositories) { if (projectRepository.getId().equals(settingsRepository.getId())) { projectRepositoryItr.remove(); } } } } private RemoteRepository convertToArtifactRepository( final org.apache.maven.artifact.repository.ArtifactRepository artifactRepository) { final MavenEmbedder mavenEmbedder = MavenProjectLoader .newMavenEmbedder(MavenSettings.getSettings().isOffline()); final RemoteRepository.Builder remoteRepoBuilder = new RemoteRepository.Builder(artifactRepository.getId(), artifactRepository.getLayout().getId(), artifactRepository.getUrl()) .setSnapshotPolicy(new RepositoryPolicy(true, RepositoryPolicy.UPDATE_POLICY_DAILY, RepositoryPolicy.CHECKSUM_POLICY_WARN)) .setReleasePolicy(new RepositoryPolicy(true, RepositoryPolicy.UPDATE_POLICY_ALWAYS, RepositoryPolicy.CHECKSUM_POLICY_WARN)); final Settings settings = MavenSettings.getSettings(); final Server server = settings.getServer(artifactRepository.getId()); if (server != null) { final Authentication authentication = mavenEmbedder.getMavenSession().getRepositorySession() .getAuthenticationSelector().getAuthentication(remoteRepoBuilder.build()); remoteRepoBuilder.setAuthentication(authentication); } return remoteRepoBuilder.build(); } }