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