001: /**
002: * EasyBeans
003: * Copyright (C) 2006 Bull S.A.S.
004: * Contact: easybeans@ow2.org
005: *
006: * This library is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU Lesser General Public
008: * License as published by the Free Software Foundation; either
009: * version 2.1 of the License, or any later version.
010: *
011: * This library is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * Lesser General Public License for more details.
015: *
016: * You should have received a copy of the GNU Lesser General Public
017: * License along with this library; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
019: * USA
020: *
021: * --------------------------------------------------------------------------
022: * $Id: FileUtils.java 1970 2007-10-16 11:49:25Z benoitf $
023: * --------------------------------------------------------------------------
024: */package org.ow2.easybeans.util.files;
025:
026: import java.io.File;
027: import java.io.FileInputStream;
028: import java.io.FileOutputStream;
029: import java.io.IOException;
030: import java.io.InputStream;
031: import java.nio.channels.FileChannel;
032: import java.util.Enumeration;
033: import java.util.jar.JarEntry;
034: import java.util.jar.JarFile;
035:
036: import org.ow2.util.log.Log;
037: import org.ow2.util.log.LogFactory;
038:
039: /**
040: * This class manages operation done many times on files, like copying them.
041: * @author Florent Benoit
042: */
043: public final class FileUtils {
044:
045: /**
046: * Size of the buffer.
047: */
048: private static final int BUFFER_SIZE = 2048;
049:
050: /**
051: * Logger.
052: */
053: private static Log logger = LogFactory.getLog(FileUtils.class);
054:
055: /**
056: * Utility class, no public constructor.
057: */
058: private FileUtils() {
059:
060: }
061:
062: /**
063: * Unpack the source archive in a given directory and returns directory
064: * directory created.
065: * @param packedJar source JarFile to be unpacked
066: * @param dest the destination folder
067: * @throws FileUtilsException When unpack fails
068: */
069: public static void unpack(final JarFile packedJar, final File dest)
070: throws FileUtilsException {
071:
072: JarEntry entry = null;
073:
074: // get entries of the jar file
075: Enumeration entries = packedJar.entries();
076: while (entries.hasMoreElements()) {
077: entry = (JarEntry) entries.nextElement();
078:
079: // File entry
080: File entryFile = new File(dest, entry.getName());
081:
082: // Create directory
083: if (entry.isDirectory()) {
084: if (!entryFile.exists()) {
085: // create parent directories (with mkdirs)
086: if (!entryFile.mkdirs()) {
087: String err = "Can not create directory "
088: + entryFile
089: + ", Check the write access.";
090: throw new FileUtilsException(err);
091: }
092: }
093: continue;
094: }
095:
096: // If it's a file, we must extract the file
097: // Ensure that the directory exists.
098: entryFile.getParentFile().mkdirs();
099:
100: InputStream is = null;
101: // get the input stream
102: try {
103: is = packedJar.getInputStream(entry);
104: // Dump to the file
105: dump(is, entryFile);
106: } catch (IOException ioe) {
107: throw new FileUtilsException(
108: "Cannot get inputstream of entry '" + entry
109: + "' of file '" + packedJar + "'.");
110: } finally {
111: try {
112: is.close();
113: } catch (IOException ioe) {
114: logger.debug("Cannot close input stream", ioe);
115: }
116: }
117:
118: }
119: }
120:
121: /**
122: * Write the given input stream in the given file.
123: * @param in the inputStream to copy.
124: * @param entryFile the file where the inputStream must be dumped.
125: * @throws FileUtilsException if the dump failed.
126: */
127: public static void dump(final InputStream in, final File entryFile)
128: throws FileUtilsException {
129:
130: try {
131: // File output
132: FileOutputStream out = new FileOutputStream(entryFile);
133: int n = 0;
134: try {
135: // buffer
136: byte[] buffer = new byte[BUFFER_SIZE];
137: n = in.read(buffer);
138: while (n > 0) {
139: out.write(buffer, 0, n);
140: n = in.read(buffer);
141: }
142: } finally {
143: out.close();
144: }
145: } catch (IOException e) {
146: String err = "Error while unpacking entry " + entryFile
147: + " : ";
148: throw new FileUtilsException(err, e);
149: }
150: }
151:
152: /**
153: * Copy a file.
154: * @param src source file
155: * @param dest dest file
156: * @throws FileUtilsException if the copy of the file failed
157: */
158: public static void copyFile(final String src, final String dest)
159: throws FileUtilsException {
160: copyFile(new File(src), new File(dest));
161: }
162:
163: /**
164: * Copy a file.
165: * @param src source file
166: * @param dest dest file
167: * @throws FileUtilsException if the copy of the file failed
168: */
169: public static void copyFile(final File src, final File dest)
170: throws FileUtilsException {
171: File newDest = null;
172: if (dest.isDirectory()) {
173: logger
174: .debug("Copy a file to a directory, append source filename to directory.");
175: newDest = new File(dest, src.getName());
176: } else {
177: newDest = dest;
178: }
179:
180: FileInputStream fIn = null;
181: FileOutputStream fOut = null;
182: FileChannel fcIn = null;
183: try {
184:
185: // InputStream
186: fIn = new FileInputStream(src);
187: fOut = new FileOutputStream(newDest);
188:
189: // nio channel
190: FileChannel sourceFC = fIn.getChannel();
191: FileChannel targetFC = fOut.getChannel();
192:
193: targetFC.transferFrom(sourceFC, 0, sourceFC.size());
194: } catch (Exception e) {
195: throw new FileUtilsException("Error during copy file : "
196: + src + " -> " + dest, e);
197: } finally {
198: try {
199: fOut.close();
200: fIn.close();
201: fcIn.close();
202: } catch (Exception e) {
203: logger
204: .debug("Cannot close some i/o which are open.",
205: e);
206: }
207:
208: }
209: }
210:
211: /**
212: * @param path file/directory to be deleted
213: * @return true if deletion was OK
214: */
215: public static boolean delete(final String path) {
216: return delete(new File(path));
217: }
218:
219: /**
220: * @param f file/directory to be deleted
221: * @return true if deletion was OK
222: */
223: public static boolean delete(final File f) {
224: if (f.isFile()) {
225: return f.delete();
226: }
227: // else (if directory)
228: File[] children = f.listFiles();
229: if (children == null) {
230: // no children
231: return f.delete();
232: }
233:
234: // There are children
235: boolean result = true;
236: for (int i = 0; i < children.length; i++) {
237: result &= delete(children[i]);
238: }
239: return result && f.delete();
240: }
241:
242: /**
243: * Copy a directory recursively.
244: * @param src source directory
245: * @param dest dest directory
246: * @throws FileUtilsException if the copy of the directory failed
247: */
248: public static void copyDirectory(final String src, final String dest)
249: throws FileUtilsException {
250: copyDirectory(new File(src), new File(dest));
251: }
252:
253: /**
254: * Copy a directory recursively.
255: * @param src source directory
256: * @param dest dest directory
257: * @throws FileUtilsException if the copy of the directory failed
258: */
259: public static void copyDirectory(final File src, final File dest)
260: throws FileUtilsException {
261:
262: if (!src.isDirectory()) {
263: // We don not accept file arguments !
264: throw new IllegalArgumentException("Source '" + src
265: + "' must be a directory");
266: }
267:
268: // create the destination directory if it is inexistant
269: if (!dest.exists()) {
270: dest.mkdirs();
271: }
272:
273: // copy the files of the source directory
274: File[] childs = src.listFiles();
275: if (childs != null) {
276: // childs
277: for (int i = 0; i < childs.length; i++) {
278: File child = childs[i];
279: if (child.isFile()) {
280: // file
281: copyFile(child, dest);
282: } else {
283: // directory
284: copyDirectory(child,
285: new File(dest, child.getName()));
286: }
287: }
288: }
289: }
290:
291: }
|