Java tutorial
/* * Copyright 2010 Red Hat, Inc. * * 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.commonjava.emb.project; 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.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.commonjava.emb.EMBException; import org.commonjava.emb.project.graph.DependencyGraph; import org.commonjava.emb.project.graph.DependencyGraphResolver; 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; 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.Collections; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; @Component(role = ProjectLoader.class) public class ProjectLoader { private static final Logger LOGGER = Logger.getLogger(ProjectLoader.class); @Requirement private RepositorySystem aetherRepositorySystem; @Requirement private org.apache.maven.repository.RepositorySystem mavenRepositorySystem; @Requirement private ProjectBuilder projectBuilder; @Requirement private DependencyGraphResolver dependencyGraphResolver; @Requirement private ProjectToolsSessionInjector sessionInjector; public DependencyGraph resolveProjectDependencies(final File rootPom, final ProjectToolsSession session, final boolean includeModuleProjects) throws EMBException { List<MavenProject> projects; if (includeModuleProjects) { projects = buildReactorProjectInstances(session, rootPom); } else { projects = Collections.singletonList(buildProjectInstance(rootPom, session)); } dependencyGraphResolver.resolveGraph(projects, sessionInjector.getRepositorySystemSession(session), session); return session.getDependencyGraph(); } public List<MavenProject> buildReactorProjectInstances(final ProjectToolsSession session, final File... rootPoms) throws ProjectToolsException { final ProjectBuildingRequest pbr = sessionInjector.getProjectBuildingRequest(session); try { final List<File> pomFiles = Arrays.asList(rootPoms); final List<ProjectBuildingResult> results = projectBuilder.build(pomFiles, true, 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) { // 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 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) { final List<ModelProblem> problems = result.getProblems(); if (problems != null && !problems.isEmpty()) { sb.append("\n").append(result.getProjectId()); for (final ModelProblem problem : problems) { sb.append("\n\t").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); sb.append("\n").append(sWriter); } sb.append((++i)).append(" ").append(sb); } } } } 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) { final DependencyGraph depGraph = session.getDependencyGraph(); 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); } depGraph.addDependency(next, current, true, true); if (!parentage.isEmpty()) { current = parentage.removeFirst(); } } } } public MavenProject buildProjectInstance(final File pomFile, final ProjectToolsSession session) throws ProjectToolsException { 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); } } 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()); } } 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); } } }