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