Java tutorial
/* * $Id$ * -------------------------------------------------------------------------------------- * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com * * The software in this package is published under the terms of the CPAL v1.0 * license, a copy of which has been included with this distribution in the * LICENSE.txt file. */ package com.mulesoft.jockey.maven; import com.mulesoft.jockey.AbstractCommand; import com.mulesoft.jockey.CommandRunner; import com.mulesoft.jockey.GroovyCommandWrapper; import com.mulesoft.jockey.script.GenerateCommands; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.zip.GZIPOutputStream; import org.apache.commons.compress.archivers.ArchiveException; import org.apache.commons.compress.archivers.ArchiveOutputStream; import org.apache.commons.compress.archivers.ArchiveStreamFactory; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream; import org.apache.commons.compress.archivers.zip.ZipArchiveEntry; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.resolver.ArtifactResolver; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.project.MavenProject; import org.apache.maven.project.MavenProjectHelper; import org.jruby.ext.posix.POSIX; import org.jruby.ext.posix.POSIX.ERRORS; import org.jruby.ext.posix.POSIXFactory; import org.jruby.ext.posix.POSIXHandler; /** * * @goal generate * @requiresDependencyResolution */ public class GenerateMojo extends AbstractMojo { private static int USER_READ = 00400; // read by owner private static int USER_WRITE = 00200;// write by owner private static int USER_EXEC = 00100; // execute/search by owner private static int GROUP_READ = 00040; // read by group private static int GROUP_EXEC = 00010; // execute/search by group private static int ALL_READ = 00004; // read by all private static int ALL_EXEC = 00001; // execute/search by all private static int EXECUTABLE_MODE = USER_EXEC | USER_READ | USER_WRITE | GROUP_EXEC | GROUP_READ | ALL_EXEC | ALL_READ; /** * @parameter default-value="${project.name}" */ private String distributionName; /** * The greeting to display. * * @parameter default-value="src/main/groovy" */ private String scriptsSourceDirectory; /** * Location to build the CLI distribution. * * @parameter expression="${outputDirectory}" * default-value="${project.build.directory}" * @optional */ private String buildDirectory; /** * @parameter default-value="${project}" * @required * @readonly */ private MavenProject project; /** * Used to look up Artifacts in the remote repository. * * @component */ protected ArtifactResolver resolver; /** * @parameter expression="${createZip}" * @optional */ private boolean createZip = true; /** * @parameter expression="${createTarGz}" * @optional */ private boolean createTarGz = true; /** * Maven ProjectHelper. * * @component * @readonly */ private MavenProjectHelper projectHelper; private URLClassLoader classLoader; public void execute() throws MojoExecutionException, MojoFailureException { getLog().info("Creating a new Mule Jockey distribution..."); getLog().info("Output directory " + buildDirectory); File distDir = new File(buildDirectory, distributionName); distDir.mkdirs(); populateScripts(distDir); copyDependencies(distDir); if (createZip) { createZip(distDir); } if (createTarGz) { createTarGz(distDir); } } protected ClassLoader getCompileClassLoader() throws Exception { if (classLoader == null) { List<URL> urls = new ArrayList<URL>(); for (Object object : project.getCompileClasspathElements()) { String path = (String) object; urls.add(new File(path).toURL()); } classLoader = new URLClassLoader(urls.toArray(new URL[] {})); } return classLoader; } private void createTarGz(File distDir) throws MojoExecutionException { File output = new File(buildDirectory, distributionName + ".tar.gz"); try { final OutputStream out = new FileOutputStream(output); TarArchiveOutputStream os = new TarArchiveOutputStream(new GZIPOutputStream(out)); os.setLongFileMode(TarArchiveOutputStream.LONGFILE_GNU); copyArchiveFile(distDir, os, false); os.finish(); os.close(); out.close(); } catch (IOException e) { throw new MojoExecutionException("Could not create zip file.", e); } projectHelper.attachArtifact(project, "tar.gz", "", output); } private void createZip(File distDir) throws MojoExecutionException { File output = new File(buildDirectory, distributionName + ".zip"); try { final OutputStream out = new FileOutputStream(output); ArchiveOutputStream os = new ArchiveStreamFactory().createArchiveOutputStream("zip", out); copyArchiveFile(distDir, os, true); os.finish(); os.close(); out.close(); } catch (IOException e) { throw new MojoExecutionException("Could not create zip file.", e); } catch (ArchiveException e) { throw new MojoExecutionException("Could not create zip file.", e); } projectHelper.attachArtifact(project, "zip", "", output); } private void copyArchiveFile(File file, ArchiveOutputStream os, boolean zipFile) throws IOException { if (file.isDirectory()) { File[] children = file.listFiles(); if (children != null) { for (File child : children) { copyArchiveFile(child, os, zipFile); } } } else { String relativePath = file.getAbsolutePath(); relativePath = relativePath.substring(new File(buildDirectory).getAbsolutePath().length() + 1); relativePath = relativePath.replaceAll("\\\\", "/"); if (zipFile) { ZipArchiveEntry entry = new ZipArchiveEntry(relativePath); os.putArchiveEntry(entry); if (isScript(file)) { entry.setUnixMode(EXECUTABLE_MODE); } } else { TarArchiveEntry entry = new TarArchiveEntry(relativePath); if (isScript(file)) { entry.setMode(EXECUTABLE_MODE); } entry.setSize(file.length()); os.putArchiveEntry(entry); } IOUtils.copy(new FileInputStream(file), os); os.closeArchiveEntry(); } } private boolean isScript(File file) { return file.getParentFile().getName().equals("bin") && !file.getName().contains("groovy"); } private void copyDependencies(File distDir) throws MojoExecutionException { File libDir = new File(distDir, "/lib"); libDir.mkdir(); if (project != null) { // for testing Set artifacts = project.getArtifacts(); for (Iterator itr = artifacts.iterator(); itr.hasNext();) { Artifact a = (Artifact) itr.next(); try { FileUtils.copyFile(a.getFile(), new File(libDir, a.getFile().getName())); } catch (IOException e) { throw new MojoExecutionException("Could not copy artifact " + a.toString(), e); } } } } protected void populateScripts(File distDir) throws MojoFailureException, MojoExecutionException { File binDir = new File(distDir, "/bin"); binDir.mkdir(); File scriptsDirFile = new File(project.getBasedir(), scriptsSourceDirectory); if (!scriptsDirFile.exists()) { throw new MojoFailureException("Could not find scripts directory " + scriptsSourceDirectory); } ClassLoader oldCL = Thread.currentThread().getContextClassLoader(); try { ClassLoader cl = getCompileClassLoader(); Thread.currentThread().setContextClassLoader(cl); copyGroovyScripts(scriptsDirFile.listFiles(), binDir); // There has to be a better way to do this, but I am clearly not thinking of it right now Class crCls = cl.loadClass(CommandRunner.class.getName()); Class absCmdCls = cl.loadClass(AbstractCommand.class.getName()); Class commandWrapperCls = cl.loadClass(GroovyCommandWrapper.class.getName()); Class generateCmdsCls = cl.loadClass(GenerateCommands.class.getName()); Object runner = crCls.newInstance(); Object wrapper = commandWrapperCls.getConstructor(Class.class).newInstance(generateCmdsCls); crCls.getMethod("addCommand", absCmdCls).invoke(runner, wrapper); crCls.getMethod("run", String[].class).invoke(runner, new Object[] { new String[] { "generate-commands", "-p", binDir.getAbsolutePath() } }); POSIX posix = POSIXFactory.getPOSIX(getHandler(), true); for (File file : binDir.listFiles()) { posix.chmod(file.getAbsolutePath(), EXECUTABLE_MODE); } } catch (IOException e) { throw new MojoExecutionException("Could not copy script files to distribution.", e); } catch (Exception e) { throw new MojoExecutionException("Could not generate scripts", e); } finally { Thread.currentThread().setContextClassLoader(oldCL); } } private POSIXHandler getHandler() { return new POSIXHandler() { public void error(ERRORS error, String extraData) { } public void unimplementedError(String methodName) { } public void warn(WARNING_ID id, String message, Object... data) { } public boolean isVerbose() { return false; } public File getCurrentWorkingDirectory() { return null; } public String[] getEnv() { return null; } public InputStream getInputStream() { return null; } public PrintStream getOutputStream() { return null; } public int getPID() { return 0; } public PrintStream getErrorStream() { return null; } }; } private void copyGroovyScripts(File[] files, File dest) throws IOException { if (files == null) { return; } for (File f : files) { if (f.isDirectory()) { copyGroovyScripts(f.listFiles(), dest); } else if (f.getName().endsWith(".groovy")) { IOUtils.copy(new FileInputStream(f), new FileOutputStream(new File(dest, f.getName()))); } } } public void setDistributionName(String distributionName) { this.distributionName = distributionName; } public void setScriptsSourceDirectory(String scriptsSourceDirectory) { this.scriptsSourceDirectory = scriptsSourceDirectory; } public void setBuildDirectory(String buildDirectory) { this.buildDirectory = buildDirectory; } public void setProject(MavenProject project) { this.project = project; } public void setResolver(ArtifactResolver resolver) { this.resolver = resolver; } public void setCreateZip(boolean createZip) { this.createZip = createZip; } public void setCreateTarGz(boolean createTarGz) { this.createTarGz = createTarGz; } public MavenProjectHelper getProjectHelper() { return projectHelper; } public void setProjectHelper(MavenProjectHelper projectHelper) { this.projectHelper = projectHelper; } }