/*
* Copyright (c) 2010-2012 Thiago T. Sá
*
* This file is part of CloudReports.
*
* CloudReports is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* CloudReports 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 General Public License for more details.
*
* For more information about your rights as a user of CloudReports,
* refer to the LICENSE file or see <http://www.gnu.org/licenses/>.
*/
package cloudreports.utils;
import java.io.*;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* A helper class that provides utility methods related to files IO.
*
* @author Thiago T. Sá
* @since 1.0
*/
public class FileIO {
/**
* Gets the path to the application's executable.
*
* @return the path to the application's executable.
*/
public static String getPathOfExecutable() {
String baseDirectory = FileIO.class.getProtectionDomain().getCodeSource().getLocation().getPath();
String executableName = baseDirectory.substring(baseDirectory.lastIndexOf('/')+1);
if(baseDirectory.indexOf(executableName) > 0) return baseDirectory.substring(0, baseDirectory.indexOf(executableName));
else return baseDirectory;
}
/**
* Gets a string from a project resource.
*
* @param filePath the path to the resource.
* @return a string loaded from the resource.
*/
public static String readStringFromResource(String filePath) {
ClassLoader classLoader = FileIO.class.getClassLoader();
InputStream resourceStream = classLoader.getResourceAsStream(filePath);
String strResult = null;
try {
strResult = convertStreamToString(resourceStream);
} catch (Exception ex) {
Logger.getLogger(FileIO.class.getName()).log(Level.SEVERE, null, ex);
}
finally {
try {
if(resourceStream != null) resourceStream.close();
} catch (IOException ex) {
Logger.getLogger(FileIO.class.getName()).log(Level.SEVERE, null, ex);
}
}
return strResult;
}
/**
* Writes a string to a file.
*
* @param filePath the path to the output file.
* @param content the string to be written.
* @return <code>true</code> if the operation was successful;
* <code>false</code> otherwise.
*/
public static boolean writeStringToFile(String filePath, String content) {
FileOutputStream out = null;
try {
File file = new File(filePath);
if (file.exists()) {
file.delete();
}
file.createNewFile();
out = new FileOutputStream(file);
out.write(content.getBytes());
return true;
} catch (IOException ex) {
Logger.getLogger(FileIO.class.getName()).log(Level.SEVERE, null, ex);
return false;
}
finally {
try {
if(out != null) out.close();
} catch (IOException ex) {
Logger.getLogger(FileIO.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
/**
* Appends a string to a file.
*
* @param filePath the path to the output file.
* @param content the string to be appended.
* @return <code>true</code> if the operation was successful;
* <code>false</code> otherwise.
*/
public static boolean appendStringToFile(String filePath, String content) {
FileWriter fstream;
BufferedWriter out = null;
try {
fstream = new FileWriter(filePath, true);
out = new BufferedWriter(fstream);
out.write(content);
return true;
} catch (IOException ex) {
Logger.getLogger(FileIO.class.getName()).log(Level.SEVERE, null, ex);
return false;
} finally {
try {
if(out != null) out.close();
} catch (IOException ex) {
Logger.getLogger(FileIO.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
/**
* Reads a byte array from a file.
*
* @param filePath the path to the file.
* @return the byte array if the operation was successful;
* <code>null</code> otherwise.
*/
public static byte[] readBytesFromFile(String filePath) {
InputStream resourceStream = null;
try {
ClassLoader classLoader = FileIO.class.getClassLoader();
resourceStream = classLoader.getResourceAsStream(filePath);
int bufferSize = resourceStream.read(new byte[200000]); //TODO: Set the buffer size dinamically.
byte[] bytes = new byte[bufferSize];
resourceStream = classLoader.getResourceAsStream(filePath);
resourceStream.read(bytes);
return bytes;
} catch (IOException ex) {
Logger.getLogger(FileIO.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
finally {
try {
if(resourceStream != null) resourceStream.close();
} catch (IOException ex) {
Logger.getLogger(FileIO.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
/**
* Writes a byte array into a file.
*
* @param filePath the path to the output file.
* @param content the byte array to be written.
* @return <code>true</code> if the operation was successful;
* <code>false</code> otherwise.
*/
public static boolean writeBytesToFile(String filePath, byte[] content) {
FileOutputStream out = null;
try {
File f = new File(filePath);
if (f.exists()) f.delete();
f.createNewFile();
out = new FileOutputStream(f);
out.write(content);
return true;
} catch (IOException ex) {
Logger.getLogger(FileIO.class.getName()).log(Level.SEVERE, null, ex);
return false;
}
finally {
try {
if(out != null) out.close();
} catch (IOException ex) {
Logger.getLogger(FileIO.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
/**
* Converts a memory stream into a string.
*
* @param is the input stream to be converted.
* @return the resulting string, if the operation was successful;
* <code>null</code> otherwise.
*/
private static String convertStreamToString(InputStream is) {
try {
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line).append("\n");
}
is.close();
return sb.toString();
} catch (IOException ex) {
Logger.getLogger(FileIO.class.getName()).log(Level.SEVERE, null, ex);
return null;
}
}
/**
* List directory contents for a resource folder. Not recursive.
* This is basically a brute-force implementation.
* Works for regular files and also JARs.
*
* @author Greg Briggs
* @param clazz Any java class that lives in the same place as the resources you want.
* @param path Should end with "/", but not start with one.
* @return Just the name of each member item, not the full paths.
* @throws URISyntaxException
* @throws IOException
*/
public static String[] getResourceListing(Class clazz, String path) throws URISyntaxException, IOException {
URL dirURL = clazz.getClassLoader().getResource(path);
if (dirURL != null && dirURL.getProtocol().equals("file")) {
/* A file path: easy enough */
return new File(dirURL.toURI()).list();
}
if (dirURL == null) {
/*
* In case of a jar file, we can't actually find a directory.
* Have to assume the same jar as clazz.
*/
String me = clazz.getName().replace(".", "/")+".class";
dirURL = clazz.getClassLoader().getResource(me);
}
if (dirURL.getProtocol().equals("jar")) {
/* A JAR path */
String jarPath = dirURL.getPath().substring(5, dirURL.getPath().indexOf("!")); //strip out only the JAR file
JarFile jar = new JarFile(URLDecoder.decode(jarPath, "UTF-8"));
Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar
Set<String> result = new HashSet<String>(); //avoid duplicates in case it is a subdirectory
while(entries.hasMoreElements()) {
String name = entries.nextElement().getName();
if (name.startsWith(path)) { //filter according to the path
String entry = name.substring(path.length());
int checkSubdir = entry.indexOf("/");
if (checkSubdir >= 0) {
// if it is a subdirectory, we just return the directory name
entry = entry.substring(0, checkSubdir);
}
result.add(entry);
}
}
return result.toArray(new String[result.size()]);
}
throw new UnsupportedOperationException("Cannot list files for URL "+dirURL);
}
/**
* Removes a directory and all its content recursively.
*
* @param dir the directory to be removed.
* @return <code>true</code> if the operation was successful;
* <code>false</code> otherwise.
*/
public static boolean deleteDirectory(File dir) {
if (dir.isDirectory()) {
String[] children = dir.list();
for (int i=0; i<children.length; i++) {
boolean success = deleteDirectory(new File(dir, children[i]));
if (!success) return false;
}
}
return dir.delete();
}
}