/** * Copyright 2015-2016 Red Hat, Inc, and 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.wildfly.swarm.plugin.maven; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.SimpleFileVisitor; import java.nio.file.attribute.BasicFileAttributes; import java.util.Enumeration; import java.util.Set; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.maven.artifact.Artifact; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Execute; import org.apache.maven.plugins.annotations.LifecyclePhase; 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; /** * @author Bob McWhirter */ @Mojo(name = "analyze", requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME) @Execute(phase = LifecyclePhase.PACKAGE) public class AnalyzeMojo extends AbstractMojo { private static Pattern ARTIFACT = Pattern.compile("<artifact name=\"([^\"]+)\""); private static Pattern MODULE = Pattern.compile("<module name=\"([^\"]+)\".*(slot=\"[^\"]+\")?"); @Parameter(defaultValue = "${project.build.directory}") protected String projectBuildDir; @Parameter(defaultValue = "${project}", readonly = true) protected MavenProject project; @Parameter(alias = "gav", defaultValue = "${gav}", required = true) private String gav; private Path dir; private Path modulesDir; private Graph graph = new Graph(); @Override public void execute() throws MojoExecutionException, MojoFailureException { getLog().info("Analyzing for " + this.gav); this.dir = Paths.get(this.projectBuildDir, "wildfly-swarm-archive"); this.modulesDir = this.dir.resolve("modules"); try { walkModulesDir(); walkDependencies(); } catch (IOException e) { throw new MojoFailureException("Unable to inspect modules/ dir", e); } Graph.Artifact artifact = this.graph.getClosestArtifact(this.gav); if (artifact == null) { throw new MojoFailureException("Unable to find artifact: " + this.gav); } DumpGraphVisitor visitor = new DumpGraphVisitor(); artifact.accept(visitor); } protected void walkModulesDir() throws IOException { Files.walkFileTree(this.modulesDir, new SimpleFileVisitor<Path>() { @Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { if (file.getFileName().toString().equals("module.xml")) { Path dir = file.getParent(); Path relative = modulesDir.relativize(dir); String slot = relative.getFileName().toString(); String module = relative.getParent().toString().replace(File.separatorChar, '.'); analyzeModuleXml(module, slot, new FileInputStream(file.toFile())); } return super.visitFile(file, attrs); } }); } protected void walkDependencies() throws IOException { Set<Artifact> deps = this.project.getArtifacts(); for (Artifact each : deps) { walkDependency(each); } } protected void walkDependency(Artifact artifact) throws IOException { if (artifact.getFile() != null && artifact.getType().equals("jar")) { try (JarFile jar = new JarFile(artifact.getFile())) { Enumeration<JarEntry> entries = jar.entries(); while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); if (entry.getName().startsWith("modules/") && entry.getName().endsWith("module.xml")) { String[] parts = entry.getName().split("/"); String slot = parts[parts.length - 2]; String module = null; for (int i = 1; i < parts.length - 2; ++i) { if (module != null) { module = module + "."; ; } else { module = ""; } module = module + parts[i]; } analyzeModuleXml(module, slot, jar.getInputStream(entry)); } } } } } protected void analyzeModuleXml(String module, String slot, InputStream in) throws IOException { Graph.Module curModule = this.graph.getModule(module, slot); try (BufferedReader reader = new BufferedReader(new InputStreamReader(in))) { String line = null; while ((line = reader.readLine()) != null) { Matcher matcher = null; matcher = ARTIFACT.matcher(line); if (matcher.find()) { String gav = matcher.group(1); String parts[] = gav.split(":"); String groupId = parts[0]; String artifactId = parts[1]; String version = parts[2]; String classifier = null; if (parts.length >= 4) { classifier = parts[3]; } curModule.addArtifact(this.graph.getArtifact(groupId, artifactId, version, classifier)); } else { matcher = MODULE.matcher(line); if (matcher.find()) { String depModule = matcher.group(1); String depSlot = "main"; if (matcher.groupCount() >= 3) { depSlot = matcher.group(3); } curModule.addDependency(this.graph.getModule(depModule, depSlot)); } } } } } }