org.apache.marmotta.maven.plugins.refpack.RefPackMojo.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.marmotta.maven.plugins.refpack.RefPackMojo.java

Source

/**
 * 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;
        }

    }
}