View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.transaction.util;
18  
19  import java.io.File;
20  import java.io.FileInputStream;
21  import java.io.FileOutputStream;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.io.OutputStream;
25  
26  /**
27   * Helper methods for file manipulation. 
28   * All methods are <em>thread safe</em>.
29   * 
30   * @version $Id: FileHelper.java 493628 2007-01-07 01:42:48Z joerg $
31   */
32  public final class FileHelper {
33  
34      private static int BUF_SIZE = 50000;
35      private static byte[] BUF = new byte[BUF_SIZE];
36  
37      /**
38       * Deletes a file specified by a path.
39       *  
40       * @param path path of file to be deleted
41       * @return <code>true</code> if file has been deleted, <code>false</code> otherwise
42       */
43      public static boolean deleteFile(String path) {
44          File file = new File(path);
45          return file.delete();
46      }
47  
48      /**
49       * Checks if a file specified by a path exits.
50       *  
51       * @param path path of file to be checked
52       * @return <code>true</code> if file exists, <code>false</code> otherwise
53       */
54      public static boolean fileExists(String path) {
55          File file = new File(path);
56          return file.exists();
57      }
58  
59      /**
60       * Creates a file specified by a path. All necessary directories will be created.
61       * 
62       * @param path path of file to be created
63       * @return <code>true</code> if file has been created, <code>false</code> if the file already exists
64       * @throws  IOException
65       *          If an I/O error occurred
66       */
67      public static boolean createFile(String path) throws IOException {
68          File file = new File(path);
69          if (file.isDirectory()) {
70              return file.mkdirs();
71          } else {
72              File dir = file.getParentFile();
73              // do not check if this worked, as it may also return false, when all neccessary dirs are present
74              dir.mkdirs();
75              return file.createNewFile();
76          }
77      }
78  
79      /**
80       * Removes a file. If the specified file is a directory all contained files will
81       * be removed recursively as well. 
82       * 
83       * @param toRemove file to be removed
84       */
85      public static void removeRec(File toRemove) {
86          if (toRemove.isDirectory()) {
87              File fileList[] = toRemove.listFiles();
88              for (int a = 0; a < fileList.length; a++) {
89                  removeRec(fileList[a]);
90              }
91          }
92          toRemove.delete();
93      }
94  
95      /**
96       * Moves one directory or file to another. Existing files will be replaced.
97       * 
98       * @param source file to move from
99       * @param target file to move to
100      * @throws IOException if an I/O error occurs (may result in partially done work)  
101      */
102     public static void moveRec(File source, File target) throws IOException {
103         byte[] sharedBuffer = new byte[BUF_SIZE];
104         moveRec(source, target, sharedBuffer);
105     }
106 
107     static void moveRec(File source, File target, byte[] sharedBuffer) throws IOException {
108         if (source.isDirectory()) {
109             if (!target.exists()) {
110                 target.mkdirs();
111             }
112             if (target.isDirectory()) {
113 
114                 File[] files = source.listFiles();
115                 for (int i = 0; i < files.length; i++) {
116                     File file = files[i];
117                     File targetFile = new File(target, file.getName());
118                     if (file.isFile()) {
119                         if (targetFile.exists()) {
120                             targetFile.delete();
121                         }
122                         if (!file.renameTo(targetFile)) {
123                             copy(file, targetFile, sharedBuffer);
124                             file.delete();
125                         }
126                     } else {
127                         if (!targetFile.exists()) {
128                             if (!targetFile.mkdirs()) {
129                                 throw new IOException("Could not create target directory: "
130                                         + targetFile);
131                             }
132                         }
133                         moveRec(file, targetFile);
134                     }
135                 }
136                 source.delete();
137             }
138         } else {
139             if (!target.isDirectory()) {
140                 copy(source, target, sharedBuffer);
141                 source.delete();
142             }
143         }
144     }
145 
146     /**
147      * Copies one directory or file to another. Existing files will be replaced.
148      * 
149      * @param source directory or file to copy from
150      * @param target directory or file to copy to
151      * @throws IOException if an I/O error occurs (may result in partially done work)  
152      */
153     public static void copyRec(File source, File target) throws IOException {
154         byte[] sharedBuffer = new byte[BUF_SIZE];
155         copyRec(source, target, sharedBuffer);
156     }
157 
158     static void copyRec(File source, File target, byte[] sharedBuffer) throws IOException {
159         if (source.isDirectory()) {
160             if (!target.exists()) {
161                 target.mkdirs();
162             }
163             if (target.isDirectory()) {
164 
165                 File[] files = source.listFiles();
166                 for (int i = 0; i < files.length; i++) {
167                     File file = files[i];
168                     File targetFile = new File(target, file.getName());
169                     if (file.isFile()) {
170                         if (targetFile.exists()) {
171                             targetFile.delete();
172                         }
173                         copy(file, targetFile, sharedBuffer);
174                     } else {
175                         targetFile.mkdirs();
176                         copyRec(file, targetFile);
177                     }
178                 }
179             }
180         } else {
181             if (!target.isDirectory()) {
182                 if (!target.exists()) {
183                     File dir = target.getParentFile();
184                     if(!dir.exists() && !dir.mkdirs()) {
185                         throw new IOException("Could not create target directory: " + dir);
186                     }
187                     if (!target.createNewFile()) {
188                         throw new IOException("Could not create target file: " + target);
189                     }
190                 }
191                 copy(source, target, sharedBuffer);
192             }
193         }
194     }
195 
196     /**
197      * Copies one file to another using {@link #copy(InputStream, OutputStream)}.
198      * 
199      * @param input
200      *            source file
201      * @param output
202      *            destination file
203      * @return the number of bytes copied
204      * @throws IOException
205      *             if an I/O error occurs (may result in partially done work)
206      * @see #copy(InputStream, OutputStream)
207      */
208     public static long copy(File input, File output) throws IOException {
209         FileInputStream in = null;
210         try {
211             in = new FileInputStream(input);
212             return copy(in, output);
213         } finally {
214             if (in != null) {
215                 try {
216                     in.close();
217                 } catch (IOException e) {
218                 }
219             }
220         }
221     }
222 
223     /**
224      * Copies one file to another using the supplied buffer.
225      * 
226      * @param input source file
227      * @param output destination file
228      * @param copyBuffer buffer used for copying
229      * @return the number of bytes copied
230      * @throws IOException if an I/O error occurs (may result in partially done work)  
231      * @see #copy(InputStream, OutputStream)
232      */
233     public static long copy(File input, File output, byte[] copyBuffer) throws IOException {
234         FileInputStream in = null;
235         FileOutputStream out = null;
236         try {
237             in = new FileInputStream(input);
238             out = new FileOutputStream(output);
239             return copy(in, out, copyBuffer);
240         } finally {
241             if (in != null) {
242                 try {
243                     in.close();
244                 } catch (IOException e) {
245                 }
246             }
247             if (out != null) {
248                 try {
249                     out.close();
250                 } catch (IOException e) {
251                 }
252             }
253         }
254     }
255 
256     /**
257      * Copies an <code>InputStream</code> to a file using {@link #copy(InputStream, OutputStream)}.
258      * 
259      * @param in stream to copy from 
260      * @param outputFile file to copy to
261      * @return the number of bytes copied
262      * @throws IOException if an I/O error occurs (may result in partially done work)  
263      * @see #copy(InputStream, OutputStream)
264      */
265     public static long copy(InputStream in, File outputFile) throws IOException {
266         FileOutputStream out = null;
267         try {
268             out = new FileOutputStream(outputFile);
269             return copy(in, out);
270         } finally {
271             if (out != null) {
272                 try {
273                     out.close();
274                 } catch (IOException e) {
275                 }
276             }
277         }
278     }
279 
280     /**
281      * Copies an <code>InputStream</code> to an <code>OutputStream</code> using a local internal buffer for performance.
282      * Compared to {@link #globalBufferCopy(InputStream, OutputStream)} this method allows for better
283      * concurrency, but each time it is called generates a buffer which will be garbage.
284      * 
285      * @param in stream to copy from 
286      * @param out stream to copy to
287      * @return the number of bytes copied
288      * @throws IOException if an I/O error occurs (may result in partially done work)  
289      * @see #globalBufferCopy(InputStream, OutputStream)
290      */
291     public static long copy(InputStream in, OutputStream out) throws IOException {
292         // we need a buffer of our own, so no one else interferes
293         byte[] buf = new byte[BUF_SIZE];
294         return copy(in, out, buf);
295     }
296 
297     /**
298      * Copies an <code>InputStream</code> to an <code>OutputStream</code> using a global internal buffer for performance.
299      * Compared to {@link #copy(InputStream, OutputStream)} this method generated no garbage,
300      * but decreases concurrency.
301      * 
302      * @param in stream to copy from 
303      * @param out stream to copy to
304      * @return the number of bytes copied
305      * @throws IOException if an I/O error occurs (may result in partially done work)  
306      * @see #copy(InputStream, OutputStream)
307      */
308     public static long globalBufferCopy(InputStream in, OutputStream out) throws IOException {
309         synchronized (BUF) {
310             return copy(in, out, BUF);
311         }
312     }
313 
314     /**
315      * Copies an <code>InputStream</code> to an <code>OutputStream</code> using the specified buffer. 
316      * 
317      * @param in stream to copy from 
318      * @param out stream to copy to
319      * @param copyBuffer buffer used for copying
320      * @return the number of bytes copied
321      * @throws IOException if an I/O error occurs (may result in partially done work)  
322      * @see #globalBufferCopy(InputStream, OutputStream)
323      * @see #copy(InputStream, OutputStream)
324      */
325     public static long copy(InputStream in, OutputStream out, byte[] copyBuffer) throws IOException {
326         long bytesCopied = 0;
327         int read = -1;
328 
329         while ((read = in.read(copyBuffer, 0, copyBuffer.length)) != -1) {
330             out.write(copyBuffer, 0, read);
331             bytesCopied += read;
332         }
333         return bytesCopied;
334     }
335 }