org.lilyproject.tools.mavenplugin.lilyruntimedepresolver.LilyRuntimeProjectClasspath.java Source code

Java tutorial

Introduction

Here is the source code for org.lilyproject.tools.mavenplugin.lilyruntimedepresolver.LilyRuntimeProjectClasspath.java

Source

/*
 * Copyright 2010 Outerthought bvba
 *
 * 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.lilyproject.tools.mavenplugin.lilyruntimedepresolver;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.factory.ArtifactFactory;
import org.apache.maven.artifact.repository.ArtifactRepository;
import org.apache.maven.artifact.resolver.ArtifactResolver;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.logging.Log;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.MavenProjectBuilder;
import org.lilyproject.util.Version;
import org.springframework.util.AntPathMatcher;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class LilyRuntimeProjectClasspath {
    protected XPathFactory xpathFactory = XPathFactory.newInstance();
    private String lilyVersion;
    private ArtifactFilter filter;
    private ArtifactFactory artifactFactory;
    protected ArtifactResolver resolver;
    protected ArtifactRepository localRepository;
    private Log log;

    public LilyRuntimeProjectClasspath(Log log, ArtifactFilter filter, ArtifactFactory artifactFactory,
            ArtifactResolver resolver, ArtifactRepository localRepository) {
        this.filter = filter;
        this.artifactFactory = artifactFactory;
        this.resolver = resolver;
        this.localRepository = localRepository;
        this.log = log;
        this.lilyVersion = Version.readVersion("org.lilyproject", "lily-runtime-plugin");
    }

    public Set<Artifact> getAllArtifacts(Set<Artifact> moduleArtifacts, List remoteRepositories)
            throws MojoExecutionException {
        Set<Artifact> result = new HashSet<Artifact>();
        result.addAll(moduleArtifacts);

        for (Artifact moduleArtifact : moduleArtifacts) {
            result.addAll(getClassPathArtifacts(moduleArtifact, remoteRepositories));
        }

        return result;
    }

    public ModuleArtifacts getModuleArtifactsFromLilyRuntimeConfig(File confDirectory, List remoteRepos)
            throws MojoExecutionException {
        File configFile = new File(confDirectory, "runtime/wiring.xml");
        try {
            FileInputStream fis = null;
            try {
                fis = new FileInputStream(configFile);

                ModuleArtifacts result = new ModuleArtifacts();
                result.artifacts = getModuleArtifactsFromLilyRuntimeConfig(fis, configFile.getAbsolutePath(),
                        remoteRepos);

                return result;
            } finally {
                if (fis != null) {
                    fis.close();
                }
            }
        } catch (Exception e) {
            throw new MojoExecutionException("Error reading lily runtime XML configuration from " + configFile, e);
        }
    }

    public ModuleArtifacts getModuleArtifactsFromLilyRuntimeConfig(Set<Artifact> dependencies,
            String[] wiringPathPatterns, MavenProjectBuilder mavenProjectBuilder, List remoteRepos)
            throws MojoExecutionException {

        ModuleArtifacts result = new ModuleArtifacts();
        result.artifacts = new HashSet<Artifact>();
        result.remoteRepositories = new ArrayList();

        boolean foundAtLeastOneWiring = false;

        try {
            // Search in the jars of all the direct dependencies of the project for the wiring file
            // (not sure if this won't be too slow? it's just to avoid the user having to specify the artifact)
            log.info("Searching " + dependencies.size() + " dependencies for " + wiringPathPatterns.length
                    + " path patterns.");

            for (Artifact artifact : dependencies) {
                if ("jar".equals(artifact.getType())) {
                    resolver.resolve(artifact, remoteRepos, localRepository);

                    AntPathMatcher matcher = new AntPathMatcher();
                    ZipFile zipFile;
                    zipFile = new ZipFile(artifact.getFile());
                    try {
                        Enumeration<? extends ZipEntry> entryEnum = zipFile.entries();
                        while (entryEnum.hasMoreElements()) {
                            ZipEntry zipEntry = entryEnum.nextElement();
                            for (String pattern : wiringPathPatterns) {
                                if (matcher.match(pattern, zipEntry.getName())) {
                                    foundAtLeastOneWiring = true;
                                    log.info("Reading " + zipEntry.getName() + " from " + artifact.getFile());
                                    Set<Artifact> moduleArtifacts = getModuleArtifactsFromLilyRuntimeConfig(
                                            zipFile.getInputStream(zipEntry), zipEntry.getName(), remoteRepos);

                                    MavenProject wiringSourceProject = mavenProjectBuilder
                                            .buildFromRepository(artifact, remoteRepos, localRepository);
                                    List repositories = wiringSourceProject.getRemoteArtifactRepositories();

                                    result.artifacts.addAll(moduleArtifacts);
                                    result.remoteRepositories.addAll(repositories);
                                }
                            }
                        }
                    } finally {
                        zipFile.close();
                    }
                }
            }

        } catch (Exception e) {
            throw new MojoExecutionException("Error searching/reading wiring.xml file from dependency jars.", e);
        }

        if (!foundAtLeastOneWiring) {
            throw new MojoExecutionException("No wiring xml's were found.");
        }

        return result;
    }

    public Set<Artifact> getModuleArtifactsFromLilyRuntimeConfig(InputStream wiringStream, String path,
            List remoteRepos) throws MojoExecutionException {
        Document configDoc;
        try {
            configDoc = parse(wiringStream);
        } catch (Exception e) {
            throw new MojoExecutionException("Error reading lily runtime wiring from " + path, e);
        }

        return getArtifacts(configDoc, "/*/modules/artifact", path, remoteRepos);
    }

    public Set<Artifact> getClassPathArtifacts(Artifact moduleArtifact, List remoteRepositories)
            throws MojoExecutionException {
        return getClassPathArtifacts(moduleArtifact, "LILY-INF/classloader.xml", remoteRepositories);
    }

    public Set<Artifact> getClassPathArtifacts(Artifact moduleArtifact, String entryPath, List remoteRepos)
            throws MojoExecutionException {
        ZipFile zipFile = null;
        InputStream is = null;
        Document classLoaderDocument;
        try {
            zipFile = new ZipFile(moduleArtifact.getFile());
            ZipEntry zipEntry = zipFile.getEntry(entryPath);
            if (zipEntry == null) {
                log.debug("No " + entryPath + " found in " + moduleArtifact);
                return Collections.emptySet();
            } else {
                is = zipFile.getInputStream(zipEntry);
                classLoaderDocument = parse(is);
            }
        } catch (Exception e) {
            throw new MojoExecutionException("Error reading " + entryPath + " from " + moduleArtifact, e);
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (Exception e) {
                    /* ignore */ }
            }
            if (zipFile != null) {
                try {
                    zipFile.close();
                } catch (Exception e) {
                    /* ignore */ }
            }
        }

        return getArtifacts(classLoaderDocument, "/classloader/classpath/artifact",
                "classloader.xml from module " + moduleArtifact, remoteRepos);
    }

    protected Set<Artifact> getArtifacts(Document configDoc, String artifactXPath, String sourceDescr,
            List remoteRepos) throws MojoExecutionException {
        Set<Artifact> artifacts = new HashSet<Artifact>();
        NodeList nodeList;
        try {
            nodeList = (NodeList) xpathFactory.newXPath().evaluate(artifactXPath, configDoc,
                    XPathConstants.NODESET);
        } catch (XPathExpressionException e) {
            throw new MojoExecutionException(
                    "Error resolving XPath expression " + artifactXPath + " on " + sourceDescr);
        }
        for (int i = 0; i < nodeList.getLength(); i++) {
            Element el = (Element) nodeList.item(i);
            String groupId = el.getAttribute("groupId");
            String artifactId = el.getAttribute("artifactId");
            String version = el.getAttribute("version");
            String classifier = el.getAttribute("classifier");
            if (version.equals("") && groupId.startsWith("org.lilyproject")) {
                version = lilyVersion;
            }
            if (classifier.equals("")) {
                classifier = null;
            }

            Artifact artifact = artifactFactory.createArtifactWithClassifier(groupId, artifactId, version, "jar",
                    classifier);

            if (filter == null || filter.include(artifact)) {
                if (!artifacts.contains(artifact)) {
                    if (resolver != null) {
                        try {
                            resolver.resolve(artifact, remoteRepos, localRepository);
                        } catch (Exception e) {
                            throw new MojoExecutionException(
                                    "Error resolving artifact listed in " + sourceDescr + ": " + artifact, e);
                        }
                    }
                    artifacts.add(artifact);
                }
            }
        }

        return artifacts;
    }

    protected Document parse(InputStream is) throws ParserConfigurationException, IOException, SAXException {
        DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        dbf.setNamespaceAware(true);
        return dbf.newDocumentBuilder().parse(is);
    }

    public static interface ArtifactFilter {
        boolean include(Artifact artifact);
    }
}