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 }
--- EOF ---