org.xchain.tools.monitoring.MonitoringMojo.java Source code

Java tutorial

Introduction

Here is the source code for org.xchain.tools.monitoring.MonitoringMojo.java

Source

/**
 *    Copyright 2011 meltmedia
 *
 *    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.xchain.tools.monitoring;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.model.Resource;

import java.io.InputStream;
import java.io.IOException;
import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.jar.JarFile;
import java.util.jar.JarEntry;

import org.xml.sax.Attributes;

import org.apache.commons.digester.Digester;
import org.apache.commons.digester.Rule;
import org.apache.commons.digester.WithDefaultsRulesWrapper;

import org.xml.sax.SAXException;

import org.codehaus.plexus.util.xml.XMLWriter;
import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter;

/**
 * @goal monitoring-info
 * @phase generate-resources
 * @requiresProject
 * @requiresDependencyResolution runtime
 * @author Christian Trimble
 */
public class MonitoringMojo extends AbstractMojo {
    /**
     * Location of the file.
     * @parameter expression="${project.build.directory}"
     * @required
     */
    private File outputDirectory;

    /**
     * The monitor flag.  If true, then the monitoring information will be generated.
     * @parameter expression="${build.monitor}" default-value="false"
     */
    private boolean monitor;

    /**
     * The packaging type.
     * @parameter expression="${project.packaging}"
     * @required
     */
    private String packaging;

    /**
     * The maven project for this artifact.
     * @parameter expression="${project}"
     * @required
     */
    private MavenProject project;

    /**
     * The set of war dependencies that will be included in this project.
     * @parameter
     */
    private Resource[] webResources;

    public void execute() throws MojoExecutionException {
        getLog().info("Executing the monitoring information plugin.");
        if (monitor) {
            getLog().info("Building monitoring information.");

            if (!"jar".equals(packaging) && !"war".equals(packaging)) {
                throw new MojoExecutionException(
                        "Mojo information can only be created for projects packaged as 'jar' or 'war'.");
            }

            MonitoringInfo monitoringInfo = new MonitoringInfo();

            // find all of the directories to get resources from.  If they are filtered, then ignore them.
            List<Resource> resourceSet = (List<Resource>) project.getResources();
            for (Resource resource : resourceSet) {
                monitoringInfo.getResourceList().add(copy(resource));
            }

            // if this is a war, then we need to merge all of the monitoring-info.xml files into this file.
            if ("war".equals(packaging)) {
                if (webResources != null) {
                    for (Resource resource : webResources) {
                        monitoringInfo.getWarResourceList().add(copy(resource));
                    }

                    // get all of the directories that hold resources, both static and generated.
                    Set<Artifact> artifactSet = (Set<Artifact>) project.getArtifacts();
                    for (Artifact artifact : artifactSet) {
                        // if this file is a jar, then try to load its monitoring-info.xml file and add it to this class.
                        if ("war".equals(artifact.getType())) {
                            mergeWarMonitoringInfo(monitoringInfo, artifact.getFile());
                        }
                    }
                }
            }

            File metaInfDir = new File(project.getBuild().getOutputDirectory(), "META-INF");
            metaInfDir.mkdirs();

            getLog().info("Creating '" + metaInfDir.toString() + "'.");

            File monitoringFile = new File(metaInfDir, "monitoring-info.xml");
            PrintWriter writer = null;
            XMLWriter xmlWriter = null;

            // write the artifact out.
            try {
                writer = new PrintWriter(monitoringFile, "UTF-8");
                xmlWriter = new PrettyPrintXMLWriter(writer, "  ");

                xmlWriter.startElement("monitoring-info");

                // write the resource tags.
                for (Resource resource : monitoringInfo.getResourceList()) {
                    xmlWriter.startElement("resource");
                    writeResource(xmlWriter, resource);
                    xmlWriter.endElement();
                }
                for (Resource warResource : monitoringInfo.getWarResourceList()) {
                    xmlWriter.startElement("web-resource");
                    writeResource(xmlWriter, warResource);
                    xmlWriter.endElement();
                }
                xmlWriter.endElement();

                writer.flush();
            } catch (IOException ioe) {
                throw new MojoExecutionException("Could not write out META-INF/monitoring-info.xml file.", ioe);
            } finally {
                if (writer != null) {
                    try {
                        writer.close();
                    } catch (Exception ioe) {
                        getLog().warn("Could not close writer for META-INF/monitoring-info.xml file.", ioe);
                    }
                }
            }
        }
    }

