package com.gorillalogic.cloud.ideversion; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; 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.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.util.ArrayList; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; public class FileUtils { private static final String TEMP_DIR_PREFIX = "cloud"; private static final int BUFFER_SIZE = 4096; private FileUtils() { } /** * Read the given file with UTF-8 encoding into a string and return it. * * @param f * the file to be read * @return the contents as text * @throws IOException */ public static String readFile(File f) throws FileNotFoundException, IOException { return readStream(new FileInputStream(f)); } /** * Read the given input stream with UTF-8 encoding into a string and return it. * * @param in * the input stream to be read * @return the contents as text * @throws IOException */ public static String readStream(InputStream in) throws IOException { StringBuilder sb = new StringBuilder(); String line = null; BufferedReader reader = new BufferedReader(new InputStreamReader(in, "UTF-8")); while ((line = reader.readLine()) != null) { sb.append(line).append('\n'); } return (sb.length() > 0 ? sb.substring(0, sb.length() - 1) : ""); } /** * Write the given contents with UTF-8 encoding to the given file. * * @param f * the file to be written * @param contents * the contents to be written * @throws IOException */ public static void writeFile(File f, String contents) throws IOException { Writer out = new OutputStreamWriter(new FileOutputStream(f), "UTF-8"); try { out.write(contents); } finally { out.close(); } } /** * Write the binary input stream to the given file. * * @param f * the file to be written * @param in * the contents * @throws IOException */ public static void writeFile(File f, InputStream in) throws IOException { byte[] buf = new byte[BUFFER_SIZE]; try { OutputStream out = new FileOutputStream(f); try { int len; while ((len = in.read(buf)) != -1) { out.write(buf, 0, len); } } finally { out.close(); } } finally { in.close(); } } /** * Remote the extension (if it exists) from the given filename and return the trimmed filename. * * @param filename * the filename * @param ext * the extension to be removed * @return the filename trimmed of the extension */ public static String removeExt(String filename, String ext) { if (filename != null && filename.toLowerCase().endsWith(ext)) { return filename.substring(0, filename.length() - ext.length()); } return filename; } /** * Delete the given dir and recursively delete all of its children. * * @param dir * the folder to be deleted * @throws IOException */ public static void deleteDir(File dir) throws IOException { for (File f : dir.listFiles()) { if (f.isDirectory()) { deleteDir(f); } else { f.delete(); } } dir.delete(); } /** * Find a file by filename in the given directory (does not search recursively). NOTE: search is * case-insensitive on filename. * * @param filename * the filename to search for * @param dir * the search directory * @return the file if found, otherwise null */ public static File findFile(String filename, File dir) { if (dir != null && dir.isDirectory()) { for (File f : dir.listFiles()) { if (f.getName().equalsIgnoreCase(filename)) { return f; } } } return null; } /** * Make the given folder (and any parent folders), throws an {@link IOException} on failure. * * @param dir * the folder * @throws IOException */ public static void makeDir(File dir) throws IOException { makeDir(dir, null); } /** * Make the given folder (and any parent folders), throws an {@link IOException} with the error * message on failure. * * @param dir * the folder * @param msg * the error message * @throws IOException */ public static void makeDir(File dir, String msg) throws IOException { if (dir == null) { throw new IOException((msg != null ? msg : "dir") + " is null"); } else if (!dir.exists()) { boolean success = dir.mkdirs(); if (!success) { throw new IOException("Failed to make " + (msg != null ? msg : "dir") + ": " + dir.getAbsolutePath()); } } else if (!dir.isDirectory()) { throw new IOException((msg != null ? msg : "dir") + " not a folder: " + dir.getAbsolutePath()); } } /** * Validate the given file (is not null, exists, and is actually a file), throws an * {@link IOException} with the error message on failure. * * @param f * the file * @param msg * the error message * @throws IOException */ public static void checkFile(File f, String msg) throws IOException { if (f == null) { throw new IOException((msg != null ? msg : "file") + " is null"); } else if (!f.exists()) { throw new IOException((msg != null ? msg : "file") + " not found: " + f.getAbsolutePath()); } else if (!f.isFile()) { throw new IOException((msg != null ? msg : "file") + " not a file: " + f.getAbsolutePath()); } } /** * Cleanup all child folders in the main temp dir. * * @throws IOException */ public static void cleanup() throws IOException { File dummy = File.createTempFile("dummy", null); dummy.deleteOnExit(); for (File f : dummy.getParentFile().listFiles()) { if (f.isDirectory() && f.getName().startsWith(TEMP_DIR_PREFIX)) { FileUtils.deleteDir(f); } } } /** * Create a child temp folder inside the main temp dir. * * @return the folder * @throws IOException */ public static File tempDir() throws IOException { final File dir = File.createTempFile(TEMP_DIR_PREFIX, Long.toString(System.nanoTime())); if (!dir.delete()) { throw new IOException("failed to delete file: " + dir.getAbsolutePath()); } if (!dir.mkdir()) { throw new IOException("failed to create dir: " + dir.getAbsolutePath()); } return dir; } /** * Create a temp file with the given contents in the given folder. * * @param filename * the temp file to be created * @param contents * the contents * @param dir * the folder * @return the temp file * @throws IOException */ public static File tempFile(String filename, String contents, File dir) throws IOException { final File tmp = new File(dir, filename); FileUtils.writeFile(tmp, contents); return tmp; } /** * Print all the files in the given folder and recursively print all its children too. * * @param dir * the folder * @throws IOException */ public static String printDir(File dir) throws IOException { StringBuilder sb = new StringBuilder(); sb.append(dir.getAbsolutePath()); if (dir.isDirectory()) { for (File f : dir.listFiles()) { sb.append('\n').append(printDir(f)); } } return sb.toString(); } /** * create a zip file of the contents of the folder, optionally including the folder itself. * * if "includeDirInZip" is true, the specified directory - one level only - will be included * in the zip file, i.e. all entry paths will begin with the directory name. For example, suppose * the "dir" is /home/user/banana and contains two files, "apple.txt" and "orange.txt". * If "includeDirInZip" is false, the zip file will contain two entries, "apple.txt" and "orange.txt". * If "includeDirInZip" is true, the zip file will contain three entries, "banana" (a directory), and * "banana/apple.txt" and "banana/orange.txt". * * @param dir * the folder * @param includeDirInZip * if true, include the target directory in the zip file * @return the zip file * @throws IOException */ public static File zipDirectory(File dir, boolean includeDirInZip, boolean includeHidden) throws IOException { return zipDirectory(dir, includeDirInZip, includeHidden, null); } /** * create a zip file of the contents of the folder, optionally including the folder itself, with optional filter by Extensions to include * * if "includeDirInZip" is true, the specified directory - one level only - will be included * in the zip file, i.e. all entry paths will begin with the directory name. For example, suppose * the "dir" is /home/user/banana and contains two files, "apple.txt" and "orange.txt". * If "includeDirInZip" is false, the zip file will contain two entries, "apple.txt" and "orange.txt". * If "includeDirInZip" is true, the zip file will contain three entries, "banana" (a directory), and * "banana/apple.txt" and "banana/orange.txt". * * @param dir * the folder * @param includeDirInZip * if true, include the target directory in the zip file * @param excludeExtensions * a list of file extensions to include; if null, all files will be included * @return the zip file * @throws IOException */ public static File zipDirectory(File dir, boolean includeDirInZip, boolean includeHidden, List<String> extFilter) throws IOException { if (dir==null) { throw new IOException("zipDirectory was passed a null directory to zip"); } File outputDir=tempDir(); String dirName=dir.getName(); File zipFile = new File(outputDir, dirName + ".zip"); FileOutputStream dest = new FileOutputStream(zipFile); ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest)); BufferedInputStream origin = null; try { //out.setMethod(ZipOutputStream.DEFLATED); byte data[] = new byte[BUFFER_SIZE]; // get a list of files from current directory List<String> files = getAllFilesInDir(true, dir, includeHidden, null); for (String file : files) { if(extFilter != null && !extFilter.contains(getExtFromFileName(file))) { System.out.println("zipDirectory: " + file + " excluded by extension"); continue; } File ff=new File(dir, file); if(!ff.exists()) { System.out.println("zipDirectory: " + file + " no longer exists...."); continue; } if (includeDirInZip) { file = dir.getName() + "/" + file; } System.out.println("zipDirectory: adding " + file); FileInputStream fi = new FileInputStream(ff); ZipEntry entry = new ZipEntry(file); out.putNextEntry(entry); if (!ff.isDirectory()) { try { origin = new BufferedInputStream(fi, BUFFER_SIZE); int count; while((count = origin.read(data, 0, BUFFER_SIZE)) != -1) { out.write(data, 0, count); } } finally { origin.close(); } } } } finally { if (out!=null) { out.close(); } } return zipFile; } // relative filenames private static List<String> getAllFilesInDir(boolean traverseSubDirs, File dir, boolean includeHidden, String prefix){ List<String> files = new ArrayList<String>(); String fileNames[] = dir.list(); for (String fileName : fileNames) { File currentFile = new File(dir, fileName); if (currentFile.isHidden() && !includeHidden) { continue; } if(currentFile.isDirectory()) { if (traverseSubDirs){ String pfx; if (prefix==null || prefix.length()==0) { pfx=fileName; } else { pfx = prefix + "/" + fileName; } files.addAll(getAllFilesInDir(true, currentFile, includeHidden, pfx)); } } else { String fullname=fileName; if (prefix!=null && prefix.length()>0) { fullname = prefix + "/" + fileName; } files.add(fullname); } } return files; } public static String getExtFromFileName(String name) { name = new File(name).getName(); return name.substring(name.lastIndexOf(".") + 1); } }