/*******************************************************************************
* Copyright (c) 2011 Red Hat, Inc.
* Distributed under license by Red Hat, Inc. All rights reserved.
* This program is made available under the terms of the
* Eclipse Public License v1.0 which accompanies this distribution,
* and is available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
******************************************************************************/
package org.jboss.tools.openshift.common.core.utils;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.text.MessageFormat;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.commons.io.FilenameUtils;
import org.eclipse.core.runtime.Assert;
/**
* @author André Dietisheim
*/
public class FileUtils {
private static final String EXT_TAR_GZ = ".tar.gz";
private static final char SUFFIX_DELIMITER = '.';
private static final String NUMERIC_SUFFIX_FILENAME_PATTERN = "{0}/{1}({2}){3}";
private static final Pattern NUMERIC_SUFFIX_FILENAME_REGEX = Pattern.compile("(.*)\\([0-9]+\\)");
private static final byte[] buffer = new byte[1024];
public static boolean canRead(String path) {
if (path == null) {
return false;
}
return canRead(new File(path));
}
public static boolean canRead(File file) {
if (file == null) {
return false;
}
return file.canRead();
}
public static boolean canWrite(String path) {
if (path == null) {
return false;
}
return canWrite(new File(path));
}
public static boolean canWrite(File file) {
if (file == null) {
return false;
}
if (!file.exists()) {
return canWrite(file.getParent());
}
return file.canWrite();
}
public static boolean exists(File file) {
return file != null
&& file.exists();
}
public static boolean isDirectory(File file) {
return file != null
&& file.isDirectory();
}
public static File getSystemTmpFolder() {
String tmpFolder = System.getProperty("java.io.tmpdir");
return new File(tmpFolder);
}
public static File getRandomTmpFolder() {
String randomName = String.valueOf(System.currentTimeMillis());
return new File(getSystemTmpFolder(), randomName);
}
/**
* Copies the ginve source to the given destination recursively. Overwrites
* existing files/directory on the destination path if told so.
*
* @param source
* the source file/directory to copy
* @param destination
* the destination to copy to
* @param overwrite
* overwrites existing files/directories if <code>true</code>.
* Does not overwrite otherwise.
* @throws IOException
*/
public static void copy(File source, File destination, boolean overwrite) throws IOException {
if (!exists(source)
|| destination == null) {
return;
}
if (source.isDirectory()) {
copyDirectory(source, destination, overwrite);
} else {
copyFile(source, destination, overwrite);
}
}
private static void copyDirectory(File source, File destination, boolean overwrite) throws IOException {
Assert.isLegal(source != null);
Assert.isLegal(source.isDirectory());
Assert.isLegal(destination != null);
destination = getDestinationDirectory(source, destination);
if (!destination.exists()) {
destination.mkdir();
copyPermissions(source, destination);
}
for (File content : source.listFiles()) {
if (content.isDirectory()) {
copyDirectory(content, new File(destination, content.getName()), overwrite);
} else {
copyFile(content, new File(destination, content.getName()), overwrite);
}
}
}
private static File getDestinationDirectory(File source, File destination) {
if (!source.getName().equals(destination.getName())) {
destination = new File(destination, source.getName());
}
return destination;
}
private static void copyFile(File source, File destination, boolean overwrite) throws IOException {
Assert.isLegal(source != null);
Assert.isLegal(source.isFile());
Assert.isLegal(destination != null);
destination = getDestinationFile(source, destination);
if (exists(destination)
&& !overwrite) {
return;
}
if (isDirectory(destination)) {
if (!overwrite) {
return;
}
destination.delete();
}
writeTo(source, destination);
}
private static File getDestinationFile(File source, File destination) {
if (!source.getName().equals(destination.getName())) {
destination = new File(destination, source.getName());
}
return destination;
}
private static final void writeTo(File source, File destination) throws IOException {
Assert.isLegal(source != null);
Assert.isLegal(destination != null);
writeTo(new BufferedInputStream(new FileInputStream(source)), destination);
copyPermissions(source, destination);
}
public static final void writeTo(String content, File destination) throws FileNotFoundException {
PrintWriter writer = new PrintWriter(destination);
writer.write(content);
writer.flush();
writer.close();
}
private static final void writeTo(InputStream in, File destination) throws IOException {
Assert.isLegal(in != null);
Assert.isLegal(destination != null);
OutputStream out = null;
try {
out = new BufferedOutputStream(new FileOutputStream(destination));
for (int read = -1; (read = in.read(buffer)) != -1;) {
out.write(buffer, 0, read);
}
out.flush();
} finally {
silentlyClose(in);
silentlyClose(out);
}
}
/**
* Replicates the owner permissions from the source to the destination. Due
* to limitation in java6 this is the best we can do (there's no way in
* java6 to know if rights are due to owner or group)
*
* @param source
* @param destination
*
* @see File#canRead()
* @see File#setReadable(boolean)
* @see File#canWrite()
* @see File#setWritable(boolean)
* @see File#canExecute()
* @see File#setExecutable(boolean)
*/
private static void copyPermissions(File source, File destination) {
Assert.isLegal(source != null);
Assert.isLegal(destination != null);
destination.setReadable(source.canRead());
destination.setWritable(source.canWrite());
destination.setExecutable(source.canExecute());
}
private static void silentlyClose(InputStream in) {
try {
if (in != null) {
in.close();
}
} catch (IOException e) {
// ignore
}
}
private static void silentlyClose(OutputStream out) {
try {
if (out != null) {
out.close();
}
} catch (IOException e) {
// ignore
}
}
public static String getParent(String filepath) {
String parent = null;
if (!StringUtils.isEmpty(filepath)) {
parent = new File(filepath).getParent();
}
return parent;
}
/**
* Returns the given filepath with a suffix if the given filepath already
* exists.
*
* @param filepath
* @return the filepath or filepath + numeric suffix if not available.
*
* @see #NUMERIC_SUFFIX_FILENAME_PATTERN
*/
public static String getAvailableFilepath(String filepath) {
if (StringUtils.isEmpty(filepath)) {
return filepath;
}
String extension = getExtension(filepath);
String dir = FilenameUtils.getFullPathNoEndSeparator(filepath);
String filenameWithoutExtension = stripNumericSuffix(getBaseName(filepath));
String newFilename = filepath;
int i = 1;
while (new File(newFilename).exists()) {
newFilename = MessageFormat.format(NUMERIC_SUFFIX_FILENAME_PATTERN, dir, filenameWithoutExtension, i++, extension);
}
return newFilename;
}
/**
* Strips the numeric suffix off the given filepath if present. Returns the
* given filepath otherwise.
*
* @param filepath
* @return
*/
private static String stripNumericSuffix(String filepath) {
if (StringUtils.isEmpty(filepath)) {
return filepath;
}
Matcher matcher = NUMERIC_SUFFIX_FILENAME_REGEX.matcher(filepath);
if (!matcher.matches()
|| matcher.groupCount() < 1) {
return filepath;
}
return matcher.group(1);
}
private static String getExtension(String filename) {
if (StringUtils.isEmpty(filename)) {
return filename;
}
if(filename.endsWith(EXT_TAR_GZ)){
return EXT_TAR_GZ;
}
return FilenameUtils.getExtension(filename);
}
/**
* Returns the filename without the suffix
*
* @param filename
* @return
*/
public static String getBaseName(String filename) {
if (StringUtils.isEmpty(filename)) {
return filename;
}
if (filename.endsWith(EXT_TAR_GZ)) {
filename = filename.substring(0,
filename.length() - EXT_TAR_GZ.length());
}
return FilenameUtils.getBaseName(filename);
}
}