    private void writeResource(XMLWriter xmlWriter, Resource resource) {
        xmlWriter.startElement("directory");
        xmlWriter.writeText(resource.getDirectory());
        xmlWriter.endElement();
        xmlWriter.startElement("filtering");
        xmlWriter.writeText("" + resource.isFiltering());
        xmlWriter.endElement();
        if (resource.getIncludes().size() > 0) {
            xmlWriter.startElement("includes");
            for (String include : ((List<String>) resource.getIncludes())) {
                xmlWriter.startElement("include");
                xmlWriter.writeText(include);
                xmlWriter.endElement();
            }
            xmlWriter.endElement();
        }
        if (resource.getExcludes().size() > 0) {
            xmlWriter.startElement("excludes");
            for (String exclude : ((List<String>) resource.getExcludes())) {
                xmlWriter.startElement("exclude");
                xmlWriter.writeText(exclude);
                xmlWriter.endElement();
            }
            xmlWriter.endElement();
        }
    }

    private class LoggingRule extends Rule {
        public void begin(String namespace, String name, Attributes attributes) throws Exception {
            getLog().warn("Unknown monitoring-info element encountered {" + namespace + "}" + name + ".");
        }
    }

    private void mergeWarMonitoringInfo(MonitoringInfo monitoringInfo, File file) throws MojoExecutionException {
        JarFile artifactJar = null;
        JarEntry monitoringInfoEntry = null;
        InputStream in = null;
        try {
            getLog().info("Getting monitoring info from file " + file.toString());
            artifactJar = new JarFile(file);
            monitoringInfoEntry = artifactJar.getJarEntry("WEB-INF/classes/META-INF/monitoring-info.xml");
            if (monitoringInfoEntry != null) {
                in = artifactJar.getInputStream(monitoringInfoEntry);

                // digest the xml file and get all of the entries.
                Digester digester = new Digester();
                digester.push(monitoringInfo);
                digester.addRuleSet(new MonitoringInfoRuleSet());
                WithDefaultsRulesWrapper wrapper = new WithDefaultsRulesWrapper(digester.getRules());
                wrapper.addDefault(new LoggingRule());
                digester.setRules(wrapper);
                digester.parse(in);
            } else {
                getLog().info("Monitoring info file not found in " + file.toString());
            }
        } catch (SAXException se) {
            throw new MojoExecutionException("Could not parse a monitoring-info.xml file.", se);
        } catch (IOException ioe) {
            throw new MojoExecutionException("Could not open jar file.", ioe);
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException ioe) {
                    getLog().warn("Could not close a jar entry input stream.", ioe);
                }
            }
            try {
                artifactJar.close();
            } catch (IOException ioe) {
                getLog().warn("Could not close a jar.", ioe);
            }
        }
    }

    private Resource copy(Resource resource) {
        Resource copy = new Resource();
        copy.setDirectory(resource.getDirectory());
        copy.setTargetPath(resource.getTargetPath());
        copy.setFiltering(resource.isFiltering());
        copy.setModelEncoding(resource.getModelEncoding());
        copy.setIncludes(copy(resource.getIncludes()));
        copy.setExcludes(copy(resource.getExcludes()));
        return copy;
    }

    private List copy(List list) {
        List copy = new ArrayList();
        if (list != null) {
            copy.addAll(list);
        }
        return copy;
    }
}