org.apache.ivy.util.FileUtil Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.ivy.util;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import org.apache.ivy.util.url.URLHandlerRegistry;
/**
* Utility class used to deal with file related operations, like copy, full reading, symlink, ...
*/
public final class FileUtil {
private FileUtil() {
//Utility class
}
// according to tests by users, 64kB seems to be a good value for the buffer used during copy
// further improvements could be obtained using NIO API
private static final int BUFFER_SIZE = 64 * 1024;
private static final byte[] EMPTY_BUFFER = new byte[0];
public static void symlink(File src, File dest, CopyProgressListener l, boolean overwrite)
throws IOException {
try {
if (dest.exists()) {
if (!dest.isFile()) {
throw new IOException("impossible to copy: destination is not a file: " + dest);
}
if (!overwrite) {
Message.verbose(dest + " already exists, nothing done");
return;
}
}
if (dest.getParentFile() != null) {
dest.getParentFile().mkdirs();
}
Runtime runtime = Runtime.getRuntime();
Message.verbose("executing 'ln -s -f " + src.getAbsolutePath() + " " + dest.getPath()
+ "'");
Process process = runtime.exec(new String[] {"ln", "-s", "-f", src.getAbsolutePath(),
dest.getPath()});
if (process.waitFor() != 0) {
InputStream errorStream = process.getErrorStream();
InputStreamReader isr = new InputStreamReader(errorStream);
BufferedReader br = new BufferedReader(isr);
StringBuffer error = new StringBuffer();
String line;
while ((line = br.readLine()) != null) {
error.append(line);
error.append('\n');
}
throw new IOException("error symlinking " + src + " to " + dest + ":\n" + error);
}
// check if the creation of the symbolic link was successful
if (!dest.exists()) {
throw new IOException("error symlinking: " + dest + " doesn't exists");
}
// check if the result is a true symbolic link
if (dest.getAbsolutePath().equals(dest.getCanonicalPath())) {
dest.delete(); // just make sure we do delete the invalid symlink!
throw new IOException("error symlinking: " + dest + " isn't a symlink");
}
} catch (IOException x) {
Message.verbose("symlink failed; falling back to copy");
StringWriter buffer = new StringWriter();
x.printStackTrace(new PrintWriter(buffer));
Message.debug(buffer.toString());
copy(src, dest, l, overwrite);
} catch (InterruptedException x) {
Thread.currentThread().interrupt();
}
}
public static boolean copy(File src, File dest, CopyProgressListener l) throws IOException {
return copy(src, dest, l, false);
}
public static boolean copy(File src, File dest, CopyProgressListener l, boolean overwrite)
throws IOException {
if (dest.exists()) {
if (!dest.isFile()) {
throw new IOException("impossible to copy: destination is not a file: " + dest);
}
if (overwrite) {
if (!dest.canWrite()) {
dest.delete();
} // if dest is writable, the copy will overwrite it without requiring a delete
} else {
Message.verbose(dest + " already exists, nothing done");
return false;
}
}
copy(new FileInputStream(src), dest, l);
long srcLen = src.length();
long destLen = dest.length();
if (srcLen != destLen) {
dest.delete();
throw new IOException("size of source file " + src.toString() + "(" + srcLen
+ ") differs from size of dest file " + dest.toString() + "(" + destLen
+ ") - please retry");
}
dest.setLastModified(src.lastModified());
return true;
}
public static void copy(URL src, File dest, CopyProgressListener l) throws IOException {
URLHandlerRegistry.getDefault().download(src, dest, l);
}
public static void copy(File src, URL dest, CopyProgressListener l) throws IOException {
URLHandlerRegistry.getDefault().upload(src, dest, l);
}
public static void copy(InputStream src, File dest, CopyProgressListener l) throws IOException {
if (dest.getParentFile() != null) {
dest.getParentFile().mkdirs();
}
copy(src, new FileOutputStream(dest), l);
}
public static void copy(InputStream src, OutputStream dest, CopyProgressListener l)
throws IOException {
CopyProgressEvent evt = null;
if (l != null) {
evt = new CopyProgressEvent();
}
try {
byte[] buffer = new byte[BUFFER_SIZE];
int c;
long total = 0;
if (l != null) {
l.start(evt);
}
while ((c = src.read(buffer)) != -1) {
if (Thread.currentThread().isInterrupted()) {
throw new IOException("transfer interrupted");
}
dest.write(buffer, 0, c);
total += c;
if (l != null) {
l.progress(evt.update(buffer, c, total));
}
}
if (l != null) {
evt.update(EMPTY_BUFFER, 0, total);
}
try {
dest.flush();
} catch (IOException ex) {
// ignore
}
// close the streams
src.close();
dest.close();
} finally {
try {
src.close();
} catch (IOException ex) {
// ignore
}
try {
dest.close();
} catch (IOException ex) {
// ignore
}
}
if (l != null) {
l.end(evt);
}
}
/**
* Reads the whole BufferedReader line by line, using \n as line separator for each line.
*
* Note that this method will add a final \n to the last line even though there is no new line
* character at the end of last line in the original reader.
*
*
* The BufferedReader is closed when this method returns.
*
*
* @param in
* the {@link BufferedReader} to read from
* @return a String with the whole content read from the {@link BufferedReader}
* @throws IOException
* if an IO problems occur during reading
*/
public static String readEntirely(BufferedReader in) throws IOException {
try {
StringBuffer buf = new StringBuffer();
String line = in.readLine();
while (line != null) {
buf.append(line + "\n");
line = in.readLine();
}
return buf.toString();
} finally {
in.close();
}
}
/**
* Reads the entire content of the file and returns it as a String.
*
* @param f
* the file to read from
* @return a String with the file content
* @throws IOException
* if an IO problems occurs during reading
*/
public static String readEntirely(File f) throws IOException {
return readEntirely(new FileInputStream(f));
}
/**
* Reads the entire content of the {@link InputStream} and returns it as a String.
*
* The input stream is closed when this method returns.
*
*
* @param is
* the {@link InputStream} to read from
* @return a String with the input stream content
* @throws IOException
* if an IO problems occurs during reading
*/
public static String readEntirely(InputStream is) throws IOException {
try {
StringBuffer sb = new StringBuffer();
byte[] buffer = new byte[BUFFER_SIZE];
int c;
while ((c = is.read(buffer)) != -1) {
sb.append(new String(buffer, 0, c));
}
return sb.toString();
} finally {
is.close();
}
}
public static String concat(String dir, String file) {
return dir + "/" + file;
}
/**
* Recursively delete file
*
* @param file
* the file to delete
* @return true if the deletion completed successfully (ie if the file does not exist on the
* filesystem after this call), false if a deletion was not performed successfully.
*/
public static boolean forceDelete(File file) {
if (!file.exists()) {
return true;
}
if (file.isDirectory()) {
File[] files = file.listFiles();
for (int i = 0; i < files.length; i++) {
if (!forceDelete(files[i])) {
return false;
}
}
}
return file.delete();
}
/**
* Returns a list of Files composed of all directories being parent of file and child of root +
* file and root themselves. Example: getPathFiles(new File("test"), new
* File("test/dir1/dir2/file.txt")) => {new File("test/dir1"), new File("test/dir1/dir2"), new
* File("test/dir1/dir2/file.txt") } Note that if root is not an ancester of file, or if root is
* null, all directories from the file system root will be returned.
*/
public static List getPathFiles(File root, File file) {
List ret = new ArrayList();
while (file != null && !file.getAbsolutePath().equals(root.getAbsolutePath())) {
ret.add(file);
file = file.getParentFile();
}
if (root != null) {
ret.add(root);
}
Collections.reverse(ret);
return ret;
}
/**
* Returns a collection of all Files being contained in the given directory, recursively,
* including directories.
*
* @param dir The directory from which all files, including files in subdirectory)
* are extracted.
* @param ignore a Collection of filenames which must be excluded from listing
* @return A collectoin containing all the files of the given directory and it's
* subdirectories.
*/
public static Collection listAll(File dir, Collection ignore) {
return listAll(dir, new ArrayList(), ignore);
}
private static Collection listAll(File file, Collection list, Collection ignore) {
if (ignore.contains(file.getName())) {
return list;
}
if (file.exists()) {
list.add(file);
}
if (file.isDirectory()) {
File[] files = file.listFiles();
for (int i = 0; i < files.length; i++) {
listAll(files[i], list, ignore);
}
}
return list;
}
public static File resolveFile(File file, String filename) {
/*
* very simple resolveFile algorithm compared to what is done in Ant. It must be enough in
* most common cases though.
*/
File f = new File(filename);
if (f.isAbsolute()) {
return f;
}
return new File(file, filename);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy