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