001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common
008: * Development and Distribution License("CDDL") (collectively, the
009: * "License"). You may not use this file except in compliance with the
010: * License. You can obtain a copy of the License at
011: * http://www.netbeans.org/cddl-gplv2.html
012: * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
013: * specific language governing permissions and limitations under the
014: * License. When distributing the software, include this License Header
015: * Notice in each file and include the License file at
016: * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
017: * particular file as subject to the "Classpath" exception as provided
018: * by Sun in the GPL Version 2 section of the License file that
019: * accompanied this code. If applicable, add the following below the
020: * License Header, with the fields enclosed by brackets [] replaced by
021: * your own identifying information:
022: * "Portions Copyrighted [year] [name of copyright owner]"
023: *
024: * Contributor(s):
025: *
026: * The Original Software is NetBeans. The Initial Developer of the Original
027: * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
028: * Microsystems, Inc. All Rights Reserved.
029: *
030: * If you wish your version of this file to be governed by only the CDDL
031: * or only the GPL Version 2, indicate your decision by adding
032: * "[Contributor] elects to include this software in this distribution
033: * under the [CDDL or GPL Version 2] license." If you do not indicate a
034: * single choice of license, a recipient has the option to distribute
035: * your version of this file under either the CDDL, the GPL Version 2 or
036: * to extend the choice of license to its licensees as provided above.
037: * However, if you add GPL Version 2 code and therefore, elected the GPL
038: * Version 2 license, then the option applies only if the new code is
039: * made subject to such option by the copyright holder.
040: */
041:
042: package org.netbeans.modules.subversion.util;
043:
044: import java.io.*;
045: import java.util.logging.Level;
046: import org.netbeans.modules.subversion.Subversion;
047: import org.openide.filesystems.FileUtil;
048:
049: /**
050: *
051: * @author pkuzel
052: */
053: public class FileUtils {
054:
055: /**
056: * Copies the specified sourceFile to the specified targetFile.
057: */
058: public static void copyFile(File sourceFile, File targetFile)
059: throws IOException {
060: if (sourceFile == null || targetFile == null) {
061: throw new NullPointerException(
062: "sourceFile and targetFile must not be null"); // NOI18N
063: }
064:
065: InputStream inputStream = null;
066: try {
067: inputStream = createInputStream(sourceFile);
068: copyStreamToFile(inputStream, targetFile);
069: } finally {
070: if (inputStream != null) {
071: try {
072: inputStream.close();
073: } catch (IOException ex) {
074: // ignore
075: }
076: }
077: }
078: }
079:
080: public static void copyDirFiles(File sourceDir, File targetDir) {
081: copyDirFiles(sourceDir, targetDir, false);
082: }
083:
084: public static void copyDirFiles(File sourceDir, File targetDir,
085: boolean preserveTimestamp) {
086: File[] files = sourceDir.listFiles();
087:
088: if (files == null || files.length == 0) {
089: targetDir.mkdirs();
090: if (preserveTimestamp)
091: targetDir.setLastModified(sourceDir.lastModified());
092: return;
093: }
094: if (preserveTimestamp)
095: targetDir.setLastModified(sourceDir.lastModified());
096: for (int i = 0; i < files.length; i++) {
097: try {
098: File target = FileUtil.normalizeFile(new File(targetDir
099: .getAbsolutePath()
100: + "/" + files[i].getName())); // NOI18N
101: if (files[i].isDirectory()) {
102: copyDirFiles(files[i], target, preserveTimestamp);
103: } else {
104: FileUtils.copyFile(files[i], target);
105: if (preserveTimestamp)
106: target.setLastModified(files[i].lastModified());
107: }
108: } catch (IOException ex) {
109: Subversion.LOG.log(Level.INFO, null, ex); // should not happen
110: }
111: }
112: }
113:
114: /**
115: * Copies the specified sourceFile to the specified targetFile.
116: * It <b>closes</b> the input stream.
117: */
118: public static void copyStreamToFile(InputStream inputStream,
119: File targetFile) throws IOException {
120: if (inputStream == null || targetFile == null) {
121: throw new NullPointerException(
122: "sourcStream and targetFile must not be null"); // NOI18N
123: }
124:
125: // ensure existing parent directories
126: File directory = targetFile.getParentFile();
127: if (!directory.exists() && !directory.mkdirs()) {
128: throw new IOException("Could not create directory '"
129: + directory + "'"); // NOI18N
130: }
131:
132: OutputStream outputStream = null;
133: try {
134: outputStream = createOutputStream(targetFile);
135: try {
136: byte[] buffer = new byte[32768];
137: for (int readBytes = inputStream.read(buffer); readBytes > 0; readBytes = inputStream
138: .read(buffer)) {
139: outputStream.write(buffer, 0, readBytes);
140: }
141: } catch (IOException ex) {
142: targetFile.delete();
143: throw ex;
144: }
145: } finally {
146: if (inputStream != null) {
147: try {
148: inputStream.close();
149: } catch (IOException ex) {
150: // ignore
151: }
152: }
153: if (outputStream != null) {
154: try {
155: outputStream.close();
156: } catch (IOException ex) {
157: // ignore
158: }
159: }
160: }
161: }
162:
163: /**
164: * Recursively deletes all files and directories under a given file/directory.
165: *
166: * @param file file/directory to delete
167: */
168: public static void deleteRecursively(File file) {
169: if (file.isDirectory()) {
170: File[] files = file.listFiles();
171: for (int i = 0; i < files.length; i++) {
172: deleteRecursively(files[i]);
173: }
174: }
175: file.delete();
176: }
177:
178: /**
179: * Do the best to rename the file.
180: * @param orig regular file
181: * @param dest regular file (if exists it's rewritten)
182: */
183: public static void renameFile(File orig, File dest)
184: throws IOException {
185: boolean destExists = dest.exists();
186: if (destExists) {
187: for (int i = 0; i < 3; i++) {
188: if (dest.delete()) {
189: destExists = false;
190: break;
191: }
192: try {
193: Thread.sleep(71);
194: } catch (InterruptedException e) {
195: }
196: }
197: }
198:
199: if (destExists == false) {
200: for (int i = 0; i < 3; i++) {
201: if (orig.renameTo(dest)) {
202: return;
203: }
204: try {
205: Thread.sleep(71);
206: } catch (InterruptedException e) {
207: }
208: }
209: }
210:
211: // requires less permisions than renameTo
212: FileUtils.copyFile(orig, dest);
213:
214: for (int i = 0; i < 3; i++) {
215: if (orig.delete()) {
216: return;
217: }
218: try {
219: Thread.sleep(71);
220: } catch (InterruptedException e) {
221: }
222: }
223: throw new IOException("Can not delete: "
224: + orig.getAbsolutePath()); // NOI18N
225: }
226:
227: /**
228: * This utility class needs not to be instantiated anywhere.
229: */
230: private FileUtils() {
231: }
232:
233: public static BufferedInputStream createInputStream(File file)
234: throws IOException {
235: int retry = 0;
236: while (true) {
237: try {
238: return new BufferedInputStream(
239: new FileInputStream(file));
240: } catch (IOException ex) {
241: retry++;
242: if (retry > 7) {
243: throw ex;
244: }
245: try {
246: Thread.sleep(retry * 34);
247: } catch (InterruptedException iex) {
248: throw ex;
249: }
250: }
251: }
252: }
253:
254: public static BufferedOutputStream createOutputStream(File file)
255: throws IOException {
256: int retry = 0;
257: while (true) {
258: try {
259: return new BufferedOutputStream(new FileOutputStream(
260: file));
261: } catch (IOException ex) {
262: retry++;
263: if (retry > 7) {
264: throw ex;
265: }
266: try {
267: Thread.sleep(retry * 34);
268: } catch (InterruptedException iex) {
269: throw ex;
270: }
271: }
272: }
273: }
274:
275: /** Creates new tmp dir in java.io.tmpdir */
276: public static File createTmpFolder(String prefix) {
277: String tmpDir = System.getProperty("java.io.tmpdir"); // NOI18N
278: File tmpFolder = new File(tmpDir);
279: File checkoutFolder = null;
280: try {
281: // generate unique name for tmp folder
282: File tmp = File.createTempFile(prefix, "", tmpFolder); // NOI18N
283: if (tmp.delete() == false) {
284: return checkoutFolder;
285: }
286: if (tmp.mkdirs() == false) {
287: return checkoutFolder;
288: }
289: checkoutFolder = FileUtil.normalizeFile(tmp);
290: } catch (IOException e) {
291: Subversion.LOG.log(Level.SEVERE, null, e);
292: }
293: return checkoutFolder;
294: }
295:
296: }
|