Author: khmarbaise Date: Sun Oct 2 18:16:07 2016 New Revision: 1763091 URL: http://svn.apache.org/viewvc?rev=1763091&view=rev Log: First starting point of maven-jlink-plugin
Added: maven/plugins/trunk/maven-jlink-plugin/ (with props) maven/plugins/trunk/maven-jlink-plugin/pom.xml maven/plugins/trunk/maven-jlink-plugin/src/ maven/plugins/trunk/maven-jlink-plugin/src/main/ maven/plugins/trunk/maven-jlink-plugin/src/main/java/ maven/plugins/trunk/maven-jlink-plugin/src/main/java/org/ maven/plugins/trunk/maven-jlink-plugin/src/main/java/org/apache/ maven/plugins/trunk/maven-jlink-plugin/src/main/java/org/apache/maven/ maven/plugins/trunk/maven-jlink-plugin/src/main/java/org/apache/maven/plugins/ maven/plugins/trunk/maven-jlink-plugin/src/main/java/org/apache/maven/plugins/jlink/ maven/plugins/trunk/maven-jlink-plugin/src/main/java/org/apache/maven/plugins/jlink/AbstractJLinkMojo.java maven/plugins/trunk/maven-jlink-plugin/src/main/java/org/apache/maven/plugins/jlink/JLinkMojo.java Propchange: maven/plugins/trunk/maven-jlink-plugin/ ------------------------------------------------------------------------------ --- svn:ignore (added) +++ svn:ignore Sun Oct 2 18:16:07 2016 @@ -0,0 +1,13 @@ +cobertura.ser +*~ +*.log +.classpath +.project +*.ipr +*.iws +*.iml +.idea +target +.wtpmodules +.settings +bin Added: maven/plugins/trunk/maven-jlink-plugin/pom.xml URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-jlink-plugin/pom.xml?rev=1763091&view=auto ============================================================================== --- maven/plugins/trunk/maven-jlink-plugin/pom.xml (added) +++ maven/plugins/trunk/maven-jlink-plugin/pom.xml Sun Oct 2 18:16:07 2016 @@ -0,0 +1,89 @@ +<?xml version='1.0' encoding='UTF-8'?> + +<!-- + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you 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. +--> + +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-plugins</artifactId> + <version>30</version> + <relativePath>../maven-plugins/pom.xml</relativePath> + </parent> + + <artifactId>maven-jlink-plugin</artifactId> + <version>3.0.0-SNAPSHOT</version> + <packaging>maven-plugin</packaging> + + <name>Apache Maven JLink Plugin</name> + <description>JLink http://openjdk.java.net/jeps/282, http://openjdk.java.net/jeps/220</description> + <inceptionYear>2016</inceptionYear> + + <prerequisites> + <maven>${mavenVersion}</maven> + </prerequisites> + + <scm> + <connection>scm:svn:http://svn.apache.org/repos/asf/maven/plugins/trunk/maven-jlink-plugin/</connection> + <developerConnection>scm:svn:https://svn.apache.org/repos/asf/maven/plugins/trunk/maven-jlink-plugin/ + </developerConnection> + <url>http://svn.apache.org/viewvc/maven/plugins/trunk/maven-jlink-plugin/</url> + </scm> + <issueManagement> + <system>jira</system> + <url>https://issues.apache.org/jira/browse/MJLINK</url> + </issueManagement> + <distributionManagement> + <site> + <id>apache.website</id> + <url>scm:svn:https://svn.apache.org/repos/infra/websites/production/maven/components/${maven.site.path}</url> + </site> + </distributionManagement> + + <properties> + <mavenVersion>3.0</mavenVersion> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.maven.plugin-tools</groupId> + <artifactId>maven-plugin-annotations</artifactId> + <scope>provided</scope> + </dependency> + <!-- Maven --> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-plugin-api</artifactId> + <version>${mavenVersion}</version> + </dependency> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-core</artifactId> + <version>${mavenVersion}</version> + </dependency> + <dependency> + <groupId>commons-lang</groupId> + <artifactId>commons-lang</artifactId> + <version>2.4</version> + </dependency> + </dependencies> +</project> Added: maven/plugins/trunk/maven-jlink-plugin/src/main/java/org/apache/maven/plugins/jlink/AbstractJLinkMojo.java URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-jlink-plugin/src/main/java/org/apache/maven/plugins/jlink/AbstractJLinkMojo.java?rev=1763091&view=auto ============================================================================== --- maven/plugins/trunk/maven-jlink-plugin/src/main/java/org/apache/maven/plugins/jlink/AbstractJLinkMojo.java (added) +++ maven/plugins/trunk/maven-jlink-plugin/src/main/java/org/apache/maven/plugins/jlink/AbstractJLinkMojo.java Sun Oct 2 18:16:07 2016 @@ -0,0 +1,219 @@ +package org.apache.maven.plugins.jlink; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import java.io.File; +import java.io.IOException; +import java.util.Properties; + +import org.apache.commons.lang.SystemUtils; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugins.annotations.Component; +import org.apache.maven.plugins.annotations.Parameter; +import org.apache.maven.project.MavenProject; +import org.apache.maven.toolchain.Toolchain; +import org.apache.maven.toolchain.ToolchainManager; +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; + +/** + * + * @author Karl Heinz Marbaise <a href="mailto:khmarba...@apache.org">khmarba...@apache.org</a> + * + */ +public abstract class AbstractJLinkMojo + extends AbstractMojo +{ + + @Parameter( defaultValue = "${project}", readonly = true, required = true ) + private MavenProject project; + + @Parameter( defaultValue = "${session}", readonly = true, required = true ) + private MavenSession session; + + @Component + private ToolchainManager toolchainManager; + + protected String getJLinkExecutable() throws IOException + { + Toolchain tc = getToolchain(); + + String jLinkExecutable = null; + if ( tc != null ) + { + jLinkExecutable = tc.findTool( "jlink" ); + } + + String jLinkCommand = "jlink" + ( SystemUtils.IS_OS_WINDOWS ? ".exe" : "" ); + + File jLinkExe; + + if ( StringUtils.isNotEmpty( jLinkExecutable ) ) + { + jLinkExe = new File( jLinkExecutable ); + + if ( jLinkExe.isDirectory() ) + { + jLinkExe = new File( jLinkExe, jLinkCommand ); + } + + if ( SystemUtils.IS_OS_WINDOWS && jLinkExe.getName().indexOf( '.' ) < 0 ) + { + jLinkExe = new File( jLinkExe.getPath() + ".exe" ); + } + + if ( !jLinkExe.isFile() ) + { + throw new IOException( "The jlink executable '" + jLinkExe + + "' doesn't exist or is not a file." ); + } + return jLinkExe.getAbsolutePath(); + } + + // ---------------------------------------------------------------------- + // Try to find jlink from System.getProperty( "java.home" ) + // By default, System.getProperty( "java.home" ) = JRE_HOME and JRE_HOME + // should be in the JDK_HOME + // ---------------------------------------------------------------------- + // For IBM's JDK 1.2 + // Really ? + if ( SystemUtils.IS_OS_AIX ) + { + jLinkExe = + new File( SystemUtils.getJavaHome() + File.separator + ".." + File.separator + "sh", jLinkCommand ); + } + // For Apple's JDK 1.6.x (and older?) on Mac OSX + // CHECKSTYLE_OFF: MagicNumber + else if ( SystemUtils.IS_OS_MAC_OSX && SystemUtils.JAVA_VERSION_FLOAT < 1.7f ) + // CHECKSTYLE_ON: MagicNumber + { + jLinkExe = new File( SystemUtils.getJavaHome() + File.separator + "bin", jLinkCommand ); + } + else + { + jLinkExe = + new File( SystemUtils.getJavaHome() + File.separator + ".." + File.separator + "bin", jLinkCommand ); + } + + // ---------------------------------------------------------------------- + // Try to find javadocExe from JAVA_HOME environment variable + // ---------------------------------------------------------------------- + if ( !jLinkExe.exists() || !jLinkExe.isFile() ) + { + Properties env = CommandLineUtils.getSystemEnvVars(); + String javaHome = env.getProperty( "JAVA_HOME" ); + if ( StringUtils.isEmpty( javaHome ) ) + { + throw new IOException( "The environment variable JAVA_HOME is not correctly set." ); + } + if ( ( !new File( javaHome ).getCanonicalFile().exists() ) + || ( new File( javaHome ).getCanonicalFile().isFile() ) ) + { + throw new IOException( "The environment variable JAVA_HOME=" + javaHome + + " doesn't exist or is not a valid directory." ); + } + + jLinkExe = new File( javaHome + File.separator + "bin", jLinkCommand ); + } + + if ( !jLinkExe.getCanonicalFile().exists() || !jLinkExe.getCanonicalFile().isFile() ) + { + throw new IOException( "The jlink executable '" + jLinkExe + + "' doesn't exist or is not a file. Verify the JAVA_HOME environment variable." ); + } + + return jLinkExe.getAbsolutePath(); + } + + protected void executeCommand ( Commandline cmd, File outputDirectory ) throws MojoExecutionException + { + if ( getLog().isDebugEnabled() ) + { + // no quoted arguments ??? + getLog().debug( CommandLineUtils.toString( cmd.getCommandline() ).replaceAll( "'", "" ) ); + } + + CommandLineUtils.StringStreamConsumer err = new CommandLineUtils.StringStreamConsumer(); + CommandLineUtils.StringStreamConsumer out = new CommandLineUtils.StringStreamConsumer(); + try + { + int exitCode = CommandLineUtils.executeCommandLine( cmd, out, err ); + + String output = ( StringUtils.isEmpty( out.getOutput() ) ? null : '\n' + out.getOutput().trim() ); + + if ( exitCode != 0 ) + { + if ( StringUtils.isNotEmpty( output ) ) + { + //Reconsider to use WARN / ERROR ? + getLog().info( output ); + } + + StringBuilder msg = new StringBuilder( "\nExit code: " ); + msg.append( exitCode ); + if ( StringUtils.isNotEmpty( err.getOutput() ) ) + { + msg.append( " - " ).append( err.getOutput() ); + } + msg.append( '\n' ); + msg.append( "Command line was: " ).append( cmd ).append( '\n' ).append( '\n' ); + + throw new MojoExecutionException( msg.toString() ); + } + + if ( StringUtils.isNotEmpty( output ) ) + { + getLog().info( output ); + } + } + catch ( CommandLineException e ) + { + throw new MojoExecutionException( "Unable to execute jlink command: " + e.getMessage(), e ); + } + + } + + private Toolchain getToolchain() + { + Toolchain tc = null; + if ( toolchainManager != null ) + { + tc = toolchainManager.getToolchainFromBuildContext( "jdk", session ); + } + + return tc; + } + + public MavenProject getProject() + { + return project; + } + + public MavenSession getSession() + { + return session; + } + + +} Added: maven/plugins/trunk/maven-jlink-plugin/src/main/java/org/apache/maven/plugins/jlink/JLinkMojo.java URL: http://svn.apache.org/viewvc/maven/plugins/trunk/maven-jlink-plugin/src/main/java/org/apache/maven/plugins/jlink/JLinkMojo.java?rev=1763091&view=auto ============================================================================== --- maven/plugins/trunk/maven-jlink-plugin/src/main/java/org/apache/maven/plugins/jlink/JLinkMojo.java (added) +++ maven/plugins/trunk/maven-jlink-plugin/src/main/java/org/apache/maven/plugins/jlink/JLinkMojo.java Sun Oct 2 18:16:07 2016 @@ -0,0 +1,235 @@ +package org.apache.maven.plugins.jlink; + +import java.io.File; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ + +import java.io.IOException; +import java.util.List; + +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.apache.maven.plugins.annotations.ResolutionScope; +import org.codehaus.plexus.util.FileUtils; +import org.codehaus.plexus.util.cli.Commandline; + +/** + * <pre> + * Usage: jlink <options> --module-path <modulepath> --add-modules <mods> --output <path> + * Possible options include: + * -h, --help Print this help message + * -p <modulepath> + * --module-path <modulepath> Module path + * --limit-modules <mod>[,<mod>...] Limit the universe of observable modules + * --add-modules <mod>[,<mod>...] Root modules to resolve + * --output <path> Location of output path + * --endian <little|big> Byte order of generated jimage (default:native) + * --version Version information + * --save-opts <filename> Save jlink options in the given file + * -G, --strip-debug Strip debug information + * -c, --compress=<0|1|2> Enable compression of resources (level 2) + * --plugin-module-path <modulepath> Custom plugin module path + * --list-plugins List available plugins + * @<filename> Read options from file + * </pre> + * + * @author Karl Heinz Marbaise <a href="mailto:khmarba...@apache.org">khmarba...@apache.org</a> + */ +// TODO: Think if ResultionScope is needed here? May be we need to reconsider package phase? +// May be it would be wise to put into PREPARE-PACKAGE and the generation of the final jimage in the package phase? +// Furthermore It could make sense so we can change the conf files if needed... +@Mojo( name = "jlink", requiresDependencyResolution = ResolutionScope.COMPILE, defaultPhase = LifecyclePhase.PACKAGE ) +public class JLinkMojo + extends AbstractJLinkMojo +{ + /** + * <code>-G, --strip-debug</code> strip debug information. + */ + @Parameter( defaultValue = "false" ) + private boolean stripDebug; + + /** + * <code>-c, --compress=<0|1|2></code> Enabled compression of resources. + */ + @Parameter + private Integer compression; + + /** + * Define the modulepath for the <code>JLink</code> call. <code>--module-path <modulepath></code> + */ + @Parameter( required = true ) + private File modulePath; + + /** + * Limit the univers of observable modules. <code>--limit-modules <mod>[,<mod>...]</code> + */ + @Parameter + private List<String> limitModules; + + /** + * Root modules to resolve. <code>--add-modules <mod>[,<mod>...]</code> + */ + @Parameter + private List<String> addModules; + + /** + * Custom plugin module path <code>--plugin-module-path <modulepath></code> + */ + @Parameter + private File pluginModulePath; + + /** + * <code>--output <path></code> + * </p> + * TODO: Think about the default value? I'm not sure if something different would + * be better? + */ + @Parameter( defaultValue = "${project.build.output}/link-result" ) + private File outputDirectory; + + /** + * Byte order of generated jimage (default:native). <code>--endian <little|big></code>. + * </p> + * TODO: Reconsider setting the default value? Hasn't that been set already? + */ + @Parameter( defaultValue = "native" ) + private String endian; + + public void execute() + throws MojoExecutionException, MojoFailureException + { + + failIfParametersAreNotInTheirValidValueRanges(); + + String jLinkExecutable; + try + { + jLinkExecutable = getJLinkExecutable(); + } + catch ( IOException e ) + { + throw new MojoFailureException( "Unable to find jlink command: " + e.getMessage(), e ); + } + + deleteOutputDirectoryIfItAlreadyExists(); + + // Synopsis + // Usage: jlink <options> --module-path <modulepath> --add-modules <mods> --output <path> + Commandline cmd = createJLinkCommandLine(); + cmd.setExecutable( jLinkExecutable ); + + executeCommand( cmd, outputDirectory ); + + } + + private void failIfParametersAreNotInTheirValidValueRanges() + throws MojoFailureException + { + if ( compression != null && ( compression < 0 || compression > 2 ) ) + { + String message = + "The given compression parameters " + compression + " is not in the valid value range from 0..2"; + getLog().error( message ); + throw new MojoFailureException( message ); + } + } + + private void deleteOutputDirectoryIfItAlreadyExists() + throws MojoExecutionException + { + if ( outputDirectory.exists() ) + { + // Delete the output folder of JLink before we start + // otherwise JLink will fail with a message "Error: directory already exists: ..." + try + { + FileUtils.forceDelete( outputDirectory ); + } + catch ( IOException e ) + { + getLog().error( "IOException", e ); + throw new MojoExecutionException( "Failure during deletion of " + outputDirectory.getAbsolutePath() + + " occured." ); + } + } + } + + private Commandline createJLinkCommandLine() + { + Commandline cmd = new Commandline(); + + if ( stripDebug ) + { + cmd.createArg().setValue( "--strip-debug" ); + } + + if ( compression != null ) + { + cmd.createArg().setValue( "--compression" ); + cmd.createArg().setValue( compression.toString() ); + } + + // CHECK if this assumption here is correct? + if ( modulePath != null && modulePath.exists() && modulePath.isDirectory() ) + { + cmd.createArg().setValue( "--module-path" ); + cmd.createArg().setFile( modulePath ); + } + + if ( limitModules != null && !limitModules.isEmpty() ) + { + cmd.createArg().setValue( "--limit-modules" ); + StringBuilder sb = getCommaSeparatedList( limitModules ); + cmd.createArg().setValue( sb.toString() ); + } + + if ( addModules != null && !addModules.isEmpty() ) + { + cmd.createArg().setValue( "--add-modules" ); + StringBuilder sb = getCommaSeparatedList( addModules ); + cmd.createArg().setValue( sb.toString() ); + } + + if ( outputDirectory != null ) + { + cmd.createArg().setValue( "--output" ); + cmd.createArg().setFile( outputDirectory ); + } + + return cmd; + } + + private StringBuilder getCommaSeparatedList( List<String> modules ) + { + StringBuilder sb = new StringBuilder(); + for ( String module : modules ) + { + if ( sb.length() > 0 ) + { + sb.append( ',' ); + } + sb.append( module ); + } + return sb; + } +}