1 package org.apache.maven.plugins.jlink;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.commons.lang3.StringUtils;
23 import org.apache.commons.lang3.SystemUtils;
24 import org.apache.maven.plugin.MojoExecutionException;
25 import org.apache.maven.plugin.logging.Log;
26 import org.apache.maven.shared.utils.cli.CommandLineException;
27 import org.apache.maven.shared.utils.cli.CommandLineUtils;
28 import org.apache.maven.shared.utils.cli.Commandline;
29 import org.apache.maven.toolchain.Toolchain;
30
31 import java.io.File;
32 import java.util.List;
33 import java.util.NoSuchElementException;
34 import java.util.Optional;
35
36 abstract class AbstractJLinkToolchainExecutor extends AbstractJLinkExecutor
37 {
38 private final Toolchain toolchain;
39
40 AbstractJLinkToolchainExecutor( Toolchain toolchain, Log log )
41 {
42 super( log );
43 this.toolchain = toolchain;
44 }
45
46 protected Optional<Toolchain> getToolchain()
47 {
48 return Optional.ofNullable( this.toolchain );
49 }
50
51
52
53
54
55
56 @Override
57 public int executeJlink( List<String> jlinkArgs ) throws MojoExecutionException
58 {
59 File jlinkExecutable = getJlinkExecutable();
60 getLog().info( "Toolchain in maven-jlink-plugin: jlink [ " + jlinkExecutable + " ]" );
61
62 Commandline cmd = createJLinkCommandLine( jlinkArgs );
63 cmd.setExecutable( jlinkExecutable.getAbsolutePath() );
64
65 return executeCommand( cmd );
66 }
67
68 private File getJlinkExecutable()
69 {
70 return new File( getJLinkExecutable() );
71 }
72
73 @Override
74 public Optional<File> getJmodsFolder( File sourceJdkModules )
75 {
76
77 File jLinkParent = getJlinkExecutable().getParentFile().getParentFile();
78 File jmodsFolder;
79 if ( sourceJdkModules != null && sourceJdkModules.isDirectory() )
80 {
81 jmodsFolder = new File( sourceJdkModules, JMODS );
82 }
83 else
84 {
85 jmodsFolder = new File( jLinkParent, JMODS );
86 }
87
88 getLog().debug( " Parent: " + jLinkParent.getAbsolutePath() );
89 getLog().debug( " jmodsFolder: " + jmodsFolder.getAbsolutePath() );
90
91 return Optional.of( jmodsFolder );
92 }
93
94 private Commandline createJLinkCommandLine( List<String> jlinkArgs )
95 {
96 Commandline cmd = new Commandline();
97 jlinkArgs.forEach( arg -> cmd.createArg().setValue( arg ) );
98
99 return cmd;
100 }
101
102 private String getJLinkExecutable()
103 {
104 Optional<Toolchain> toolchain = getToolchain();
105
106 if ( !toolchain.isPresent() )
107 {
108 getLog().error( "Either JDK9+ or a toolchain "
109 + "pointing to a JDK9+ containing a jlink binary is required." );
110 getLog().info( "See https://maven.apache.org/guides/mini/guide-using-toolchains.html "
111 + "for mor information." );
112 throw new IllegalStateException( "Running on JDK8 and no toolchain found." );
113 }
114
115 String jLinkExecutable = toolchain.orElseThrow( NoSuchElementException::new ).findTool( "jlink" );
116
117 if ( jLinkExecutable.isEmpty() )
118 {
119 throw new IllegalStateException( "The jlink executable '"
120 + jLinkExecutable + "' doesn't exist or is not a file." );
121 }
122
123
124 String jLinkCommand = "jlink" + ( SystemUtils.IS_OS_WINDOWS ? ".exe" : "" );
125
126 File jLinkExe = new File( jLinkExecutable );
127
128 if ( jLinkExe.isDirectory() )
129 {
130 jLinkExe = new File( jLinkExe, jLinkCommand );
131 }
132
133 if ( SystemUtils.IS_OS_WINDOWS && jLinkExe.getName().indexOf( '.' ) < 0 )
134 {
135 jLinkExe = new File( jLinkExe.getPath() + ".exe" );
136 }
137
138 if ( !jLinkExe.isFile() )
139 {
140 throw new IllegalStateException( "The jlink executable '"
141 + jLinkExe + "' doesn't exist or is not a file." );
142 }
143 return jLinkExe.getAbsolutePath();
144 }
145
146 private int executeCommand( Commandline cmd )
147 throws MojoExecutionException
148 {
149 if ( getLog().isDebugEnabled() )
150 {
151
152 getLog().debug( CommandLineUtils.toString( cmd.getCommandline() ).replaceAll( "'", "" ) );
153 }
154
155 CommandLineUtils.StringStreamConsumer err = new CommandLineUtils.StringStreamConsumer();
156 CommandLineUtils.StringStreamConsumer out = new CommandLineUtils.StringStreamConsumer();
157 try
158 {
159 int exitCode = CommandLineUtils.executeCommandLine( cmd, out, err );
160
161 String output = ( StringUtils.isEmpty( out.getOutput() ) ? null : '\n' + out.getOutput().trim() );
162
163 if ( exitCode != 0 )
164 {
165
166 if ( StringUtils.isNotEmpty( output ) )
167 {
168
169
170 for ( String outputLine : output.split( "\n" ) )
171 {
172 getLog().error( outputLine );
173 }
174 }
175
176 StringBuilder msg = new StringBuilder( "\nExit code: " );
177 msg.append( exitCode );
178 if ( StringUtils.isNotEmpty( err.getOutput() ) )
179 {
180 msg.append( " - " ).append( err.getOutput() );
181 }
182 msg.append( '\n' );
183 msg.append( "Command line was: " ).append( cmd ).append( '\n' ).append( '\n' );
184
185 throw new MojoExecutionException( msg.toString() );
186 }
187
188 if ( StringUtils.isNotEmpty( output ) )
189 {
190
191 for ( String outputLine : output.split( "\n" ) )
192 {
193 getLog().info( outputLine );
194 }
195 }
196
197 return exitCode;
198 }
199 catch ( CommandLineException e )
200 {
201 throw new MojoExecutionException( "Unable to execute jlink command: " + e.getMessage(), e );
202 }
203 }
204 }