You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by hb...@apache.org on 2017/12/09 15:27:47 UTC

[maven-jlink-plugin] 21/38: Added plexus-java cause we need information about module-info.class to correctly create a Java Run Time Image. Using the dependencies only to handle modules.

This is an automated email from the ASF dual-hosted git repository.

hboutemy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/maven-jlink-plugin.git

commit 2c19e6dfeed24f17b3a404f7d5aaaad8395fe1f8
Author: Karl Heinz Marbaise <kh...@apache.org>
AuthorDate: Tue Sep 5 17:47:16 2017 +0000

    Added plexus-java cause we need information about module-info.class
    to correctly create a Java Run Time Image.
    Using the dependencies only to handle modules.
    
    
    git-svn-id: https://svn.apache.org/repos/asf/maven/plugins/trunk@1807376 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml                                            |  34 +++
 .../maven/plugins/jlink/AbstractJLinkMojo.java     |   2 +-
 .../org/apache/maven/plugins/jlink/JLinkMojo.java  | 234 ++++++++++++---------
 src/site/apt/usage.apt.vm                          |  10 +-
 4 files changed, 182 insertions(+), 98 deletions(-)

diff --git a/pom.xml b/pom.xml
index a76de0e..56b3dda 100644
--- a/pom.xml
+++ b/pom.xml
@@ -95,6 +95,11 @@
       <version>3.5</version>
     </dependency>
     <dependency>
+      <groupId>org.codehaus.plexus</groupId>
+      <artifactId>plexus-java</artifactId>
+      <version>0.9.3-SNAPSHOT</version>
+    </dependency>
+    <dependency>
       <groupId>org.apache.commons</groupId>
       <artifactId>commons-lang3</artifactId>
       <version>3.6</version>
@@ -121,6 +126,35 @@
   </dependencies>
 
   <build>
+    <pluginManagement>
+      <plugins>
+        <plugin>
+          <groupId>org.apache.maven.plugins</groupId>
+          <artifactId>maven-plugin-plugin</artifactId>
+          <version>3.5</version>
+        </plugin>
+
+        <plugin>
+          <artifactId>maven-enforcer-plugin</artifactId>
+          <executions>
+            <execution>
+              <id>enforce-bytecode-version</id>
+              <configuration>
+                <rules>
+                  <enforceBytecodeVersion>
+                    <maxJdkVersion>1.7</maxJdkVersion>
+                    <excludes>
+                      <exclude>org.ow2.asm:asm</exclude>
+                    </excludes>
+                  </enforceBytecodeVersion>
+                  <requireSameVersions />
+                </rules>
+              </configuration>
+            </execution>
+          </executions>
+        </plugin>
+      </plugins>
+    </pluginManagement>
     <resources>
       <resource>
         <directory>src/main/filtered-resources</directory>
diff --git a/src/main/java/org/apache/maven/plugins/jlink/AbstractJLinkMojo.java b/src/main/java/org/apache/maven/plugins/jlink/AbstractJLinkMojo.java
index 9c5bab7..5c904a6 100644
--- a/src/main/java/org/apache/maven/plugins/jlink/AbstractJLinkMojo.java
+++ b/src/main/java/org/apache/maven/plugins/jlink/AbstractJLinkMojo.java
@@ -189,7 +189,7 @@ public abstract class AbstractJLinkMojo
 
     }
 
