View Javadoc
1   package org.apache.maven.plugins.dependency.utils;
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 java.io.BufferedReader;
23  import java.io.File;
24  import java.io.FileOutputStream;
25  import java.io.IOException;
26  import java.io.OutputStreamWriter;
27  import java.io.StringReader;
28  import java.io.Writer;
29  import java.util.Objects;
30  
31  import org.apache.maven.artifact.Artifact;
32  import org.apache.maven.artifact.ArtifactUtils;
33  import org.apache.maven.plugin.logging.Log;
34  import org.codehaus.plexus.util.StringUtils;
35  
36  /**
37   * Utility class with static helper methods.
38   * 
39   * @author <a href="mailto:brianf@apache.org">Brian Fox</a>
40   */
41  public final class DependencyUtil
42  {
43  
44      /**
45       * Builds the file name. If removeVersion is set, then the file name must be reconstructed from the artifactId,
46       * Classifier (if used) and Type. Otherwise, this method returns the artifact file name.
47       * 
48       * @param artifact File to be formatted.
49       * @param removeVersion Specifies if the version should be removed from the file name.
50       * @return Formatted file name in the format artifactId-[version]-[classifier].[type]
51       * @see #getFormattedFileName(Artifact, boolean, boolean)
52       */
53      public static String getFormattedFileName( Artifact artifact, boolean removeVersion )
54      {
55          return getFormattedFileName( artifact, removeVersion, false );
56      }
57  
58      /**
59       * Builds the file name. If removeVersion is set, then the file name must be reconstructed from the groupId (if
60       * <b>prependGroupId</b> is true) artifactId, Classifier (if used) and Type. Otherwise, this method returns the
61       * artifact file name.
62       * 
63       * @param artifact File to be formatted.
64       * @param removeVersion Specifies if the version should be removed from the file name.
65       * @param prependGroupId Specifies if the groupId should be prepended to the file name.
66       * @return Formatted file name in the format [groupId].artifactId-[version]-[classifier].[type]
67       */
68      public static String getFormattedFileName( Artifact artifact, boolean removeVersion, boolean prependGroupId )
69      {
70          return getFormattedFileName( artifact, removeVersion, prependGroupId, false );
71      }
72  
73      /**
74       * Builds the file name. If removeVersion is set, then the file name must be reconstructed from the groupId (if
75       * <b>prependGroupId</b> is true) artifactId, Classifier (if used), and Type. Otherwise, this method returns the
76       * artifact file name.
77       * 
78       * @param artifact file to be formatted
79       * @param removeVersion Specifies if the version should be removed from the file name
80       * @param prependGroupId Specifies if the groupId should be prepended to the file name
81       * @param useBaseVersion Specifies if the baseVersion of the artifact should be used instead of the version
82       * @return Formatted file name in the format [groupId].artifactId-[version]-[classifier].[type]
83       */
84      public static String getFormattedFileName( Artifact artifact, boolean removeVersion, boolean prependGroupId,
85                                                 boolean useBaseVersion )
86      {
87          return getFormattedFileName( artifact, removeVersion, prependGroupId, useBaseVersion, false );
88      }
89  
90      /**
91       * Builds the file name. If removeVersion is set, then the file name must be reconstructed from the groupId (if
92       * <b>prependGroupId</b> is true) artifactId, Classifier (if used) and Type. Otherwise, this method returns the
93       * artifact file name.
94       * 
95       * @param artifact File to be formatted.
96       * @param removeVersion Specifies if the version should be removed from the file name.
97       * @param prependGroupId Specifies if the groupId should be prepended to the file name.
98       * @param useBaseVersion Specifies if the baseVersion of the artifact should be used instead of the version.
99       * @param removeClassifier Specifies if the classifier of the artifact should be remved from the file name.
100      * @return Formatted file name in the format [groupId].artifactId-[version]-[classifier].[type]
101      */
102     public static String getFormattedFileName( Artifact artifact, boolean removeVersion, boolean prependGroupId,
103                                                boolean useBaseVersion, boolean removeClassifier )
104     {
105         StringBuilder destFileName = new StringBuilder();
106 
107         if ( prependGroupId )
108         {
109             destFileName.append( artifact.getGroupId() ).append( "." );
110         }
111 
112         String versionString;
113         if ( !removeVersion )
114         {
115             if ( useBaseVersion )
116             {
117                 versionString = "-" + ArtifactUtils.toSnapshotVersion( artifact.getVersion() );
118             }
119             else
120             {
121                 versionString = "-" + artifact.getVersion();
122             }
123         }
124         else
125         {
126             versionString = "";
127         }
128 
129         String classifierString = "";
130 
131         if ( !removeClassifier && StringUtils.isNotEmpty( artifact.getClassifier() ) )
132         {
133             classifierString = "-" + artifact.getClassifier();
134         }
135         destFileName.append( artifact.getArtifactId() ).append( versionString );
136         destFileName.append( classifierString ).append( "." );
137         destFileName.append( artifact.getArtifactHandler().getExtension() );
138 
139         return destFileName.toString();
140     }
141 
142     /**
143      * Formats the outputDirectory based on type.
144      * 
145      * @param useSubdirsPerScope if a new sub directory should be used for each scope.
146      * @param useSubdirsPerType if a new sub directory should be used for each type.
147      * @param useSubdirPerArtifact if a new sub directory should be used for each artifact.
148      * @param useRepositoryLayout if dependencies must be moved into a Maven repository layout, if set, other settings
149      *            will be ignored.
150      * @param removeVersion if the version must not be mentioned in the filename
151      * @param outputDirectory base outputDirectory.
152      * @param artifact information about the artifact.
153      * @return a formatted File object to use for output.
154      */
155     public static File getFormattedOutputDirectory( boolean useSubdirsPerScope, boolean useSubdirsPerType,
156                                                     boolean useSubdirPerArtifact, boolean useRepositoryLayout,
157                                                     boolean removeVersion, File outputDirectory, Artifact artifact )
158     {
159         StringBuilder sb = new StringBuilder( 128 );
160         if ( useRepositoryLayout )
161         {
162             // group id
163             sb.append( artifact.getGroupId().replace( '.', File.separatorChar ) ).append( File.separatorChar );
164             // artifact id
165             sb.append( artifact.getArtifactId() ).append( File.separatorChar );
166             // version
167             sb.append( artifact.getBaseVersion() ).append( File.separatorChar );
168         }
169         else
170         {
171             if ( useSubdirsPerScope )
172             {
173                 sb.append( artifact.getScope() ).append( File.separatorChar );
174             }
175             if ( useSubdirsPerType )
176             {
177                 sb.append( artifact.getType() ).append( "s" ).append( File.separatorChar );
178             }
179             if ( useSubdirPerArtifact )
180             {
181                 String artifactString = getDependencyId( artifact, removeVersion );
182                 sb.append( artifactString ).append( File.separatorChar );
183             }
184         }
185         return new File( outputDirectory, sb.toString() );
186     }
187 
188     private static String getDependencyId( Artifact artifact, boolean removeVersion )
189     {
190         StringBuilder sb = new StringBuilder();
191 
192         sb.append( artifact.getArtifactId() );
193 
194         if ( !removeVersion )
195         {
196             sb.append( "-" );
197             sb.append( artifact.getVersion() );
198         }
199 
200         if ( StringUtils.isNotEmpty( artifact.getClassifier() ) )
201         {
202             sb.append( "-" );
203             sb.append( artifact.getClassifier() );
204         }
205 
206         // if the classifier and type are the same (sources), then don't
207         // repeat.
208         // avoids names like foo-sources-sources
209         if ( !Objects.equals( artifact.getClassifier(), artifact.getType() ) )
210         {
211             sb.append( "-" );
212             sb.append( artifact.getType() );
213         }
214 
215         return sb.toString();
216     }
217 
218     /**
219      * Writes the specified string to the specified file.
220      * 
221      * @param string the string to write
222      * @param file the file to write to
223      * @param append append to existing file or not
224      * @param log ignored
225      * @throws IOException if an I/O error occurs
226      * @deprecated specify an encoding instead of a log
227      */
228     @Deprecated
229     public static synchronized void write( String string, File file, boolean append, Log log )
230         throws IOException
231     {
232         write( string, file, append, "UTF-8" );
233     }
234     
235     /**
236      * Writes the specified string to the specified file.
237      * 
238      * @param string the string to write
239      * @param file the file to write to
240      * @param append append to existing file or not
241      * @param encoding character set name
242      * @throws IOException if an I/O error occurs
243      */
244     public static synchronized void write( String string, File file, boolean append, String encoding )
245         throws IOException
246     {
247         file.getParentFile().mkdirs(); 
248 
249         try ( Writer writer = new OutputStreamWriter( new FileOutputStream( file, append ), encoding ) )
250         {
251             writer.write( string );
252         }
253     }
254 
255     /**
256      * Writes the specified string to the log at info level.
257      * 
258      * @param string the string to write
259      * @param log where to log information
260      * @throws IOException if an I/O error occurs
261      */
262     public static synchronized void log( String string, Log log )
263         throws IOException
264     {
265         BufferedReader reader = new BufferedReader( new StringReader( string ) );
266 
267         String line;
268 
269         while ( ( line = reader.readLine() ) != null )
270         {
271             log.info( line );
272         }
273 
274         reader.close();
275     }
276 
277     /**
278      * Mainly used to parse excludes, includes configuration.
279      * 
280      * @param str the string to split
281      * @return the result items
282      */
283     public static String[] tokenizer( String str )
284     {
285         return StringUtils.split( cleanToBeTokenizedString( str ), "," );
286     }
287 
288     /**
289      * Clean up configuration string before it can be tokenized.
290      * 
291      * @param str the string which should be cleaned
292      * @return cleaned up string
293      */
294     public static String cleanToBeTokenizedString( String str )
295     {
296         String ret = "";
297         if ( !StringUtils.isEmpty( str ) )
298         {
299             // remove initial and ending spaces, plus all spaces next to commas
300             ret = str.trim().replaceAll( "[\\s]*,[\\s]*", "," );
301         }
302 
303         return ret;
304     }
305 }