View Javadoc

1   package org.apache.maven.plugin.assembly.mojos;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.archiver.MavenArchiveConfiguration;
23  import org.apache.maven.artifact.repository.ArtifactRepository;
24  import org.apache.maven.execution.MavenSession;
25  import org.apache.maven.plugin.AbstractMojo;
26  import org.apache.maven.plugin.MojoExecutionException;
27  import org.apache.maven.plugin.MojoFailureException;
28  import org.apache.maven.plugin.assembly.AssemblerConfigurationSource;
29  import org.apache.maven.plugin.assembly.InvalidAssemblerConfigurationException;
30  import org.apache.maven.plugin.assembly.archive.ArchiveCreationException;
31  import org.apache.maven.plugin.assembly.archive.AssemblyArchiver;
32  import org.apache.maven.plugin.assembly.format.AssemblyFormattingException;
33  import org.apache.maven.plugin.assembly.io.AssemblyReadException;
34  import org.apache.maven.plugin.assembly.io.AssemblyReader;
35  import org.apache.maven.plugin.assembly.model.Assembly;
36  import org.apache.maven.plugin.assembly.utils.AssemblyFormatUtils;
37  import org.apache.maven.plugin.logging.Log;
38  import org.apache.maven.project.MavenProject;
39  import org.apache.maven.project.MavenProjectHelper;
40  import org.apache.maven.shared.filtering.MavenFileFilter;
41  import org.codehaus.plexus.configuration.PlexusConfiguration;
42  
43  import java.io.File;
44  import java.util.Collections;
45  import java.util.Iterator;
46  import java.util.List;
47  
48  /**
49   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
50   * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
51   * @version $Id: AbstractAssemblyMojo.java 1072548 2011-02-20 10:35:48Z dennisl $
52   * @threadSafe
53   */
54  public abstract class AbstractAssemblyMojo
55      extends AbstractMojo
56      implements AssemblerConfigurationSource
57  {
58  
59      /**
60       * Flag allowing one or more executions of the assembly plugin to be configured as skipped for a particular build.
61       * This makes the assembly plugin more controllable from profiles.
62       * 
63       * @parameter expression="${assembly.skipAssembly}" default-value="false"
64       */
65      private boolean skipAssembly;
66  
67      /**
68       * If this flag is set, everything up to the call to Archiver.createArchive() will be executed.
69       * 
70       * @parameter expression="${assembly.dryRun}" default-value="false"
71       */
72      private boolean dryRun;
73  
74      /**
75       * If this flag is set, the ".dir" suffix will be suppressed in the output directory name when using assembly/format
76       * == 'dir' and other formats that begin with 'dir'. <br/>
77       * <b>NOTE:</b> Since 2.2-beta-3, the default-value for this is true, NOT false as it used to be.
78       * 
79       * @parameter default-value="true"
80       */
81      private boolean ignoreDirFormatExtensions;
82  
83      /**
84       * Local Maven repository where artifacts are cached during the build process.
85       * 
86       * @parameter default-value="${localRepository}"
87       * @required
88       * @readonly
89       */
90      private ArtifactRepository localRepository;
91  
92      /**
93       * @parameter default-value="${project.remoteArtifactRepositories}"
94       * @required
95       * @readonly
96       */
97      private List<ArtifactRepository> remoteRepositories;
98  
99      /**
100      * Contains the full list of projects in the reactor.
101      * 
102      * @parameter default-value="${reactorProjects}"
103      * @required
104      * @readonly
105      */
106     private List<MavenProject> reactorProjects;
107 
108     /**
109      * The output directory of the assembled distribution file.
110      * 
111      * @parameter default-value="${project.build.directory}"
112      * @required
113      */
114     private File outputDirectory;
115 
116     /**
117      * The filename of the assembled distribution file.
118      * 
119      * @parameter default-value="${project.build.finalName}"
120      * @required
121      */
122     private String finalName;
123 
124     /**
125      * Directory to unpack JARs into if needed
126      * 
127      * @parameter default-value="${project.build.directory}/assembly/work"
128      * @required
129      */
130     private File workDirectory;
131 
132     /**
133      * This is the artifact classifier to be used for the resultant assembly artifact. Normally, you would use the
134      * assembly-id instead of specifying this here.
135      * 
136      * @parameter expression="${classifier}"
137      * @deprecated Please use the Assembly's id for classifier instead
138      */
139     @Deprecated
140     @SuppressWarnings( "unused" )
141     private String classifier;
142 
143     /**
144      * A list of descriptor files to generate from.
145      * 
146      * @parameter
147      */
148     private String[] descriptors;
149 
150     /**
151      * A list of references to assembly descriptors available on the plugin's classpath. The default classpath
152      * includes these built-in descriptors: <code>bin</code>,
153      * <code>jar-with-dependencies</code>, <code>src</code>, and 
154      * <code>project</code>. You can add others by adding dependencies
155      * to the plugin.
156      * 
157      * @parameter
158      */
159     private String[] descriptorRefs;
160 
161     /**
162      * Directory to scan for descriptor files in. <b>NOTE:</b> This may not work correctly with assembly components.
163      * 
164      * @parameter
165      */
166     private File descriptorSourceDirectory;
167 
168     /**
169      * This is the base directory from which archive files are created. This base directory pre-pended to any
170      * <code>&lt;directory&gt;</code> specifications in the assembly descriptor. This is an optional parameter.
171      * 
172      * @parameter
173      */
174     private File archiveBaseDirectory;
175 
176     /**
177      * Predefined Assembly Descriptor Id's. You can select bin, jar-with-dependencies, or src.
178      * 
179      * @parameter expression="${descriptorId}"
180      * @deprecated Please use descriptorRefs instead
181      */
182     @Deprecated
183     protected String descriptorId;
184 
185     /**
186      * Assembly XML Descriptor file. This must be the path to your customized descriptor file.
187      * 
188      * @parameter expression="${descriptor}"
189      * @deprecated Please use descriptors instead
190      */
191     @Deprecated
192     protected String descriptor;
193 
194     /**
195      * Sets the TarArchiver behavior on file paths with more than 100 characters length. Valid values are: "warn"
196      * (default), "fail", "truncate", "gnu", or "omit".
197      * 
198      * @parameter expression="${assembly.tarLongFileMode}" default-value="warn"
199      */
200     private String tarLongFileMode;
201 
202     /**
203      * Base directory of the project.
204      * 
205      * @parameter default-value="${project.basedir}"
206      * @required
207      * @readonly
208      */
209     private File basedir;
210 
211     /**
212      * Maven ProjectHelper.
213      * 
214      * @component
215      */
216     private MavenProjectHelper projectHelper;
217 
218     /**
219      * Maven shared filtering utility.
220      * 
221      * @component
222      */
223     private MavenFileFilter mavenFileFilter;
224 
225     /**
226      * The Maven Session Object
227      * 
228      * @parameter default-value="${session}"
229      * @required
230      * @readonly
231      */
232     private MavenSession mavenSession;
233 
234     /**
235      * Temporary directory that contain the files to be assembled.
236      * 
237      * @parameter default-value="${project.build.directory}/archive-tmp"
238      * @required
239      * @readonly
240      */
241     private File tempRoot;
242 
243     /**
244      * Directory for site generated.
245      * 
246      * @parameter default-value="${project.reporting.outputDirectory}"
247      * @readonly
248      */
249     private File siteDirectory;
250 
251     /**
252      * Set to true to include the site generated by site:site goal.
253      * 
254      * @parameter expression="${includeSite}" default-value="false"
255      * @deprecated Please set this variable in the assembly descriptor instead
256      */
257     @Deprecated
258     private boolean includeSite;
259 
260     /**
261      * Set to false to exclude the assembly id from the assembly final name.
262      * 
263      * @parameter expression="${assembly.appendAssemblyId}" default-value="true"
264      */
265     protected boolean appendAssemblyId;
266 
267     /**
268      * Set to true in order to not fail when a descriptor is missing.
269      * 
270      * @parameter expression="${assembly.ignoreMissingDescriptor}" default-value="false"
271      */
272     protected boolean ignoreMissingDescriptor;
273 
274     /**
275      * This is a set of instructions to the archive builder, especially for building .jar files. It enables you to
276      * specify a Manifest file for the jar, in addition to other options.
277      * 
278      * @parameter
279      */
280     private MavenArchiveConfiguration archive;
281 
282     /**
283      * @parameter
284      */
285     protected List<String> filters;
286 
287     /**
288      * Controls whether the assembly plugin tries to attach the resulting assembly to the project.
289      * 
290      * @parameter expression="${assembly.attach}" default-value="true"
291      * @since 2.2-beta-1
292      */
293     private boolean attach;
294 
295     /**
296      * @component
297      */
298     private AssemblyArchiver assemblyArchiver;
299 
300     /**
301      * @component
302      */
303     private AssemblyReader assemblyReader;
304 
305     /**
306      * Allows additional configuration options that are specific to a particular type of archive format. This is
307      * intended to capture an XML configuration that will be used to reflectively setup the options on the archiver
308      * instance. <br/>
309      * For instance, to direct an assembly with the "ear" format to use a particular deployment descriptor, you should
310      * specify the following for the archiverConfig value in your plugin configuration: <br/>
311      * 
312      * <pre>
313      * &lt;appxml&gt;${project.basedir}/somepath/app.xml&lt;/appxml&gt;
314      * </pre>
315      * 
316      * @parameter
317      * @since 2.2-beta-3
318      */
319     private PlexusConfiguration archiverConfig;
320 
321     /**
322      * This will cause the assembly to run only at the top of a given module tree. That is, run in the project contained
323      * in the same folder where the mvn execution was launched.
324      * 
325      * @parameter expression="${assembly.runOnlyAtExecutionRoot}" default-value="false"
326      * @since 2.2-beta-4
327      */
328     private boolean runOnlyAtExecutionRoot;
329 
330     /**
331      * This will cause the assembly to only update an existing archive, if it exists.
332      * 
333      * @parameter expression="${assembly.updatOnly}" default-value="false"
334      * @since 2.2
335      */
336     private boolean updateOnly;
337 
338     /**
339      * <p>
340      * will use the jvm chmod, this is available for user and all level group level will be ignored
341      * </p>
342      * 
343      * @parameter expression="${assembly.useJvmChmod}" default-value="false"
344      * @since 2.2
345      */
346     private boolean useJvmChmod;
347 
348     /**
349      * <p>
350      * Set to <code>true</code> in order to avoid all chmod calls.
351      * </p>
352      * 
353      * <p>
354      * <b>NOTE:</b> This will cause the assembly plugin to <b>DISREGARD</b> all fileMode/directoryMode settings in the
355      * assembly descriptor, and all file permissions in unpacked dependencies!
356      * </p>
357      * 
358      * @parameter expression="${assembly.ignorePermissions}" default-value="false"
359      * @since 2.2
360      */
361     private boolean ignorePermissions;
362 
363     /**
364      * Create the binary distribution.
365      * 
366      * @throws org.apache.maven.plugin.MojoExecutionException
367      * 
368      */
369     public void execute()
370         throws MojoExecutionException, MojoFailureException
371     {
372         if ( skipAssembly )
373         {
374             getLog().info( "Assemblies have been skipped per configuration of the skipAssembly parameter." );
375             return;
376         }
377 
378         // run only at the execution root.
379         if ( runOnlyAtExecutionRoot && !isThisTheExecutionRoot() )
380         {
381             getLog().info( "Skipping the assembly in this project because it's not the Execution Root" );
382             return;
383         }
384 
385         List<Assembly> assemblies;
386         try
387         {
388             assemblies = assemblyReader.readAssemblies( this );
389         }
390         catch ( final AssemblyReadException e )
391         {
392             throw new MojoExecutionException( "Error reading assemblies: " + e.getMessage(), e );
393         }
394         catch ( final InvalidAssemblerConfigurationException e )
395         {
396             throw new MojoFailureException( assemblyReader, e.getMessage(), "Mojo configuration is invalid: "
397                             + e.getMessage() );
398         }
399 
400         // TODO: include dependencies marked for distribution under certain formats
401         // TODO: how, might we plug this into an installer, such as NSIS?
402 
403         boolean warnedAboutMainProjectArtifact = false;
404         for ( final Iterator<Assembly> assemblyIterator = assemblies.iterator(); assemblyIterator.hasNext(); )
405         {
406             final Assembly assembly = assemblyIterator.next();
407             try
408             {
409                 final String fullName = AssemblyFormatUtils.getDistributionName( assembly, this );
410 
411                 for ( final String format : assembly.getFormats() )
412                 {
413                     final File destFile = assemblyArchiver.createArchive( assembly, fullName, format, this );
414 
415                     final MavenProject project = getProject();
416                     final String classifier = getClassifier();
417                     final String type = project.getArtifact()
418                                                .getType();
419 
420                     if ( attach && destFile.isFile() )
421                     {
422                         if ( isAssemblyIdAppended() )
423                         {
424                             projectHelper.attachArtifact( project, format, assembly.getId(), destFile );
425                         }
426                         else if ( classifier != null )
427                         {
428                             projectHelper.attachArtifact( project, format, classifier, destFile );
429                         }
430                         else if ( !"pom".equals( type ) && format.equals( type ) )
431                         {
432                             if ( !warnedAboutMainProjectArtifact )
433                             {
434                                 final StringBuffer message = new StringBuffer();
435 
436                                 message.append( "Configuration options: 'appendAssemblyId' is set to false, and 'classifier' is missing." );
437                                 message.append( "\nInstead of attaching the assembly file: " )
438                                        .append( destFile )
439                                        .append( ", it will become the file for main project artifact." );
440                                 message.append( "\nNOTE: If multiple descriptors or descriptor-formats are provided for this project, the value of this file will be non-deterministic!" );
441 
442                                 getLog().warn( message );
443                                 warnedAboutMainProjectArtifact = true;
444                             }
445 
446                             final File existingFile = project.getArtifact()
447                                                              .getFile();
448                             if ( ( existingFile != null ) && existingFile.exists() )
449                             {
450                                 getLog().warn( "Replacing pre-existing project main-artifact file: " + existingFile
451                                                                + "\nwith assembly file: " + destFile );
452                             }
453 
454                             project.getArtifact()
455                                    .setFile( destFile );
456                         }
457                         else
458                         {
459                             projectHelper.attachArtifact( project, format, null, destFile );
460                         }
461                     }
462                     else if ( attach )
463                     {
464                         getLog().warn( "Assembly file: "
465                                                        + destFile
466                                                        + " is not a regular file (it may be a directory). It cannot be attached to the project build for installation or deployment." );
467                     }
468                 }
469             }
470             catch ( final ArchiveCreationException e )
471             {
472                 throw new MojoExecutionException( "Failed to create assembly: " + e.getMessage(), e );
473             }
474             catch ( final AssemblyFormattingException e )
475             {
476                 throw new MojoExecutionException( "Failed to create assembly: " + e.getMessage(), e );
477             }
478             catch ( final InvalidAssemblerConfigurationException e )
479             {
480                 throw new MojoFailureException( assembly, "Assembly is incorrectly configured: " + assembly.getId(),
481                                                 "Assembly: " + assembly.getId() + " is not configured correctly: "
482                                                                 + e.getMessage() );
483             }
484         }
485     }
486 
487     /**
488      * Returns true if the current project is located at the Execution Root Directory (where mvn was launched)
489      * 
490      * @return
491      */
492     protected boolean isThisTheExecutionRoot()
493     {
494         final Log log = getLog();
495         log.debug( "Root Folder:" + mavenSession.getExecutionRootDirectory() );
496         log.debug( "Current Folder:" + basedir );
497         final boolean result = mavenSession.getExecutionRootDirectory()
498                                            .equalsIgnoreCase( basedir.toString() );
499         if ( result )
500         {
501             log.debug( "This is the execution root." );
502         }
503         else
504         {
505             log.debug( "This is NOT the execution root." );
506         }
507 
508         return result;
509     }
510 
511     protected AssemblyArchiver getAssemblyArchiver()
512     {
513         return assemblyArchiver;
514     }
515 
516     protected AssemblyReader getAssemblyReader()
517     {
518         return assemblyReader;
519     }
520 
521     public File getBasedir()
522     {
523         return basedir;
524     }
525 
526     /**
527      * {@inheritDoc}
528      * 
529      * @deprecated This has been replaced by {@link #getDescriptors()}
530      */
531     @Deprecated
532     public String getDescriptor()
533     {
534         return descriptor;
535     }
536 
537     /**
538      * {@inheritDoc}
539      * 
540      * @deprecated This has been replaced by {@link #getDescriptorReferences()}
541      */
542     @Deprecated
543     public String getDescriptorId()
544     {
545         return descriptorId;
546     }
547 
548     public String[] getDescriptorReferences()
549     {
550         return descriptorRefs;
551     }
552 
553     public File getDescriptorSourceDirectory()
554     {
555         return descriptorSourceDirectory;
556     }
557 
558     public String[] getDescriptors()
559     {
560         return descriptors;
561     }
562 
563     public abstract MavenProject getProject();
564 
565     public File getSiteDirectory()
566     {
567         return siteDirectory;
568     }
569 
570     public boolean isSiteIncluded()
571     {
572         return includeSite;
573     }
574 
575     public String getFinalName()
576     {
577         return finalName;
578     }
579 
580     public boolean isAssemblyIdAppended()
581     {
582         return appendAssemblyId;
583     }
584 
585     public String getTarLongFileMode()
586     {
587         return tarLongFileMode;
588     }
589 
590     public File getOutputDirectory()
591     {
592         return outputDirectory;
593     }
594 
595     public MavenArchiveConfiguration getJarArchiveConfiguration()
596     {
597         return archive;
598     }
599 
600     public File getWorkingDirectory()
601     {
602         return workDirectory;
603     }
604 
605     public ArtifactRepository getLocalRepository()
606     {
607         return localRepository;
608     }
609 
610     public File getTemporaryRootDirectory()
611     {
612         return tempRoot;
613     }
614 
615     public File getArchiveBaseDirectory()
616     {
617         return archiveBaseDirectory;
618     }
619 
620     public List<String> getFilters()
621     {
622         if ( filters == null )
623         {
624             filters = getProject().getBuild()
625                                   .getFilters();
626             if ( filters == null )
627             {
628                 filters = Collections.emptyList();
629             }
630         }
631         return filters;
632     }
633 
634     public List<MavenProject> getReactorProjects()
635     {
636         return reactorProjects;
637     }
638 
639     public String getClassifier()
640     {
641         // TODO Auto-generated method stub
642         return null;
643     }
644 
645     protected MavenProjectHelper getProjectHelper()
646     {
647         return projectHelper;
648     }
649 
650     public void setAppendAssemblyId( final boolean appendAssemblyId )
651     {
652         this.appendAssemblyId = appendAssemblyId;
653     }
654 
655     public void setArchive( final MavenArchiveConfiguration archive )
656     {
657         this.archive = archive;
658     }
659 
660     public void setArchiveBaseDirectory( final File archiveBaseDirectory )
661     {
662         this.archiveBaseDirectory = archiveBaseDirectory;
663     }
664 
665     public void setAssemblyArchiver( final AssemblyArchiver assemblyArchiver )
666     {
667         this.assemblyArchiver = assemblyArchiver;
668     }
669 
670     public void setAssemblyReader( final AssemblyReader assemblyReader )
671     {
672         this.assemblyReader = assemblyReader;
673     }
674 
675     public void setBasedir( final File basedir )
676     {
677         this.basedir = basedir;
678     }
679 
680     public void setClassifier( final String classifier )
681     {
682         this.classifier = classifier;
683     }
684 
685     /**
686      * {@inheritDoc}
687      * 
688      * @deprecated This has been replaced by {@link #setDescriptors(String[])}
689      */
690     @Deprecated
691     public void setDescriptor( final String descriptor )
692     {
693         this.descriptor = descriptor;
694     }
695 
696     /**
697      * {@inheritDoc}
698      * 
699      * @deprecated This has been replaced by {@link #setDescriptorRefs(String[])}
700      */
701     @Deprecated
702     public void setDescriptorId( final String descriptorId )
703     {
704         this.descriptorId = descriptorId;
705     }
706 
707     public void setDescriptorRefs( final String[] descriptorRefs )
708     {
709         this.descriptorRefs = descriptorRefs;
710     }
711 
712     public void setDescriptors( final String[] descriptors )
713     {
714         this.descriptors = descriptors;
715     }
716 
717     public void setDescriptorSourceDirectory( final File descriptorSourceDirectory )
718     {
719         this.descriptorSourceDirectory = descriptorSourceDirectory;
720     }
721 
722     public void setFilters( final List<String> filters )
723     {
724         this.filters = filters;
725     }
726 
727     public void setFinalName( final String finalName )
728     {
729         this.finalName = finalName;
730     }
731 
732     public void setIncludeSite( final boolean includeSite )
733     {
734         this.includeSite = includeSite;
735     }
736 
737     public void setLocalRepository( final ArtifactRepository localRepository )
738     {
739         this.localRepository = localRepository;
740     }
741 
742     public void setOutputDirectory( final File outputDirectory )
743     {
744         this.outputDirectory = outputDirectory;
745     }
746 
747     public void setProjectHelper( final MavenProjectHelper projectHelper )
748     {
749         this.projectHelper = projectHelper;
750     }
751 
752     public void setReactorProjects( final List<MavenProject> reactorProjects )
753     {
754         this.reactorProjects = reactorProjects;
755     }
756 
757     public void setSiteDirectory( final File siteDirectory )
758     {
759         this.siteDirectory = siteDirectory;
760     }
761 
762     public void setTarLongFileMode( final String tarLongFileMode )
763     {
764         this.tarLongFileMode = tarLongFileMode;
765     }
766 
767     public void setTempRoot( final File tempRoot )
768     {
769         this.tempRoot = tempRoot;
770     }
771 
772     public void setWorkDirectory( final File workDirectory )
773     {
774         this.workDirectory = workDirectory;
775     }
776 
777     public List<ArtifactRepository> getRemoteRepositories()
778     {
779         return remoteRepositories;
780     }
781 
782     public boolean isDryRun()
783     {
784         return dryRun;
785     }
786 
787     public boolean isIgnoreDirFormatExtensions()
788     {
789         return ignoreDirFormatExtensions;
790     }
791 
792     public boolean isIgnoreMissingDescriptor()
793     {
794         return ignoreMissingDescriptor;
795     }
796 
797     public void setIgnoreMissingDescriptor( final boolean ignoreMissingDescriptor )
798     {
799         this.ignoreMissingDescriptor = ignoreMissingDescriptor;
800     }
801 
802     public MavenSession getMavenSession()
803     {
804         return mavenSession;
805     }
806 
807     public String getArchiverConfig()
808     {
809         return archiverConfig == null ? null : archiverConfig.toString();
810     }
811 
812     public MavenFileFilter getMavenFileFilter()
813     {
814         return mavenFileFilter;
815     }
816 
817     public boolean isUpdateOnly()
818     {
819         return updateOnly;
820     }
821 
822     public boolean isUseJvmChmod()
823     {
824         return useJvmChmod;
825     }
826 
827     public boolean isIgnorePermissions()
828     {
829         return ignorePermissions;
830     }
831 }