-    private Toolchain getToolchain()
+    protected Toolchain getToolchain()
     {
         Toolchain tc = null;
 
diff --git a/src/main/java/org/apache/maven/plugins/jlink/JLinkMojo.java b/src/main/java/org/apache/maven/plugins/jlink/JLinkMojo.java
index 32ed9d0..6ddbd0b 100644
--- a/src/main/java/org/apache/maven/plugins/jlink/JLinkMojo.java
+++ b/src/main/java/org/apache/maven/plugins/jlink/JLinkMojo.java
@@ -23,9 +23,13 @@ import java.io.File;
 import java.io.IOException;
 import java.io.PrintStream;
 import java.util.ArrayList;
+import java.util.Collection;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
 
-import org.apache.maven.model.Dependency;
+import org.apache.maven.artifact.Artifact;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
 import org.apache.maven.plugins.annotations.Component;
@@ -34,9 +38,18 @@ 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 org.apache.maven.shared.utils.StringUtils;
+import org.apache.maven.shared.utils.logging.MessageUtils;
+import org.apache.maven.toolchain.Toolchain;
+import org.apache.maven.toolchain.java.DefaultJavaToolChain;
 import org.codehaus.plexus.archiver.Archiver;
 import org.codehaus.plexus.archiver.ArchiverException;
 import org.codehaus.plexus.archiver.zip.ZipArchiver;
+import org.codehaus.plexus.languages.java.jpms.JavaModuleDescriptor;
+import org.codehaus.plexus.languages.java.jpms.LocationManager;
+import org.codehaus.plexus.languages.java.jpms.ResolvePathsRequest;
+import org.codehaus.plexus.languages.java.jpms.ResolvePathsResult;
+import org.codehaus.plexus.languages.java.jpms.ResolvePathsResult.ModuleNameSource;
 import org.codehaus.plexus.util.FileUtils;
 import org.codehaus.plexus.util.cli.Commandline;
 
@@ -49,16 +62,31 @@ import org.codehaus.plexus.util.cli.Commandline;
  */
 // TODO: Check if the resolution scope is correct?
 // CHECKSTYLE_OFF: LineLength
-@Mojo( name = "jlink", requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, defaultPhase = LifecyclePhase.PACKAGE, requiresProject = true )
+@Mojo( name = "jlink", requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME, defaultPhase = LifecyclePhase.PACKAGE, requiresProject = true )
 // CHECKSTYLE_ON: LineLength
 public class JLinkMojo
     extends AbstractJLinkMojo
 {
-    private static final String JMOD_PACKAGING = "jmod";
-
     private static final String JMODS = "jmods";
 
-    private static final String JAR_PACKAGING = "jar";
+    private List<String> classpathElements;
+
+    private List<String> modulepathElements;
+
+    private Map<String, JavaModuleDescriptor> pathElements;
+
+    @Component
+    private LocationManager locationManager;
+
+    /**
+     * <p>
+     * Specify the requirements for this jdk toolchain. This overrules the toolchain selected by the
+     * maven-toolchain-plugin.
+     * </p>
+     * <strong>note:</strong> requires at least Maven 3.3.1
+     */
+    @Parameter
+    private Map<String, String> jdkToolchain;
 
     /**
      * This is intended to strip debug information out. The command line equivalent of <code>jlink</code> is:
@@ -137,8 +165,6 @@ public class JLinkMojo
     @Parameter
     private String endian;
 
-    // TODO: Check if we should allow to extend the modulePaths by manual additions in the pom file?
-    @Parameter( defaultValue = "${project.compileClasspathElements}", readonly = true, required = true )
     private List<String> modulePaths;
 
     /**
@@ -230,35 +256,30 @@ public class JLinkMojo
 
         ifOutputDirectoryExistsDelteIt();
 
-        List<Dependency> dependencies = getSession().getCurrentProject().getDependencies();
+        preparePaths();
 
-        List<MavenProject> modulesToAdd = new ArrayList<>();
-        // if ( dependencies.isEmpty() )
-        // {
-        // // Do we need to do something if no dependencies have been defined ?
-        // // WARNING / ERROR or failure?
-        // }
         getLog().info( "The following dependencies will be linked into the runtime image:" );
-        for ( Dependency dependency : dependencies )
+
+        this.addModules = new ArrayList<>();
+        this.modulePaths = new ArrayList<>();
+        for ( Entry<String, JavaModuleDescriptor> item : pathElements.entrySet() )
         {
-            // We will support "jmod" as well as "jar"
-            // TODO: Think about jmod's cause they can contain config files etc. ? What todo with them? Are they already
-            // handled by jlink ?
-            if ( JAR_PACKAGING.equals( dependency.getType() ) || JMOD_PACKAGING.equals( dependency.getType() ) )
+            // Isn't there a better solution?
+            if ( item.getValue() == null )
             {
-                MavenProject mp = findDependencyInProjects( dependency );
-                getLog().info( " -> " + mp.getId() );
-                // TODO: What about module name != artifactId which has been
-                // defined in module-info.java file!
-                // This would mean to read the module-info information from the jmod/jar file for example to
-                // get the appropriate information.
-                modulesToAdd.add( mp );
+                String message = "The given dependency " + item.getKey()
+                    + " does not have a module-info.java file. So it can't be linked.";
+                getLog().error( message );
+                throw new MojoFailureException( message );
             }
+            getLog().debug( "pathElements Item:" + item.getKey() + " v:" + item.getValue().name() );
+            getLog().info( " -> module: " + item.getValue().name() + " ( " + item.getKey() + " )" );
+            // We use the real module name and not the artifact Id...
+            this.addModules.add( item.getValue().name() );
+            this.modulePaths.add( item.getKey() );
         }
-
-        handleAddModules( modulesToAdd );
-
-        handleModulePath( jmodsFolder, modulesToAdd );
+        // The jmods directory of the JDK
+        this.modulePaths.add( jmodsFolder.getAbsolutePath() );
 
         Commandline cmd;
         try
@@ -284,6 +305,86 @@ public class JLinkMojo
         getProject().getArtifact().setFile( createZipArchiveFromImage );
     }
 
+    private List<File> getCompileClasspathElements( MavenProject project )
+    {
+        List<File> list = new ArrayList<File>( project.getArtifacts().size() + 1 );
+
+        for ( Artifact a : project.getArtifacts() )
+        {
+            list.add( a.getFile() );
+        }
+        return list;
+    }
+
+    private void preparePaths()
+    {
+        // For now only allow named modules. Once we can create a graph with ASM we can specify exactly the modules
+        // and we can detect if auto modules are used. In that case, MavenProject.setFile() should not be used, so
+        // you cannot depend on this project and so it won't be distributed.
+
+        modulepathElements = new ArrayList<String>();
+        classpathElements = new ArrayList<String>();
+        pathElements = new LinkedHashMap<String, JavaModuleDescriptor>();
+
+        ResolvePathsResult<File> resolvePathsResult;
+        try
+        {
+            Collection<File> dependencyArtifacts = getCompileClasspathElements( getProject() );
+
+            ResolvePathsRequest<File> request = ResolvePathsRequest.withFiles( dependencyArtifacts );
+
+            Toolchain toolchain = getToolchain();
+            if ( toolchain != null && toolchain instanceof DefaultJavaToolChain )
+            {
+                request.setJdkHome( new File( ( (DefaultJavaToolChain) toolchain ).getJavaHome() ) );
+            }
+
+            resolvePathsResult = locationManager.resolvePaths( request );
+
+            JavaModuleDescriptor moduleDescriptor = resolvePathsResult.getMainModuleDescriptor();
+
+            for ( Map.Entry<File, ModuleNameSource> entry : resolvePathsResult.getModulepathElements().entrySet() )
+            {
+                if ( ModuleNameSource.FILENAME.equals( entry.getValue() ) )
+                {
+                    final String message = "Required filename-based automodules detected. "
+                        + "Please don't publish this project to a public artifact repository!";
+
+                    if ( moduleDescriptor.exports().isEmpty() )
+                    {
+                        // application
+                        getLog().info( message );
+                    }
+                    else
+                    {
+                        // library
+                        writeBoxedWarning( message );
+                    }
+                    break;
+                }
+            }
+
+            for ( Map.Entry<File, JavaModuleDescriptor> entry : resolvePathsResult.getPathElements().entrySet() )
+            {
+                pathElements.put( entry.getKey().getPath(), entry.getValue() );
+            }
+
+            for ( File file : resolvePathsResult.getClasspathElements() )
+            {
+                classpathElements.add( file.getPath() );
+            }
+
+            for ( File file : resolvePathsResult.getModulepathElements().keySet() )
+            {
+                modulepathElements.add( file.getPath() );
+            }
+        }
+        catch ( IOException e )
+        {
+            getLog().warn( e.getMessage() );
+        }
+    }
+
     private String getExecutable()
         throws MojoFailureException
     {
@@ -338,58 +439,6 @@ public class JLinkMojo
 
     }
 
-    private void handleAddModules( List<MavenProject> modulesToAdd )
-    {
-        if ( addModules == null )
-        {
-            addModules = new ArrayList<>();
-        }
-
-        for ( MavenProject module : modulesToAdd )
-        {
-            // TODO: Check if this is the correct way?
-            // This implies the artifactId is equal to moduleName which might not always be the case!
-            addModules.add( module.getArtifactId() );
-        }
-    }
-
-    /**
-     * @param jmodsFolder The folder where to find the jmods of the JDK.
-     * @param modulesToAdd The modules to be added.
-     */
-    private void handleModulePath( File jmodsFolder, List<MavenProject> modulesToAdd )
-    {
-        if ( modulePaths == null )
-        {
-            modulePaths = new ArrayList<>();
-        }
-
-        // The jmods directory of the JDK
-        modulePaths.add( jmodsFolder.getAbsolutePath() );
-
-        for ( MavenProject mavenProject : modulesToAdd )
-        {
-            File output = new File( mavenProject.getBuild().getDirectory(), JMODS );
-            modulePaths.add( output.getAbsolutePath() );
-        }
-    }
-
-    private MavenProject findDependencyInProjects( Dependency dep )
-    {
-        List<MavenProject> sortedProjects = getSession().getProjectDependencyGraph().getSortedProjects();
-        MavenProject result = null;
-        for ( MavenProject mavenProject : sortedProjects )
-        {
-            if ( dep.getGroupId().equals( mavenProject.getGroupId() )
-                && dep.getArtifactId().equals( mavenProject.getArtifactId() )
-                && dep.getVersion().equals( mavenProject.getVersion() ) )
-            {
-                result = mavenProject;
-            }
-        }
-        return result;
-    }
-
     private void failIfParametersAreNotInTheirValidValueRanges()
         throws MojoFailureException
     {
@@ -408,18 +457,6 @@ public class JLinkMojo
             getLog().error( message );
             throw new MojoFailureException( message );
         }
-
-        // CHECK if this assumption here is correct?
-        // if ( modulePaths != null && ( !modulePaths.isEmpty() ) )
-        // {
-        //
-        // // FIXME: Need to check if the given paths exists? and if they are
-        // // folders?
-        // // String message = "The given module-paths parameter " + modulePath.getAbsolutePath()
-        // // + " is not a directory or does not exist.";
-        // // getLog().error( message );
-        // // throw new MojoFailureException( message );
-        // }
     }
 
     private void ifOutputDirectoryExistsDelteIt()
@@ -571,4 +608,13 @@ public class JLinkMojo
     {
         return addModules != null && !addModules.isEmpty();
     }
+    
+    private void writeBoxedWarning( String message )
+    {
+        String line = StringUtils.repeat( "*", message.length() + 4 );
+        getLog().warn( line );
+        getLog().warn( "* " + MessageUtils.buffer().strong( message )  + " *" );
+        getLog().warn( line );
+    }
+    
 }
