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 try 049 { 050 deleteFile( TMP ); 051 } 052 catch ( IOException e ) 053 { 054 e.printStackTrace(); 055 } 056 } ) ); 057 } 058 059 private TestFileUtils() 060 { 061 // hide constructor 062 } 063 064 public static void deleteTempFiles() 065 throws IOException 066 { 067 deleteFile( TMP ); 068 } 069 070 public static void deleteFile( File file ) 071 throws IOException 072 { 073 if ( file == null ) 074 { 075 return; 076 } 077 078 Collection<File> undeletables = new ArrayList<>(); 079 080 delete( file, undeletables ); 081 082 if ( !undeletables.isEmpty() ) 083 { 084 throw new IOException( "Failed to delete " + undeletables ); 085 } 086 } 087 088 private static void delete( File file, Collection<File> undeletables ) 089 { 090 String[] children = file.list(); 091 if ( children != null ) 092 { 093 for ( String child : children ) 094 { 095 delete( new File( file, child ), undeletables ); 096 } 097 } 098 099 if ( !del( file ) ) 100 { 101 undeletables.add( file.getAbsoluteFile() ); 102 } 103 } 104 105 private static boolean del( File file ) 106 { 107 for ( int i = 0; i < 10; i++ ) 108 { 109 if ( file.delete() || !file.exists() ) 110 { 111 return true; 112 } 113 } 114 return false; 115 } 116 117 public static boolean mkdirs( File directory ) 118 { 119 if ( directory == null ) 120 { 121 return false; 122 } 123 124 if ( directory.exists() ) 125 { 126 return false; 127 } 128 if ( directory.mkdir() ) 129 { 130 return true; 131 } 132 133 File canonDir = null; 134 try 135 { 136 canonDir = directory.getCanonicalFile(); 137 } 138 catch ( IOException e ) 139 { 140 return false; 141 } 142 143 File parentDir = canonDir.getParentFile(); 144 return ( parentDir != null && ( mkdirs( parentDir ) || parentDir.exists() ) && canonDir.mkdir() ); 145 } 146 147 public static File createTempFile( String contents ) 148 throws IOException 149 { 150 return createTempFile( contents.getBytes( StandardCharsets.UTF_8 ), 1 ); 151 } 152 153 public static File createTempFile( byte[] pattern, int repeat ) 154 throws IOException 155 { 156 mkdirs( TMP ); 157 File tmpFile = File.createTempFile( "tmpfile-", ".data", TMP ); 158 writeBytes( tmpFile, pattern, repeat ); 159 return tmpFile; 160 } 161 162 public static File createTempDir() 163 throws IOException 164 { 165 return createTempDir( "" ); 166 } 167 168 public static File createTempDir( String suffix ) 169 throws IOException 170 { 171 mkdirs( TMP ); 172 File tmpFile = File.createTempFile( "tmpdir-", suffix, TMP ); 173 deleteFile( tmpFile ); 174 mkdirs( tmpFile ); 175 return tmpFile; 176 } 177 178 public static long copyFile( File source, File target ) 179 throws IOException 180 { 181 long total = 0; 182 183 FileInputStream fis = null; 184 OutputStream fos = null; 185 try 186 { 187 fis = new FileInputStream( source ); 188 189 mkdirs( target.getParentFile() ); 190 191 fos = new BufferedOutputStream( new FileOutputStream( target ) ); 192 193 for ( byte[] buffer = new byte[ 1024 * 32 ];; ) 194 { 195 int bytes = fis.read( buffer ); 196 if ( bytes < 0 ) 197 { 198 break; 199 } 200 201 fos.write( buffer, 0, bytes ); 202 203 total += bytes; 204 } 205 206 fos.close(); 207 fos = null; 208 209 fis.close(); 210 fis = null; 211 } 212 finally 213 { 214 try 215 { 216 if ( fos != null ) 217 { 218 fos.close(); 219 } 220 } 221 catch ( final IOException e ) 222 { 223 // Suppressed due to an exception already thrown in the try block. 224 } 225 finally 226 { 227 try 228 { 229 if ( fis != null ) 230 { 231 fis.close(); 232 } 233 } 234 catch ( final IOException e ) 235 { 236 // Suppressed due to an exception already thrown in the try block. 237 } 238 } 239 } 240 241 return total; 242 } 243 244 public static byte[] readBytes( File file ) 245 throws IOException 246 { 247 RandomAccessFile in = null; 248 try 249 { 250 in = new RandomAccessFile( file, "r" ); 251 byte[] actual = new byte[ (int) in.length() ]; 252 in.readFully( actual ); 253 in.close(); 254 in = null; 255 return actual; 256 } 257 finally 258 { 259 try 260 { 261 if ( in != null ) 262 { 263 in.close(); 264 } 265 } 266 catch ( final IOException e ) 267 { 268 // Suppressed due to an exception already thrown in the try block. 269 } 270 } 271 } 272 273 public static void writeBytes( File file, byte[] pattern, int repeat ) 274 throws IOException 275 { 276 file.deleteOnExit(); 277 file.getParentFile().mkdirs(); 278 OutputStream out = null; 279 try 280 { 281 out = new BufferedOutputStream( new FileOutputStream( file ) ); 282 for ( int i = 0; i < repeat; i++ ) 283 { 284 out.write( pattern ); 285 } 286 out.close(); 287 out = null; 288 } 289 finally 290 { 291 try 292 { 293 if ( out != null ) 294 { 295 out.close(); 296 } 297 } 298 catch ( final IOException e ) 299 { 300 // Suppressed due to an exception already thrown in the try block. 301 } 302 } 303 } 304 305 public static String readString( File file ) 306 throws IOException 307 { 308 byte[] content = readBytes( file ); 309 return new String( content, StandardCharsets.UTF_8 ); 310 } 311 312 public static void writeString( File file, String content ) 313 throws IOException 314 { 315 writeBytes( file, content.getBytes( StandardCharsets.UTF_8 ), 1 ); 316 } 317 318 public static void readProps( File file, Properties props ) 319 throws IOException 320 { 321 FileInputStream fis = null; 322 try 323 { 324 fis = new FileInputStream( file ); 325 props.load( fis ); 326 fis.close(); 327 fis = null; 328 } 329 finally 330 { 331 try 332 { 333 if ( fis != null ) 334 { 335 fis.close(); 336 } 337 } 338 catch ( final IOException e ) 339 { 340 // Suppressed due to an exception already thrown in the try block. 341 } 342 } 343 } 344 345 public static void writeProps( File file, Properties props ) 346 throws IOException 347 { 348 file.getParentFile().mkdirs(); 349 350 FileOutputStream fos = null; 351 try 352 { 353 fos = new FileOutputStream( file ); 354 props.store( fos, "aether-test" ); 355 fos.close(); 356 fos = null; 357 } 358 finally 359 { 360 try 361 { 362 if ( fos != null ) 363 { 364 fos.close(); 365 } 366 } 367 catch ( final IOException e ) 368 { 369 // Suppressed due to an exception already thrown in the try block. 370 } 371 } 372 } 373 374}