1   /**
2    * Distribution License:
3    * JSword is free software; you can redistribute it and/or modify it under
4    * the terms of the GNU Lesser General Public License, version 2.1 as published by
5    * the Free Software Foundation. This program is distributed in the hope
6    * that it will be useful, but WITHOUT ANY WARRANTY; without even the
7    * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
8    * See the GNU Lesser General Public License for more details.
9    *
10   * The License is available on the internet at:
11   *       http://www.gnu.org/copyleft/lgpl.html
12   * or by writing to:
13   *      Free Software Foundation, Inc.
14   *      59 Temple Place - Suite 330
15   *      Boston, MA 02111-1307, USA
16   *
17   * Copyright: 2005
18   *     The copyright to this program is held by it's authors.
19   *
20   * ID: $Id: IOUtil.java 2234 2012-03-07 19:14:34Z mjdenham $
21   */
22  package org.crosswire.common.util;
23  
24  import java.io.File;
25  import java.io.IOException;
26  import java.io.InputStream;
27  import java.io.OutputStream;
28  import java.io.RandomAccessFile;
29  import java.io.Reader;
30  import java.net.MalformedURLException;
31  import java.net.URI;
32  import java.util.Enumeration;
33  import java.util.zip.ZipEntry;
34  import java.util.zip.ZipFile;
35  
36  import org.crosswire.jsword.JSMsg;
37  
38  /**
39   * .
40   * 
41   * @see gnu.lgpl.License for license details.<br>
42   *      The copyright to this program is held by it's authors.
43   * @author Joe Walker [joe at eireneh dot com]
44   */
45  public final class IOUtil {
46      /**
47       * Prevent instantiation
48       */
49      private IOUtil() {
50      }
51  
52      /**
53       * Unpack a zip file to a given directory. Honor the paths as given in the
54       * zip file.
55       * 
56       * @param file
57       *            The zip file to download
58       * @param destdir
59       *            The directory to unpack up
60       * @throws IOException
61       *             If there is an file error
62       */
63      public static void unpackZip(File file, File destdir) throws IOException {
64          // unpack the zip.
65          byte[] dbuf = new byte[4096];
66          ZipFile zf = null;
67          try {
68              zf = new ZipFile(file);
69              Enumeration<? extends ZipEntry> entries = zf.entries();
70              while (entries.hasMoreElements()) {
71                  ZipEntry entry = entries.nextElement();
72                  String entrypath = entry.getName();
73                  File entryFile = new File(destdir, entrypath);
74                  File parentDir = entryFile.getParentFile();
75                  // Is it already a directory ?
76                  if (!parentDir.isDirectory()) {
77                      // Create the directory and make sure it worked.
78                      if (!parentDir.mkdirs()) {
79                          // TRANSLATOR: Error condition: A directory could not be created. {0} is a placeholder for the directory
80                          throw new MalformedURLException(JSMsg.gettext("The URL {0} could not be created as a directory.", parentDir.toString()));
81                      }
82                  }
83                  
84                  // write entryFile from zip to filesystem but avoid writing dir entries out as files
85                  if (!entry.isDirectory()) {
86  
87                      URI child = NetUtil.getURI(entryFile);
88      
89                      OutputStream dataOut = NetUtil.getOutputStream(child);
90                      InputStream dataIn = zf.getInputStream(entry);
91      
92                      while (true) {
93                          int count = dataIn.read(dbuf);
94                          if (count == -1) {
95                              break;
96                          }
97                          dataOut.write(dbuf, 0, count);
98                      }
99      
100                     dataOut.close();
101                 }
102             }
103         } finally {
104             IOUtil.close(zf);
105         }
106     }
107 
108     /**
109      * Close the zip file without complaining
110      * 
111      * @param zip
112      *            The zip file to close
113      */
114     public static void close(ZipFile zip) {
115         if (null != zip) {
116             try {
117                 zip.close();
118             } catch (IOException ex) {
119                 log.error("close", ex);
120             }
121         }
122     }
123 
124     /**
125      * Close the random access file without complaining
126      * 
127      * @param raf
128      *            The random access file to close
129      */
130     public static void close(RandomAccessFile raf) {
131         if (null != raf) {
132             try {
133                 raf.close();
134             } catch (IOException ex) {
135                 log.error("close", ex);
136             }
137         }
138     }
139 
140     /**
141      * Close the stream whatever without complaining
142      * 
143      * @param out
144      *            The stream to close
145      */
146     public static void close(OutputStream out) {
147         if (null != out) {
148             try {
149                 out.close();
150             } catch (IOException ex) {
151                 log.error("close", ex);
152             }
153         }
154     }
155 
156     /**
157      * Close the stream whatever without complaining
158      * 
159      * @param in
160      *            The stream to close
161      */
162     public static void close(InputStream in) {
163         if (null != in) {
164             try {
165                 in.close();
166             } catch (IOException ex) {
167                 log.error("close", ex);
168             }
169         }
170     }
171 
172     /**
173      * Close the stream whatever without complaining
174      * 
175      * @param in
176      *            The stream to close
177      */
178     public static void close(Reader in) {
179         if (null != in) {
180             try {
181                 in.close();
182             } catch (IOException ex) {
183                 log.error("close", ex);
184             }
185         }
186     }
187 
188     /**
189      * The log stream
190      */
191     private static final Logger log = Logger.getLogger(IOUtil.class);
192 }
193