org.ehoffman.resources.ResourceUtils Maven / Gradle / Ivy
The newest version!
package org.ehoffman.resources;
import java.io.ByteArrayOutputStream;
import java.io.Closeable;
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.net.JarURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Using the classpath as a filesystem. Usually via temp dirs.
*
* @author rex
*/
public final class ResourceUtils {
private static final String JBOSS_VFS_VIRTUAL_CLASSNAME = "org.jboss.vfs.VirtualFile";
private static final int BUFFER_SIZE_4K = 4096;
private static final Logger LOGGER = LoggerFactory.getLogger(ResourceUtils.class);
private static final String ERROR_COPYING_FILE = "error copying file";
private ResourceUtils() {
}
public static boolean copyFile(final File toCopy, final File destFile, final boolean overwrite) {
try {
if (destFile.exists()) {
if (!overwrite) {
return true;
}
} else {
destFile.createNewFile();
}
return ResourceUtils.copyStream(new FileInputStream(toCopy), new FileOutputStream(destFile));
} catch (final FileNotFoundException e) {
LOGGER.error("error creating file to copy in to", e);
} catch (final IOException e) {
LOGGER.error(ERROR_COPYING_FILE, e);
}
return false;
}
private static boolean copyFilesRecusively(final File toCopy, final File destDir, final boolean overwrite) {
if (!destDir.exists() && !destDir.mkdir()) {
return false;
}
if (!toCopy.isDirectory()) {
return ResourceUtils.copyFile(toCopy, new File(destDir, toCopy.getName()), overwrite);
} else {
for (final File child : toCopy.listFiles()) {
File newDestDir = destDir;
if (child.isDirectory()) {
newDestDir = new File(destDir, child.getName());
}
if (!ResourceUtils.copyFilesRecusively(child, newDestDir, overwrite)) {
return false;
}
}
}
return true;
}
private static String removeStart(final String value, final String potentialPrefix) {
if (value.startsWith(potentialPrefix)) {
return value.substring(potentialPrefix.length());
}
return value;
}
public static boolean copyJarResourcesRecursively(final File destDir, final JarURLConnection jarConnection,
final boolean overwrite) throws IOException {
final JarFile jarFile = jarConnection.getJarFile();
for (final Enumeration e = jarFile.entries(); e.hasMoreElements();) {
final JarEntry entry = e.nextElement();
if (entry.getName().startsWith(jarConnection.getEntryName())) {
String filename = removeStart(entry.getName(), jarConnection.getEntryName());
if (filename.endsWith("/")) {
filename = filename.substring(0, filename.length() - 1);
}
if (filename != null && !filename.isEmpty()) {
final File f = new File(destDir, filename).getAbsoluteFile();
if (!entry.isDirectory()) {
InputStream entryInputStream = null;
try {
entryInputStream = jarFile.getInputStream(entry);
if (!ResourceUtils.copyStream(entryInputStream, f, overwrite)) {
return false;
}
} finally {
closeQuietly(entryInputStream);
}
} else {
if (!ResourceUtils.ensureDirectoryExists(f)) {
throw new IOException("Could not create directory: " + f.getAbsolutePath() + " for file " + filename);
}
}
}
}
}
return true;
}
public static File getHomeFolder() {
try {
final String homedirpath = System.getProperty("user.home");
if (homedirpath == null) {
return null;
}
final File homedir = new File(homedirpath).getAbsoluteFile();
if (homedir.exists()) {
return homedir;
} else {
return null;
}
} catch (final SecurityException e) {
return null;
}
}
public static boolean isHomeFolderWritable() {
final File home = getHomeFolder();
return home != null && home.canWrite();
}
public static File getWriteableTempDir() {
try {
final File tempdir = new File(File.createTempFile("testGetIrradiance", "test")
.getAbsoluteFile().getParent().toString());
return tempdir;
} catch (final IOException e) {
return null;
} catch (final SecurityException e) {
return null;
}
}
static File getLongLivedWritableDirIfPossible() {
File destFile = null;
if (isHomeFolderWritable()) {
return getHomeFolder();
}
if (destFile == null) {
destFile = getWriteableTempDir();
}
return destFile;
}
/**
*
* @param originUrl
* @param dirName
* a directory to create as a root to copy the originUrls to. The directory name is meant to be a simple single dir.
* that will likely end up in the users home dir if possible, or as a folder in a temp directory otherwise.
*
* @return File root dir where resources end up or null;
*/
public static File ensureResourcesAreAvailable(final URL originUrl, final String dirName, final boolean overwrite) {
final File destFile = getLongLivedWritableDirIfPossible();
if (destFile != null && copyResourcesRecursively(originUrl, destFile, overwrite)) {
return destFile;
} else {
return null;
}
}
public static boolean copyResourcesRecursively(final URL originUrl, final File destination, final boolean overwrite) {
try {
LOGGER.info("Attempting to copy URL :" + originUrl);
final URLConnection urlConnection = originUrl.openConnection();
if (urlConnection instanceof JarURLConnection) {
return ResourceUtils.copyJarResourcesRecursively(destination, (JarURLConnection) urlConnection, overwrite);
} else if (urlConnection.getContent().getClass().getName().equals(JBOSS_VFS_VIRTUAL_CLASSNAME)) {
return ResourceUtils.copyFilesRecusively(JbossVitualFileSystemWTFWorkAround.fixJbossesScrewUp(urlConnection),
destination, overwrite);
} else {
return ResourceUtils.copyFilesRecusively(new File(originUrl.getPath()), destination, overwrite);
}
} catch (final IOException e) {
LOGGER.error(ERROR_COPYING_FILE, e);
}
return false;
}
private static boolean copyStream(final InputStream is, final File f, final boolean overwrite) {
if (!overwrite && f.exists()) {
return true;
}
try {
f.createNewFile();
return ResourceUtils.copyStream(is, new FileOutputStream(f));
} catch (final FileNotFoundException e) {
LOGGER.error(ERROR_COPYING_FILE, e);
} catch (final IOException e) {
LOGGER.error(ERROR_COPYING_FILE, e);
}
return false;
}
/**
* Reads all bytes from an input stream into a byte array.
* Does not close the stream.
* @param input stream read from
* @return a byte array containing all the bytes from the stream
* @throws IOException
*/
public static byte[] toByteArray(final InputStream input) throws IOException {
final ByteArrayOutputStream out = new ByteArrayOutputStream();
copyStream(input, out);
return out.toByteArray();
}
private static boolean copyStream(final InputStream is, final OutputStream os) {
try {
final byte[] buf = new byte[BUFFER_SIZE_4K];
int len = 0;
while ((len = is.read(buf)) > 0) {
os.write(buf, 0, len);
}
return true;
} catch (final IOException e) {
LOGGER.error(ERROR_COPYING_FILE, e);
} finally {
closeQuietly(is);
closeQuietly(os);
}
return false;
}
private static boolean ensureDirectoryExists(final File f) {
return (f.exists() && f.isDirectory()) || f.mkdirs();
}
private static void closeQuietly(final Closeable closeable) {
if (closeable != null) {
try {
closeable.close();
} catch (final IOException e) {
LOGGER.warn("Could not close cleanly", e);
}
}
}
public static boolean deleteRecursively(final File root) {
if (root != null && root.exists()) {
if (root.isDirectory()) {
final File[] children = root.listFiles();
if (children != null) {
for (int i = 0; i < children.length; i++) {
deleteRecursively(children[i]);
}
}
}
return root.delete();
}
return false;
}
}