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