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