| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you 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.apache.maven.mae.project; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.PrintWriter; |
| import java.io.Reader; |
| import java.io.StringWriter; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.HashSet; |
| import java.util.LinkedHashMap; |
| import java.util.LinkedList; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.apache.commons.io.IOUtils; |
| import org.apache.log4j.Logger; |
| import org.apache.maven.RepositoryUtils; |
| import org.apache.maven.artifact.ArtifactUtils; |
| import org.apache.maven.mae.project.key.FullProjectKey; |
| import org.apache.maven.mae.project.session.ProjectToolsSession; |
| import org.apache.maven.mae.project.session.SessionInjector; |
| import org.apache.maven.model.Model; |
| import org.apache.maven.model.Parent; |
| import org.apache.maven.model.building.ModelProblem; |
| import org.apache.maven.model.io.xpp3.MavenXpp3Reader; |
| import org.apache.maven.project.MavenProject; |
| import org.apache.maven.project.ProjectBuilder; |
| import org.apache.maven.project.ProjectBuildingException; |
| import org.apache.maven.project.ProjectBuildingRequest; |
| import org.apache.maven.project.ProjectBuildingResult; |
| import org.codehaus.plexus.component.annotations.Component; |
| import org.codehaus.plexus.component.annotations.Requirement; |
| import org.codehaus.plexus.util.Os; |
| import org.codehaus.plexus.util.ReaderFactory; |
| import org.codehaus.plexus.util.StringUtils; |
| import org.codehaus.plexus.util.xml.pull.XmlPullParserException; |
| import org.sonatype.aether.RepositorySystem; |
| import org.sonatype.aether.artifact.Artifact; |
| import org.sonatype.aether.resolution.ArtifactRequest; |
| import org.sonatype.aether.resolution.ArtifactResolutionException; |
| import org.sonatype.aether.resolution.ArtifactResult; |
| |
| @Component( role = ProjectLoader.class ) |
| public class DefaultProjectLoader |
| implements ProjectLoader |
| { |
| |
| private static final Logger LOGGER = Logger.getLogger( DefaultProjectLoader.class ); |
| |
| @Requirement |
| private RepositorySystem aetherRepositorySystem; |
| |
| @Requirement |
| private org.apache.maven.repository.RepositorySystem mavenRepositorySystem; |
| |
| @Requirement |
| private ProjectBuilder projectBuilder; |
| |
| @Requirement |
| private SessionInjector sessionInjector; |
| |
| @Override |
| public List<MavenProject> buildReactorProjectInstances( final ProjectToolsSession session, final boolean recursive, |
| final File... rootPoms ) |
| throws ProjectToolsException |
| { |
| sessionInjector.getRemoteRepositories( session ); |
| final ProjectBuildingRequest pbr = sessionInjector.getProjectBuildingRequest( session ); |
| |
| try |
| { |
| final List<File> pomFiles = Arrays.asList( rootPoms ); |
| final List<ProjectBuildingResult> results = projectBuilder.build( pomFiles, recursive, pbr ); |
| |
| final List<MavenProject> projects = new ArrayList<MavenProject>( results.size() ); |
| for ( final ProjectBuildingResult result : results ) |
| { |
| final MavenProject project = result.getProject(); |
| project.setRemoteArtifactRepositories( session.getRemoteArtifactRepositories() ); |
| |
| projects.add( project ); |
| } |
| |
| session.setReactorProjects( projects ); |
| |
| if ( LOGGER.isDebugEnabled() ) |
| { |
| LOGGER.debug( "Adding projects to dependency graph:\n\t" |
| + StringUtils.join( projects.iterator(), "\n\t" ) ); |
| } |
| addProjects( session, projects ); |
| |
| return projects; |
| } |
| catch ( final ProjectBuildingException e ) |
| { |
| final List<ProjectBuildingResult> results = e.getResults(); |
| |
| final StringBuilder sb = new StringBuilder(); |
| |
| if ( results == null ) |
| { |
| sb.append( "Cannot build reactor project instances for root-POM: " ).append( rootPoms ); |
| |
| final StringWriter sWriter = new StringWriter(); |
| final PrintWriter pWriter = new PrintWriter( sWriter ); |
| |
| e.printStackTrace( pWriter ); |
| sb.append( "\n" ).append( sWriter ); |
| } |
| else |
| { |
| int i = 0; |
| for ( final ProjectBuildingResult result : results ) |
| { |
| StringBuilder builder = new StringBuilder(); |
| final List<ModelProblem> problems = result.getProblems(); |
| if ( problems != null && !problems.isEmpty() ) |
| { |
| builder.append( "\n" ).append( result.getProjectId() ); |
| for ( final ModelProblem problem : problems ) |
| { |
| builder.append( "\n\t" ).append( ( ++i ) ).append( " " ).append( problem.getMessage() ).append( "\n\t\t" ).append( problem.getSource() ).append( "@" ).append( problem.getLineNumber() ).append( ":" |
| + problem.getColumnNumber() ); |
| |
| if ( problem.getException() != null ) |
| { |
| final StringWriter sWriter = new StringWriter(); |
| final PrintWriter pWriter = new PrintWriter( sWriter ); |
| |
| problem.getException().printStackTrace( pWriter ); |
| builder.append( "\n" ).append( sWriter ); |
| } |
| } |
| } |
| |
| sb.append( builder ); |
| } |
| } |
| |
| throw new ProjectToolsException( "Failed to build project instance. \n\n%s", e, sb ); |
| } |
| } |
| |
| private void addProjects( final ProjectToolsSession session, final MavenProject... projects ) |
| { |
| if ( projects == null || projects.length == 0 ) |
| { |
| return; |
| } |
| |
| addProjects( session, Arrays.asList( projects ) ); |
| } |
| |
| private void addProjects( final ProjectToolsSession session, final List<MavenProject> projects ) |
| { |
| for ( final MavenProject project : projects ) |
| { |
| final LinkedList<Artifact> parentage = new LinkedList<Artifact>(); |
| MavenProject parent = project; |
| while ( parent != null ) |
| { |
| final org.apache.maven.artifact.Artifact pomArtifact = |
| mavenRepositorySystem.createArtifact( project.getGroupId(), project.getArtifactId(), |
| project.getVersion(), "pom" ); |
| |
| final Artifact aetherPomArtifact = RepositoryUtils.toArtifact( pomArtifact ); |
| |
| parentage.addFirst( aetherPomArtifact ); |
| |
| parent = parent.getParent(); |
| } |
| |
| Artifact current = parentage.removeFirst(); |
| while ( !parentage.isEmpty() ) |
| { |
| final Artifact next = parentage.getFirst(); |
| |
| // This is WEIRD, but the parent POM is actually a dependency of the current one, |
| // since it's required in order to build the current project... |
| if ( LOGGER.isDebugEnabled() ) |
| { |
| LOGGER.debug( "Marking parent POM: " + current + " as dependency of POM: " + next ); |
| } |
| |
| session.connectProjectHierarchy( next, true, current, true ); |
| |
| if ( !parentage.isEmpty() ) |
| { |
| current = parentage.removeFirst(); |
| } |
| } |
| } |
| } |
| |
| @Override |
| public MavenProject buildProjectInstance( final File pomFile, final ProjectToolsSession session ) |
| throws ProjectToolsException |
| { |
| sessionInjector.getRemoteRepositories( session ); |
| final ProjectBuildingRequest pbr = sessionInjector.getProjectBuildingRequest( session ); |
| |
| try |
| { |
| final ProjectBuildingResult result = projectBuilder.build( pomFile, pbr ); |
| |
| final MavenProject project = result.getProject(); |
| project.setRemoteArtifactRepositories( session.getRemoteArtifactRepositories() ); |
| |
| addProjects( session, project ); |
| |
| return project; |
| } |
| catch ( final ProjectBuildingException e ) |
| { |
| // logger.error( "Failed to build MavenProject instances from POM files for sorting: " + e.getMessage(), e |
| // ); |
| final List<ProjectBuildingResult> results = e.getResults(); |
| |
| final StringBuilder sb = new StringBuilder(); |
| |
| if ( results == null ) |
| { |
| sb.append( "Cannot build project instance for: " ).append( pomFile ); |
| |
| final StringWriter sWriter = new StringWriter(); |
| final PrintWriter pWriter = new PrintWriter( sWriter ); |
| |
| e.printStackTrace( pWriter ); |
| sb.append( "\n" ).append( sWriter ); |
| } |
| else |
| { |
| int i = 0; |
| for ( final ProjectBuildingResult result : results ) |
| { |
| final List<ModelProblem> problems = result.getProblems(); |
| for ( final ModelProblem problem : problems ) |
| { |
| sb.append( problem.getMessage() ).append( "\n\t" ).append( problem.getSource() ).append( "@" ).append( problem.getLineNumber() ).append( ":" |
| + problem.getColumnNumber() ); |
| |
| if ( problem.getException() != null ) |
| { |
| final StringWriter sWriter = new StringWriter(); |
| final PrintWriter pWriter = new PrintWriter( sWriter ); |
| |
| problem.getException().printStackTrace( pWriter ); |
| sb.append( "\n" ).append( sWriter ); |
| } |
| |
| sb.append( ( ++i ) ).append( " " ).append( sb ); |
| } |
| } |
| } |
| |
| throw new ProjectToolsException( "Failed to build project instance. \n\n%s", e, sb ); |
| } |
| } |
| |
| @Override |
| public MavenProject buildProjectInstance( final FullProjectKey key, final ProjectToolsSession session ) |
| throws ProjectToolsException |
| { |
| return buildProjectInstance( key.getGroupId(), key.getArtifactId(), key.getVersion(), session ); |
| } |
| |
| @Override |
| public MavenProject buildProjectInstance( final String groupId, final String artifactId, final String version, |
| final ProjectToolsSession session ) |
| throws ProjectToolsException |
| { |
| final ProjectBuildingRequest req = sessionInjector.getProjectBuildingRequest( session ); |
| |
| try |
| { |
| final org.apache.maven.artifact.Artifact pomArtifact = |
| mavenRepositorySystem.createArtifact( groupId, artifactId, version, "pom" ); |
| |
| final Artifact aetherPomArtifact = RepositoryUtils.toArtifact( pomArtifact ); |
| |
| final ArtifactRequest artifactRequest = |
| new ArtifactRequest( aetherPomArtifact, sessionInjector.getRemoteRepositories( session ), "project" ); |
| |
| final ArtifactResult artifactResult = |
| aetherRepositorySystem.resolveArtifact( req.getRepositorySession(), artifactRequest ); |
| |
| final File pomFile = artifactResult.getArtifact().getFile(); |
| final ProjectBuildingResult result = projectBuilder.build( pomFile, req ); |
| |
| final MavenProject project = result.getProject(); |
| project.setRemoteArtifactRepositories( session.getRemoteArtifactRepositories() ); |
| |
| project.setFile( pomFile ); |
| |
| addProjects( session, project ); |
| |
| return project; |
| } |
| catch ( final ProjectBuildingException e ) |
| { |
| // logger.error( "Failed to build MavenProject instances from POM files for sorting: " + e.getMessage(), e |
| // ); |
| final List<ProjectBuildingResult> results = e.getResults(); |
| |
| final StringBuilder sb = new StringBuilder(); |
| |
| int i = 0; |
| if ( results == null ) |
| { |
| sb.append( "Cannot build project instance for: " ).append( groupId ).append( ':' ).append( artifactId ).append( ':' ).append( version ); |
| |
| final StringWriter sWriter = new StringWriter(); |
| final PrintWriter pWriter = new PrintWriter( sWriter ); |
| |
| e.printStackTrace( pWriter ); |
| sb.append( "\n" ).append( sWriter ); |
| } |
| else |
| { |
| for ( final ProjectBuildingResult result : results ) |
| { |
| final List<ModelProblem> problems = result.getProblems(); |
| for ( final ModelProblem problem : problems ) |
| { |
| sb.append( problem.getMessage() ).append( "\n\t" ).append( problem.getSource() ).append( "@" ).append( problem.getLineNumber() ).append( ":" |
| + problem.getColumnNumber() ); |
| |
| if ( problem.getException() != null ) |
| { |
| final StringWriter sWriter = new StringWriter(); |
| final PrintWriter pWriter = new PrintWriter( sWriter ); |
| |
| problem.getException().printStackTrace( pWriter ); |
| sb.append( "\n" ).append( sWriter ); |
| } |
| |
| sb.append( ( ++i ) ).append( " " ).append( sb ); |
| } |
| } |
| } |
| |
| throw new ProjectToolsException( "Failed to build project instance. \n\n%s", e, sb ); |
| } |
| catch ( final ArtifactResolutionException e ) |
| { |
| throw new ProjectToolsException( "Failed to resolve POM: %s:%s:%s\nReason: %s", e, groupId, artifactId, |
| version, e.getMessage() ); |
| } |
| } |
| |
| @Override |
| public Set<String> retrieveReactorProjectIds( final File rootPom ) |
| throws ProjectToolsException |
| { |
| if ( LOGGER.isInfoEnabled() ) |
| { |
| if ( LOGGER.isDebugEnabled() ) |
| { |
| LOGGER.debug( "Finding projectIds contained within reactor for: " + rootPom ); |
| } |
| } |
| |
| final Map<File, Model> models = new LinkedHashMap<File, Model>(); |
| readReactorModels( rootPom, rootPom, models ); |
| |
| final Set<String> projectIds = new HashSet<String>( models.size() ); |
| for ( final Model model : models.values() ) |
| { |
| String groupId = model.getGroupId(); |
| final String artifactId = model.getArtifactId(); |
| String version = model.getVersion(); |
| String packaging = model.getPackaging(); |
| |
| if ( packaging == null ) |
| { |
| packaging = "jar"; |
| } |
| |
| if ( groupId == null || version == null ) |
| { |
| final Parent parent = model.getParent(); |
| if ( parent != null ) |
| { |
| if ( groupId == null ) |
| { |
| groupId = parent.getGroupId(); |
| } |
| if ( version == null ) |
| { |
| version = parent.getVersion(); |
| } |
| } |
| else |
| { |
| LOGGER.warn( String.format( "Invalid POM: %s", model.getId() ) ); |
| continue; |
| } |
| } |
| |
| final String key = ArtifactUtils.key( groupId, artifactId, version ); |
| if ( LOGGER.isInfoEnabled() ) |
| { |
| if ( LOGGER.isDebugEnabled() ) |
| { |
| LOGGER.debug( "Found: " + key ); |
| } |
| } |
| |
| projectIds.add( key ); |
| } |
| |
| return projectIds; |
| } |
| |
| private void readReactorModels( final File topPom, final File pom, final Map<File, Model> models ) |
| throws ProjectToolsException |
| { |
| final Model model = readModel( pom ); |
| models.put( pom, model ); |
| |
| if ( model.getModules() != null && !model.getModules().isEmpty() ) |
| { |
| final File basedir = pom.getParentFile(); |
| |
| final List<File> moduleFiles = new ArrayList<File>(); |
| |
| for ( String module : model.getModules() ) |
| { |
| if ( StringUtils.isEmpty( module ) ) |
| { |
| continue; |
| } |
| |
| module = module.replace( '\\', File.separatorChar ).replace( '/', File.separatorChar ); |
| |
| File moduleFile = new File( basedir, module ); |
| |
| if ( moduleFile.isDirectory() ) |
| { |
| moduleFile = new File( moduleFile, "pom.xml" ); |
| } |
| |
| if ( !moduleFile.isFile() ) |
| { |
| LOGGER.warn( String.format( "In reactor of: %s: Child module %s of %s does not exist.", topPom, |
| moduleFile, pom ) ); |
| continue; |
| } |
| |
| if ( Os.isFamily( Os.FAMILY_WINDOWS ) ) |
| { |
| // we don't canonicalize on unix to avoid interfering with symlinks |
| try |
| { |
| moduleFile = moduleFile.getCanonicalFile(); |
| } |
| catch ( final IOException e ) |
| { |
| moduleFile = moduleFile.getAbsoluteFile(); |
| } |
| } |
| else |
| { |
| moduleFile = new File( moduleFile.toURI().normalize() ); |
| } |
| |
| moduleFiles.add( moduleFile ); |
| readReactorModels( topPom, moduleFile, models ); |
| } |
| } |
| } |
| |
| private Model readModel( final File pom ) |
| throws ProjectToolsException |
| { |
| Reader reader = null; |
| try |
| { |
| reader = ReaderFactory.newPlatformReader( pom ); |
| |
| return new MavenXpp3Reader().read( reader, false ); |
| } |
| catch ( final IOException e ) |
| { |
| LOGGER.error( String.format( "Failed to read POM: %s.\nReason: %s", pom, e.getMessage() ), e ); |
| throw new ProjectToolsException( "Failed to read POM: %s. Reason: %s", e, pom.getAbsolutePath(), |
| e.getMessage() ); |
| } |
| catch ( final XmlPullParserException e ) |
| { |
| LOGGER.error( String.format( "Failed to read POM: %s.\nReason: %s", pom, e.getMessage() ), e ); |
| throw new ProjectToolsException( "Failed to read POM: %s. Reason: %s", e, pom.getAbsolutePath(), |
| e.getMessage() ); |
| } |
| finally |
| { |
| IOUtils.closeQuietly( reader ); |
| } |
| } |
| |
| } |