View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.plugins.assembly.mojos;
20  
21  import java.io.File;
22  import java.nio.file.attribute.FileTime;
23  import java.util.Collections;
24  import java.util.List;
25  import java.util.Properties;
26  
27  import org.apache.maven.archiver.MavenArchiveConfiguration;
28  import org.apache.maven.archiver.MavenArchiver;
29  import org.apache.maven.execution.MavenSession;
30  import org.apache.maven.plugin.AbstractMojo;
31  import org.apache.maven.plugin.MojoExecutionException;
32  import org.apache.maven.plugin.MojoFailureException;
33  import org.apache.maven.plugin.logging.Log;
34  import org.apache.maven.plugins.annotations.Component;
35  import org.apache.maven.plugins.annotations.Parameter;
36  import org.apache.maven.plugins.assembly.AssemblerConfigurationSource;
37  import org.apache.maven.plugins.assembly.InvalidAssemblerConfigurationException;
38  import org.apache.maven.plugins.assembly.archive.ArchiveCreationException;
39  import org.apache.maven.plugins.assembly.archive.AssemblyArchiver;
40  import org.apache.maven.plugins.assembly.format.AssemblyFormattingException;
41  import org.apache.maven.plugins.assembly.io.AssemblyReadException;
42  import org.apache.maven.plugins.assembly.io.AssemblyReader;
43  import org.apache.maven.plugins.assembly.model.Assembly;
44  import org.apache.maven.plugins.assembly.utils.AssemblyFormatUtils;
45  import org.apache.maven.plugins.assembly.utils.InterpolationConstants;
46  import org.apache.maven.project.MavenProject;
47  import org.apache.maven.project.MavenProjectHelper;
48  import org.apache.maven.shared.filtering.MavenReaderFilter;
49  import org.codehaus.plexus.configuration.PlexusConfiguration;
50  import org.codehaus.plexus.interpolation.fixed.FixedStringSearchInterpolator;
51  import org.codehaus.plexus.interpolation.fixed.PrefixedPropertiesValueSource;
52  import org.codehaus.plexus.interpolation.fixed.PropertiesBasedValueSource;
53  import org.codehaus.plexus.util.cli.CommandLineUtils;
54  
55  /**
56   * @author <a href="mailto:brett@apache.org">Brett Porter</a>
57   * @author <a href="mailto:vincent.siveton@gmail.com">Vincent Siveton</a>
58   */
59  public abstract class AbstractAssemblyMojo extends AbstractMojo implements AssemblerConfigurationSource {
60  
61      protected FixedStringSearchInterpolator commandLinePropertiesInterpolator;
62  
63      protected FixedStringSearchInterpolator envInterpolator;
64  
65      protected FixedStringSearchInterpolator mainProjectInterpolator;
66  
67      protected FixedStringSearchInterpolator rootInterpolator;
68  
69      /**
70       * Set to false to exclude the assembly id from the assembly final name, and to create the resultant assembly
71       * artifacts without classifier. As such, an assembly artifact having the same format as the packaging of the
72       * current Maven project will replace the file for this main project artifact.
73       */
74      @Parameter(property = "assembly.appendAssemblyId", defaultValue = "true")
75      boolean appendAssemblyId;
76  
77      /**
78       * The character encoding scheme to be applied when filtering resources.
79       */
80      @Parameter(property = "encoding", defaultValue = "${project.build.sourceEncoding}")
81      private String encoding;
82  
83      /**
84       * Expressions preceded with this String won't be interpolated. If you use "\" as the escape string then \${foo}
85       * will be replaced with ${foo}.
86       *
87       * @since 2.4
88       */
89      @Parameter(property = "assembly.escapeString")
90      private String escapeString;
91  
92      /**
93       * Flag allowing one or more executions of the assembly plugin to be configured as skipped for a particular build.
94       * This makes the assembly plugin more controllable from profiles.
95       */
96      @Parameter(property = "assembly.skipAssembly", defaultValue = "false")
97      private boolean skipAssembly;
98  
99      /**
100      * If this flag is set, everything up to the call to Archiver.createArchive() will be executed.
101      */
102     @Parameter(property = "assembly.dryRun", defaultValue = "false")
103     private boolean dryRun;
104 
105     /**
106      * If this flag is set, the ".dir" suffix will be suppressed in the output directory name when using assembly/format
107      * == 'dir' and other formats that begin with 'dir'. <br/>
108      * <b>NOTE:</b> Since 2.2-beta-3, the default-value for this is true, NOT false as it used to be.
109      */
110     @Parameter(defaultValue = "true")
111     private boolean ignoreDirFormatExtensions;
112 
113     /**
114      * Contains the full list of projects in the reactor.
115      */
116     @Parameter(defaultValue = "${reactorProjects}", required = true, readonly = true)
117     private List<MavenProject> reactorProjects;
118 
119     /**
120      * The output directory of the assembled distribution file.
121      */
122     @Parameter(defaultValue = "${project.build.directory}", required = true)
123     private File outputDirectory;
124 
125     /**
126      * The filename of the assembled distribution file.<br/>
127      * <b>NOTE:</b> This parameter has only impact on name in project target directory,
128      * installed/deployed artifacts will follow convention for artifact names.
129      */
130     @Parameter(defaultValue = "${project.build.finalName}", required = true)
131     private String finalName;
132 
133     /**
134      * Directory to unpack JARs into if needed
135      */
136     @Parameter(defaultValue = "${project.build.directory}/assembly/work", required = true)
137     private File workDirectory;
138 
139     /**
140      * Specifies the formats of the assembly. Multiple formats can be supplied and the Assembly Plugin will generate an
141      * archive for each desired formats. When deploying your project, all file formats specified will also be deployed.
142      * A format is specified by supplying one of the following values in a &lt;format&gt; subelement:
143      * <ul>
144      * <li><em>dir</em> - Creates a directory</li>
145      * <li><em>zip</em> - Creates a ZIP file format</li>
146      * <li><em>tar</em> - Creates a TAR format</li>
147      * <li><em>tar.gz</em> or <em>tgz</em> - Creates a gzip'd TAR format</li>
148      * <li><em>tar.bz2</em> or <em>tbz2</em> - Creates a bzip'd TAR format</li>
149      * <li><em>tar.snappy</em> - Creates a snappy'd TAR format</li>
150      * <li><em>tar.xz</em> or <em>txz</em> - Creates a xz'd TAR format</li>
151      * <li><em>tar.zst</em> or <em>tzst</em> - Creates a zst'd TAR format</li>
152      * </ul>
153      */
154     @Parameter
155     private List<String> formats;
156 
157     /**
158      * A list of descriptor files to generate from.
159      */
160     @Parameter
161     private String[] descriptors;
162 
163     /**
164      * A list of references to assembly descriptors available on the plugin's classpath. The default classpath includes
165      * these built-in descriptors: <code>bin</code>, <code>jar-with-dependencies</code>, <code>src</code>, and
166      * <code>project</code>. You can add others by adding dependencies
167      * to the plugin.
168      */
169     @Parameter
170     private String[] descriptorRefs;
171 
172     /**
173      * An inline list of descriptor to generate from.
174      * <p/>
175      * Each element of list must follow <a href="./assembly.html">Assembly Descriptor</a> format.
176      *
177      * @since 3.7.0
178      */
179     @Parameter
180     private List<Assembly> inlineDescriptors;
181 
182     /**
183      * Directory to scan for descriptor files in. <b>NOTE:</b> This may not work correctly with assembly components.
184      */
185     @Parameter
186     private File descriptorSourceDirectory;
187 
188     /**
189      * This is the base directory from which archive files are created. This base directory pre-pended to any
190      * <code>&lt;directory&gt;</code> specifications in the assembly descriptor. This is an optional parameter.
191      */
192     @Parameter
193     private File archiveBaseDirectory;
194 
195     /**
196      * Sets the TarArchiver behavior on file paths with more than 100 characters length. Valid values are: "warn"
197      * (default), "fail", "truncate", "gnu", "posix", "posix_warn" or "omit".
198      */
199     @Parameter(property = "assembly.tarLongFileMode", defaultValue = "warn")
200     private String tarLongFileMode;
201 
202     /**
203      * Base directory of the project.
204      */
205     @Parameter(defaultValue = "${project.basedir}", required = true, readonly = true)
206     private File basedir;
207 
208     /**
209      * Maven ProjectHelper.
210      */
211     @Component
212     private MavenProjectHelper projectHelper;
213 
214     /**
215      * Maven shared filtering utility.
216      */
217     @Component
218     private MavenReaderFilter mavenReaderFilter;
219 
220     /**
221      * The Maven Session Object
222      */
223     @Parameter(defaultValue = "${session}", readonly = true, required = true)
224     private MavenSession mavenSession;
225 
226     /**
227      * Temporary directory that contain the files to be assembled.
228      */
229     @Parameter(defaultValue = "${project.build.directory}/archive-tmp", required = true, readonly = true)
230     private File tempRoot;
231 
232     /**
233      * Directory for site generated.
234      */
235     @Parameter(defaultValue = "${project.reporting.outputDirectory}", readonly = true)
236     private File siteDirectory;
237 
238     /**
239      * Set to true in order to not fail when a descriptor is missing.
240      */
241     @Parameter(property = "assembly.ignoreMissingDescriptor", defaultValue = "false")
242     private boolean ignoreMissingDescriptor;
243 
244     /**
245      * This is a set of instructions to the archive builder, especially for building .jar files. It enables you to
246      * specify a Manifest file for the jar, in addition to other options. See
247      * <a href="http://maven.apache.org/shared/maven-archiver/index.html">Maven Archiver Reference</a>.
248      */
249     @Parameter
250     private MavenArchiveConfiguration archive;
251 
252     /**
253      * The list of extra filter properties files to be used along with System properties, project properties, and filter
254      * properties files specified in the POM build/filters section, which should be used for the filtering during the
255      * current mojo execution. <br/> Normally, these will be configured from a plugin's execution section, to provide a
256      * different set of filters for a particular execution.
257      */
258     @Parameter
259     private List<String> filters;
260 
261     /**
262      * A set of additional properties to use for filtering
263      *
264      * @since 3.3.0
265      */
266     @Parameter
267     private Properties additionalProperties;
268 
269     /**
270      * If True (default) then the ${project.build.filters} are also used in addition to any further filters defined for
271      * the Assembly.
272      *
273      * @since 2.4.2
274      */
275     @Parameter(property = "assembly.includeProjectBuildFilters", defaultValue = "true")
276     private boolean includeProjectBuildFilters;
277 
278     /**
279      * Controls whether the assembly plugin tries to attach the resulting assembly to the project.
280      *
281      * @since 2.2-beta-1
282      */
283     @Parameter(property = "assembly.attach", defaultValue = "true")
284     private boolean attach;
285 
286     /**
287      * Indicates if zip archives (jar,zip etc) being added to the assembly should be compressed again. Compressing again
288      * can result in smaller archive size, but gives noticeably longer execution time.
289      *
290      * @since 2.4
291      */
292     @Parameter(defaultValue = "true")
293     private boolean recompressZippedFiles;
294 
295     /**
296      * sets the merge manifest mode in the JarArchiver
297      *
298      * @since 3
299      */
300     @Parameter
301     private String mergeManifestMode;
302 
303     /**
304      *
305      */
306     @Component
307     private AssemblyArchiver assemblyArchiver;
308 
309     /**
310      *
311      */
312     @Component
313     private AssemblyReader assemblyReader;
314 
315     /**
316      * Allows additional configuration options that are specific to a particular type of archive format. This is
317      * intended to capture an XML configuration that will be used to reflectively setup the options on the archiver
318      * instance. <br/> To see the possible options for archiver configuration visit the
319      * <a href="https://codehaus-plexus.github.io/plexus-archiver/apidocs/org/codehaus/plexus/archiver/Archiver.html">
320      * Plexus Archiver Documentation</a> <br/> For instance, to direct an assembly with the "ear" format to use a
321      * particular deployment descriptor, you should specify the following for the archiverConfig value in your plugin
322      * configuration: <br/>
323      * <p/>
324      * <p/>
325      * <pre>
326      * &lt;appxml&gt;${project.basedir}/somepath/app.xml&lt;/appxml&gt;
327      * </pre>
328      * <p/>
329      *
330      * @since 2.2-beta-3
331      */
332     @Parameter
333     private PlexusConfiguration archiverConfig;
334 
335     /**
336      * This will cause the assembly to run only at the top of a given module tree. That is, run in the project contained
337      * in the same folder where the mvn execution was launched.
338      *
339      * @since 2.2-beta-4
340      */
341     @Parameter(property = "assembly.runOnlyAtExecutionRoot", defaultValue = "false")
342     private boolean runOnlyAtExecutionRoot;
343 
344     /**
345      * This will cause the assembly to only update an existing archive, if it exists.
346      * <p>
347      * <strong>Note:</strong> The property that can be used on the command line was misspelled as "assembly.updatOnly"
348      * in versions prior to version 2.4.
349      * </p>
350      *
351      * @since 2.2
352      */
353     @Parameter(property = "assembly.updateOnly", defaultValue = "false")
354     private boolean updateOnly;
355 
356     /**
357      * <p>
358      * Set to <code>true</code> in order to avoid all chmod calls.
359      * </p>
360      * <p/>
361      * <p>
362      * <b>NOTE:</b> This will cause the assembly plugin to <b>DISREGARD</b> all fileMode/directoryMode settings in the
363      * assembly descriptor, and all file permissions in unpacked dependencies!
364      * </p>
365      *
366      * @since 2.2
367      */
368     @Parameter(property = "assembly.ignorePermissions", defaultValue = "false")
369     private boolean ignorePermissions;
370 
371     /**
372      * <p>
373      * Set of delimiters for expressions to filter within the resources. These delimiters are specified in the form
374      * 'beginToken*endToken'. If no '*' is given, the delimiter is assumed to be the same for start and end.
375      * </p>
376      * <p>
377      * So, the default filtering delimiters might be specified as:
378      * </p>
379      * <p/>
380      * <pre>
381      * &lt;delimiters&gt;
382      *   &lt;delimiter&gt;${*}&lt;/delimiter&gt;
383      *   &lt;delimiter&gt;@&lt;/delimiter&gt;
384      * &lt;/delimiters&gt;
385      * </pre>
386      * <p>
387      * Since the '@' delimiter is the same on both ends, we don't need to specify '@*@' (though we can).
388      * </p>
389      *
390      * @since 2.4
391      */
392     @Parameter
393     private List<String> delimiters;
394 
395     /**
396      * Timestamp for reproducible output archive entries, either formatted as ISO 8601
397      * <code>yyyy-MM-dd'T'HH:mm:ssXXX</code> or as an int representing seconds since the epoch (like
398      * <a href="https://reproducible-builds.org/docs/source-date-epoch/">SOURCE_DATE_EPOCH</a>).
399      *
400      * @since 3.2.0
401      */
402     @Parameter(defaultValue = "${project.build.outputTimestamp}")
403     private String outputTimestamp;
404 
405     /**
406      * Override of user ID in archive type which can store it.
407      */
408     @Parameter
409     private Integer overrideUid;
410 
411     /**
412      * Override of user name in archive type which can store it.
413      */
414     @Parameter
415     private String overrideUserName;
416 
417     /**
418      * Override of group ID in archive type which can store it.
419      */
420     @Parameter
421     private Integer overrideGid;
422 
423     /**
424      * Override of group name in archive type which can store it.
425      */
426     @Parameter
427     private String overrideGroupName;
428 
429     public static FixedStringSearchInterpolator mainProjectInterpolator(MavenProject mainProject) {
430         if (mainProject != null) {
431             // 5
432             return FixedStringSearchInterpolator.create(
433                     new org.codehaus.plexus.interpolation.fixed.PrefixedObjectValueSource(
434                             InterpolationConstants.PROJECT_PREFIXES, mainProject, true),
435 
436                     // 6
437                     new org.codehaus.plexus.interpolation.fixed.PrefixedPropertiesValueSource(
438                             InterpolationConstants.PROJECT_PROPERTIES_PREFIXES, mainProject.getProperties(), true));
439         } else {
440             return FixedStringSearchInterpolator.empty();
441         }
442     }
443 
444     /**
445      * Create the binary distribution.
446      */
447     @Override
448     public void execute() throws MojoExecutionException, MojoFailureException {
449 
450         if (skipAssembly) {
451             getLog().info("Assemblies have been skipped per configuration of the skipAssembly parameter.");
452             return;
453         }
454 
455         // run only at the execution root.
456         if (runOnlyAtExecutionRoot && !isThisTheExecutionRoot()) {
457             getLog().info("Skipping the assembly in this project because it's not the Execution Root");
458             return;
459         }
460 
461         List<Assembly> assemblies;
462         try {
463             assemblies = assemblyReader.readAssemblies(this);
464         } catch (final AssemblyReadException e) {
465             throw new MojoExecutionException("Error reading assemblies: " + e.getMessage(), e);
466         } catch (final InvalidAssemblerConfigurationException e) {
467             throw new MojoFailureException(
468                     assemblyReader, e.getMessage(), "Mojo configuration is invalid: " + e.getMessage());
469         }
470 
471         // TODO: include dependencies marked for distribution under certain formats
472         // TODO: how, might we plug this into an installer, such as NSIS?
473 
474         FileTime outputDate = MavenArchiver.parseBuildOutputTimestamp(outputTimestamp)
475                 .map(FileTime::from)
476                 .orElse(null);
477 
478         boolean warnedAboutMainProjectArtifact = false;
479         for (final Assembly assembly : assemblies) {
480             try {
481                 final String fullName = AssemblyFormatUtils.getDistributionName(assembly, this);
482 
483                 List<String> effectiveFormats = formats;
484                 if (effectiveFormats == null || effectiveFormats.isEmpty()) {
485                     effectiveFormats = assembly.getFormats();
486                 }
487                 if (effectiveFormats == null || effectiveFormats.isEmpty()) {
488                     throw new MojoFailureException(
489                             "No formats specified in the execution parameters or the assembly descriptor.");
490                 }
491 
492                 for (final String format : effectiveFormats) {
493                     final File destFile = assemblyArchiver.createArchive(assembly, fullName, format, this, outputDate);
494 
495                     final MavenProject project = getProject();
496                     final String type = project.getArtifact().getType();
497 
498                     if (attach && destFile.isFile()) {
499                         if (isAssemblyIdAppended()) {
500                             projectHelper.attachArtifact(project, format, assembly.getId(), destFile);
501                         } else if (!"pom".equals(type) && format.equals(type)) {
502                             if (!warnedAboutMainProjectArtifact) {
503                                 final StringBuilder message = new StringBuilder();
504 
505                                 message.append("Configuration option 'appendAssemblyId' is set to false.");
506                                 message.append("\nInstead of attaching the assembly file: ")
507                                         .append(destFile);
508                                 message.append(", it will become the file for main project artifact.");
509                                 message.append("\nNOTE: If multiple descriptors or descriptor-formats are provided "
510                                         + "for this project, the value of this file will be "
511                                         + "non-deterministic!");
512 
513                                 getLog().warn(message);
514                                 warnedAboutMainProjectArtifact = true;
515                             }
516 
517                             final File existingFile = project.getArtifact().getFile();
518                             if ((existingFile != null) && existingFile.exists()) {
519                                 getLog().warn("Replacing pre-existing project main-artifact file: " + existingFile
520                                         + "\nwith assembly file: " + destFile);
521                             }
522 
523                             project.getArtifact().setFile(destFile);
524                         } else {
525                             projectHelper.attachArtifact(project, format, null, destFile);
526                         }
527                     } else if (attach) {
528                         getLog().warn("Assembly file: " + destFile + " is not a regular file (it may be a directory). "
529                                 + "It cannot be attached to the project build for installation or "
530                                 + "deployment.");
531                     }
532                 }
533             } catch (final ArchiveCreationException | AssemblyFormattingException e) {
534                 throw new MojoExecutionException("Failed to create assembly: " + e.getMessage(), e);
535             } catch (final InvalidAssemblerConfigurationException e) {
536                 throw new MojoFailureException(
537                         assembly,
538                         "Assembly is incorrectly configured: " + assembly.getId(),
539                         "Assembly: " + assembly.getId() + " is not configured correctly: " + e.getMessage());
540             }
541         }
542     }
543 
544     private FixedStringSearchInterpolator createRepositoryInterpolator() {
545         final Properties settingsProperties = new Properties();
546         final MavenSession session = getMavenSession();
547         final File basedir = session.getRepositorySession()
548                 .getLocalRepositoryManager()
549                 .getRepository()
550                 .getBasedir();
551 
552         settingsProperties.setProperty("localRepository", basedir.toString());
553         settingsProperties.setProperty("settings.localRepository", basedir.toString());
554 
555         return FixedStringSearchInterpolator.create(new PropertiesBasedValueSource(settingsProperties));
556     }
557 
558     private FixedStringSearchInterpolator createCommandLinePropertiesInterpolator() {
559         Properties commandLineProperties = System.getProperties();
560         final MavenSession session = getMavenSession();
561 
562         if (session != null) {
563             commandLineProperties = new Properties();
564             commandLineProperties.putAll(session.getSystemProperties());
565             commandLineProperties.putAll(session.getUserProperties());
566         }
567 
568         PropertiesBasedValueSource cliProps = new PropertiesBasedValueSource(commandLineProperties);
569         return FixedStringSearchInterpolator.create(cliProps);
570     }
571 
572     private FixedStringSearchInterpolator createEnvInterpolator() {
573         PrefixedPropertiesValueSource envProps = new PrefixedPropertiesValueSource(
574                 Collections.singletonList("env."), CommandLineUtils.getSystemEnvVars(false), true);
575         return FixedStringSearchInterpolator.create(envProps);
576     }
577 
578     /**
579      * Returns true if the current project is located at the Execution Root Directory (where mvn was launched)
580      *
581      * @return if this is the execution root
582      */
583     boolean isThisTheExecutionRoot() {
584         final Log log = getLog();
585         log.debug("Root Folder:" + mavenSession.getExecutionRootDirectory());
586         log.debug("Current Folder:" + basedir);
587         final boolean result = mavenSession.getExecutionRootDirectory().equalsIgnoreCase(basedir.toString());
588         if (result) {
589             log.debug("This is the execution root.");
590         } else {
591             log.debug("This is NOT the execution root.");
592         }
593 
594         return result;
595     }
596 
597     @Override
598     public File getBasedir() {
599         return basedir;
600     }
601 
602     public void setBasedir(final File basedir) {
603         this.basedir = basedir;
604     }
605 
606     @Override
607     public String[] getDescriptorReferences() {
608         return descriptorRefs;
609     }
610 
611     public List<Assembly> getInlineDescriptors() {
612         return inlineDescriptors;
613     }
614 
615     @Override
616     public File getDescriptorSourceDirectory() {
617         return descriptorSourceDirectory;
618     }
619 
620     @Override
621     public String[] getDescriptors() {
622         return descriptors;
623     }
624 
625     public void setDescriptors(final String[] descriptors) {
626         this.descriptors = descriptors;
627     }
628 
629     @Override
630     public File getSiteDirectory() {
631         return siteDirectory;
632     }
633 
634     public void setSiteDirectory(final File siteDirectory) {
635         this.siteDirectory = siteDirectory;
636     }
637 
638     @Override
639     public String getFinalName() {
640         return finalName;
641     }
642 
643     public void setFinalName(final String finalName) {
644         this.finalName = finalName;
645     }
646 
647     @Override
648     public boolean isAssemblyIdAppended() {
649         return appendAssemblyId;
650     }
651 
652     @Override
653     public String getTarLongFileMode() {
654         return tarLongFileMode;
655     }
656 
657     public void setTarLongFileMode(final String tarLongFileMode) {
658         this.tarLongFileMode = tarLongFileMode;
659     }
660 
661     @Override
662     public File getOutputDirectory() {
663         return outputDirectory;
664     }
665 
666     public void setOutputDirectory(final File outputDirectory) {
667         this.outputDirectory = outputDirectory;
668     }
669 
670     @Override
671     public MavenArchiveConfiguration getJarArchiveConfiguration() {
672         return archive;
673     }
674 
675     @Override
676     public File getWorkingDirectory() {
677         return workDirectory;
678     }
679 
680     @Override
681     public File getTemporaryRootDirectory() {
682         return tempRoot;
683     }
684 
685     @Override
686     public File getArchiveBaseDirectory() {
687         return archiveBaseDirectory;
688     }
689 
690     @Override
691     public List<String> getFilters() {
692         if (filters == null) {
693             filters = getProject().getBuild().getFilters();
694             if (filters == null) {
695                 filters = Collections.emptyList();
696             }
697         }
698         return filters;
699     }
700 
701     public void setFilters(final List<String> filters) {
702         this.filters = filters;
703     }
704 
705     public Properties getAdditionalProperties() {
706         return additionalProperties;
707     }
708 
709     @Override
710     public boolean isIncludeProjectBuildFilters() {
711         return includeProjectBuildFilters;
712     }
713 
714     @Override
715     public List<MavenProject> getReactorProjects() {
716         return reactorProjects;
717     }
718 
719     public void setReactorProjects(final List<MavenProject> reactorProjects) {
720         this.reactorProjects = reactorProjects;
721     }
722 
723     public void setAppendAssemblyId(final boolean appendAssemblyId) {
724         this.appendAssemblyId = appendAssemblyId;
725     }
726 
727     public void setArchive(final MavenArchiveConfiguration archive) {
728         this.archive = archive;
729     }
730 
731     public void setDescriptorRefs(final String[] descriptorRefs) {
732         this.descriptorRefs = descriptorRefs;
733     }
734 
735     public void setTempRoot(final File tempRoot) {
736         this.tempRoot = tempRoot;
737     }
738 
739     public void setWorkDirectory(final File workDirectory) {
740         this.workDirectory = workDirectory;
741     }
742 
743     @Override
744     public boolean isDryRun() {
745         return dryRun;
746     }
747 
748     @Override
749     public boolean isIgnoreDirFormatExtensions() {
750         return ignoreDirFormatExtensions;
751     }
752 
753     @Override
754     public boolean isIgnoreMissingDescriptor() {
755         return ignoreMissingDescriptor;
756     }
757 
758     @Override
759     public MavenSession getMavenSession() {
760         return mavenSession;
761     }
762 
763     @Override
764     public String getArchiverConfig() {
765         return archiverConfig == null ? null : archiverConfig.toString();
766     }
767 
768     @Override
769     public MavenReaderFilter getMavenReaderFilter() {
770         return mavenReaderFilter;
771     }
772 
773     @Override
774     public boolean isUpdateOnly() {
775         return updateOnly;
776     }
777 
778     @Override
779     public boolean isIgnorePermissions() {
780         return ignorePermissions;
781     }
782 
783     @Override
784     public String getEncoding() {
785         return encoding;
786     }
787 
788     @Override
789     public boolean isRecompressZippedFiles() {
790         return recompressZippedFiles;
791     }
792 
793     @Override
794     public String getMergeManifestMode() {
795         return mergeManifestMode;
796     }
797 
798     @Override
799     public String getEscapeString() {
800         return escapeString;
801     }
802 
803     @Override
804     public List<String> getDelimiters() {
805         return delimiters;
806     }
807 
808     public void setDelimiters(List<String> delimiters) {
809         this.delimiters = delimiters;
810     }
811 
812     @Override
813     public synchronized FixedStringSearchInterpolator getCommandLinePropsInterpolator() {
814         if (commandLinePropertiesInterpolator == null) {
815             this.commandLinePropertiesInterpolator = createCommandLinePropertiesInterpolator();
816         }
817         return commandLinePropertiesInterpolator;
818     }
819 
820     @Override
821     public synchronized FixedStringSearchInterpolator getEnvInterpolator() {
822         if (envInterpolator == null) {
823             this.envInterpolator = createEnvInterpolator();
824         }
825         return envInterpolator;
826     }
827 
828     @Override
829     public synchronized FixedStringSearchInterpolator getRepositoryInterpolator() {
830         if (rootInterpolator == null) {
831             this.rootInterpolator = createRepositoryInterpolator();
832         }
833         return rootInterpolator;
834     }
835 
836     @Override
837     public synchronized FixedStringSearchInterpolator getMainProjectInterpolator() {
838         if (mainProjectInterpolator == null) {
839             this.mainProjectInterpolator = mainProjectInterpolator(getProject());
840         }
841         return mainProjectInterpolator;
842     }
843 
844     @Override
845     public Integer getOverrideUid() {
846         return this.overrideUid;
847     }
848 
849     @Override
850     public String getOverrideUserName() {
851         return this.overrideUserName;
852     }
853 
854     @Override
855     public Integer getOverrideGid() {
856         return this.overrideGid;
857     }
858 
859     @Override
860     public String getOverrideGroupName() {
861         return this.overrideGroupName;
862     }
863 }