/* * The MIT License * * Copyright 2014 Rui Martinho (rmartinho@gmail.com), António Braz (antoniocbraz@gmail.com) * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package org.poreid.manifestupdate; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.List; import java.util.Properties; import org.apache.maven.plugin.AbstractMojo; import org.apache.maven.plugin.MojoExecutionException; import org.apache.maven.plugin.MojoFailureException; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.codehaus.plexus.util.FileUtils; import org.codehaus.plexus.util.Os; import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.cli.CommandLineException; import org.codehaus.plexus.util.cli.CommandLineUtils; import org.codehaus.plexus.util.cli.Commandline; import org.codehaus.plexus.util.cli.StreamConsumer; /** * * @author rmartinho@gmail.com */ @Mojo(name = "update-manifest", defaultPhase = LifecyclePhase.PROCESS_SOURCES) public class ManifestUpdate extends AbstractMojo { @Parameter(defaultValue = "${project.build.directory}", property = "archiveDirectory", required = true) private File archiveDirectory; @Parameter(alias = "includes", property = "includes", required = true) private String[] mIncludes; @Parameter(alias = "excludes", property = "excludes") private String[] mExcludes; @Parameter(property = "verbose", defaultValue="false") private boolean verbose; @Parameter(alias = "Codebase", property = "Codebase") private String codebase; @Parameter(alias = "Trusted-Library", property = "Trusted-Library", defaultValue="false") private boolean trustedlib; @Parameter(alias = "Caller-Allowable-Codebase", property = "Caller-Allowable-Codebase") private String callerAllowableCodebase; @Parameter(alias = "Permissions", property = "Permissions") private String permissions; @Parameter(alias = "Application-Library-Allowable-Codebase", property = "Application-Library-Allowable-Codebase") private String appLibAllCodeBase; private String executable; private File mfTemp; public ManifestUpdate() {} public void execute() throws MojoExecutionException, MojoFailureException { String codeBase = (null!=this.codebase && !this.codebase.isEmpty()) ? String.format("Codebase: %s\n", this.codebase) : ""; String trustedLib = (trustedlib) ? String.format("Trusted-Library: %s\n", this.trustedlib) : ""; String permissions_ = (null!=this.permissions && !this.permissions.isEmpty()) ? String.format("Permissions: %s\n", this.permissions) : ""; String callerAC = (null!=this.callerAllowableCodebase && !this.callerAllowableCodebase.isEmpty()) ? String.format("Caller-Allowable-Codebase: %s\n", callerAllowableCodebase) : ""; String alac = (null!=this.appLibAllCodeBase && !this.appLibAllCodeBase.isEmpty()) ? String.format("Application-Library-Allowable-Codebase: %s\n", appLibAllCodeBase) : ""; String includeList = ( mIncludes != null ) ? StringUtils.join( mIncludes, "," ) : null; String excludeList = ( mExcludes != null ) ? StringUtils.join( mExcludes, "," ) : null; List<File> jarFiles; executable = getExecutable(); try { jarFiles = FileUtils.getFiles(archiveDirectory, includeList, excludeList); FileUtils.mkdir(archiveDirectory.getAbsolutePath()+File.separator+"META-INF"); mfTemp = new File(archiveDirectory.getAbsolutePath()+File.separator+"META-INF", "MANIFEST.MF"); mfTemp.deleteOnExit(); FileUtils.fileWrite(mfTemp, "UTF-8", codeBase+trustedLib+permissions_+callerAC+alac); } catch (IOException e) { throw new MojoExecutionException("Failed to scan archive directory for JARs: "+ e.getMessage(), e); } for (File file : jarFiles) { processArchive(file); } getLog().info("Properties: "+codeBase+trustedLib+permissions_+callerAC+alac); getLog().info(jarFiles.size() + " archive(s) processed (" + archiveDirectory.toString() + ")"); try { FileUtils.deleteDirectory(archiveDirectory + File.separator + "META-INF"); } catch (IOException ex) { throw new MojoExecutionException("Failed to delete META-INF directory: " + ex.getMessage(), ex); } } private void processArchive(final File archive) throws MojoExecutionException { if (archive == null) { throw new NullPointerException("archive"); } if (this.verbose) { getLog().info(getMessage("processing", archive.getAbsolutePath())); } else if (getLog().isDebugEnabled()) { getLog().debug(getMessage("processing", archive.getAbsolutePath())); } Commandline addManisfestToJarCommand = new Commandline(); addManisfestToJarCommand.setExecutable(this.executable); addManisfestToJarCommand.setWorkingDirectory(archiveDirectory); addManisfestToJarCommand.createArg().setValue("-umf"); addManisfestToJarCommand.createArg().setFile(this.mfTemp); addManisfestToJarCommand.createArg().setFile(archive); try { if (getLog().isDebugEnabled()) { getLog().debug(getMessage("command", addManisfestToJarCommand.toString())); } final int result = CommandLineUtils.executeCommandLine(addManisfestToJarCommand, new InputStream() { public int read() { return -1; } }, new StreamConsumer() { public void consumeLine(final String line) { if (verbose) { getLog().info(line); } else { getLog().debug(line); } } }, new StreamConsumer() { public void consumeLine(final String line) { getLog().warn(line); } }); if (result != 0) { throw new MojoExecutionException(getMessage("failure", addManisfestToJarCommand.toString())); } } catch (CommandLineException e) { throw new MojoExecutionException(getMessage("commandLineException", addManisfestToJarCommand.toString()), e); } } private String getExecutable() { String command = "jar" + (Os.isFamily(Os.FAMILY_WINDOWS) ? ".exe" : ""); String exec = findExecutable(command, System.getProperty("java.home"), new String[]{"../bin", "bin", "../sh"}); if (exec == null) { try { Properties env = CommandLineUtils.getSystemEnvVars(); String[] variables = {"JDK_HOME", "JAVA_HOME"}; for (int i = 0; i < variables.length && exec == null; i++) { exec = findExecutable(command, env.getProperty(variables[i]), new String[]{"bin", "sh"}); } } catch (IOException e) { if (getLog().isDebugEnabled()) { getLog().warn("Failed to retrieve environment variables, cannot search for " + command, e); } else { getLog().warn("Failed to retrieve environment variables, cannot search for " + command); } } } if (exec == null) { exec = command; } return exec; } private String findExecutable(String command, String homeDir, String[] subDirs) { if (StringUtils.isNotEmpty(homeDir)) { for (String subDir : subDirs) { File file = new File(new File(homeDir, subDir), command); if (file.isFile()) { return file.getAbsolutePath(); } } } return null; } private String getMessage(String info, String msg){ return info + " --- " + msg; } }