Java tutorial
/* * JBoss, Home of Professional Open Source * Copyright 2014, Red Hat Middleware LLC, and individual contributors * by the @authors tag. See the copyright.txt in the distribution for a * full listing of individual contributors. * * 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.jboss.shrinkwrap.resolver.plugin; import java.io.File; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.Reader; import java.io.StringWriter; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import org.apache.maven.classrealm.ClassRealmManager; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugins.annotations.Component; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.classworlds.realm.ClassRealm; import org.jboss.shrinkwrap.resolver.api.maven.ConfigurableMavenResolverSystem; import org.jboss.shrinkwrap.resolver.api.maven.Maven; import org.jboss.shrinkwrap.resolver.api.maven.MavenArtifactInfo; import org.jboss.shrinkwrap.resolver.api.maven.MavenResolvedArtifact; import org.jboss.shrinkwrap.resolver.api.maven.ScopeType; /** * Writes a dependency tree output * */ @Mojo(name = "dependency-tree", requiresDirectInvocation = true, requiresDependencyCollection = ResolutionScope.TEST) public class DependencyTreeMojo extends AbstractResolverMojo { private static final String OUTPUT_DELIMITER; static { StringBuilder sb = new StringBuilder(); for (int i = 0; i < 79; i++) { sb.append('-'); } OUTPUT_DELIMITER = sb.toString(); } @Parameter(defaultValue = "${outputFile}") private File outputFile; /** * Optional scope to use for dependency tree resolution * * @parameter expression="${scope}" */ @Parameter(defaultValue = "${scope}") private String scope; // Maven is by default removing some of the artifacts from plugin classpath // namely, org.apache.maven.DefaultArtifactFilterManager does that // as the API is not configurable, we need to get Core Class Realm and combine it with plugin ClassRealm @Component private ClassRealmManager classRealmManager; @Override public void execute() throws MojoExecutionException { // first, we need to propagate environment settings PropagateExecutionContextMojo mojo = new PropagateExecutionContextMojo(); mojo.setNamespace("maven.execution."); mojo.setSession(session); mojo.execute(); // propagate into current environment SecurityActions.addProperties(session.getUserProperties()); MavenProject project = session.getCurrentProject(); // set scope ScopeType[] scopes = ScopeType.values(); if (scope != null && !"".equals(scope)) { scopes = new ScopeType[] { ScopeType.fromScopeType(scope) }; } // get ClassLoader that contains both Maven and plugin class path ClassLoader cls = getCombinedClassLoader(classRealmManager); // skip resolution if no dependencies are in the project (e.g. parent agreggator) MavenResolvedArtifact[] artifacts; if (project.getDependencies() == null || project.getDependencies().size() == 0) { artifacts = new MavenResolvedArtifact[0]; } else { artifacts = Maven.configureResolverViaPlugin(cls).importDependencies(scopes).resolve() .withTransitivity().asResolvedArtifact(); } StringBuilder projectGAV = new StringBuilder(); projectGAV.append(project.getGroupId()).append(":").append(project.getArtifactId()).append(":") .append(project.getPackaging()).append(":").append(project.getVersion()).append("\n"); String dependencyTree = buildDependencyTree(projectGAV, "+- ", artifacts); // write output to file if specified if (outputFile != null) { FileWriter writer = null; try { writer = new FileWriter(outputFile); writer.write(dependencyTree); getLog().info("Dependency tree output was writen into: " + outputFile.getAbsolutePath()); } catch (IOException e) { } finally { try { if (writer != null) { writer.close(); } } catch (IOException e) { } } } // write an output to console else { StringBuilder outputBuffer = new StringBuilder(); outputBuffer.append(OUTPUT_DELIMITER).append("\nShrinkWrap Maven: Dependency Tree\n") .append(OUTPUT_DELIMITER).append("\n").append(dependencyTree).append(OUTPUT_DELIMITER); getLog().info(outputBuffer.toString()); } } private static String buildDependencyTree(StringBuilder sb, String indent, MavenArtifactInfo[] artifacts) { int length = artifacts.length - 1; for (int i = 0; i <= length; i++) { MavenArtifactInfo artifact = artifacts[i]; String parsedIndent = indent; String nextLevelIndent = indent.replaceAll("\\+- $", "\\| ") + "+- "; // indent last one in different manner if (i == length) { parsedIndent = parsedIndent.replaceAll("\\+- $", "\\\\- "); nextLevelIndent = indent.replaceAll("\\+- $", " ") + "+- "; } sb.append(parsedIndent).append(artifact.getCoordinate().toCanonicalForm()).append(" [") .append(artifact.getScope()).append("]").append("\n"); buildDependencyTree(sb, nextLevelIndent, artifact.getDependencies()); } return sb.toString(); } // creates a class loader that has access to both current thread classloader and Maven Core classloader private ClassLoader getCombinedClassLoader(ClassRealmManager manager) { List<URL> urlList = new ArrayList<URL>(); // add thread classpath ClassLoader threadCL = SecurityActions.getThreadContextClassLoader(); if (threadCL instanceof URLClassLoader) { urlList.addAll(Arrays.asList(((URLClassLoader) threadCL).getURLs())); } // add maven core libraries ClassRealm core = manager.getCoreRealm(); if (core != null) { urlList.addAll(Arrays.asList(core.getURLs())); } ClassRealm mavenApi = manager.getMavenApiRealm(); if (mavenApi != null) { urlList.addAll(Arrays.asList(mavenApi.getURLs())); } // we need to keep threadCL as parent, otherwise we'll get ClassCastException in runtime URLClassLoader cl = new URLClassLoader(urlList.toArray(new URL[0]), threadCL); // for (URL u : cl.getURLs()) { // System.out.println("CLR: " + u); // } return cl; } }