001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.commons.transaction.util;
018:
019: import java.io.File;
020: import java.io.FileInputStream;
021: import java.io.FileOutputStream;
022: import java.io.IOException;
023: import java.io.InputStream;
024: import java.io.OutputStream;
025:
026: /**
027: * Helper methods for file manipulation.
028: * All methods are <em>thread safe</em>.
029: *
030: * @version $Id: FileHelper.java 493628 2007-01-07 01:42:48Z joerg $
031: */
032: public final class FileHelper {
033:
034: private static int BUF_SIZE = 50000;
035: private static byte[] BUF = new byte[BUF_SIZE];
036:
037: /**
038: * Deletes a file specified by a path.
039: *
040: * @param path path of file to be deleted
041: * @return <code>true</code> if file has been deleted, <code>false</code> otherwise
042: */
043: public static boolean deleteFile(String path) {
044: File file = new File(path);
045: return file.delete();
046: }
047:
048: /**
049: * Checks if a file specified by a path exits.
050: *
051: * @param path path of file to be checked
052: * @return <code>true</code> if file exists, <code>false</code> otherwise
053: */
054: public static boolean fileExists(String path) {
055: File file = new File(path);
056: return file.exists();
057: }
058:
059: /**
060: * Creates a file specified by a path. All necessary directories will be created.
061: *
062: * @param path path of file to be created
063: * @return <code>true</code> if file has been created, <code>false</code> if the file already exists
064: * @throws IOException
065: * If an I/O error occurred
066: */
067: public static boolean createFile(String path) throws IOException {
068: File file = new File(path);
069: if (file.isDirectory()) {
070: return file.mkdirs();
071: } else {
072: File dir = file.getParentFile();
073: // do not check if this worked, as it may also return false, when all neccessary dirs are present
074: dir.mkdirs();
075: return file.createNewFile();
076: }
077: }
078:
079: /**
080: * Removes a file. If the specified file is a directory all contained files will
081: * be removed recursively as well.
082: *
083: * @param toRemove file to be removed
084: */
085: public static void removeRec(File toRemove) {
086: if (toRemove.isDirectory()) {
087: File fileList[] = toRemove.listFiles();
088: for (int a = 0; a < fileList.length; a++) {
089: removeRec(fileList[a]);
090: }
091: }
092: toRemove.delete();
093: }
094:
095: /**
096: * Moves one directory or file to another. Existing files will be replaced.
097: *
098: * @param source file to move from
099: * @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)
103: throws IOException {
104: byte[] sharedBuffer = new byte[BUF_SIZE];
105: moveRec(source, target, sharedBuffer);
106: }
107:
108: static void moveRec(File source, File target, byte[] sharedBuffer)
109: throws IOException {
110: if (source.isDirectory()) {
111: if (!target.exists()) {
112: target.mkdirs();
113: }
114: if (target.isDirectory()) {
115:
116: File[] files = source.listFiles();
117: for (int i = 0; i < files.length; i++) {
118: File file = files[i];
119: File targetFile = new File(target, file.getName());
120: if (file.isFile()) {
121: if (targetFile.exists()) {
122: targetFile.delete();
123: }
124: if (!file.renameTo(targetFile)) {
125: copy(file, targetFile, sharedBuffer);
126: file.delete();
127: }
128: } else {
129: if (!targetFile.exists()) {
130: if (!targetFile.mkdirs()) {
131: throw new IOException(
132: "Could not create target directory: "
133: + targetFile);
134: }
135: }
136: moveRec(file, targetFile);
137: }
138: }
139: source.delete();
140: }
141: } else {
142: if (!target.isDirectory()) {
143: copy(source, target, sharedBuffer);
144: source.delete();
145: }
146: }
147: }
148:
149: /**
150: * Copies one directory or file to another. Existing files will be replaced.
151: *
152: * @param source directory or file to copy from
153: * @param target directory or file to copy to
154: * @throws IOException if an I/O error occurs (may result in partially done work)
155: */
156: public static void copyRec(File source, File target)
157: throws IOException {
158: byte[] sharedBuffer = new byte[BUF_SIZE];
159: copyRec(source, target, sharedBuffer);
160: }
161:
162: static void copyRec(File source, File target, byte[] sharedBuffer)
163: throws IOException {
164: if (source.isDirectory()) {
165: if (!target.exists()) {
166: target.mkdirs();
167: }
168: if (target.isDirectory()) {
169:
170: File[] files = source.listFiles();
171: for (int i = 0; i < files.length; i++) {
172: File file = files[i];
173: File targetFile = new File(target, file.getName());
174: if (file.isFile()) {
175: if (targetFile.exists()) {
176: targetFile.delete();
177: }
178: copy(file, targetFile, sharedBuffer);
179: } else {
180: targetFile.mkdirs();
181: copyRec(file, targetFile);
182: }
183: }
184: }
185: } else {
186: if (!target.isDirectory()) {
187: if (!target.exists()) {
188: File dir = target.getParentFile();
189: if (!dir.exists() && !dir.mkdirs()) {
190: throw new IOException(
191: "Could not create target directory: "
192: + dir);
193: }
194: if (!target.createNewFile()) {
195: throw new IOException(
196: "Could not create target file: "
197: + target);
198: }
199: }
200: copy(source, target, sharedBuffer);
201: }
202: }
203: }
204:
205: /**
206: * Copies one file to another using {@link #copy(InputStream, OutputStream)}.
207: *
208: * @param input
209: * source file
210: * @param output
211: * destination file
212: * @return the number of bytes copied
213: * @throws IOException
214: * if an I/O error occurs (may result in partially done work)
215: * @see #copy(InputStream, OutputStream)
216: */
217: public static long copy(File input, File output) throws IOException {
218: FileInputStream in = null;
219: try {
220: in = new FileInputStream(input);
221: return copy(in, output);
222: } finally {
223: if (in != null) {
224: try {
225: in.close();
226: } catch (IOException e) {
227: }
228: }
229: }
230: }
231:
232: /**
233: * Copies one file to another using the supplied buffer.
234: *
235: * @param input source file
236: * @param output destination file
237: * @param copyBuffer buffer used for copying
238: * @return the number of bytes copied
239: * @throws IOException if an I/O error occurs (may result in partially done work)
240: * @see #copy(InputStream, OutputStream)
241: */
242: public static long copy(File input, File output, byte[] copyBuffer)
243: throws IOException {
244: FileInputStream in = null;
245: FileOutputStream out = null;
246: try {
247: in = new FileInputStream(input);
248: out = new FileOutputStream(output);
249: return copy(in, out, copyBuffer);
250: } finally {
251: if (in != null) {
252: try {
253: in.close();
254: } catch (IOException e) {
255: }
256: }
257: if (out != null) {
258: try {
259: out.close();
260: } catch (IOException e) {
261: }
262: }
263: }
264: }
265:
266: /**
267: * Copies an <code>InputStream</code> to a file using {@link #copy(InputStream, OutputStream)}.
268: *
269: * @param in stream to copy from
270: * @param outputFile file to copy to
271: * @return the number of bytes copied
272: * @throws IOException if an I/O error occurs (may result in partially done work)
273: * @see #copy(InputStream, OutputStream)
274: */
275: public static long copy(InputStream in, File outputFile)
276: throws IOException {
277: FileOutputStream out = null;
278: try {
279: out = new FileOutputStream(outputFile);
280: return copy(in, out);
281: } finally {
282: if (out != null) {
283: try {
284: out.close();
285: } catch (IOException e) {
286: }
287: }
288: }
289: }
290:
291: /**
292: * Copies an <code>InputStream</code> to an <code>OutputStream</code> using a local internal buffer for performance.
293: * Compared to {@link #globalBufferCopy(InputStream, OutputStream)} this method allows for better
294: * concurrency, but each time it is called generates a buffer which will be garbage.
295: *
296: * @param in stream to copy from
297: * @param out stream to copy to
298: * @return the number of bytes copied
299: * @throws IOException if an I/O error occurs (may result in partially done work)
300: * @see #globalBufferCopy(InputStream, OutputStream)
301: */
302: public static long copy(InputStream in, OutputStream out)
303: throws IOException {
304: // we need a buffer of our own, so no one else interferes
305: byte[] buf = new byte[BUF_SIZE];
306: return copy(in, out, buf);
307: }
308:
309: /**
310: * Copies an <code>InputStream</code> to an <code>OutputStream</code> using a global internal buffer for performance.
311: * Compared to {@link #copy(InputStream, OutputStream)} this method generated no garbage,
312: * but decreases concurrency.
313: *
314: * @param in stream to copy from
315: * @param out stream to copy to
316: * @return the number of bytes copied
317: * @throws IOException if an I/O error occurs (may result in partially done work)
318: * @see #copy(InputStream, OutputStream)
319: */
320: public static long globalBufferCopy(InputStream in, OutputStream out)
321: throws IOException {
322: synchronized (BUF) {
323: return copy(in, out, BUF);
324: }
325: }
326:
327: /**
328: * Copies an <code>InputStream</code> to an <code>OutputStream</code> using the specified buffer.
329: *
330: * @param in stream to copy from
331: * @param out stream to copy to
332: * @param copyBuffer buffer used for copying
333: * @return the number of bytes copied
334: * @throws IOException if an I/O error occurs (may result in partially done work)
335: * @see #globalBufferCopy(InputStream, OutputStream)
336: * @see #copy(InputStream, OutputStream)
337: */
338: public static long copy(InputStream in, OutputStream out,
339: byte[] copyBuffer) throws IOException {
340: long bytesCopied = 0;
341: int read = -1;
342:
343: while ((read = in.read(copyBuffer, 0, copyBuffer.length)) != -1) {
344: out.write(copyBuffer, 0, read);
345: bytesCopied += read;
346: }
347: return bytesCopied;
348: }
349: }
|