View Javadoc
1   package org.apache.maven.plugins.dependency.utils.filters;
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.plugins.dependency.fromConfiguration.ArtifactItem;
24  import org.apache.maven.plugins.dependency.utils.DependencyUtil;
25  import org.apache.maven.shared.artifact.filter.collection.AbstractArtifactsFilter;
26  import org.apache.maven.shared.artifact.filter.collection.ArtifactFilterException;
27  import org.codehaus.plexus.util.StringUtils;
28  
29  import java.io.File;
30  import java.io.IOException;
31  import java.nio.file.Files;
32  import java.util.LinkedHashSet;
33  import java.util.Set;
34  
35  /**
36   * @author <a href="mailto:brianf@apache.org">Brian Fox</a>
37   */
38  public class DestFileFilter
39      extends AbstractArtifactsFilter
40      implements ArtifactItemFilter
41  {
42      private boolean overWriteReleases;
43  
44      private boolean overWriteSnapshots;
45  
46      private boolean overWriteIfNewer;
47  
48      private boolean useSubDirectoryPerArtifact;
49  
50      private boolean useSubDirectoryPerType;
51  
52      private final boolean useSubDirectoryPerScope;
53  
54      private boolean useRepositoryLayout;
55  
56      private boolean removeVersion;
57  
58      private boolean removeType;
59  
60      private boolean removeClassifier;
61  
62      private final boolean prependGroupId;
63  
64      private final boolean useBaseVersion;
65  
66      private File outputFileDirectory;
67  
68      /**
69       * @param outputFileDirectory the output directory.
70       */
71      public DestFileFilter( File outputFileDirectory )
72      {
73          this( false, false, false, false, false, false, false, false, false, false, outputFileDirectory );
74      }
75  
76      /**
77       * @param overWriteReleases true/false.
78       * @param overWriteSnapshots true/false.
79       * @param overWriteIfNewer true/false.
80       * @param useSubDirectoryPerArtifact true/false.
81       * @param useSubDirectoryPerType true/false.
82       * @param useSubDirectoryPerScope true/false.
83       * @param useRepositoryLayout true/false.
84       * @param removeVersion true/false.
85       * @param prependGroupId true/false.
86       * @param useBaseVersion true/false.
87       * @param outputFileDirectory the output directory.
88       */
89      public DestFileFilter( boolean overWriteReleases, boolean overWriteSnapshots, boolean overWriteIfNewer,
90                             boolean useSubDirectoryPerArtifact, boolean useSubDirectoryPerType,
91                             boolean useSubDirectoryPerScope, boolean useRepositoryLayout, boolean removeVersion,
92                             boolean prependGroupId, boolean useBaseVersion, File outputFileDirectory )
93      {
94          this.overWriteReleases = overWriteReleases;
95          this.overWriteSnapshots = overWriteSnapshots;
96          this.overWriteIfNewer = overWriteIfNewer;
97          this.useSubDirectoryPerArtifact = useSubDirectoryPerArtifact;
98          this.useSubDirectoryPerType = useSubDirectoryPerType;
99          this.useSubDirectoryPerScope = useSubDirectoryPerScope;
100         this.useRepositoryLayout = useRepositoryLayout;
101         this.removeVersion = removeVersion;
102         this.prependGroupId = prependGroupId;
103         this.useBaseVersion = useBaseVersion;
104         this.outputFileDirectory = outputFileDirectory;
105     }
106 
107     /*
108      * (non-Javadoc)
109      * @see org.apache.mojo.dependency.utils.filters.ArtifactsFilter#filter(java.util.Set,
110      * org.apache.maven.plugin.logging.Log)
111      */
112     @Override
113     public Set<Artifact> filter( Set<Artifact> artifacts )
114         throws ArtifactFilterException
115     {
116         Set<Artifact> result = new LinkedHashSet<>();
117 
118         for ( Artifact artifact : artifacts )
119         {
120             if ( isArtifactIncluded( new ArtifactItem( artifact ) ) )
121             {
122                 result.add( artifact );
123             }
124         }
125         return result;
126     }
127 
128     /**
129      * @return Returns the overWriteReleases.
130      */
131     public boolean isOverWriteReleases()
132     {
133         return this.overWriteReleases;
134     }
135 
136     /**
137      * @param overWriteReleases The overWriteReleases to set.
138      */
139     public void setOverWriteReleases( boolean overWriteReleases )
140     {
141         this.overWriteReleases = overWriteReleases;
142     }
143 
144     /**
145      * @return Returns the overWriteSnapshots.
146      */
147     public boolean isOverWriteSnapshots()
148     {
149         return this.overWriteSnapshots;
150     }
151 
152     /**
153      * @param overWriteSnapshots The overWriteSnapshots to set.
154      */
155     public void setOverWriteSnapshots( boolean overWriteSnapshots )
156     {
157         this.overWriteSnapshots = overWriteSnapshots;
158     }
159 
160     /**
161      * @return Returns the overWriteIfNewer.
162      */
163     public boolean isOverWriteIfNewer()
164     {
165         return this.overWriteIfNewer;
166     }
167 
168     /**
169      * @param overWriteIfNewer The overWriteIfNewer to set.
170      */
171     public void setOverWriteIfNewer( boolean overWriteIfNewer )
172     {
173         this.overWriteIfNewer = overWriteIfNewer;
174     }
175 
176     /**
177      * @return Returns the outputFileDirectory.
178      */
179     public File getOutputFileDirectory()
180     {
181         return this.outputFileDirectory;
182     }
183 
184     /**
185      * @param outputFileDirectory The outputFileDirectory to set.
186      */
187     public void setOutputFileDirectory( File outputFileDirectory )
188     {
189         this.outputFileDirectory = outputFileDirectory;
190     }
191 
192     /**
193      * @return Returns the removeVersion.
194      */
195     public boolean isRemoveVersion()
196     {
197         return this.removeVersion;
198     }
199 
200     /**
201      * @param removeType The removeType to set.
202      */
203     public void setRemoveType( boolean removeType )
204     {
205         this.removeType = removeType;
206     }
207 
208     /**
209      * @return Returns the removeType.
210      */
211     public boolean isRemoveType()
212     {
213         return this.removeType;
214     }
215 
216     /**
217      * @param removeVersion The removeVersion to set.
218      */
219     public void setRemoveVersion( boolean removeVersion )
220     {
221         this.removeVersion = removeVersion;
222     }
223 
224     /**
225      * @return Returns the removeClassifier.
226      */
227     public boolean isRemoveClassifier()
228     {
229         return this.removeClassifier;
230     }
231 
232     /**
233      * @param removeClassifier The removeClassifier to set.
234      */
235     public void setRemoveClassifier( boolean removeClassifier )
236     {
237         this.removeClassifier = removeClassifier;
238     }
239 
240     /**
241      * @return Returns the useSubDirectoryPerArtifact.
242      */
243     public boolean isUseSubDirectoryPerArtifact()
244     {
245         return this.useSubDirectoryPerArtifact;
246     }
247 
248     /**
249      * @param useSubDirectoryPerArtifact The useSubDirectoryPerArtifact to set.
250      */
251     public void setUseSubDirectoryPerArtifact( boolean useSubDirectoryPerArtifact )
252     {
253         this.useSubDirectoryPerArtifact = useSubDirectoryPerArtifact;
254     }
255 
256     /**
257      * @return Returns the useSubDirectoryPerType.
258      */
259     public boolean isUseSubDirectoryPerType()
260     {
261         return this.useSubDirectoryPerType;
262     }
263 
264     /**
265      * @param useSubDirectoryPerType The useSubDirectoryPerType to set.
266      */
267     public void setUseSubDirectoryPerType( boolean useSubDirectoryPerType )
268     {
269         this.useSubDirectoryPerType = useSubDirectoryPerType;
270     }
271 
272     /**
273      * @return Returns the useRepositoryLayout
274      */
275     public boolean isUseRepositoryLayout()
276     {
277         return useRepositoryLayout;
278     }
279 
280     /**
281      * @param useRepositoryLayout the useRepositoryLayout to set
282      */
283     public void setUseRepositoryLayout( boolean useRepositoryLayout )
284     {
285         this.useRepositoryLayout = useRepositoryLayout;
286     }
287 
288     @Override
289     public boolean isArtifactIncluded( ArtifactItem item ) throws ArtifactFilterException
290     {
291         Artifact artifact = item.getArtifact();
292 
293         boolean overWrite = ( artifact.isSnapshot() && this.overWriteSnapshots )
294             || ( !artifact.isSnapshot() && this.overWriteReleases );
295 
296         File destFolder = item.getOutputDirectory();
297         if ( destFolder == null )
298         {
299             destFolder =
300                 DependencyUtil.getFormattedOutputDirectory( useSubDirectoryPerScope, useSubDirectoryPerType,
301                                                             useSubDirectoryPerArtifact, useRepositoryLayout,
302                                                             removeVersion, removeType, this.outputFileDirectory,
303                                                             artifact );
304         }
305 
306         File destFile;
307         if ( StringUtils.isEmpty( item.getDestFileName() ) )
308         {
309             String formattedFileName = DependencyUtil.getFormattedFileName( artifact, removeVersion, prependGroupId,
310                                                                             useBaseVersion, removeClassifier );
311             destFile = new File( destFolder, formattedFileName );
312         }
313         else
314         {
315             destFile = new File( destFolder, item.getDestFileName() );
316         }
317 
318         return overWrite || !destFile.exists() || ( overWriteIfNewer && getLastModified(
319                 artifact.getFile() ) > getLastModified( destFile ) );
320     }
321 
322     /**
323      * Using simply {@code File.getLastModified} will return sometimes a wrong value see JDK bug for details.
324      *
325      * https://bugs.openjdk.java.net/browse/JDK-8177809
326      *
327      * @param file {@link File}
328      * @return the last modification time in milliseconds.
329      * @throws ArtifactFilterException in case of a IO Exception.
330      */
331     private long getLastModified( File file ) throws ArtifactFilterException
332     {
333         try
334         {
335             return Files.getLastModifiedTime( file.toPath() ).toMillis();
336         }
337         catch ( IOException e )
338         {
339             throw new ArtifactFilterException( "IO Exception", e );
340         }
341     }
342 }