1 package org.apache.maven.plugin.gpg;
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.artifact.deployer.ArtifactDeployer;
24 import org.apache.maven.artifact.deployer.ArtifactDeploymentException;
25 import org.apache.maven.artifact.factory.ArtifactFactory;
26 import org.apache.maven.artifact.metadata.ArtifactMetadata;
27 import org.apache.maven.artifact.repository.ArtifactRepository;
28 import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
29 import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
30 import org.apache.maven.model.Model;
31 import org.apache.maven.model.Parent;
32 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
33 import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
34 import org.apache.maven.plugin.MojoExecutionException;
35 import org.apache.maven.plugin.MojoFailureException;
36 import org.apache.maven.project.MavenProject;
37 import org.apache.maven.project.MavenProjectHelper;
38 import org.apache.maven.project.artifact.AttachedArtifact;
39 import org.apache.maven.project.artifact.ProjectArtifactMetadata;
40 import org.apache.maven.project.validation.ModelValidationResult;
41 import org.apache.maven.project.validation.ModelValidator;
42 import org.codehaus.plexus.util.FileUtils;
43 import org.codehaus.plexus.util.IOUtil;
44 import org.codehaus.plexus.util.ReaderFactory;
45 import org.codehaus.plexus.util.StringUtils;
46 import org.codehaus.plexus.util.WriterFactory;
47 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
48
49 import java.io.File;
50 import java.io.FileNotFoundException;
51 import java.io.IOException;
52 import java.io.Reader;
53 import java.io.Writer;
54 import java.util.Iterator;
55 import java.util.List;
56 import java.util.Map;
57
58
59
60
61
62
63
64
65
66
67 public class SignAndDeployFileMojo
68 extends AbstractGpgMojo
69 {
70
71
72
73
74
75
76 private File ascDirectory;
77
78
79
80
81
82
83
84 private boolean offline;
85
86
87
88
89
90
91 private String groupId;
92
93
94
95
96
97
98 private String artifactId;
99
100
101
102
103
104
105 private String version;
106
107
108
109
110
111
112
113 private String packaging;
114
115
116
117
118
119
120 private String classifier;
121
122
123
124
125
126
127 private String description;
128
129
130
131
132
133
134
135 private File file;
136
137
138
139
140
141
142 private File pomFile;
143
144
145
146
147
148
149 private boolean generatePom;
150
151
152
153
154
155
156 private boolean uniqueVersion;
157
158
159
160
161
162
163
164
165 private String url;
166
167
168
169
170
171
172
173
174 private String repositoryId;
175
176
177
178
179
180
181 private String repositoryLayout;
182
183
184
185
186 private ArtifactDeployer deployer;
187
188
189
190
191
192
193 private ArtifactRepository localRepository;
194
195
196
197
198
199
200 private Map repositoryLayouts;
201
202
203
204
205
206
207 private ArtifactFactory artifactFactory;
208
209
210
211
212
213
214 private ArtifactRepositoryFactory repositoryFactory;
215
216
217
218
219
220
221 private ModelValidator modelValidator;
222
223
224
225
226
227
228
229
230
231 private MavenProject project;
232
233
234
235
236
237
238
239 private MavenProjectHelper projectHelper;
240
241
242
243
244
245
246
247 private File javadoc;
248
249
250
251
252
253
254
255 private File sources;
256
257
258
259
260
261
262
263
264 private int retryFailedDeploymentCount;
265
266
267
268
269
270
271
272 protected boolean updateReleaseInfo;
273
274 private void initProperties()
275 throws MojoExecutionException
276 {
277
278 if ( pomFile != null )
279 {
280 generatePom = false;
281
282 Model model = readModel( pomFile );
283
284 processModel( model );
285 }
286
287 if ( packaging == null && file != null )
288 {
289 packaging = FileUtils.getExtension( file.getName() );
290 }
291 }
292
293 public void execute()
294 throws MojoExecutionException, MojoFailureException
295 {
296 GpgSigner signer = newSigner( null );
297 signer.setOutputDirectory( ascDirectory );
298 signer.setBaseDirectory( new File( "" ).getAbsoluteFile() );
299
300 if ( offline )
301 {
302 throw new MojoFailureException( "Cannot deploy artifacts when Maven is in offline mode" );
303 }
304
305 initProperties();
306
307 validateArtifactInformation();
308
309 if ( !file.exists() )
310 {
311 throw new MojoFailureException( file.getPath() + " not found." );
312 }
313
314 ArtifactRepositoryLayout layout = (ArtifactRepositoryLayout) repositoryLayouts.get( repositoryLayout );
315 if ( layout == null )
316 {
317 throw new MojoFailureException( "Invalid repository layout: " + repositoryLayout );
318 }
319
320 ArtifactRepository deploymentRepository =
321 repositoryFactory.createDeploymentArtifactRepository( repositoryId, url, layout, uniqueVersion );
322
323 if ( StringUtils.isEmpty( deploymentRepository.getProtocol() ) )
324 {
325 throw new MojoFailureException( "No transfer protocol found." );
326 }
327
328 Artifact artifact =
329 artifactFactory.createArtifactWithClassifier( groupId, artifactId, version, packaging, classifier );
330
331 if ( file.equals( getLocalRepoFile( artifact ) ) )
332 {
333 throw new MojoFailureException( "Cannot deploy artifact from the local repository: " + file );
334 }
335
336 File fileSig = signer.generateSignatureForArtifact( file );
337 ArtifactMetadata metadata = new AscArtifactMetadata( artifact, fileSig, false );
338 artifact.addMetadata( metadata );
339
340 if ( !"pom".equals( packaging ) )
341 {
342 if ( pomFile == null && generatePom )
343 {
344 pomFile = generatePomFile();
345 }
346 if ( pomFile != null )
347 {
348 metadata = new ProjectArtifactMetadata( artifact, pomFile );
349 artifact.addMetadata( metadata );
350
351 fileSig = signer.generateSignatureForArtifact( pomFile );
352 metadata = new AscArtifactMetadata( artifact, fileSig, true );
353 artifact.addMetadata( metadata );
354 }
355 }
356
357 if ( updateReleaseInfo )
358 {
359 artifact.setRelease( true );
360 }
361
362 project.setArtifact( artifact );
363
364 try
365 {
366 deploy( file, artifact, deploymentRepository, localRepository );
367 }
368 catch ( ArtifactDeploymentException e )
369 {
370 throw new MojoExecutionException( e.getMessage(), e );
371 }
372
373 if ( sources != null )
374 {
375 projectHelper.attachArtifact( project, "jar", "sources", sources );
376 }
377
378 if ( javadoc != null )
379 {
380 projectHelper.attachArtifact( project, "jar", "javadoc", javadoc );
381 }
382
383 List attachedArtifacts = project.getAttachedArtifacts();
384
385 for ( Iterator i = attachedArtifacts.iterator(); i.hasNext(); )
386 {
387 Artifact attached = (Artifact) i.next();
388
389 fileSig = signer.generateSignatureForArtifact( attached.getFile() );
390 attached = new AttachedSignedArtifact(attached, new AscArtifactMetadata( attached, fileSig, false ) );
391 try
392 {
393 deploy( attached.getFile(), attached, deploymentRepository, localRepository );
394 }
395 catch ( ArtifactDeploymentException e )
396 {
397 throw new MojoExecutionException(
398 "Error deploying attached artifact " + attached.getFile() + ": " + e.getMessage(), e );
399 }
400 }
401
402 }
403
404
405
406
407
408
409
410
411 private File getLocalRepoFile( Artifact artifact )
412 {
413 String path = localRepository.pathOf( artifact );
414 return new File( localRepository.getBasedir(), path );
415 }
416
417
418
419
420
421
422 private void processModel( Model model )
423 {
424 Parent parent = model.getParent();
425
426 if ( this.groupId == null )
427 {
428 this.groupId = model.getGroupId();
429 if ( this.groupId == null && parent != null )
430 {
431 this.groupId = parent.getGroupId();
432 }
433 }
434 if ( this.artifactId == null )
435 {
436 this.artifactId = model.getArtifactId();
437 }
438 if ( this.version == null )
439 {
440 this.version = model.getVersion();
441 if ( this.version == null && parent != null )
442 {
443 this.version = parent.getVersion();
444 }
445 }
446 if ( this.packaging == null )
447 {
448 this.packaging = model.getPackaging();
449 }
450 }
451
452
453
454
455
456
457
458
459 private Model readModel( File pomFile )
460 throws MojoExecutionException
461 {
462 Reader reader = null;
463 try
464 {
465 reader = ReaderFactory.newXmlReader( pomFile );
466 return new MavenXpp3Reader().read( reader );
467 }
468 catch ( FileNotFoundException e )
469 {
470 throw new MojoExecutionException( "POM not found " + pomFile, e );
471 }
472 catch ( IOException e )
473 {
474 throw new MojoExecutionException( "Error reading POM " + pomFile, e );
475 }
476 catch ( XmlPullParserException e )
477 {
478 throw new MojoExecutionException( "Error parsing POM " + pomFile, e );
479 }
480 finally
481 {
482 IOUtil.close( reader );
483 }
484 }
485
486
487
488
489
490
491
492 private File generatePomFile()
493 throws MojoExecutionException
494 {
495 Model model = generateModel();
496
497 Writer fw = null;
498 try
499 {
500 File tempFile = File.createTempFile( "mvndeploy", ".pom" );
501 tempFile.deleteOnExit();
502
503 fw = WriterFactory.newXmlWriter( tempFile );
504 new MavenXpp3Writer().write( fw, model );
505
506 return tempFile;
507 }
508 catch ( IOException e )
509 {
510 throw new MojoExecutionException( "Error writing temporary pom file: " + e.getMessage(), e );
511 }
512 finally
513 {
514 IOUtil.close( fw );
515 }
516 }
517
518
519
520
521
522
523 private void validateArtifactInformation()
524 throws MojoFailureException
525 {
526 Model model = generateModel();
527
528 ModelValidationResult result = modelValidator.validate( model );
529
530 if ( result.getMessageCount() > 0 )
531 {
532 throw new MojoFailureException( "The artifact information is incomplete or not valid:\n"
533 + result.render( " " ) );
534 }
535 }
536
537
538
539
540
541
542 private Model generateModel()
543 {
544 Model model = new Model();
545
546 model.setModelVersion( "4.0.0" );
547
548 model.setGroupId( groupId );
549 model.setArtifactId( artifactId );
550 model.setVersion( version );
551 model.setPackaging( packaging );
552
553 model.setDescription( description );
554
555 return model;
556 }
557
558
559
560
561
562
563
564
565
566
567 protected void deploy( File source, Artifact artifact, ArtifactRepository deploymentRepository,
568 ArtifactRepository localRepository )
569 throws ArtifactDeploymentException
570 {
571 int retryFailedDeploymentCount = Math.max( 1, Math.min( 10, this.retryFailedDeploymentCount ) );
572 ArtifactDeploymentException exception = null;
573 for ( int count = 0; count < retryFailedDeploymentCount; count++ )
574 {
575 try
576 {
577 if (count > 0)
578 {
579 getLog().info(
580 "Retrying deployment attempt " + ( count + 1 ) + " of " + retryFailedDeploymentCount );
581 }
582 deployer.deploy( source, artifact, deploymentRepository, localRepository );
583 for ( Iterator i = artifact.getMetadataList().iterator(); i.hasNext(); )
584 {
585 ArtifactMetadata metadata = (ArtifactMetadata) i.next();
586 getLog().info( "Metadata[" + metadata.getKey() + "].filename = " + metadata.getRemoteFilename());
587 }
588 exception = null;
589 }
590 catch ( ArtifactDeploymentException e )
591 {
592 if (count + 1 < retryFailedDeploymentCount) {
593 getLog().warn( "Encountered issue during deployment: " + e.getLocalizedMessage());
594 getLog().debug( e );
595 }
596 if ( exception == null )
597 {
598 exception = e;
599 }
600 }
601 }
602 if ( exception != null )
603 {
604 throw exception;
605 }
606 }
607 }