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 org.apache.maven.artifact.Artifact;
23 import org.apache.maven.execution.MavenSession;
24 import org.apache.maven.plugin.AbstractMojo;
25 import org.apache.maven.plugin.MojoExecutionException;
26 import org.apache.maven.plugins.annotations.Component;
27 import org.apache.maven.plugins.annotations.Parameter;
28 import org.apache.maven.project.MavenProject;
29 import org.apache.maven.shared.jarsigner.JarSigner;
30 import org.apache.maven.shared.jarsigner.JarSignerRequest;
31 import org.apache.maven.shared.jarsigner.JarSignerUtil;
32 import org.apache.maven.shared.utils.StringUtils;
33 import org.apache.maven.shared.utils.cli.Commandline;
34 import org.apache.maven.shared.utils.cli.javatool.JavaToolException;
35 import org.apache.maven.shared.utils.cli.javatool.JavaToolResult;
36 import org.apache.maven.shared.utils.io.FileUtils;
37 import org.apache.maven.toolchain.Toolchain;
38 import org.apache.maven.toolchain.ToolchainManager;
39 import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher;
40 import org.sonatype.plexus.components.sec.dispatcher.SecDispatcherException;
41
42 import java.io.File;
43 import java.io.IOException;
44 import java.text.MessageFormat;
45 import java.util.Arrays;
46 import java.util.Collection;
47 import java.util.HashSet;
48 import java.util.List;
49 import java.util.ResourceBundle;
50
51
52
53
54
55
56
57 public abstract class AbstractJarsignerMojo
58 extends AbstractMojo
59 {
60
61
62
63
64 @Parameter( property = "jarsigner.verbose", defaultValue = "false" )
65 private boolean verbose;
66
67
68
69
70 @Parameter( property = "jarsigner.keystore" )
71 private String keystore;
72
73
74
75
76 @Parameter( property = "jarsigner.storetype" )
77 private String storetype;
78
79
80
81
82 @Parameter( property = "jarsigner.storepass" )
83 private String storepass;
84
85
86
87
88 @Parameter( property = "jarsigner.providerName" )
89 private String providerName;
90
91
92
93
94 @Parameter( property = "jarsigner.providerClass" )
95 private String providerClass;
96
97
98
99
100 @Parameter( property = "jarsigner.providerArg" )
101 private String providerArg;
102
103
104
105
106 @Parameter( property = "jarsigner.alias" )
107 private String alias;
108
109
110
111
112
113 @Parameter( property = "jarsigner.maxMemory" )
114 private String maxMemory;
115
116
117
118
119 @Parameter( property = "jarsigner.archive" )
120 private File archive;
121
122
123
124
125
126
127 @Parameter( property = "jarsigner.archiveDirectory" )
128 private File archiveDirectory;
129
130
131
132
133
134
135
136
137 @Parameter
138 private String[] includes = { "**/*.?ar" };
139
140
141
142
143
144
145
146 @Parameter
147 private String[] excludes = { };
148
149
150
151
152 @Parameter( property = "jarsigner.arguments" )
153 private String[] arguments;
154
155
156
157
158 @Parameter( property = "jarsigner.skip", defaultValue = "false" )
159 private boolean skip;
160
161
162
163
164
165
166 @Parameter( property = "jarsigner.processMainArtifact", defaultValue = "true" )
167 private boolean processMainArtifact;
168
169
170
171
172
173
174
175 @Parameter( property = "jarsigner.processAttachedArtifacts", defaultValue = "true" )
176 private boolean processAttachedArtifacts;
177
178
179
180
181
182
183
184 @Parameter( property = "jarsigner.protectedAuthenticationPath", defaultValue = "false" )
185 private boolean protectedAuthenticationPath;
186
187
188
189
190
191
192 @Parameter( property = "jarsigner.attachments" )
193 private Boolean attachments;
194
195
196
197
198
199
200
201 @Parameter
202 private String[] includeClassifiers;
203
204
205
206
207
208
209
210 @Parameter
211 private String[] excludeClassifiers;
212
213
214
215
216 @Component
217 private MavenProject project;
218
219
220
221
222
223
224 @Parameter( defaultValue = "${project.basedir}" )
225 private File workingDirectory;
226
227
228
229 @Component
230 private JarSigner jarSigner;
231
232
233
234
235
236
237
238 @Component
239 private MavenSession session;
240
241
242
243
244
245
246 @Component
247 private ToolchainManager toolchainManager;
248
249
250
251
252 @Component( hint = "mng-4384" )
253 private SecDispatcher securityDispatcher;
254
255 public final void execute()
256 throws MojoExecutionException
257 {
258 if ( !this.skip )
259 {
260 Toolchain toolchain = getToolchain();
261
262 if ( toolchain != null )
263 {
264 jarSigner.setToolchain(toolchain);
265 }
266
267 int processed = 0;
268
269 if ( this.archive != null )
270 {
271 processArchive( this.archive );
272 processed++;
273 }
274 else
275 {
276 if ( processMainArtifact )
277 {
278 processed += processArtifact( this.project.getArtifact() ) ? 1 : 0;
279 }
280
281 if ( processAttachedArtifacts && !Boolean.FALSE.equals( attachments ) )
282 {
283 Collection<String> includes = new HashSet<String>();
284 if ( includeClassifiers != null )
285 {
286 includes.addAll( Arrays.asList( includeClassifiers ) );
287 }
288
289 Collection<String> excludes = new HashSet<String>();
290 if ( excludeClassifiers != null )
291 {
292 excludes.addAll( Arrays.asList( excludeClassifiers ) );
293 }
294
295 for ( Object o : this.project.getAttachedArtifacts() )
296 {
297 final Artifact artifact = (Artifact) o;
298
299 if ( !includes.isEmpty() && !includes.contains( artifact.getClassifier() ) )
300 {
301 continue;
302 }
303
304 if ( excludes.contains( artifact.getClassifier() ) )
305 {
306 continue;
307 }
308
309 processed += processArtifact( artifact ) ? 1 : 0;
310 }
311 }
312 else
313 {
314 if ( verbose )
315 {
316 getLog().info( getMessage( "ignoringAttachments" ) );
317 }
318 else
319 {
320 getLog().debug( getMessage( "ignoringAttachments" ) );
321 }
322 }
323
324 if ( archiveDirectory != null )
325 {
326 String includeList = ( includes != null ) ? StringUtils.join( includes, "," ) : null;
327 String excludeList = ( excludes != null ) ? StringUtils.join( excludes, "," ) : null;
328
329 List<File> jarFiles;
330 try
331 {
332 jarFiles = FileUtils.getFiles( archiveDirectory, includeList, excludeList );
333 }
334 catch ( IOException e )
335 {
336 throw new MojoExecutionException(
337 "Failed to scan archive directory for JARs: " + e.getMessage(), e );
338 }
339
340 for ( File jarFile : jarFiles )
341 {
342 processArchive( jarFile );
343 processed++;
344 }
345 }
346 }
347
348 getLog().info( getMessage( "processed", processed) );
349 }
350 else
351 {
352 getLog().info( getMessage( "disabled", null ) );
353 }
354 }
355
356
357
358
359
360
361
362
363 protected abstract JarSignerRequest createRequest( File archive )
364 throws MojoExecutionException;
365
366
367
368
369
370
371
372
373
374 protected String getCommandlineInfo( final Commandline commandLine )
375 {
376 if ( commandLine == null )
377 {
378 throw new NullPointerException( "commandLine" );
379 }
380
381 String commandLineInfo = commandLine.toString();
382 commandLineInfo = StringUtils.replace( commandLineInfo, this.storepass, "'*****'" );
383 return commandLineInfo;
384 }
385
386 public String getStoretype()
387 {
388 return storetype;
389 }
390
391 public String getStorepass()
392 {
393 return storepass;
394 }
395
396
397
398
399
400
401
402 private boolean isZipFile( final Artifact artifact )
403 {
404 return artifact != null && artifact.getFile() != null && JarSignerUtil.isZipFile( artifact.getFile() );
405 }
406
407
408
409
410
411
412
413
414
415 private boolean processArtifact( final Artifact artifact )
416 throws MojoExecutionException
417 {
418 if ( artifact == null )
419 {
420 throw new NullPointerException( "artifact" );
421 }
422
423 boolean processed = false;
424
425 if ( isZipFile( artifact ) )
426 {
427 processArchive( artifact.getFile() );
428
429 processed = true;
430 }
431 else
432 {
433 if ( this.verbose )
434 {
435 getLog().info( getMessage( "unsupported", artifact ) );
436 }
437 else if ( getLog().isDebugEnabled() )
438 {
439 getLog().debug( getMessage( "unsupported", artifact ) );
440 }
441 }
442
443 return processed;
444 }
445
446
447
448
449
450
451
452 protected void preProcessArchive( final File archive )
453 throws MojoExecutionException
454 {
455
456 }
457
458
459
460
461
462
463
464
465 private void processArchive( final File archive )
466 throws MojoExecutionException
467 {
468 if ( archive == null )
469 {
470 throw new NullPointerException( "archive" );
471 }
472
473 preProcessArchive( archive );
474
475 if ( this.verbose )
476 {
477 getLog().info( getMessage( "processing", archive ) );
478 }
479 else if ( getLog().isDebugEnabled() )
480 {
481 getLog().debug( getMessage( "processing", archive ) );
482 }
483
484 JarSignerRequest request = createRequest( archive );
485 request.setVerbose( verbose );
486 request.setAlias( alias );
487 request.setArchive( archive );
488 request.setKeystore( keystore );
489 request.setStoretype( storetype );
490 request.setProviderArg( providerArg );
491 request.setProviderClass( providerClass );
492 request.setProviderName( providerName );
493 request.setWorkingDirectory( workingDirectory );
494 request.setMaxMemory( maxMemory );
495 request.setArguments( arguments );
496 request.setProtectedAuthenticationPath( protectedAuthenticationPath );
497
498
499 request.setStorepass( decrypt( storepass ) );
500
501 try
502 {
503 JavaToolResult result = jarSigner.execute( request );
504
505 Commandline commandLine = result.getCommandline();
506
507 int resultCode = result.getExitCode();
508
509 if ( resultCode != 0 )
510 {
511 throw new MojoExecutionException(
512 getMessage( "failure", getCommandlineInfo( commandLine ), resultCode) );
513 }
514
515 }
516 catch ( JavaToolException e )
517 {
518 throw new MojoExecutionException( getMessage( "commandLineException", e.getMessage() ), e );
519 }
520 }
521
522 protected String decrypt(String encoded)
523 throws MojoExecutionException
524 {
525 try
526 {
527 return securityDispatcher.decrypt( encoded );
528 }
529 catch ( SecDispatcherException e )
530 {
531 getLog().error( "error using security dispatcher: " + e.getMessage(), e );
532 throw new MojoExecutionException( "error using security dispatcher: " + e.getMessage(), e );
533 }
534 }
535
536
537
538
539
540
541
542
543
544
545
546
547 private String getMessage( final String key, final Object[] args )
548 {
549 if ( key == null )
550 {
551 throw new NullPointerException( "key" );
552 }
553
554 return new MessageFormat( ResourceBundle.getBundle( "jarsigner" ).getString( key ) ).format( args );
555 }
556
557 private String getMessage( final String key )
558 {
559 return getMessage( key, null );
560 }
561
562 String getMessage( final String key, final Object arg )
563 {
564 return getMessage( key, new Object[]{ arg } );
565 }
566
567 private String getMessage( final String key, final Object arg1, final Object arg2 )
568 {
569 return getMessage( key, new Object[]{ arg1, arg2 } );
570 }
571
572
573
574
575
576
577
578
579 private Toolchain getToolchain()
580 {
581 Toolchain tc = null;
582 if ( toolchainManager != null )
583 {
584 tc = toolchainManager.getToolchainFromBuildContext( "jdk", session );
585 }
586
587 return tc;
588 }
589 }