diff --git a/src/site/apt/usage.apt.vm b/src/site/apt/usage.apt.vm
index 93f631a..f5db5ea 100644
--- a/src/site/apt/usage.apt.vm
+++ b/src/site/apt/usage.apt.vm
@@ -30,6 +30,11 @@ Usage
   The Maven JLink plugin is used to create {{{http://openjdk.java.net/jeps/220}Modular Run-Time Images}} with
   JDK 9.
   
+  The intended artifacts to be linked together into a Modular Run-Time Image 
+  are the <<jmod>> and <<jar>> files. JMod files can be created by using the
+  {{{../maven-jmod-plugin/}Maven JMod Plugin}} and <<jar>> files can be
+  created by using the {{{../maven-jar-plugin/}Maven JAR Plugin}}.
+   
 * Configuration of the Maven JLink Plugin
 
   To use the Maven JLink Plugin you have to configure it as an <<<extensions>>> which means
@@ -54,9 +59,8 @@ Usage
 </project>
 +-----
 
-  The configuration elements contains the configuration for the plugin like
-  any other Maven plugins.
-
+  The configuration elements contains the configuration for the plugin 
+  {{{https://maven.apache.org/guides/mini/guide-configuring-plugins.html}}like any other Maven plugin}}.
   
 * Usage of the Maven JLink Plugin
 

-- 
To stop receiving notification emails like this one, please contact
"commits@maven.apache.org" <co...@maven.apache.org>.