1 package org.apache.maven.plugins.jarsigner;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.text.MessageFormat;
27 import java.util.Iterator;
28 import java.util.Properties;
29 import java.util.ResourceBundle;
30 import java.util.zip.ZipEntry;
31 import java.util.zip.ZipInputStream;
32
33 import org.apache.maven.artifact.Artifact;
34 import org.apache.maven.plugin.AbstractMojo;
35 import org.apache.maven.plugin.MojoExecutionException;
36 import org.apache.maven.project.MavenProject;
37
38 import org.codehaus.plexus.util.Os;
39 import org.codehaus.plexus.util.StringUtils;
40 import org.codehaus.plexus.util.cli.CommandLineException;
41 import org.codehaus.plexus.util.cli.CommandLineUtils;
42 import org.codehaus.plexus.util.cli.Commandline;
43 import org.codehaus.plexus.util.cli.StreamConsumer;
44
45
46
47
48
49
50
51 public abstract class AbstractJarsignerMojo
52 extends AbstractMojo
53 {
54
55
56
57
58
59
60 private boolean verbose;
61
62
63
64
65
66
67
68 private String maxMemory;
69
70
71
72
73
74
75
76 private File archive;
77
78
79
80
81
82
83
84 private String[] arguments;
85
86
87
88
89
90
91 private boolean skip;
92
93
94
95
96
97
98 private boolean attachments;
99
100
101
102
103
104
105
106
107 private MavenProject project;
108
109
110
111
112 private String executable;
113
114 public final void execute()
115 throws MojoExecutionException
116 {
117 if ( !this.skip )
118 {
119 this.executable = getExecutable();
120
121 if ( this.archive != null )
122 {
123 this.processArchive( this.archive );
124 }
125 else
126 {
127 this.processArtifact( this.project.getArtifact() );
128
129 for ( Iterator it = this.project.getAttachedArtifacts().iterator(); it.hasNext(); )
130 {
131 final Artifact artifact = (Artifact) it.next();
132
133 if ( this.attachments )
134 {
135 this.processArtifact( artifact );
136 }
137 else if ( this.isJarFile( artifact ) )
138 {
139 this.getLog().info( this.getMessage( "ignoringAttachment", new Object[]
140 {
141 artifact.toString()
142 } ) );
143
144 }
145 }
146 }
147 }
148 else
149 {
150 this.getLog().info( this.getMessage( "disabled", null ) );
151 }
152 }
153
154
155
156
157
158
159
160
161
162
163
164
165 protected abstract Commandline getCommandline( final File archive, final Commandline commandLine );
166
167
168
169
170
171
172
173
174
175
176
177 protected String getCommandlineInfo( final Commandline commandLine )
178 {
179 if ( commandLine == null )
180 {
181 throw new NullPointerException( "commandLine" );
182 }
183
184 return commandLine.toString();
185 }
186
187
188
189
190
191
192
193
194 private boolean isJarFile( final Artifact artifact )
195 {
196 return artifact != null && artifact.getFile() != null && isJarFile( artifact.getFile() );
197 }
198
199
200
201
202
203
204
205
206 private boolean isJarFile( final File file )
207 {
208 try
209 {
210
211
212 ZipInputStream zis = new ZipInputStream( new FileInputStream( file ) );
213 try
214 {
215 for ( ZipEntry ze = zis.getNextEntry(); ze != null; ze = zis.getNextEntry() )
216 {
217 if ( ze.getName().startsWith( "META-INF/" ) || ze.getName().endsWith( ".class" ) )
218 {
219 return true;
220 }
221 }
222 }
223 finally
224 {
225 zis.close();
226 }
227 }
228 catch ( Exception e )
229 {
230
231 }
232
233 return false;
234 }
235
236
237
238
239
240
241
242
243
244 private void processArtifact( final Artifact artifact )
245 throws MojoExecutionException
246 {
247 if ( artifact == null )
248 {
249 throw new NullPointerException( "artifact" );
250 }
251
252 if ( this.isJarFile( artifact ) )
253 {
254 if ( this.verbose )
255 {
256 this.getLog().info( this.getMessage( "processing", new Object[]
257 {
258 artifact.toString()
259 } ) );
260
261 }
262 else if ( this.getLog().isDebugEnabled() )
263 {
264 this.getLog().debug( this.getMessage( "processing", new Object[]
265 {
266 artifact.toString()
267 } ) );
268
269 }
270
271 this.processArchive( artifact.getFile() );
272 }
273 else
274 {
275 if ( this.verbose )
276 {
277 this.getLog().info( this.getMessage( "unsupported", new Object[]
278 {
279 artifact.toString()
280 } ) );
281
282 }
283 else if ( this.getLog().isDebugEnabled() )
284 {
285 this.getLog().debug( this.getMessage( "unsupported", new Object[]
286 {
287 artifact.toString()
288 } ) );
289
290 }
291 }
292 }
293
294
295
296
297
298
299
300
301
302 private void processArchive( final File archive )
303 throws MojoExecutionException
304 {
305 if ( archive == null )
306 {
307 throw new NullPointerException( "archive" );
308 }
309
310 Commandline commandLine = new Commandline();
311
312 commandLine.setExecutable( this.executable );
313
314 commandLine.setWorkingDirectory( this.project.getBasedir() );
315
316 if ( this.verbose )
317 {
318 commandLine.createArg().setValue( "-verbose" );
319 }
320
321 if ( StringUtils.isNotEmpty( maxMemory ) )
322 {
323 commandLine.createArg().setValue( "-J-Xmx" + maxMemory );
324 }
325
326 if ( this.arguments != null )
327 {
328 commandLine.addArguments( this.arguments );
329 }
330
331 commandLine = this.getCommandline( archive, commandLine );
332
333 try
334 {
335 if ( this.getLog().isDebugEnabled() )
336 {
337 this.getLog().debug( this.getMessage( "command", new Object[]
338 {
339 this.getCommandlineInfo( commandLine )
340 } ) );
341
342 }
343
344 final int result = CommandLineUtils.executeCommandLine( commandLine,
345 new InputStream()
346 {
347
348 public int read()
349 {
350 return -1;
351 }
352
353 }, new StreamConsumer()
354 {
355
356 public void consumeLine( final String line )
357 {
358 if ( verbose )
359 {
360 getLog().info( line );
361 }
362 else
363 {
364 getLog().debug( line );
365 }
366 }
367
368 }, new StreamConsumer()
369 {
370
371 public void consumeLine( final String line )
372 {
373 getLog().warn( line );
374 }
375
376 } );
377
378 if ( result != 0 )
379 {
380 throw new MojoExecutionException( this.getMessage( "failure", new Object[]
381 {
382 this.getCommandlineInfo( commandLine ), new Integer( result )
383 } ) );
384
385 }
386 }
387 catch ( CommandLineException e )
388 {
389 throw new MojoExecutionException( this.getMessage( "commandLineException", new Object[]
390 {
391 this.getCommandlineInfo( commandLine )
392 } ), e );
393
394 }
395 }
396
397
398
399
400
401
402 private String getExecutable()
403 {
404 String command = "jarsigner" + ( Os.isFamily( Os.FAMILY_WINDOWS ) ? ".exe" : "" );
405
406 String executable =
407 findExecutable( command, System.getProperty( "java.home" ), new String[] { "../bin", "bin", "../sh" } );
408
409 if ( executable == null )
410 {
411 try
412 {
413 Properties env = CommandLineUtils.getSystemEnvVars();
414
415 String[] variables = { "JDK_HOME", "JAVA_HOME" };
416
417 for ( int i = 0; i < variables.length && executable == null; i++ )
418 {
419 executable =
420 findExecutable( command, env.getProperty( variables[i] ), new String[] { "bin", "sh" } );
421 }
422 }
423 catch ( IOException e )
424 {
425 if ( getLog().isDebugEnabled() )
426 {
427 getLog().warn( "Failed to retrieve environment variables, cannot search for " + command, e );
428 }
429 else
430 {
431 getLog().warn( "Failed to retrieve environment variables, cannot search for " + command );
432 }
433 }
434 }
435
436 if ( executable == null )
437 {
438 executable = command;
439 }
440
441 return executable;
442 }
443
444
445
446
447
448
449
450
451
452 private String findExecutable( String command, String homeDir, String[] subDirs )
453 {
454 if ( StringUtils.isNotEmpty( homeDir ) )
455 {
456 for ( int i = 0; i < subDirs.length; i++ )
457 {
458 File file = new File( new File( homeDir, subDirs[i] ), command );
459
460 if ( file.isFile() )
461 {
462 return file.getAbsolutePath();
463 }
464 }
465 }
466
467 return null;
468 }
469
470
471
472
473
474
475
476
477
478
479
480
481
482 private String getMessage( final String key, final Object[] args )
483 {
484 if ( key == null )
485 {
486 throw new NullPointerException( "key" );
487 }
488
489 return new MessageFormat( ResourceBundle.getBundle( "jarsigner" ).getString( key ) ).format( args );
490 }
491
492 }