blob: 74707cb70f3fb1727add9a9450ab8eb64d218195 [file] [log] [blame]
/**
* 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.marmotta.maven.plugins.refpack;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.model.Model;
import org.apache.maven.model.building.ModelBuildingRequest;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.*;
import org.apache.maven.project.*;
import org.jdom2.Element;
import org.jdom2.Text;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.sonatype.aether.RepositorySystem;
import org.sonatype.aether.RepositorySystemSession;
import org.sonatype.aether.artifact.Artifact;
import org.sonatype.aether.collection.CollectRequest;
import org.sonatype.aether.collection.DependencyCollectionException;
import org.sonatype.aether.graph.Dependency;
import org.sonatype.aether.graph.DependencyNode;
import org.sonatype.aether.repository.RemoteRepository;
import org.sonatype.aether.resolution.DependencyRequest;
import org.sonatype.aether.resolution.DependencyResolutionException;
import org.sonatype.aether.resolution.DependencyResult;
import org.sonatype.aether.util.artifact.DefaultArtifact;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* Generate IzPack refpack descriptions from Maven dependencies
*/
@Mojo(name = "generate", defaultPhase = LifecyclePhase.VALIDATE, requiresDependencyResolution = ResolutionScope.COMPILE)
public class RefPackMojo extends AbstractMojo {
/**
* Location of the file.
*/
@Parameter(property="project.build.directory", required = true)
private File outputDirectory;
@Parameter(property = "project", required = true, readonly = true)
private MavenProject project;
/**
* The Group Identifier of the artifacts that should be considered local modules. When walking
* the dependency tree, the process will break at each module of this group id and instead add
* a dependency to the other module to the refpacks.
*/
@Parameter(property="refpack.moduleGroupId", defaultValue="org.apache.marmotta", required = true)
private String moduleGroupId;
/**
* The entry point to Aether, i.e. the component doing all the work.
*
*/
@Component
private RepositorySystem repoSystem;
@Parameter(defaultValue = "${repositorySystemSession}", readonly = true)
private RepositorySystemSession session;
/**
* The project's remote repositories to use for the resolution of project dependencies.
*/
@Parameter(defaultValue = "${project.remoteProjectRepositories}", readonly = true)
private List<RemoteRepository> projectRepos;
@Component
private ProjectBuilder projectBuilder;
@Component
private ArtifactFactory artifactFactory;
/**
* The required modules of the refpack
*/
@Parameter(property = "refpack.requiredModules")
private List<String> requiredModules;
// we collect here the library dependencies of each module, so we can identify which of the dependencies are already
// covered by another module the current module depends on
private HashMap<Artifact,Set<Artifact>> moduleLibraries;
// and here we collect the module dependencies of each module
private HashMap<Artifact,Set<Artifact>> moduleDependencies;
public void execute() throws MojoExecutionException {
moduleLibraries = new HashMap<Artifact, Set<Artifact>>();
moduleDependencies = new HashMap<Artifact, Set<Artifact>>();
getLog().info("generating reference packs for group id "+moduleGroupId);
for(org.apache.maven.artifact.Artifact artifact : project.getArtifacts()) {
if(artifact.getGroupId().equals(moduleGroupId)) {
DefaultArtifact aetherArtifact = new DefaultArtifact(artifact.getGroupId(),artifact.getArtifactId(), artifact.getType(), artifact.getVersion());
Dependency rootDependency = new Dependency(aetherArtifact, "runtime");
try {
CollectRequest collectRequest = new CollectRequest();
collectRequest.setRoot(rootDependency);
collectRequest.setRepositories(projectRepos);
DependencyNode rootNode = repoSystem.collectDependencies( session, collectRequest ).getRoot();
DependencyRequest request = new DependencyRequest(rootNode,null);
DependencyResult result = repoSystem.resolveDependencies(session,request);
getLog().info("Artifact: " + aetherArtifact);
for(DependencyNode child : result.getRoot().getChildren()) {
if(child.getDependency().getArtifact().getGroupId().equals(moduleGroupId)) {
processModule(child);
}
}
processModule(result.getRoot());
/*
deps = aether.resolve(aetherArtifact, JavaScopes.RUNTIME);
getLog().info("Artifact: "+aetherArtifact);
for(Artifact dep : deps) {
getLog().info("- dependency "+dep.getFile().getAbsolutePath());
}
*/
} catch (DependencyResolutionException e) {
getLog().warn("could not resolve dependencies for artifact "+aetherArtifact,e);
} catch (DependencyCollectionException e) {
getLog().warn("could not resolve dependencies for artifact "+aetherArtifact,e);
}
}
}
}
/**
* Collect the dependencies to other libraries that are not already collected by modules the current
* module depends on.
*
* @param node
* @param currentModule
*/
private void collectLibraryDependencies(DependencyNode node, Artifact currentModule) {
String groupId = node.getDependency().getArtifact().getGroupId();
String artifactId = node.getDependency().getArtifact().getArtifactId();
if(!isPackDependency(groupId, artifactId)) {
// first check if the current artifact is already covered by a module the current module depends on
for(Artifact dependentArtifact : moduleDependencies.get(currentModule)) {
if(moduleLibraries.containsKey(dependentArtifact) &&
moduleLibraries.get(dependentArtifact).contains(node.getDependency().getArtifact())) {
return;
}
}
// collect the current dependency for the module
moduleLibraries.get(currentModule).add(node.getDependency().getArtifact());
for(DependencyNode child : node.getChildren()) {
collectLibraryDependencies(child, currentModule);
}
}
}
private boolean isPackDependency(String groupId, String artifactId) {
// only marmotta group-id and artifacts starting with marmotta-
return groupId.equals(moduleGroupId) && artifactId.startsWith("marmotta-")
// but not the commons and the JS-client
&& !artifactId.equals("marmotta-commons") && !artifactId.equals("marmotta-client-js")
// and not the marmotta-sesame-tools
&& !artifactId.startsWith("marmotta-util-") && !artifactId.startsWith("marmotta-sail-")
&& !artifactId.startsWith("marmotta-rio-") && !artifactId.startsWith("marmotta-model-");
}
/**
* Collect the dependencies to other modules inside the same project
* @param node
* @param currentModule
*/
private void collectModuleDependencies(DependencyNode node, Artifact currentModule) {
String groupId = node.getDependency().getArtifact().getGroupId();
String artifactId = node.getDependency().getArtifact().getArtifactId();
if(isPackDependency(groupId, artifactId)) {
moduleDependencies.get(currentModule).add(node.getDependency().getArtifact());
}
}
private void processModule(DependencyNode moduleNode) {
CollectRequest collectRequest = new CollectRequest();
collectRequest.setRoot(moduleNode.getDependency());
collectRequest.setRepositories(projectRepos);
try {
// collect all the dependency graph for the module, and print it until we reach a dependency to a local module
DependencyNode rootNode = repoSystem.collectDependencies( session, collectRequest ).getRoot();
DependencyRequest request = new DependencyRequest(rootNode,null);
DependencyResult result = repoSystem.resolveDependencies(session,request);
// add entry to module dependencies
moduleLibraries.put(moduleNode.getDependency().getArtifact(), new HashSet<Artifact>());
moduleDependencies.put(moduleNode.getDependency().getArtifact(), new HashSet<Artifact>());
getLog().info("processing module "+moduleNode.getDependency().getArtifact().getArtifactId()+":");
for(DependencyNode child : result.getRoot().getChildren()) {
collectModuleDependencies(child,moduleNode.getDependency().getArtifact());
}
for(DependencyNode child : result.getRoot().getChildren()) {
collectLibraryDependencies(child, moduleNode.getDependency().getArtifact());
}
// information output
/*
for(Artifact otherModule : moduleDependencies.get(moduleNode.getDependency().getArtifact())) {
getLog().info(" - depending on module "+otherModule.getArtifactId());
}
for(Artifact library : moduleLibraries.get(moduleNode.getDependency().getArtifact())) {
getLog().info(" - depending on library "+library);
}
*/
File destination = new File(outputDirectory, moduleNode.getDependency().getArtifact().getArtifactId() + ".xml");
if (!destination.getParentFile().exists()) {
destination.getParentFile().mkdirs();
}
if (!destination.exists()) {
destination.createNewFile();
}
getLog().info("writing refpack to " + destination.getAbsolutePath());
// write to output directory
writeModuleXML(moduleNode.getDependency().getArtifact(), new FileOutputStream(destination));
} catch (DependencyCollectionException e) {
getLog().error("error while collecting dependencies for module " + moduleNode.getDependency().getArtifact(), e);
} catch (DependencyResolutionException e) {
getLog().error("error while resolving dependencies for module " + moduleNode.getDependency().getArtifact(), e);
} catch (IOException e) {
getLog().error("I/O error while writing refpack for module " + moduleNode.getDependency().getArtifact(), e);
}
}
private void writeModuleXML(Artifact module, OutputStream out) throws IOException {
Element installation = new Element("installation");
installation.setAttribute("version","1.0");
Element packs = new Element("packs");
installation.addContent(packs);
Element pack = new Element("pack");
packs.addContent(pack);
// get the model for the artifact, we read name and description from it
Model pom = getArtifactModel(module);
// set name of pack from artifact
if(pom != null && pom.getName() != null) {
pack.setAttribute("name",pom.getName());
} else {
pack.setAttribute("name",module.getArtifactId());
}
if(pom != null && pom.getDescription() != null) {
Element description = new Element("description");
description.setText(Text.normalizeString(pom.getDescription()));
pack.addContent(description);
}
// add a file entry for the module itself
if(!module.getExtension().equals("war")) {
Element mainFile = new Element("file");
pack.addContent(mainFile);
mainFile.setAttribute("src",module.getFile().getAbsolutePath());
mainFile.setAttribute("targetdir","$INSTALL_PATH/apache-tomcat-$TOMCAT_VERSION/webapps/marmotta/WEB-INF/lib");
}
// add a file entry for each library of the artifact
for(Artifact library : moduleLibraries.get(module)) {
Element file = new Element("file");
pack.addContent(file);
file.setAttribute("src",library.getFile().getAbsolutePath());
file.setAttribute("targetdir","$INSTALL_PATH/apache-tomcat-$TOMCAT_VERSION/webapps/marmotta/WEB-INF/lib");
}
// add a depends name for each module the current one depends on (in case the project is not the webapp)
if(!module.getExtension().equals("war")) {
if(requiredModules.contains(module.getArtifactId())) {
pack.setAttribute("required","yes");
} else {
pack.setAttribute("required","no");
}
for(Artifact dependency : moduleDependencies.get(module)) {
Element depends = new Element("depends");
pack.addContent(depends);
// get the model for the artifact, we read name and description from it
Model pom2 = getArtifactModel(dependency);
// set name of pack from artifact
if(pom2 != null && pom2.getName() != null) {
depends.setAttribute("packname", pom2.getName());
} else {
depends.setAttribute("packname",module.getArtifactId());
}
}
} else {
pack.setAttribute("required","yes");
// add webapp directory from installer configuration
Element appDir = new Element("fileset");
appDir.setAttribute("dir",outputDirectory+"/../webapp/");
appDir.setAttribute("targetdir","$INSTALL_PATH/apache-tomcat-$TOMCAT_VERSION/webapps/marmotta/");
appDir.setAttribute("includes","**");
pack.addContent(appDir);
Element logDir = new Element("fileset");
logDir.setAttribute("dir",outputDirectory+"/../log/");
logDir.setAttribute("targetdir","$INSTALL_PATH/apache-tomcat-$TOMCAT_VERSION/logs/");
logDir.setAttribute("includes","**");
pack.addContent(logDir);
}
XMLOutputter writer = new XMLOutputter(Format.getPrettyFormat());
writer.output(installation,out);
}
private Model getArtifactModel(Artifact artifact) {
org.apache.maven.artifact.Artifact mavenArtifact = artifactFactory.createArtifact(artifact.getGroupId(),artifact.getArtifactId(),artifact.getVersion(),"runtime",artifact.getExtension());
DefaultProjectBuildingRequest req = new DefaultProjectBuildingRequest();
req.setRepositorySession(session);
req.setValidationLevel(ModelBuildingRequest.VALIDATION_LEVEL_STRICT);
try {
ProjectBuildingResult res = projectBuilder.build(mavenArtifact, req);
return res.getProject().getModel();
} catch (ProjectBuildingException e) {
getLog().warn("error building artifact model for artifact "+artifact,e);
return null;
}
}
}