View Javadoc
1   package org.apache.maven.plugin.assembly.archive.task;
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.artifact.Artifact;
23  import org.apache.maven.plugin.assembly.AssemblerConfigurationSource;
24  import org.apache.maven.plugin.assembly.archive.ArchiveCreationException;
25  import org.apache.maven.plugin.assembly.format.AssemblyFormattingException;
26  import org.apache.maven.plugin.assembly.utils.AssemblyFormatUtils;
27  import org.apache.maven.plugin.assembly.utils.TypeConversionUtils;
28  import org.apache.maven.project.MavenProject;
29  import org.codehaus.plexus.archiver.Archiver;
30  import org.codehaus.plexus.archiver.ArchiverException;
31  import org.codehaus.plexus.archiver.util.DefaultArchivedFileSet;
32  import org.codehaus.plexus.archiver.util.DefaultFileSet;
33  import org.codehaus.plexus.components.io.functions.InputStreamTransformer;
34  import org.codehaus.plexus.logging.Logger;
35  import org.codehaus.plexus.util.FileUtils;
36  import org.codehaus.plexus.util.StringUtils;
37  
38  import java.io.File;
39  import java.io.IOException;
40  import java.util.List;
41  
42  import static org.apache.maven.plugin.assembly.utils.AssemblyFormatUtils.artifactProjectInterpolator;
43  import static org.apache.maven.plugin.assembly.utils.AssemblyFormatUtils.moduleProjectInterpolator;
44  
45  /**
46   * @version $Id: AddArtifactTask.java 1639422 2014-11-13 18:08:07Z krosenvold $
47   */
48  public class AddArtifactTask
49  {
50  
51      public static final String[] DEFAULT_INCLUDES_ARRAY = { "**/*" };
52  
53      private int directoryMode = -1;
54  
55      private int fileMode = -1;
56  
57      private boolean unpack = false;
58  
59      private List<String> includes;
60  
61      private List<String> excludes;
62  
63      private final Artifact artifact;
64  
65      private MavenProject project;
66  
67      private MavenProject moduleProject;
68  
69      private Artifact moduleArtifact;
70  
71      private String outputDirectory;
72  
73      private String outputFileNameMapping;
74  
75      private final Logger logger;
76  
77      private final InputStreamTransformer transformer;
78  
79      public AddArtifactTask( final Artifact artifact, final Logger logger, InputStreamTransformer transformer )
80      {
81          this.artifact = artifact;
82          this.logger = logger;
83          this.transformer = transformer;
84      }
85  
86      public AddArtifactTask( final Artifact artifact, final Logger logger )
87      {
88          this( artifact, logger, null );
89      }
90  
91      public void execute( final Archiver archiver, final AssemblerConfigurationSource configSource )
92          throws ArchiveCreationException, AssemblyFormattingException
93      {
94          if ( artifactIsArchiverDestination( archiver ) )
95          {
96              artifact.setFile( moveArtifactSomewhereElse( configSource ) );
97          }
98  
99          String destDirectory =
100             AssemblyFormatUtils.getOutputDirectory( outputDirectory, configSource.getFinalName(), configSource,
101                                                     moduleProjectInterpolator( moduleProject ),
102                                                     artifactProjectInterpolator( project ) );
103 
104         boolean fileModeSet = false;
105         boolean dirModeSet = false;
106 
107         final int oldDirMode = archiver.getOverrideDirectoryMode();
108         final int oldFileMode = archiver.getOverrideFileMode();
109 
110         if ( fileMode != -1 )
111         {
112             archiver.setFileMode( fileMode );
113             fileModeSet = true;
114         }
115 
116         if ( directoryMode != -1 )
117         {
118             archiver.setDirectoryMode( directoryMode );
119             dirModeSet = true;
120         }
121         try
122         {
123 
124             if ( unpack )
125             {
126                 unpacked( archiver, destDirectory );
127             }
128             else
129             {
130                 asFile( archiver, configSource, destDirectory );
131             }
132         }
133         finally
134         {
135             if ( dirModeSet )
136             {
137                 archiver.setDirectoryMode( oldDirMode );
138             }
139 
140             if ( fileModeSet )
141             {
142                 archiver.setFileMode( oldFileMode );
143             }
144         }
145 
146     }
147 
148     private void asFile( Archiver archiver, AssemblerConfigurationSource configSource, String destDirectory )
149         throws AssemblyFormattingException, ArchiveCreationException
150     {
151         final String tempMapping =
152             AssemblyFormatUtils.evaluateFileNameMapping( outputFileNameMapping, artifact, configSource.getProject(),
153                                                          moduleArtifact, configSource,
154                                                          moduleProjectInterpolator( moduleProject ),
155                                                          artifactProjectInterpolator( project ) );
156 
157         final String outputLocation = destDirectory + tempMapping;
158 
159         try
160         {
161             final File artifactFile = artifact.getFile();
162 
163             logger.debug(
164                 "Adding artifact: " + artifact.getId() + " with file: " + artifactFile + " to assembly location: "
165                     + outputLocation + "." );
166 
167             if ( fileMode != -1 )
168             {
169                 archiver.addFile( artifactFile, outputLocation, fileMode );
170             }
171             else
172             {
173                 archiver.addFile( artifactFile, outputLocation );
174             }
175         }
176         catch ( final ArchiverException e )
177         {
178             throw new ArchiveCreationException(
179                 "Error adding file '" + artifact.getId() + "' to archive: " + e.getMessage(), e );
180         }
181     }
182 
183     private void unpacked( Archiver archiver, String destDirectory )
184         throws ArchiveCreationException
185     {
186         String outputLocation = destDirectory;
187 
188         if ( ( outputLocation.length() > 0 ) && !outputLocation.endsWith( "/" ) )
189         {
190             outputLocation += "/";
191         }
192 
193         String[] includesArray = TypeConversionUtils.toStringArray( includes );
194         if ( includesArray == null )
195         {
196             includesArray = DEFAULT_INCLUDES_ARRAY;
197         }
198         final String[] excludesArray = TypeConversionUtils.toStringArray( excludes );
199 
200         try
201         {
202 
203             final File artifactFile = artifact.getFile();
204             if ( artifactFile == null )
205             {
206                 logger.warn(
207                     "Skipping artifact: " + artifact.getId() + "; it does not have an associated file or directory." );
208             }
209             else if ( artifactFile.isDirectory() )
210             {
211                 logger.debug( "Adding artifact directory contents for: " + artifact + " to: " + outputLocation );
212 
213                 DefaultFileSet fs = DefaultFileSet.fileSet( artifactFile );
214                 fs.setIncludes( includesArray );
215                 fs.setExcludes( excludesArray );
216                 fs.setPrefix( outputLocation );
217                 fs.setStreamTransformer( transformer );
218                 archiver.addFileSet( fs );
219             }
220             else
221             {
222                 logger.debug( "Unpacking artifact contents for: " + artifact + " to: " + outputLocation );
223                 logger.debug( "includes:\n" + StringUtils.join( includesArray, "\n" ) + "\n" );
224                 logger.debug(
225                     "excludes:\n" + ( excludesArray == null ? "none" : StringUtils.join( excludesArray, "\n" ) )
226                         + "\n" );
227                 DefaultArchivedFileSet afs = DefaultArchivedFileSet.archivedFileSet( artifactFile );
228                 afs.setIncludes( includesArray );
229                 afs.setExcludes( excludesArray );
230                 afs.setPrefix( outputLocation );
231                 afs.setStreamTransformer( transformer );
232                 archiver.addArchivedFileSet( afs );
233             }
234         }
235         catch ( final ArchiverException e )
236         {
237             throw new ArchiveCreationException(
238                 "Error adding file-set for '" + artifact.getId() + "' to archive: " + e.getMessage(), e );
239         }
240     }
241 
242     private File moveArtifactSomewhereElse( AssemblerConfigurationSource configSource )
243         throws ArchiveCreationException
244     {
245         final File tempRoot = configSource.getTemporaryRootDirectory();
246         final File tempArtifactFile = new File( tempRoot, artifact.getFile().getName() );
247 
248         logger.warn( "Artifact: " + artifact.getId()
249                          + " references the same file as the assembly destination file. Moving it to a temporary location for inclusion." );
250         try
251         {
252             FileUtils.copyFile( artifact.getFile(), tempArtifactFile );
253         }
254         catch ( final IOException e )
255         {
256             throw new ArchiveCreationException(
257                 "Error moving artifact file: '" + artifact.getFile() + "' to temporary location: " + tempArtifactFile
258                     + ". Reason: " + e.getMessage(), e );
259         }
260         return tempArtifactFile;
261     }
262 
263     private boolean artifactIsArchiverDestination( Archiver archiver )
264     {
265         return ( ( artifact.getFile() != null ) && ( archiver.getDestFile() != null ) ) && artifact.getFile().equals(
266             archiver.getDestFile() );
267     }
268 
269     public void setDirectoryMode( final int directoryMode )
270     {
271         this.directoryMode = directoryMode;
272     }
273 
274     public void setFileMode( final int fileMode )
275     {
276         this.fileMode = fileMode;
277     }
278 
279     public void setExcludes( final List<String> excludes )
280     {
281         this.excludes = excludes;
282     }
283 
284     public void setIncludes( final List<String> includes )
285     {
286         this.includes = includes;
287     }
288 
289     public void setUnpack( final boolean unpack )
290     {
291         this.unpack = unpack;
292     }
293 
294     public void setProject( final MavenProject project )
295     {
296         this.project = project;
297     }
298 
299     public void setOutputDirectory( final String outputDirectory )
300     {
301         this.outputDirectory = outputDirectory;
302     }
303 
304     public void setFileNameMapping( final String outputFileNameMapping )
305     {
306         this.outputFileNameMapping = outputFileNameMapping;
307     }
308 
309     public void setOutputDirectory( final String outputDirectory, final String defaultOutputDirectory )
310     {
311         setOutputDirectory( outputDirectory == null ? defaultOutputDirectory : outputDirectory );
312     }
313 
314     public void setFileNameMapping( final String outputFileNameMapping, final String defaultOutputFileNameMapping )
315     {
316         setFileNameMapping( outputFileNameMapping == null ? defaultOutputFileNameMapping : outputFileNameMapping );
317     }
318 
319     public void setModuleProject( final MavenProject moduleProject )
320     {
321         this.moduleProject = moduleProject;
322     }
323 
324     public void setModuleArtifact( final Artifact moduleArtifact )
325     {
326         this.moduleArtifact = moduleArtifact;
327     }
328 
329 }