View Javadoc
1   package org.apache.maven.plugin.assembly.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.BufferedWriter;
24  import java.io.File;
25  import java.io.FileInputStream;
26  import java.io.FileOutputStream;
27  import java.io.IOException;
28  import java.io.InputStreamReader;
29  import java.io.OutputStreamWriter;
30  import java.io.RandomAccessFile;
31  import java.nio.channels.FileChannel;
32  
33  import org.apache.maven.plugin.assembly.archive.ArchiveExpansionException;
34  import org.apache.maven.plugin.assembly.format.AssemblyFormattingException;
35  import org.codehaus.plexus.archiver.ArchiverException;
36  import org.codehaus.plexus.archiver.UnArchiver;
37  import org.codehaus.plexus.archiver.manager.ArchiverManager;
38  import org.codehaus.plexus.archiver.manager.NoSuchArchiverException;
39  import org.codehaus.plexus.util.IOUtil;
40  
41  import javax.annotation.Nonnull;
42  import javax.annotation.Nullable;
43  
44  /**
45   * @version $Id: AssemblyFileUtils.java 1517906 2013-08-27 18:25:03Z krosenvold $
46   */
47  public final class AssemblyFileUtils
48  {
49  
50      public static final String LINE_ENDING_KEEP = "keep";
51  
52      public static final String LINE_ENDING_DOS = "dos";
53  
54      public static final String LINE_ENDING_WINDOWS = "windows";
55  
56      public static final String LINE_ENDING_UNIX = "unix";
57  
58      public static final String LINE_ENDING_CRLF = "crlf";
59  
60      public static final String LINE_ENDING_LF = "lf";
61  
62      private AssemblyFileUtils()
63      {
64          // no op
65      }
66  
67      public static String makePathRelativeTo( String path, final File basedir )
68      {
69          if ( basedir == null )
70          {
71              return path;
72          }
73  
74          if ( path == null )
75          {
76              return null;
77          }
78  
79          path = path.trim();
80  
81          String base = basedir.getAbsolutePath();
82          if ( path.startsWith( base ) )
83          {
84              path = path.substring( base.length() );
85              if ( path.length() > 0 )
86              {
87                  if ( path.startsWith( "/" ) || path.startsWith( "\\" ) )
88                  {
89                      path = path.substring( 1 );
90                  }
91              }
92  
93              if ( path.length() == 0 )
94              {
95                  path = ".";
96              }
97          }
98  
99          if ( !new File( path ).isAbsolute() )
100         {
101             path = path.replace( '\\', '/' );
102         }
103 
104         return path;
105     }
106 
107     public static void verifyTempDirectoryAvailability( @Nonnull final File tempDir )
108     {
109         if ( !tempDir.exists() )
110         {
111             //noinspection ResultOfMethodCallIgnored
112             tempDir.mkdirs();
113         }
114     }
115 
116     /**
117      * Unpacks the archive file.
118      *
119      * @param source  File to be unpacked.
120      * @param destDir Location where to put the unpacked files.
121      */
122     public static void unpack( File source, File destDir, ArchiverManager archiverManager )
123         throws ArchiveExpansionException, NoSuchArchiverException
124     {
125         try
126         {
127             UnArchiver unArchiver = archiverManager.getUnArchiver( source );
128 
129             unArchiver.setSourceFile( source );
130 
131             unArchiver.setDestDirectory( destDir );
132 
133             unArchiver.extract();
134         }
135         catch ( ArchiverException e )
136         {
137             throw new ArchiveExpansionException( "Error unpacking file: " + source + "to: " + destDir, e );
138         }
139     }
140 
141     /**
142      * Converts the line endings of a file, writing a new file.
143      * The encoding of reading and writing can be specified.
144      *
145      * @param source      The source file, not null
146      * @param dest        The destination file, not null
147      * @param lineEndings This is the result of the getLineEndingChars(..) method in this utility class; the actual
148      *                    line-ending characters, not null.
149      * @param atEndOfFile The end-of-file line ending,
150      *                    if true then the resulting file will have a new line at the end even if the input didn't have one,
151      *                    if false then the resulting file will have no new line at the end even if the input did have one,
152      *                    null to determine whether to have a new line at the end of the file based on the input file
153      * @param encoding    The encoding to use, null for platform encoding
154      */
155     public static void convertLineEndings( @Nonnull File source, @Nonnull File dest, String lineEndings,
156                                            Boolean atEndOfFile, String encoding )
157         throws IOException
158     {
159         // MASSEMBLY-637, MASSEMBLY-96
160         // find characters at the end of the file
161         // needed to preserve the last line ending
162         // only check for LF (as CRLF also ends in LF)
163         String eofChars = "";
164         if ( atEndOfFile == null )
165         {
166             RandomAccessFile raf = null;
167             try
168             {
169                 if ( source.length() >= 1 )
170                 {
171                     raf = new RandomAccessFile( source, "r" );
172                     raf.seek( source.length() - 1 );
173                     byte last = raf.readByte();
174                     if ( last == '\n' )
175                     {
176                         eofChars = lineEndings;
177                     }
178                 }
179             }
180             finally
181             {
182                 if ( raf != null )
183                 {
184                     try
185                     {
186                         raf.close();
187                     }
188                     catch ( IOException ex )
189                     {
190                         // ignore
191                     }
192                 }
193             }
194         }
195         else if (atEndOfFile == true )
196         {
197             eofChars = lineEndings;
198         }
199 
200         BufferedReader in = null;
201         BufferedWriter out = null;
202         try
203         {
204             if ( encoding == null )
205             {
206                 // platform encoding
207                 in = new BufferedReader( new InputStreamReader( new FileInputStream( source ) ) );
208                 out = new BufferedWriter( new OutputStreamWriter( new FileOutputStream( dest ) ) );
209             }
210             else
211             {
212                 // MASSEMBLY-371
213                 in = new BufferedReader( new InputStreamReader( new FileInputStream( source ), encoding ) );
214                 out = new BufferedWriter( new OutputStreamWriter( new FileOutputStream( dest ), encoding ) );
215             }
216 
217             String line;
218 
219             line = in.readLine();
220             while ( line != null )
221             {
222                 out.write( line );
223                 line = in.readLine();
224                 if ( line != null )
225                 {
226                     out.write( lineEndings );
227                 }
228                 else
229                 {
230                     out.write( eofChars );
231                 }
232             }
233 
234             out.flush();
235         }
236         finally
237         {
238             IOUtil.close( in );
239             IOUtil.close( out );
240         }
241     }
242 
243     @Nullable
244     public static String getLineEndingCharacters( @Nullable String lineEnding )
245         throws AssemblyFormattingException
246     {
247         String value = lineEnding;
248         if ( lineEnding != null )
249         {
250             if ( LINE_ENDING_KEEP.equals( lineEnding ) )
251             {
252                 value = null;
253             }
254             else if ( LINE_ENDING_DOS.equals( lineEnding ) || LINE_ENDING_WINDOWS.equals( lineEnding )
255                 || LINE_ENDING_CRLF.equals( lineEnding ) )
256             {
257                 value = "\r\n";
258             }
259             else if ( LINE_ENDING_UNIX.equals( lineEnding ) || LINE_ENDING_LF.equals( lineEnding ) )
260             {
261                 value = "\n";
262             }
263             else
264             {
265                 throw new AssemblyFormattingException( "Illegal lineEnding specified: '" + lineEnding + "'" );
266             }
267         }
268 
269         return value;
270     }
271 
272     public static void copyFile( File src, File dst )
273         throws IOException
274     {
275         FileChannel c1 = new RandomAccessFile( src, "r" ).getChannel();
276         FileChannel c2 = new RandomAccessFile( dst, "rw" ).getChannel();
277 
278         long tCount = 0, size = c1.size();
279         //noinspection StatementWithEmptyBody
280         while ( ( tCount += c2.transferFrom( c1, 0, size - tCount ) ) < size )
281         {
282         }
283 
284         c1.close();
285         c2.force( true );
286         c2.close();
287     }
288 
289     @Nonnull
290     public static String normalizePath( @Nonnull String path )
291     {
292         return path.replace( '\\', '/' );
293     }
294 
295 }