001package org.eclipse.aether.internal.test.util;
002
003/*
004 * Licensed to the Apache Software Foundation (ASF) under one
005 * or more contributor license agreements.  See the NOTICE file
006 * distributed with this work for additional information
007 * regarding copyright ownership.  The ASF licenses this file
008 * to you under the Apache License, Version 2.0 (the
009 * "License"); you may not use this file except in compliance
010 * with the License.  You may obtain a copy of the License at
011 * 
012 *  http://www.apache.org/licenses/LICENSE-2.0
013 * 
014 * Unless required by applicable law or agreed to in writing,
015 * software distributed under the License is distributed on an
016 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017 * KIND, either express or implied.  See the License for the
018 * specific language governing permissions and limitations
019 * under the License.
020 */
021
022import java.io.BufferedOutputStream;
023import java.io.File;
024import java.io.FileInputStream;
025import java.io.FileOutputStream;
026import java.io.IOException;
027import java.io.OutputStream;
028import java.io.RandomAccessFile;
029import java.nio.charset.StandardCharsets;
030import java.util.ArrayList;
031import java.util.Collection;
032import java.util.Properties;
033import java.util.UUID;
034
035/**
036 * Provides utility methods to read and write (temporary) files.
037 */
038public class TestFileUtils
039{
040
041    private static final File TMP = new File( System.getProperty( "java.io.tmpdir" ), "aether-"
042        + UUID.randomUUID().toString().substring( 0, 8 ) );
043
044    static
045    {
046        Runtime.getRuntime().addShutdownHook( new Thread()
047        {
048            @Override
049            public void run()
050            {
051                try
052                {
053                    deleteFile( TMP );
054                }
055                catch ( IOException e )
056                {
057                    e.printStackTrace();
058                }
059            }
060        } );
061    }
062
063    private TestFileUtils()
064    {
065        // hide constructor
066    }
067
068    public static void deleteTempFiles()
069        throws IOException
070    {
071        deleteFile( TMP );
072    }
073
074    public static void deleteFile( File file )
075        throws IOException
076    {
077        if ( file == null )
078        {
079            return;
080        }
081
082        Collection<File> undeletables = new ArrayList<File>();
083
084        delete( file, undeletables );
085
086        if ( !undeletables.isEmpty() )
087        {
088            throw new IOException( "Failed to delete " + undeletables );
089        }
090    }
091
092    private static void delete( File file, Collection<File> undeletables )
093    {
094        String[] children = file.list();
095        if ( children != null )
096        {
097            for ( String child : children )
098            {
099                delete( new File( file, child ), undeletables );
100            }
101        }
102
103        if ( !del( file ) )
104        {
105            undeletables.add( file.getAbsoluteFile() );
106        }
107    }
108
109    private static boolean del( File file )
110    {
111        for ( int i = 0; i < 10; i++ )
112        {
113            if ( file.delete() || !file.exists() )
114            {
115                return true;
116            }
117        }
118        return false;
119    }
120
121    public static boolean mkdirs( File directory )
122    {
123        if ( directory == null )
124        {
125            return false;
126        }
127
128        if ( directory.exists() )
129        {
130            return false;
131        }
132        if ( directory.mkdir() )
133        {
134            return true;
135        }
136
137        File canonDir = null;
138        try
139        {
140            canonDir = directory.getCanonicalFile();
141        }
142        catch ( IOException e )
143        {
144            return false;
145        }
146
147        File parentDir = canonDir.getParentFile();
148        return ( parentDir != null && ( mkdirs( parentDir ) || parentDir.exists() ) && canonDir.mkdir() );
149    }
150
151    public static File createTempFile( String contents )
152        throws IOException
153    {
154        return createTempFile( contents.getBytes( StandardCharsets.UTF_8 ), 1 );
155    }
156
157    public static File createTempFile( byte[] pattern, int repeat )
158        throws IOException
159    {
160        mkdirs( TMP );
161        File tmpFile = File.createTempFile( "tmpfile-", ".data", TMP );
162        writeBytes( tmpFile, pattern, repeat );
163        return tmpFile;
164    }
165
166    public static File createTempDir()
167        throws IOException
168    {
169        return createTempDir( "" );
170    }
171
172    public static File createTempDir( String suffix )
173        throws IOException
174    {
175        mkdirs( TMP );
176        File tmpFile = File.createTempFile( "tmpdir-", suffix, TMP );
177        deleteFile( tmpFile );
178        mkdirs( tmpFile );
179        return tmpFile;
180    }
181
182    public static long copyFile( File source, File target )
183        throws IOException
184    {
185        long total = 0;
186
187        FileInputStream fis = null;
188        OutputStream fos = null;
189        try
190        {
191            fis = new FileInputStream( source );
192
193            mkdirs( target.getParentFile() );
194
195            fos = new BufferedOutputStream( new FileOutputStream( target ) );
196
197            for ( byte[] buffer = new byte[ 1024 * 32 ];; )
198            {
199                int bytes = fis.read( buffer );
200                if ( bytes < 0 )
201                {
202                    break;
203                }
204
205                fos.write( buffer, 0, bytes );
206
207                total += bytes;
208            }
209
210            fos.close();
211            fos = null;
212
213            fis.close();
214            fis = null;
215        }
216        finally
217        {
218            try
219            {
220                if ( fos != null )
221                {
222                    fos.close();
223                }
224            }
225            catch ( final IOException e )
226            {
227                // Suppressed due to an exception already thrown in the try block.
228            }
229            finally
230            {
231                try
232                {
233                    if ( fis != null )
234                    {
235                        fis.close();
236                    }
237                }
238                catch ( final IOException e )
239                {
240                    // Suppressed due to an exception already thrown in the try block.
241                }
242            }
243        }
244
245        return total;
246    }
247
248    public static byte[] readBytes( File file )
249        throws IOException
250    {
251        RandomAccessFile in = null;
252        try
253        {
254            in = new RandomAccessFile( file, "r" );
255            byte[] actual = new byte[ (int) in.length() ];
256            in.readFully( actual );
257            in.close();
258            in = null;
259            return actual;
260        }
261        finally
262        {
263            try
264            {
265                if ( in != null )
266                {
267                    in.close();
268                }
269            }
270            catch ( final IOException e )
271            {
272                // Suppressed due to an exception already thrown in the try block.
273            }
274        }
275    }
276
277    public static void writeBytes( File file, byte[] pattern, int repeat )
278        throws IOException
279    {
280        file.deleteOnExit();
281        file.getParentFile().mkdirs();
282        OutputStream out = null;
283        try
284        {
285            out = new BufferedOutputStream( new FileOutputStream( file ) );
286            for ( int i = 0; i < repeat; i++ )
287            {
288                out.write( pattern );
289            }
290            out.close();
291            out = null;
292        }
293        finally
294        {
295            try
296            {
297                if ( out != null )
298                {
299                    out.close();
300                }
301            }
302            catch ( final IOException e )
303            {
304                // Suppressed due to an exception already thrown in the try block.
305            }
306        }
307    }
308
309    public static String readString( File file )
310        throws IOException
311    {
312        byte[] content = readBytes( file );
313        return new String( content, StandardCharsets.UTF_8 );
314    }
315
316    public static void writeString( File file, String content )
317        throws IOException
318    {
319        writeBytes( file, content.getBytes( StandardCharsets.UTF_8 ), 1 );
320    }
321
322    public static void readProps( File file, Properties props )
323        throws IOException
324    {
325        FileInputStream fis = null;
326        try
327        {
328            fis = new FileInputStream( file );
329            props.load( fis );
330            fis.close();
331            fis = null;
332        }
333        finally
334        {
335            try
336            {
337                if ( fis != null )
338                {
339                    fis.close();
340                }
341            }
342            catch ( final IOException e )
343            {
344                // Suppressed due to an exception already thrown in the try block.
345            }
346        }
347    }
348
349    public static void writeProps( File file, Properties props )
350        throws IOException
351    {
352        file.getParentFile().mkdirs();
353
354        FileOutputStream fos = null;
355        try
356        {
357            fos = new FileOutputStream( file );
358            props.store( fos, "aether-test" );
359            fos.close();
360            fos = null;
361        }
362        finally
363        {
364            try
365            {
366                if ( fos != null )
367                {
368                    fos.close();
369                }
370            }
371            catch ( final IOException e )
372            {
373                // Suppressed due to an exception already thrown in the try block.
374            }
375        }
376    }
377
378}