Java tutorial
package com.puresoltechnologies.maven.plugins.license; import java.util.ArrayList; import java.util.List; import java.util.Set; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.model.Dependency; import org.apache.maven.model.License; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.descriptor.PluginDescriptor; import org.apache.maven.plugin.logging.Log; import org.apache.maven.plugins.annotations.Component; import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProjectBuilder; import org.apache.maven.project.ProjectBuildingException; import org.apache.maven.settings.Settings; import com.puresoltechnologies.maven.plugins.license.internal.ArtifactUtilities; import com.puresoltechnologies.maven.plugins.license.internal.DependencyTree; import com.puresoltechnologies.maven.plugins.license.internal.DependencyUtilities; /** * This abstract class provides basic functionality for all license validations. * * @author Rick-Rainer Ludwig */ public abstract class AbstractValidationMojo extends AbstractMojo { @Component private MavenProject mavenProject; @Component private PluginDescriptor plugin; @Component private Settings settings; @Component private MavenProjectBuilder mavenProjectBuilder; /** * This field contains the remote artifact repositories. */ @Parameter(required = false, defaultValue = "${project.remoteArtifactRepositories}", readonly = true) private List<ArtifactRepository> remoteArtifactRepositories; /** * This field contains the local repository. */ @Parameter(required = false, defaultValue = "${localRepository}", readonly = true) private ArtifactRepository localRepository; /** * This method returns the current {@link MavenProject}. * * @return A {@link MavenProject} object is returned referencing the current * Maven project. */ protected final MavenProject getMavenProject() { return mavenProject; } /** * This method returns a {@link MavenProjectBuilder}. * * @return A {@link MavenProjectBuilder} is returned. */ protected final MavenProjectBuilder getProjectBuilder() { return mavenProjectBuilder; } /** * This method retrieves all artifacts of the current Maven module. * * <b>Attention(!):</b> This method uses * {@link MavenProject#getDependencyArtifacts()} and * {@link MavenProject#getArtifacts()} which are lazily filled with the * artifacts. * * @return A {@link Set} of {@link Artifact} is returned containing the * artifacts found. */ protected Set<Artifact> getArtifacts(boolean recursive) { Log log = getLog(); if (recursive) { log.info( "Recursive license validation is enabled. All direct and transitive dependency artifacts are going to be checked."); @SuppressWarnings("unchecked") Set<Artifact> set = mavenProject.getArtifacts(); return set; } else { log.info( "Recursive license validation is disabled. All only direct dependency artifacts are going to be checked."); @SuppressWarnings("unchecked") Set<Artifact> set = mavenProject.getDependencyArtifacts(); return set; } } /** * This method retrieves all artifacts of the current Maven module. * * @param recursive * is to be set to <code>true</code> is the dependencies shall be * loaded recursively. <code>false</code> is set if wanted * otherwise. * @param skipTestScope * is to be set to <code>true</code> is artifacts in test scope * are to be skipped and neglected. <code>false</code> is set if * wanted otherwise. * @param skipProvidedScope * is to be set to <code>true</code> if artifacts in provided * scope are to be skipped and neglected. <code>false</code> is * set if wanted otherwise. * @param skipOptionals * is to be set to <code>true</code> if artifacts in optional * scope are to be skipped and neglected. <code>false</code> is * set if wanted otherwise. * @return A {@link DependencyTree} is returned containing the artifacts * found. * @throws MojoExecutionException * is thrown in cases of issues. */ protected DependencyTree loadArtifacts(boolean recursive, boolean skipTestScope, boolean skipProvidedScope, boolean skipOptionals) throws MojoExecutionException { return loadArtifacts(0, null, mavenProject.getArtifact(), recursive, skipTestScope, skipProvidedScope, skipOptionals); } /** * Loads the artifact recursively. * * @param artifact * @param recursive * specified whether all dependencies should be loaded * recursively. * @param skipTestScope * specified whether to skip test scoped artifacts or not. * @return A {@link DependencyTree} object is returned. * @throws MojoExecutionException * is thrown if anything unexpected goes wrong. */ private DependencyTree loadArtifacts(int depth, DependencyTree parentDependencyTree, Artifact artifact, boolean recursive, boolean skipTestScope, boolean skipProvidedScope, boolean skipOptionals) throws MojoExecutionException { Log log = getLog(); MavenProject parentArtifactProject; try { parentArtifactProject = mavenProjectBuilder.buildFromRepository(artifact, remoteArtifactRepositories, localRepository); } catch (ProjectBuildingException e) { log.warn("Could not load artifacts recursively. For artifact '" + ArtifactUtilities.toString(artifact) + "' the project creation failed.", e); return null; } @SuppressWarnings("unchecked") List<Dependency> dependencies = parentArtifactProject.getDependencies(); @SuppressWarnings("unchecked") List<License> licenses = parentArtifactProject.getLicenses(); DependencyTree dependencyTree = new DependencyTree(artifact, licenses); if (parentDependencyTree != null) { parentDependencyTree.addDependency(dependencyTree); } if ((dependencies != null) && ((recursive) || (artifact == mavenProject.getArtifact()))) { for (Dependency dependency : dependencies) { StringBuffer buffer = new StringBuffer(); if (log.isDebugEnabled()) { for (int i = 0; i < depth; i++) { buffer.append(" "); } buffer.append("\\-> "); log.debug(buffer.toString() + ArtifactUtilities.toString(dependency)); } if (skipTestScope && Artifact.SCOPE_TEST.equals(dependency.getScope())) { if (log.isDebugEnabled()) { log.debug(buffer.toString() + " >> test scope is skipped"); } continue; } if (skipProvidedScope && Artifact.SCOPE_PROVIDED.equals(dependency.getScope())) { if (log.isDebugEnabled()) { log.debug(buffer.toString() + " >> provided scope is skipped"); } continue; } if (skipOptionals && dependency.isOptional()) { if (log.isDebugEnabled()) { log.debug(buffer.toString() + " >> optional is skipped"); } continue; } if (hasCycle(dependencyTree, dependency)) { if (log.isDebugEnabled()) { log.debug(buffer.toString() + " >> cylce found and needs to be skipped"); } continue; } Artifact dependencyArtifact = DependencyUtilities.buildArtifact(artifact, dependency); loadArtifacts(depth + 1, dependencyTree, dependencyArtifact, recursive, skipTestScope, skipProvidedScope, skipOptionals); } } return dependencyTree; } private boolean hasCycle(DependencyTree dependencyTree, Dependency dependency) { Log log = getLog(); List<DependencyTree> path = new ArrayList<>(); while (dependencyTree != null) { path.add(0, dependencyTree); Artifact artifact = dependencyTree.getArtifact(); String artifactString = ArtifactUtilities.toString(artifact); String dependencyString = ArtifactUtilities.toString(dependency); if (artifactString.equals(dependencyString)) { while (dependencyTree != null) { path.add(0, dependencyTree); dependencyTree = dependencyTree.getParent(); } log.warn("WARNING! Cycle detected for '" + artifactString + "':"); for (int i = 0; i < path.size(); i++) { DependencyTree node = path.get(i); StringBuffer buffer = new StringBuffer(); for (int col = 0; col < i; col++) { buffer.append(" "); } buffer.append("\\-> "); buffer.append(ArtifactUtilities.toString(node.getArtifact())); log.warn(buffer.toString()); } StringBuffer buffer = new StringBuffer(); buffer.append(" !! "); for (int col = 0; col < path.size(); col++) { buffer.append(" "); } buffer.append("\\-> "); buffer.append(artifactString); buffer.append(" !! "); log.warn(buffer.toString()); return true; } dependencyTree = dependencyTree.getParent(); } return false; } }