1 /* 2 * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package org.openjdk.jigsaw; 27 28 import java.io.*; 29 import java.util.*; 30 import java.util.jar.*; 31 import java.util.zip.*; 32 33 34 public final class Files { 35 36 private Files() { } 37 38 private static void ensureIsDirectory(File path) 39 throws IOException 40 { 41 if (!path.exists() || !path.isDirectory()) 42 throw new IOException(path + ": Not a directory"); 43 } 44 45 private static void ensureIsFile(File path) 46 throws IOException 47 { 48 if (!path.exists() || !path.isFile()) 49 throw new IOException(path + ": Not a file"); 50 } 51 52 private static String[] list(File dir) 53 throws IOException 54 { 55 ensureIsDirectory(dir); 56 String[] fs = dir.list(); 57 if (fs == null) 58 throw new IOException(dir + ": Cannot list directory contents"); 59 return fs; 60 } 61 62 private static File[] listFiles(File dir) 63 throws IOException 64 { 65 ensureIsDirectory(dir); 66 File[] fs = dir.listFiles(); 67 if (fs == null) 68 throw new IOException(dir + ": Cannot list directory contents"); 69 return fs; 70 } 71 72 public static void delete(File path) 73 throws IOException 74 { 75 if (!path.delete()) 76 throw new IOException(path + ": Cannot delete"); 77 } 78 79 public static void deleteTree(File dst) 80 throws IOException 81 { 82 File[] fs = listFiles(dst); 83 for (int i = 0; i < fs.length; i++) { 84 File f = fs[i]; 85 if (f.isDirectory()) { 86 deleteTree(f); 87 } else { 88 delete(f); 89 } 90 } 91 delete(dst); 92 } 93 94 private static void copy(File src, OutputStream out) 95 throws IOException 96 { 97 ensureIsFile(src); 98 byte[] buf = new byte[8192]; 99 FileInputStream in = new FileInputStream(src); 100 try { 101 try { 102 int n; 103 while ((n = in.read(buf)) > 0) { 104 out.write(buf, 0, n); 105 } 106 } finally { 107 out.close(); 108 } 109 } finally { 110 in.close(); 111 } 112 } 113 114 private static void copy(File src, File dst) 115 throws IOException 116 { 117 if (dst.exists()) 118 ensureIsFile(dst); 119 copy(src, new FileOutputStream(dst)); 120 dst.setLastModified(src.lastModified()); 121 if (src.canExecute()) 122 dst.setExecutable(true, false); 123 } 124 125 public static interface Filter<T> { 126 public boolean accept(T x) throws IOException; 127 } 128 129 // src, dst are directories 130 // src must exist; dst created if it does not yet exist 131 // Copy files from src to dst, modulo filtering 132 // 133 public static void copyTree(File src, File dst, Filter<File> filter) 134 throws IOException 135 { 136 ensureIsDirectory(src); 137 if (dst.exists()) { 138 if (!dst.isDirectory()) 139 delete(dst); 140 } else if (!dst.mkdirs()) 141 throw new IOException(dst + ": Cannot create directory"); 142 String[] sls = list(src); 143 for (int i = 0; i < sls.length; i++) { 144 File sf = new File(src, sls[i]); 145 if (filter != null && !filter.accept(sf)) 146 continue; 147 File df = new File(dst, sls[i]); 148 if (sf.isDirectory()) 149 copyTree(sf, df, filter); 150 else 151 copy(sf, df); 152 } 153 dst.setLastModified(src.lastModified()); 154 } 155 156 public static void copyTree(File src, File dst) 157 throws IOException 158 { 159 copyTree(src, dst, null); 160 } 161 162 private static void storeTree(File src, JarOutputStream dst, boolean deflate, 163 Filter<File> filter, String dstPath) 164 throws IOException 165 { 166 ensureIsDirectory(src); 167 String[] sls = list(src); 168 for (int i = 0; i < sls.length; i++) { 169 File sf = new File(src, sls[i]); 170 if (filter != null && !filter.accept(sf)) 171 continue; 172 String dp = (dstPath == null) ? sls[i] : dstPath + "/" + sls[i]; 173 if (sf.isDirectory()) { 174 storeTree(sf, dst, deflate, filter, dp); 175 } else { 176 copy(sf, newOutputStream(dst, deflate, dp)); 177 } 178 } 179 } 180 181 public static void storeTree(File src, JarOutputStream dst, boolean deflate, 182 Filter<File> filter) 183 throws IOException 184 { 185 storeTree(src, dst, deflate, filter, null); 186 } 187 188 public static void storeTree(File src, JarOutputStream dst, boolean deflate) 189 throws IOException 190 { 191 storeTree(src, dst, deflate, null, null); 192 } 193 194 public static interface Visitor<T> { 195 public void accept(T x) throws IOException; 196 } 197 198 public static void walkTree(File src, Visitor<File> visitor) 199 throws IOException 200 { 201 ensureIsDirectory(src); 202 String[] sls = list(src); 203 for (int i = 0; i < sls.length; i++) { 204 File sf = new File(src, sls[i]); 205 if (sf.isDirectory()) 206 walkTree(sf, visitor); 207 else 208 visitor.accept(sf); 209 } 210 } 211 212 public static byte[] load(InputStream is, int n) 213 throws IOException 214 { 215 DataInputStream in = new DataInputStream(is); 216 byte[] bs = new byte[n]; 217 try { 218 in.readFully(bs); 219 return bs; 220 } finally { 221 in.close(); 222 } 223 } 224 225 public static byte[] load(File src) 226 throws IOException 227 { 228 FileInputStream fis = new FileInputStream(src); 229 return load(fis, (int)src.length()); 230 } 231 232 public static void store(byte[] bs, File dst) 233 throws IOException 234 { 235 OutputStream out = new FileOutputStream(dst); 236 int n = bs.length; 237 try { 238 int i = 0; 239 while (i < n) { 240 int d = Math.min(n - i, 8192); 241 out.write(bs, i, d); 242 i += d; 243 } 244 } finally { 245 out.close(); 246 } 247 } 248 249 public static void mkdirs(File d, String what) 250 throws IOException 251 { 252 if (!d.mkdirs()) 253 throw new IOException(d + ": Cannot create " + what + " directory"); 254 } 255 256 private static class NonClosingInputStream 257 extends FilterInputStream 258 { 259 260 private NonClosingInputStream(InputStream out) { 261 super(out); 262 } 263 264 public void close() { } 265 266 } 267 268 public static InputStream nonClosingStream(InputStream out) { 269 return new NonClosingInputStream(out); 270 } 271 272 private static class JarEntryOutputStream 273 extends FilterOutputStream 274 { 275 276 CRC32 crc; 277 ByteArrayOutputStream baos; 278 CheckedOutputStream cos; 279 JarOutputStream jos; 280 boolean deflate; 281 String path; 282 283 private JarEntryOutputStream(JarOutputStream jos, 284 boolean deflate, 285 CRC32 crc, 286 ByteArrayOutputStream baos, 287 CheckedOutputStream cos, 288 String path) 289 { 290 super(cos); 291 this.jos = jos; 292 this.deflate = deflate; 293 this.crc = crc; 294 this.baos = baos; 295 this.cos = cos; 296 this.path = path; 297 } 298 299 public void close() throws IOException { 300 cos.close(); 301 JarEntry je = new JarEntry(path); 302 if (deflate) { 303 je.setMethod(JarEntry.DEFLATED); 304 } else { 305 je.setMethod(JarEntry.STORED); 306 je.setCrc(crc.getValue()); 307 je.setSize(baos.size()); 308 je.setCompressedSize(baos.size()); 309 } 310 jos.putNextEntry(je); 311 baos.writeTo(jos); 312 jos.closeEntry(); 313 } 314 315 } 316 317 public static JarEntryOutputStream 318 newOutputStream(JarOutputStream jos, boolean deflate, String path) 319 { 320 // Gee, dac, that zip API sure is broken, isn't it? 321 CRC32 crc = new CRC32(); 322 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 323 CheckedOutputStream cos = new CheckedOutputStream(baos, crc); 324 return new JarEntryOutputStream(jos, deflate, crc, baos, cos, path); 325 } 326 327 public static JarEntryOutputStream 328 newOutputStream(JarOutputStream jos, String path) 329 { 330 return newOutputStream(jos, false, path); 331 } 332 }