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.jar.*; 30 import java.util.zip.*; 31 32 public final class Files { 33 34 private Files() { } 35 36 // paths are stored with a platform agnostic separator, '/' 37 static String convertSeparator(String path) { 38 return path.replace(File.separatorChar, '/'); 39 } 40 41 static String platformSeparator(String path) { 42 return path.replace('/', File.separatorChar); 43 } 44 45 static void ensureWriteable(File path) throws IOException { 46 if (!path.canWrite()) 47 throw new IOException(path + ": is not writeable."); 48 } 49 50 static String ensureNonAbsolute(String path) throws IOException { 51 if ((new File(path)).isAbsolute()) 52 throw new IOException("Abolute path instead of relative: " + path); 53 return path; 54 } 55 56 static void ensureIsDirectory(File path) throws IOException { 57 if (!path.exists() || !path.isDirectory()) 58 throw new IOException(path + ": Not a directory"); 59 } 60 61 private static void ensureIsFile(File path) 62 throws IOException 63 { 64 if (!path.exists() || !path.isFile()) 65 throw new IOException(path + ": Not a file"); 66 } 67 68 private static String[] list(File dir) 69 throws IOException 70 { 71 ensureIsDirectory(dir); 72 String[] fs = dir.list(); 73 if (fs == null) 74 throw new IOException(dir + ": Cannot list directory contents"); 75 return fs; 76 } 77 78 private static File[] listFiles(File dir) 79 throws IOException 80 { 81 ensureIsDirectory(dir); 82 File[] fs = dir.listFiles(); 83 if (fs == null) 84 throw new IOException(dir + ": Cannot list directory contents"); 85 return fs; 86 } 87 88 public static void delete(File path) 89 throws IOException 90 { 91 if (!path.delete()) 92 throw new IOException(path + ": Cannot delete"); 93 } 94 95 public static void deleteTree(File dst) 96 throws IOException 97 { 98 File[] fs = listFiles(dst); 99 for (int i = 0; i < fs.length; i++) { 100 File f = fs[i]; 101 if (f.isDirectory()) { 102 deleteTree(f); 103 } else { 104 delete(f); 105 } 106 } 107 delete(dst); 108 } 109 110 private static void copy(File src, OutputStream out) 111 throws IOException 112 { 113 ensureIsFile(src); 114 byte[] buf = new byte[8192]; 115 FileInputStream in = new FileInputStream(src); 116 try { 117 try { 118 int n; 119 while ((n = in.read(buf)) > 0) { 120 out.write(buf, 0, n); 121 } 122 } finally { 123 out.close(); 124 } 125 } finally { 126 in.close(); 127 } 128 } 129 130 private static void copy(File src, File dst) 131 throws IOException 132 { 133 if (dst.exists()) 134 ensureIsFile(dst); 135 copy(src, new FileOutputStream(dst)); 136 dst.setLastModified(src.lastModified()); 137 if (src.canExecute()) 138 dst.setExecutable(true, false); 139 } 140 141 public static interface Filter<T> { 142 public boolean accept(T x) throws IOException; 143 } 144 145 // src, dst are directories 146 // src must exist; dst created if it does not yet exist 147 // Copy files from src to dst, modulo filtering 148 // 149 public static void copyTree(File src, File dst, Filter<File> filter) 150 throws IOException 151 { 152 ensureIsDirectory(src); 153 if (dst.exists()) { 154 if (!dst.isDirectory()) 155 delete(dst); 156 } else if (!dst.mkdirs()) 157 throw new IOException(dst + ": Cannot create directory"); 158 String[] sls = list(src); 159 for (int i = 0; i < sls.length; i++) { 160 File sf = new File(src, sls[i]); 161 if (filter != null && !filter.accept(sf)) 162 continue; 163 File df = new File(dst, sls[i]); 164 if (sf.isDirectory()) 165 copyTree(sf, df, filter); 166 else 167 copy(sf, df); 168 } 169 dst.setLastModified(src.lastModified()); 170 } 171 172 public static void copyTree(File src, File dst) 173 throws IOException 174 { 175 copyTree(src, dst, null); 176 } 177 178 private static void storeTree(File src, JarOutputStream dst, boolean deflate, 179 Filter<File> filter, String dstPath) 180 throws IOException 181 { 182 ensureIsDirectory(src); 183 String[] sls = list(src); 184 for (int i = 0; i < sls.length; i++) { 185 File sf = new File(src, sls[i]); 186 if (filter != null && !filter.accept(sf)) 187 continue; 188 String dp = (dstPath == null) ? sls[i] : dstPath + "/" + sls[i]; 189 if (sf.isDirectory()) { 190 storeTree(sf, dst, deflate, filter, dp); 191 } else { 192 copy(sf, newOutputStream(dst, deflate, dp)); 193 } 194 } 195 } 196 197 public static void storeTree(File src, JarOutputStream dst, boolean deflate, 198 Filter<File> filter) 199 throws IOException 200 { 201 storeTree(src, dst, deflate, filter, null); 202 } 203 204 public static void storeTree(File src, JarOutputStream dst, boolean deflate) 205 throws IOException 206 { 207 storeTree(src, dst, deflate, null, null); 208 } 209 210 public static interface Visitor<T> { 211 public void accept(T x) throws IOException; 212 } 213 214 public static void walkTree(File src, Visitor<File> visitor) 215 throws IOException 216 { 217 ensureIsDirectory(src); 218 String[] sls = list(src); 219 for (int i = 0; i < sls.length; i++) { 220 File sf = new File(src, sls[i]); 221 if (sf.isDirectory()) 222 walkTree(sf, visitor); 223 else 224 visitor.accept(sf); 225 } 226 } 227 228 public static byte[] load(InputStream is, int n) 229 throws IOException 230 { 231 DataInputStream in = new DataInputStream(is); 232 byte[] bs = new byte[n]; 233 try { 234 in.readFully(bs); 235 return bs; 236 } finally { 237 in.close(); 238 } 239 } 240 241 public static byte[] load(File src) 242 throws IOException 243 { 244 FileInputStream fis = new FileInputStream(src); 245 return load(fis, (int)src.length()); 246 } 247 248 public static void store(byte[] bs, File dst) 249 throws IOException 250 { 251 OutputStream out = new FileOutputStream(dst); 252 int n = bs.length; 253 try { 254 int i = 0; 255 while (i < n) { 256 int d = Math.min(n - i, 8192); 257 out.write(bs, i, d); 258 i += d; 259 } 260 } finally { 261 out.close(); 262 } 263 } 264 265 public static void mkdirs(File d, String what) 266 throws IOException 267 { 268 if (!d.mkdirs()) 269 throw new IOException(d + ": Cannot create " + what + " directory"); 270 } 271 272 private static class NonClosingInputStream 273 extends FilterInputStream 274 { 275 276 private NonClosingInputStream(InputStream out) { 277 super(out); 278 } 279 280 public void close() { } 281 282 } 283 284 public static InputStream nonClosingStream(InputStream out) { 285 return new NonClosingInputStream(out); 286 } 287 288 private static class JarEntryOutputStream 289 extends FilterOutputStream 290 { 291 292 CRC32 crc; 293 ByteArrayOutputStream baos; 294 CheckedOutputStream cos; 295 JarOutputStream jos; 296 boolean deflate; 297 String path; 298 299 private JarEntryOutputStream(JarOutputStream jos, 300 boolean deflate, 301 CRC32 crc, 302 ByteArrayOutputStream baos, 303 CheckedOutputStream cos, 304 String path) 305 { 306 super(cos); 307 this.jos = jos; 308 this.deflate = deflate; 309 this.crc = crc; 310 this.baos = baos; 311 this.cos = cos; 312 this.path = path; 313 } 314 315 public void close() throws IOException { 316 cos.close(); 317 JarEntry je = new JarEntry(path); 318 if (deflate) { 319 je.setMethod(JarEntry.DEFLATED); 320 } else { 321 je.setMethod(JarEntry.STORED); 322 je.setCrc(crc.getValue()); 323 je.setSize(baos.size()); 324 je.setCompressedSize(baos.size()); 325 } 326 jos.putNextEntry(je); 327 baos.writeTo(jos); 328 jos.closeEntry(); 329 } 330 331 } 332 333 public static JarEntryOutputStream 334 newOutputStream(JarOutputStream jos, boolean deflate, String path) 335 { 336 // Gee, dac, that zip API sure is broken, isn't it? 337 CRC32 crc = new CRC32(); 338 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 339 CheckedOutputStream cos = new CheckedOutputStream(baos, crc); 340 return new JarEntryOutputStream(jos, deflate, crc, baos, cos, path); 341 } 342 343 public static JarEntryOutputStream 344 newOutputStream(JarOutputStream jos, String path) 345 { 346 return newOutputStream(jos, false, path); 347 } 348 } --- EOF ---