Java tutorial
/* * RHQ Management Platform * Copyright 2013, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ package org.rhq.maven.plugins; import java.io.File; import java.io.IOException; import java.util.Collections; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.jar.JarFile; import java.util.zip.ZipEntry; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.factory.ArtifactFactory; import org.apache.maven.artifact.metadata.ArtifactMetadataSource; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.resolver.ArtifactNotFoundException; import org.apache.maven.artifact.resolver.ArtifactResolutionException; import org.apache.maven.artifact.resolver.ArtifactResolutionResult; import org.apache.maven.artifact.resolver.ArtifactResolver; import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.Component; 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; import static org.codehaus.plexus.util.StringUtils.join; import static org.rhq.maven.plugins.Utils.findParentPlugins; import static org.rhq.maven.plugins.Utils.getAgentPluginArchiveFile; import static org.rhq.maven.plugins.Utils.redirectOuput; /** * Validates a freshly built RHQ Agent Plugin. * * @author Thomas Segismont */ @Mojo(name = "validate", defaultPhase = LifecyclePhase.PACKAGE, requiresDependencyResolution = ResolutionScope.COMPILE, threadSafe = true) public class ValidateMojo extends AbstractMojo { private static final String PLUGIN_VALIDATOR_MODULE_GROUP_ID = "org.rhq"; private static final String PLUGIN_VALIDATOR_MODULE_ARTIFACT_ID = "rhq-core-plugin-container"; private static final String PLUGIN_VALIDATOR_MAIN_CLASS = "org.rhq.core.pc.plugin.PluginValidator"; /** * The build directory (root of build works) */ @Parameter(defaultValue = "${project.build.directory}", required = true, readonly = true) private File buildDirectory; /** * The name of the generated RHQ agent plugin archive */ @Parameter(defaultValue = "${project.build.finalName}", required = true, readonly = true) private String finalName; /** * Version of the RHQ Plugin Container API */ @Parameter(required = true) private String rhqVersion; /** * Whether to fail the build if an error occurs while validating the plugin. */ @Parameter(defaultValue = "true") private boolean failOnError; /** * Whether to skip the execution of this mojo. */ @Parameter(defaultValue = "false") private boolean skipValidate; @Parameter(defaultValue = "${project.remoteArtifactRepositories}", required = true, readonly = true) private List remoteRepositories; @Parameter(defaultValue = "${localRepository}", required = true, readonly = true) private ArtifactRepository localRepository; @Component private MavenProject project; @Component private ArtifactFactory artifactFactory; @Component private ArtifactResolver artifactResolver; @Component private ArtifactMetadataSource artifactMetadataSource; @Override public void execute() throws MojoExecutionException, MojoFailureException { if (skipValidate) { getLog().info("Skipped execution"); return; } File agentPluginArchive = getAgentPluginArchiveFile(buildDirectory, finalName); if (!agentPluginArchive.exists() && agentPluginArchive.isFile()) { throw new MojoExecutionException("Agent plugin archive does not exist: " + agentPluginArchive); } Set<File> parentPlugins; try { parentPlugins = findParentPlugins(project); } catch (IOException e) { throw new MojoExecutionException("Error while searching for parent plugins", e); } validate(agentPluginArchive, parentPlugins); } private void validate(File agentPluginArchive, Set<File> parentPlugins) throws MojoExecutionException { JarFile jarFile = null; try { jarFile = new JarFile(agentPluginArchive); if (jarFile.getEntry("META-INF/rhq-plugin.xml") == null) { handleFailure("Descriptor missing"); } } catch (Exception e) { handleException(e); } finally { if (jarFile != null) { try { jarFile.close(); } catch (Exception e) { handleException(e); } } } // Run the plugin validator as a forked process Process process = null; try { String pluginValidatorClasspath = buildPluginValidatorClasspath(agentPluginArchive, parentPlugins); String javaCommand = buildJavaCommand(); ProcessBuilder processBuilder = buildProcessBuilder(javaCommand, pluginValidatorClasspath); process = processBuilder.start(); redirectOuput(process); int exitCode = process.waitFor(); if (exitCode != 0) { handleFailure("Invalid plugin"); } } catch (Exception e) { handleException(e); } finally { if (process != null) { process.destroy(); } } } private String buildPluginValidatorClasspath(File agentPluginArchive, Set<File> parentPlugins) throws ArtifactNotFoundException, ArtifactResolutionException, IOException { // Resolve dependencies of the plugin validator module Artifact dummyOriginatingArtifact = artifactFactory.createBuildArtifact("org.apache.maven.plugins", "maven-downloader-plugin", "1.0", "jar"); Artifact pluginContainerArtifact = this.artifactFactory.createArtifact(PLUGIN_VALIDATOR_MODULE_GROUP_ID, PLUGIN_VALIDATOR_MODULE_ARTIFACT_ID, rhqVersion, null, "jar"); ArtifactResolutionResult artifactResolutionResult = artifactResolver.resolveTransitively( Collections.singleton(pluginContainerArtifact), dummyOriginatingArtifact, localRepository, remoteRepositories, artifactMetadataSource, null); List<String> classpathElements = new LinkedList<String>(); // Add all compile scope dependencies to the classpath Iterator iterator = artifactResolutionResult.getArtifacts().iterator(); ScopeArtifactFilter artifactFilter = new ScopeArtifactFilter(Artifact.SCOPE_COMPILE); while (iterator.hasNext()) { Artifact artifact = (Artifact) iterator.next(); if (!artifact.isOptional() && artifact.getType().equals("jar") && artifactFilter.include(artifact)) { classpathElements.add(artifact.getFile().getAbsolutePath()); } } classpathElements.add(agentPluginArchive.getAbsolutePath()); for (File parentPlugin : parentPlugins) { classpathElements.add(parentPlugin.getAbsolutePath()); } String pluginValidatorClasspath = join(classpathElements.iterator(), File.pathSeparator); if (getLog().isDebugEnabled()) { getLog().debug("pluginValidatorClasspath = " + pluginValidatorClasspath); } return pluginValidatorClasspath; } private String buildJavaCommand() { String javaHome = System.getProperty("java.home"); String javaCommand = javaHome + File.separator + "bin" + File.separator + "java"; if (getLog().isDebugEnabled()) { getLog().debug("javaCommand = " + javaCommand); } return javaCommand; } private ProcessBuilder buildProcessBuilder(String javaCommand, String pluginValidatorClasspath) { List<String> command = new LinkedList<String>(); command.add(javaCommand); command.add("-classpath"); command.add(pluginValidatorClasspath); command.add("-Dorg.apache.commons.logging.Log=org.apache.commons.logging.impl.SimpleLog"); command.add(PLUGIN_VALIDATOR_MAIN_CLASS); if (getLog().isDebugEnabled()) { getLog().debug("Built command to execute = " + join(command.iterator(), " ")); } return new ProcessBuilder().directory(buildDirectory).command(command); } private void handleFailure(String message) throws MojoFailureException { if (failOnError) { throw new MojoFailureException(message); } getLog().error(message); } private void handleException(Exception e) throws MojoExecutionException { if (failOnError) { throw new MojoExecutionException(e.getMessage(), e); } getLog().error(e.getMessage(), e); } }