/*
* JBoss, Home of Professional Open Source.
* Copyright 2013, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.as.patching;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.zip.ZipFile;
import org.jboss.as.patching.logging.PatchLogger;
import org.wildfly.common.Assert;
/**
* @author Emanuel Muckenhuber
* @author Brian Stansberry (c) 2012 Red Hat Inc.
* @author <a href="http://jmesnil/net/">Jeff Mesnil</a> (c) 2012 Red Hat Inc
*/
public class IoUtils {
public static byte[] NO_CONTENT = new byte[0];
private static final int DEFAULT_BUFFER_SIZE = 65536;
/**
* Copy input stream to output stream and close them both
*
* @param is input stream
* @param os output stream
*
* @throws IOException for any error
*/
public static void copyStreamAndClose(InputStream is, OutputStream os) throws IOException {
try {
copyStream(is, os, DEFAULT_BUFFER_SIZE);
// throw an exception if the close fails since some data might be lost
is.close();
os.close();
}
finally {
// ...but still guarantee that they're both closed
safeClose(is);
safeClose(os);
}
}
/**
* Copy input stream to output stream without closing streams. Flushes output stream when done.
*
* @param is input stream
* @param os output stream
*
* @throws IOException for any error
*/
public static void copyStream(InputStream is, OutputStream os) throws IOException {
copyStream(is, os, DEFAULT_BUFFER_SIZE);
}
/**
* Copy input stream to output stream without closing streams. Flushes output stream when done.
*
* @param is input stream
* @param os output stream
* @param bufferSize the buffer size to use
*
* @throws IOException for any error
*/
private static void copyStream(InputStream is, OutputStream os, int bufferSize)
throws IOException {
Assert.checkNotNullParam("is", is);
Assert.checkNotNullParam("os", os);
byte[] buff = new byte[bufferSize];
int rc;
while ((rc = is.read(buff)) != -1) os.write(buff, 0, rc);
os.flush();
}
public static void copyFile(File sourceFile, File targetFile) throws IOException {
if (sourceFile.isDirectory()) {
copyDir(sourceFile, targetFile);
} else {
File parent = targetFile.getParentFile();
if (!parent.exists()) {
if (!parent.mkdirs()) {
throw PatchLogger.ROOT_LOGGER.cannotCreateDirectory(parent.getAbsolutePath());
}
}
try {
Files.copy(sourceFile.toPath(), targetFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
throw PatchLogger.ROOT_LOGGER.cannotCopyFiles(sourceFile.getAbsolutePath(), targetFile.getAbsolutePath(),
e.getMessage(), e);
}
}
}
private static void copyDir(File sourceDir, File targetDir) throws IOException {
if (targetDir.exists()) {
if (!targetDir.isDirectory()) {
throw PatchLogger.ROOT_LOGGER.notADirectory(targetDir.getAbsolutePath());
}
} else if (!targetDir.mkdirs()) {
throw PatchLogger.ROOT_LOGGER.cannotCreateDirectory(targetDir.getAbsolutePath());
}
File[] children = sourceDir.listFiles();
if (children != null) {
for (File child : children) {
copyFile(child, new File(targetDir, child.getName()));
}
}
}
public static byte[] copy(final InputStream is, final File target) throws IOException {
if(! target.getParentFile().exists()) {
target.getParentFile().mkdirs(); // Hmm
}
try (final OutputStream os = new FileOutputStream(target)){
return HashUtils.copyAndGetHash(is, os);
} catch (IOException e) {
throw PatchLogger.ROOT_LOGGER.cannotCopyFiles(is.toString(), target.getAbsolutePath(),
e.getMessage(), e);
}
}
public static byte[] copy(File source, File target) throws IOException {
try (final FileInputStream is = new FileInputStream(source)){
return copy(is, target);
}
}
public static void safeClose(final Closeable closeable) {
if(closeable != null) {
try {
closeable.close();
} catch (IOException e) {
//
}
}
}
public static void safeClose(final ZipFile closeable) {
if(closeable != null) {
try {
closeable.close();
} catch (IOException e) {
//
}
}
}
public static boolean recursiveDelete(File root) {
if (root == null) {
return true;
}
boolean ok = true;
if (root.isDirectory()) {
final File[] files = root.listFiles();
for (File file : files) {
ok &= recursiveDelete(file);
}
return ok && (root.delete() || !root.exists());
} else {
ok &= root.delete() || !root.exists();
}
return ok;
}
public static File mkdir(File parent, String... segments) throws IOException {
File dir = parent;
for (String segment : segments) {
dir = new File(dir, segment);
}
dir.mkdirs();
return dir;
}
/**
* Return a new File object based on the baseDir and the segments.
*
* This method does not perform any operation on the file system.
*/
public static File newFile(File baseDir, String... segments) {
File f = baseDir;
for (String segment : segments) {
f = new File(f, segment);
}
return f;
}
}