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, File dst) 111 throws IOException 112 { 113 if (dst.exists()) 114 ensureIsFile(dst); 115 ensureIsFile(src); 116 try (FileOutputStream fos = new FileOutputStream(dst)) { 117 java.nio.file.Files.copy(src.toPath(), fos); 118 } 119 dst.setLastModified(src.lastModified()); 120 if (src.canExecute()) 121 dst.setExecutable(true, false); 122 } 123 124 public static interface Filter<T> { 125 public boolean accept(T x) throws IOException; 126 } 127 128 // src, dst are directories 129 // src must exist; dst created if it does not yet exist 130 // Copy files from src to dst, modulo filtering 131 // 132 public static void copyTree(File src, File dst, Filter<File> filter) 133 throws IOException 134 { 135 ensureIsDirectory(src); 136 if (dst.exists()) { 137 if (!dst.isDirectory()) 138 delete(dst); 139 } else if (!dst.mkdirs()) 140 throw new IOException(dst + ": Cannot create directory"); 141 String[] sls = list(src); 142 for (int i = 0; i < sls.length; i++) { 143 File sf = new File(src, sls[i]); 144 if (filter != null && !filter.accept(sf)) 145 continue; 146 File df = new File(dst, sls[i]); 147 if (sf.isDirectory()) 148 copyTree(sf, df, filter); 149 else 150 copy(sf, df); 151 } 152 dst.setLastModified(src.lastModified()); 153 } 154 155 public static void copyTree(File src, File dst) 156 throws IOException 157 { 158 copyTree(src, dst, null); 159 } 160 161 private static void storeTree(File src, JarOutputStream dst, boolean deflate, 162 Filter<File> filter, String dstPath) 163 throws IOException 164 { 165 ensureIsDirectory(src); 166 String[] sls = list(src); 167 for (int i = 0; i < sls.length; i++) { 168 File sf = new File(src, sls[i]); 169 if (filter != null && !filter.accept(sf)) 170 continue; 171 String dp = (dstPath == null) ? sls[i] : dstPath + "/" + sls[i]; 172 if (sf.isDirectory()) { 173 storeTree(sf, dst, deflate, filter, dp); 174 } else { 175 try (OutputStream out = newOutputStream(dst, deflate, dp)) { 176 java.nio.file.Files.copy(src.toPath(), out); 177 } 178 } 179 } 180 } 181 182 public static void storeTree(File src, JarOutputStream dst, boolean deflate, 183 Filter<File> filter) 184 throws IOException 185 { 186 storeTree(src, dst, deflate, filter, null); 187 } 188 189 public static void storeTree(File src, JarOutputStream dst, boolean deflate) 190 throws IOException 191 { 192 storeTree(src, dst, deflate, null, null); 193 } 194 195 public static interface Visitor<T> { 196 public void accept(T x) throws IOException; 197 } 198 199 public static void walkTree(File src, Visitor<File> visitor) 200 throws IOException 201 { 202 ensureIsDirectory(src); 203 String[] sls = list(src); 204 for (int i = 0; i < sls.length; i++) { 205 File sf = new File(src, sls[i]); 206 if (sf.isDirectory()) 207 walkTree(sf, visitor); 208 else 209 visitor.accept(sf); 210 } 211 } 212 213 public static byte[] load(InputStream is, int n) 214 throws IOException 215 { 216 DataInputStream in = new DataInputStream(is); 217 byte[] bs = new byte[n]; 218 try { 219 in.readFully(bs); 220 return bs; 221 } finally { 222 in.close(); 223 } 224 } 225 226 public static byte[] load(File src) 227 throws IOException 228 { 229 FileInputStream fis = new FileInputStream(src); 230 return load(fis, (int)src.length()); 231 } 232 233 public static void store(byte[] bs, File dst) 234 throws IOException 235 { 236 OutputStream out = new FileOutputStream(dst); 237 int n = bs.length; 238 try { 239 int i = 0; 240 while (i < n) { 241 int d = Math.min(n - i, 8192); 242 out.write(bs, i, d); 243 i += d; 244 } 245 } finally { 246 out.close(); 247 } 248 } 249 250 public static void mkdirs(File d, String what) 251 throws IOException 252 { 253 if (!d.mkdirs()) 254 throw new IOException(d + ": Cannot create " + what + " directory"); 255 } 256 257 private static class NonClosingInputStream 258 extends FilterInputStream 259 { 260 261 private NonClosingInputStream(InputStream out) { 262 super(out); 263 } 264 265 public void close() { } 266 267 } 268 269 public static InputStream nonClosingStream(InputStream out) { 270 return new NonClosingInputStream(out); 271 } 272 273 private static class JarEntryOutputStream 274 extends FilterOutputStream 275 { 276 277 CRC32 crc; 278 ByteArrayOutputStream baos; 279 CheckedOutputStream cos; 280 JarOutputStream jos; 281 boolean deflate; 282 String path; 283 284 private JarEntryOutputStream(JarOutputStream jos, 285 boolean deflate, 286 CRC32 crc, 287 ByteArrayOutputStream baos, 288 CheckedOutputStream cos, 289 String path) 290 { 291 super(cos); 292 this.jos = jos; 293 this.deflate = deflate; 294 this.crc = crc; 295 this.baos = baos; 296 this.cos = cos; 297 this.path = path; 298 } 299 300 public void close() throws IOException { 301 cos.close(); 302 JarEntry je = new JarEntry(path); 303 if (deflate) { 304 je.setMethod(JarEntry.DEFLATED); 305 } else { 306 je.setMethod(JarEntry.STORED); 307 je.setCrc(crc.getValue()); 308 je.setSize(baos.size()); 309 je.setCompressedSize(baos.size()); 310 } 311 jos.putNextEntry(je); 312 baos.writeTo(jos); 313 jos.closeEntry(); 314 } 315 316 } 317 318 public static JarEntryOutputStream 319 newOutputStream(JarOutputStream jos, boolean deflate, String path) 320 { 321 // Gee, dac, that zip API sure is broken, isn't it? 322 CRC32 crc = new CRC32(); 323 ByteArrayOutputStream baos = new ByteArrayOutputStream(); 324 CheckedOutputStream cos = new CheckedOutputStream(baos, crc); 325 return new JarEntryOutputStream(jos, deflate, crc, baos, cos, path); 326 } 327 328 public static JarEntryOutputStream 329 newOutputStream(JarOutputStream jos, String path) 330 { 331 return newOutputStream(jos, false, path); 332 } 333 } --- EOF ---