package ilarkesto.io; import ilarkesto.io.zip.Deflater; import ilarkesto.io.zip.ZipEntry; import ilarkesto.io.zip.ZipFile; import ilarkesto.io.zip.ZipOutputStream; import java.awt.Graphics2D; import java.awt.Image; import java.awt.image.BufferedImage; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileFilter; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.RandomAccessFile; import java.io.Reader; import java.io.StringReader; import java.io.UnsupportedEncodingException; import java.io.Writer; import java.net.HttpURLConnection; import java.net.InetAddress; import java.net.MalformedURLException; import java.net.Socket; import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; import java.net.UnknownHostException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Collection; import java.util.Enumeration; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Properties; import javax.imageio.ImageIO; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLSession; import javax.swing.Icon; import javax.swing.ImageIcon; /** * Set of static methods to easy work with Streams or Images */ public abstract class IO { public static final String MD5 = "MD5"; public static final String SHA1 = "SHA-1"; public static final int CR_INT = 13; public static final char CR = (char) CR_INT; public static final String ISO_LATIN_1 = "ISO-8859-1"; public static final String UTF_8 = "UTF-8"; private static LinkedList<Properties> properties = new LinkedList<Properties>(); private static LinkedList<File> propertiesFiles = new LinkedList<File>(); public static long getSize(File file) { if (file.isFile()) return file.length(); if (file.isDirectory()) { long size = 0; File[] subfiles = file.listFiles(); if (subfiles != null) { for (File f : subfiles) { size += getSize(f); } } return size; } return 0; } public static File getFirstExistingFile(File... files) { for (File file : files) { if (file.exists()) return file; } return null; } public static File getFirstExistingFile(String... filePaths) { for (String path : filePaths) { File file = new File(path); if (file.exists()) return file; } return null; } public static String getFirstExistingFilePath(String... filePaths) { for (String path : filePaths) { if (new File(path).exists()) return path; } return null; } public static byte[] hash(String algorithm, byte[] input) { MessageDigest md; try { md = MessageDigest.getInstance(algorithm); } catch (NoSuchAlgorithmException ex) { throw new RuntimeException(ex); } md.reset(); md.update(input); return md.digest(); } public static byte[] hash(String algorithm, InputStream in) { MessageDigest md; try { md = MessageDigest.getInstance(algorithm); } catch (NoSuchAlgorithmException ex) { throw new RuntimeException(ex); } md.reset(); byte[] block = new byte[1000]; try { while (true) { int amountRead; amountRead = in.read(block); if (amountRead == -1) { break; } md.update(block, 0, amountRead); } } catch (IOException ex) { throw new RuntimeException(ex); } return md.digest(); } public static byte[] hash(String algorithm, File file) { BufferedInputStream in; try { in = new BufferedInputStream(new FileInputStream(file)); } catch (FileNotFoundException ex) { throw new RuntimeException(ex); } byte[] hash = hash(algorithm, in); close(in); return hash; } public static String[] getFilenames(File... files) { if (files == null) return null; String[] names = new String[files.length]; for (int i = 0; i < files.length; i++) { names[i] = files[i].getName(); } return names; } public static void process(String path, FileProcessor processor) { process(new File(path), processor); } public static void process(File root, FileProcessor processor) { if (root.isDirectory()) { boolean continu = processor.onFolderBegin(root); if (!continu) return; for (File file : root.listFiles()) { process(file, processor); if (processor.isAbortRequested()) return; } processor.onFolderEnd(root); } else { processor.onFile(root); } } public static List<File> findFiles(File root, FileFilter filter) { List<File> ret = new LinkedList<File>(); File[] files = root.listFiles(); if (files != null) { for (File file : files) { if (filter.accept(file)) ret.add(file); if (file.isDirectory()) { ret.addAll(findFiles(file, filter)); } } } return ret; } public static File findFile(File root, FileFilter filter) { File[] files = root.listFiles(); if (files == null) return null; for (File file : files) { if (filter.accept(file)) return file; if (file.isDirectory()) { File f = findFile(file, filter); if (f != null) return f; } } return null; } public static interface FileProcessor { boolean onFolderBegin(File folder); void onFolderEnd(File folder); void onFile(File file); boolean isAbortRequested(); } public static String toHexString(byte[] data) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < data.length; i++) { String s = Integer.toHexString(data[i]); if (s.length() == 1) { sb.append('0').append(s); } else if (s.length() == 8) { sb.append(s.substring(6)); } else { sb.append(s); } } return sb.toString(); } public static void closeQuiet(OutputStream out) { try { out.close(); } catch (IOException ex) {} } public static void closeQuiet(Socket socket) { try { socket.close(); } catch (IOException ex) {} } public static void close(Socket socket) { try { socket.close(); } catch (IOException ex) { throw new RuntimeException(ex); } } public static void close(InputStream in) { if (in == null) return; try { in.close(); } catch (IOException ex) { throw new RuntimeException(ex); } } public static void close(OutputStream out) { if (out == null) return; try { out.close(); } catch (IOException ex) { throw new RuntimeException(ex); } } public static void close(Writer out) { if (out == null) return; try { out.close(); } catch (IOException ex) { throw new RuntimeException(ex); } } public static void closeQuiet(Writer out) { if (out == null) return; try { out.close(); } catch (IOException ex) {} } public static void close(Reader in) { if (in == null) return; try { in.close(); } catch (IOException ex) { throw new RuntimeException(ex); } } public static void closeQuiet(Reader in) { if (in == null) return; try { in.close(); } catch (IOException ex) {} } public static void createDirectory(String path) { createDirectory(new File(path)); } public static void createDirectory(File dir) { if (dir.exists()) { if (dir.isDirectory()) return; throw new RuntimeException("A file already exists: " + dir.getPath()); } if (!dir.mkdirs()) throw new RuntimeException("Failed to create directory: " + dir.getPath()); } public static String getFileExtension(String filename) { int idx = filename.lastIndexOf('.'); if (idx < 0 || idx == filename.length() - 1) return filename; return filename.substring(idx + 1); } public static String getFileMimeType(String filename) { return "application/" + getFileExtension(filename); } public static void move(File from, File to) { move(from, to, false); } public static void move(File from, File to, boolean overwrite) { if (to.exists()) { if (!overwrite) throw new RuntimeException("Moving file " + from + " to " + to + " failed. File already exists."); delete(to); } createDirectory(to.getParentFile()); if (from.renameTo(to)) return; copyFile(from, to); delete(from); } public static boolean isHttpAvailable() { try { downloadUrl("http://www.google.com", null, null); } catch (Exception e) { return false; } return true; } public static String getHostName() { String[] hostnames = getHostNames(); if (hostnames.length == 0) return null; if (hostnames.length == 1) return hostnames[0]; for (int i = 0; i < hostnames.length; i++) { if (!"localhost".equals(hostnames[i])) return hostnames[i]; } return hostnames[0]; } public static String[] getHostNames() { String localhostName; try { localhostName = InetAddress.getLocalHost().getHostName(); } catch (UnknownHostException ex) { throw new RuntimeException(ex); } InetAddress ia[]; try { ia = InetAddress.getAllByName(localhostName); } catch (UnknownHostException ex) { throw new RuntimeException(ex); } String[] sa = new String[ia.length]; for (int i = 0; i < ia.length; i++) { sa[i] = ia[i].getHostName(); } return sa; } public static URLConnection post(URL url, Map<String, String> parameters, String encoding, String username, String password) throws IOException { StringBuffer sb = null; if (parameters != null) { for (Map.Entry<String, String> entry : parameters.entrySet()) { if (sb == null) { sb = new StringBuffer(); } else { sb.append("&"); } sb.append(URLEncoder.encode(entry.getKey(), UTF_8)); sb.append("="); sb.append(URLEncoder.encode(entry.getValue(), UTF_8)); } } if (sb == null) sb = new StringBuffer(); URLConnection connection = url.openConnection(); if (username != null) { connection.setRequestProperty("Authorization", "Basic " + Base64.encodeBytes((username + ":" + password).getBytes())); } connection.setDoOutput(true); PrintWriter out = new PrintWriter(new OutputStreamWriter(connection.getOutputStream(), encoding)); out.println(sb.toString()); out.println(); close(out); return connection; } public static String postAndGetResult(String url, Map<String, String> parameters, String encoding, String username, String password) { try { return postAndGetResult(new URL(url), parameters, encoding, username, password); } catch (MalformedURLException ex) { throw new RuntimeException(ex); } catch (IOException ex) { throw new RuntimeException(ex); } } public static String postAndGetResult(URL url, Map<String, String> parameters, String encoding, String username, String password) throws IOException { URLConnection connection = post(url, parameters, encoding, username, password); encoding = connection.getContentEncoding(); if (encoding == null) encoding = UTF_8; return readToString(connection.getInputStream(), encoding); } public static int httpPOST(String url, String username, String password, InputStream body, OutputStream response) { return httpRequest("POST", url, username, password, body, response); } public static int httpDELETE(String url, String username, String password, OutputStream response) { return httpRequest("DELETE", url, username, password, null, response); } public static int httpRequest(String method, String url, String username, String password, InputStream body, OutputStream response) { URL javaUrl; try { javaUrl = new URL(url); } catch (MalformedURLException ex) { throw new RuntimeException("Malformed URL: " + url, ex); } HttpURLConnection connection; try { connection = (HttpURLConnection) javaUrl.openConnection(); connection.setRequestMethod(method); } catch (IOException ex) { throw new RuntimeException("Opening HTTP URL failed.", ex); } if (username != null) { // write auth header String credential = username; if (password != null) credential += ":" + password; String encodedCredential = Base64.encodeBytes(credential.getBytes()); connection.setRequestProperty("Authorization", "Basic " + encodedCredential); } if (body != null) { // write body if we're doing POST or PUT connection.setDoOutput(true); try { copyData(body, connection.getOutputStream()); } catch (IOException ex) { throw new RuntimeException("Writing HTTP request data failed.", ex); } } // do request try { connection.connect(); } catch (IOException ex) { throw new RuntimeException(ex); } int responseCode; try { responseCode = connection.getResponseCode(); } catch (IOException ex) { throw new RuntimeException("Reading HTTP response code failed.", ex); } // pipe response if (response != null) { try { copyData(connection.getInputStream(), response); } catch (IOException ex) { throw new RuntimeException("Reading HTTP response failed.", ex); } finally { connection.disconnect(); } } // cleanup connection.disconnect(); return responseCode; } public static URL getResource(String resourceName) { return IO.class.getClassLoader().getResource(resourceName); } public static boolean existResource(String resourceName) { return getResource(resourceName) != null; } public static Icon getIcon(String resourceName) { return new ImageIcon(getResource(resourceName)); } public static void appendLine(String file, String line) throws IOException { File f = new File(file); if (!f.exists()) createDirectory(f.getParentFile()); PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(f, true))); out.println(line); out.close(); } public static boolean isFinished(Process p) { try { p.exitValue(); } catch (IllegalThreadStateException e) { return false; } return true; } public static void write(byte[] data, File file, long position) { try { RandomAccessFile f = new RandomAccessFile(file, "rw"); f.seek(position); f.write(data); f.close(); } catch (IOException ex) { throw new RuntimeException(ex); } } public static byte[] readBytes(File file, int offset, int size) { RandomAccessFile f; try { f = new RandomAccessFile(file, "r"); f.seek(offset); } catch (IOException ex) { throw new RuntimeException(ex); } byte[] data = new byte[size]; try { f.readFully(data, 0, size); f.close(); return data; } catch (IOException ex) { throw new RuntimeException(ex); } } public static void write2Bytes(OutputStream out, int bytes) throws IOException { int high = bytes / 0x100; int low = bytes - high * 0x100; out.write(high); out.write(low); } public static int read4Bytes(InputStream in) throws IOException { int value = 0; int i; i = in.read(); if (i < 0) throw new IOException("Unexpected end of file."); value += 0x01000000 * i; i = in.read(); if (i < 0) throw new IOException("Unexpected end of file."); value += 0x010000 * i; i = in.read(); if (i < 0) throw new IOException("Unexpected end of file."); value += 0x0100 * i; i = in.read(); if (i < 0) throw new IOException("Unexpected end of file."); value += i; return value; } public static int read3Bytes(InputStream in) throws IOException { int value = 0; int i; i = in.read(); if (i < 0) throw new IOException("Unexpected end of file."); value += 0x010000 * i; i = in.read(); if (i < 0) throw new IOException("Unexpected end of file."); value += 0x0100 * i; i = in.read(); if (i < 0) throw new IOException("Unexpected end of file."); value += i; return value; } public static int read2Bytes(InputStream in) throws IOException { int value = 0; int i; i = in.read(); if (i < 0) throw new IOException("Unexpected end of file."); value += 0x0100 * i; i = in.read(); if (i < 0) throw new IOException("Unexpected end of file."); value += i; return value; } public static List<File> listFiles(File parent) { List<File> ret = new ArrayList<File>(); if (parent == null) return ret; File[] files = parent.listFiles(); if (files == null) return ret; for (File file : files) { ret.add(file); } return ret; } public static List<File> listFiles(File parent, FileFilter filter) { return filterFiles(parent.listFiles(), filter); } public static List<File> filterFiles(File[] files, FileFilter filter) { ArrayList<File> al = new ArrayList<File>(); if (files != null) { for (int i = 0; i < files.length; i++) { if (filter.accept(files[i])) { al.add(files[i]); } } } return al; } public static File[] toFileArray(Collection c) { Object[] oa = c.toArray(); File[] fa = new File[oa.length]; System.arraycopy(oa, 0, fa, 0, fa.length); return fa; } public static int executeProcessAndWait(String command) throws IOException { Process p = Runtime.getRuntime().exec(command); int result; try { result = p.waitFor(); } catch (InterruptedException e) { e.printStackTrace(); return Integer.MIN_VALUE; } return result; } public static void unzip(File zipfile, File destinationDir) { unzip(zipfile, destinationDir, null); } public static void unzip(File zipfile, File destinationDir, UnzipObserver observer) { ZipFile zf; try { zf = new ZipFile(zipfile); } catch (Exception ex) { throw new RuntimeException(ex); } if (observer != null) observer.onFileCountAvailable(zf.size()); try { Enumeration entries = zf.entries(); while (entries.hasMoreElements()) { if (observer != null && observer.isAbortRequested()) return; ZipEntry ze = (ZipEntry) entries.nextElement(); String name = ze.getName(); name = name.replace((char) 129, '\u00FC'); name = name.replace((char) 154, '\u00DC'); name = name.replace((char) 148, '\u00F6'); name = name.replace((char) 153, '\u00D6'); name = name.replace((char) 132, '\u00E4'); name = name.replace((char) 142, '\u00C4'); name = name.replace((char) 225, '\u00DF'); if (ze.isDirectory()) continue; File f = new File(destinationDir.getPath() + "/" + name); if (observer != null) observer.onFileBegin(f); try { createDirectory(f.getParentFile()); BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(f)); InputStream in = zf.getInputStream(ze); copyData(new BufferedInputStream(in), out); out.close(); long lastModified = ze.getTime(); if (lastModified >= 0) setLastModified(f, lastModified); } catch (Exception ex) { if (observer == null) throw new RuntimeException(ex); observer.onFileError(f, ex); } if (observer != null) observer.onFileEnd(f); } } finally { try { zf.close(); } catch (IOException ex) { ex.printStackTrace(); } } } public static void setLastModified(File file, long time) { if (!file.setLastModified(time)) throw new RuntimeException("Settring lastModified on " + file + " failed."); } public static interface UnzipObserver { void onFileCountAvailable(int count); void onFileBegin(File f); void onFileEnd(File f); void onFileError(File f, Throwable ex); boolean isAbortRequested(); } public static void zip(File zipfile, File... files) { zip(zipfile, files, null); } public static void zip(File zipfile, File[] files, FileFilter filter) { zip(zipfile, files, filter, null); } public static void zip(File zipfile, File[] files, FileFilter filter, ZipObserver observer) { if (zipfile.exists()) delete(zipfile); createDirectory(zipfile.getParentFile()); File tempFile = new File(zipfile.getPath() + "~"); try { zip(new FileOutputStream(tempFile), files, filter, observer); } catch (FileNotFoundException ex) { throw new RuntimeException(ex); } if (observer != null && observer.isAbortRequested()) { IO.delete(tempFile); } else { move(tempFile, zipfile); } } public static void zip(OutputStream os, File... files) { zip(os, files, null, null); } public static void zip(OutputStream os, File[] files, FileFilter filter, ZipObserver observer) { ZipOutputStream zipout; try { zipout = new ZipOutputStream(new BufferedOutputStream(os)); zipout.setLevel(Deflater.BEST_COMPRESSION); for (int i = 0; i < files.length; i++) { if (!files[i].exists()) continue; addZipEntry(zipout, "", files[i], filter, observer); } zipout.close(); } catch (Exception ex) { throw new RuntimeException(ex); } } public static void addZipEntry(ZipOutputStream zipout, String zippath, File f, FileFilter filter, ZipObserver observer) throws Exception { if (filter != null && !filter.accept(f)) return; if (observer != null) { if (observer.isAbortRequested()) return; observer.onFileBegin(f); } if (f.isDirectory()) { File[] fa = f.listFiles(); for (int i = 0; i < fa.length; i++) { addZipEntry(zipout, zippath + f.getName() + "/", fa[i], filter, observer); } } else { try { BufferedInputStream in = new BufferedInputStream(new FileInputStream(f)); ZipEntry entry = new ZipEntry(zippath + f.getName()); zipout.putNextEntry(entry); copyData(in, zipout); in.close(); zipout.closeEntry(); } catch (Exception ex) { if (observer == null) { throw ex; } observer.onFileError(f, ex); } } if (observer != null) observer.onFileEnd(f); } public static interface ZipObserver { void onFileBegin(File f); void onFileEnd(File f); void onFileError(File f, Throwable ex); boolean isAbortRequested(); } public static void deleteContents(String folder) { deleteContents(new File(folder)); } public static void deleteContents(File folder) { if (!folder.exists()) return; if (!folder.isDirectory()) throw new RuntimeException("Not a folder: " + folder.getAbsolutePath()); for (File file : folder.listFiles()) { delete(file); } } public static void delete(String file) { delete(new File(file)); } public static void delete(File f) { if (!f.exists()) return; if (f.isDirectory()) { File[] fa = f.listFiles(); for (int i = 0; i < fa.length; i++) { delete(fa[i]); } } if (!f.delete()) { throw new RuntimeException("Deleting file failed: " + f.getPath()); } } @Deprecated public static void writeImage(Image image, String type, String file) throws IOException { File f = new File(file); createDirectory(f.getParentFile()); ImageIO.write(toBufferedImage(image), type, f); } public static void writeImage(Image image, int width, int height, String type, String file) throws IOException { File f = new File(file); createDirectory(f.getParentFile()); ImageIO.write(toBufferedImage(image, width, height), type, f); } public static BufferedImage toBufferedImage(Image img) { if (img instanceof BufferedImage) return (BufferedImage) img; return toBufferedImage(img, img.getWidth(null), img.getHeight(null)); } public static BufferedImage toBufferedImage(Image img, int width, int height) { if (img instanceof BufferedImage) return (BufferedImage) img; BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics2D g = image.createGraphics(); g.drawImage(img, 0, 0, null); g.dispose(); return image; } public static BufferedImage loadImage(File file) { BufferedImage image; try { image = ImageIO.read(file); } catch (IOException ex) { throw new RuntimeException(ex); } if (image == null) throw new RuntimeException("Unsupported image format."); return image; } public static BufferedImage loadImage(byte[] data) { BufferedImage image; try { ByteArrayInputStream in = new ByteArrayInputStream(data); image = ImageIO.read(in); in.close(); } catch (IOException ex) { throw new RuntimeException(ex); } if (image == null) throw new RuntimeException("Unsupported image format."); return image; } public static BufferedImage loadImage(String resourcePath) { try { return ImageIO.read(IO.class.getClassLoader().getResource(resourcePath)); } catch (IOException ex) { throw new RuntimeException(ex); } } public static void saveScaled(BufferedImage image, String type, String file, int maxWidth, int maxHeight) throws IOException { Image scaled = getScaled(image, maxWidth, maxHeight); writeImage(scaled, type, file); } public static void scaleImage(String sourceFile, String destinationFile, String destinationType, int maxWidth, int maxHeight) throws IOException { saveScaled(loadImage(new File(sourceFile)), destinationType, destinationFile, maxWidth, maxHeight); } public static Image getScaled(BufferedImage image, int maxWidth, int maxHeight) { int width = image.getWidth(); int height = image.getHeight(); if (width <= maxWidth && height <= maxHeight) { return image; } if (width > maxWidth) { width = maxWidth; height = height * maxWidth / image.getWidth(); } int h; int w; if (height > maxHeight) { h = maxHeight; w = width * maxHeight / height; } else { h = height; w = width; } return image.getScaledInstance(w, h, Image.SCALE_SMOOTH); } public static Image scaledToWidth(BufferedImage image, int targetWidth) { int width = image.getWidth(); int height = image.getHeight(); if (width == targetWidth) { return image; } width = targetWidth; height = height * targetWidth / image.getWidth(); return image.getScaledInstance(width, height, Image.SCALE_SMOOTH); } public static Image scaledToHeight(BufferedImage image, int targetHeight) { int width = image.getWidth(); int height = image.getHeight(); if (height == targetHeight) { return image; } height = targetHeight; width = width * targetHeight / image.getHeight(); return image.getScaledInstance(width, height, Image.SCALE_SMOOTH); } public static void copyDataToFile(byte[] data, File file) { ByteArrayInputStream in = new ByteArrayInputStream(data); copyDataToFile(in, file); close(in); } public static void copyDataToFile(InputStream is, File file) { copyDataToFile(is, file, null); } public static void copyDataToFile(InputStream is, File dst, CopyObserver observer) { createDirectory(dst.getParentFile()); File tmp = new File(dst.getPath() + "~" + System.currentTimeMillis()); BufferedInputStream in; try { if (is instanceof BufferedInputStream) { in = (BufferedInputStream) is; } else { in = new BufferedInputStream(is); } BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(tmp, false)); copyData(in, out, observer); in.close(); out.close(); } catch (IOException ex) { ex.printStackTrace(); tmp.delete(); throw new RuntimeException(ex); } if (dst.exists()) if (!dst.delete()) { delete(tmp); throw new RuntimeException("Overwriting file '" + dst + "' failed."); } if (!tmp.renameTo(dst)) { IO.delete(tmp); throw new RuntimeException("Moving '" + tmp + "' to '" + dst + "' failed."); } } public static void copyFile(File source, File destination) { if (source.getAbsolutePath().equals(destination.getAbsolutePath())) return; if (source.isDirectory()) { copyFiles(source.listFiles(), destination); return; } FileInputStream in; try { in = new FileInputStream(source); } catch (FileNotFoundException ex) { throw new RuntimeException(ex); } try { copyDataToFile(in, destination); } finally { close(in); } } public static void copyFile(File sourceFile, OutputStream dst) { copyFile(sourceFile.getPath(), dst); } public static void copyFile(String sourceFile, String destinationFile) { FileInputStream in; try { in = new FileInputStream(sourceFile); } catch (FileNotFoundException ex) { throw new RuntimeException("File not found: " + sourceFile, ex); } try { copyDataToFile(in, new File(destinationFile)); } finally { close(in); } } public static void copyFile(String src, OutputStream dst) { BufferedInputStream in; try { in = new BufferedInputStream(new FileInputStream(src)); } catch (FileNotFoundException ex) { throw new RuntimeException(ex); } try { copyData(in, dst); } finally { close(in); } } public static void copyFiles(File[] files, File destinationDir) { copyFiles(files, destinationDir, null); } public static void copyFiles(File[] files, File destinationDir, FileFilter filter) { createDirectory(destinationDir); for (File f : files) { if (filter != null && !filter.accept(f)) continue; if (f.isDirectory()) { copyFiles(f.listFiles(), new File(destinationDir + "/" + f.getName()), filter); } else { copyFile(f, new File(destinationDir + "/" + f.getName())); } } } public static void copyFiles(Collection<File> files, File destinationDir) { copyFiles(files, destinationDir, null); } public static void copyFiles(Collection<File> files, File destinationDir, FileFilter filter) { createDirectory(destinationDir); for (File f : files) { if (filter != null && !filter.accept(f)) continue; if (f.isDirectory()) { copyFiles(f.listFiles(), new File(destinationDir + "/" + f.getName()), filter); } else { copyFile(f, new File(destinationDir + "/" + f.getName())); } } } public static void copyFiles(String[] files, String destinationDir) { createDirectory(destinationDir); for (String file : files) { File f = new File(file); if (f.isDirectory()) { copyFiles(f.listFiles(), new File(destinationDir + "/" + f.getName())); } else { copyFile(file, destinationDir + "/" + f.getName()); } } } public static void copyData(File file, OutputStream out) { BufferedInputStream in; try { in = new BufferedInputStream(new FileInputStream(file)); } catch (FileNotFoundException ex) { throw new RuntimeException(ex); } copyData(in, out); close(in); } public static void copyData(InputStream in, OutputStream out) { copyData(in, out, null); } public static void copyData(InputStream in, OutputStream out, CopyObserver observer) { byte[] block = new byte[1000]; try { while (true) { if (observer != null && observer.isAbortRequested()) return; int amountRead; amountRead = in.read(block); if (amountRead == -1) { break; } out.write(block, 0, amountRead); if (observer != null) observer.dataCopied(amountRead); } out.flush(); } catch (IOException ex) { throw new RuntimeException(ex); } } public interface CopyObserver { boolean isAbortRequested(); void totalSizeDetermined(long bytes); void dataCopied(long bytes); } private static void copyData(InputStream in, OutputStream out, long length) throws IOException { // if (!(in instanceof BufferedInputStream)) in = new // BufferedInputStream(in); // if (!(out instanceof BufferedOutputStream)) out = new // BufferedOutputStream(out); byte[] ba = new byte[(int) length]; for (int i = 0; i < length; i++) { ba[i] = (byte) in.read(); } out.write(ba, 0, (int) length); out.flush(); } public static byte[] readToByteArray(InputStream in) { ByteArrayOutputStream out = new ByteArrayOutputStream(); copyData(in, out); close(in); closeQuiet(out); return out.toByteArray(); } public static byte[] readToByteArray(File file) { ByteArrayOutputStream out = new ByteArrayOutputStream(); copyData(file, out); byte[] data = out.toByteArray(); closeQuiet(out); return data; } public static void readToByteArray(InputStream in, byte[] data) throws IOException { int read = 0; while (read < data.length) { int count = in.read(data); read += count; } } public static String readResource(String name) throws IOException { URL url = IO.class.getClassLoader().getResource(name); if (url == null) throw new IOException("Resource '" + name + "' does not exist."); URLConnection connection = url.openConnection(); return readToString(connection.getInputStream(), UTF_8); } public static void copyResource(String name, String dst) throws IOException { File dstFile = new File(dst); createDirectory(dstFile.getAbsoluteFile().getParentFile()); FileOutputStream out = new FileOutputStream(dst, false); URL url = IO.class.getClassLoader().getResource(name); if (url == null) throw new IOException("Resource '" + name + "' does not exist."); URLConnection connection = url.openConnection(); copyData(connection.getInputStream(), out, connection.getContentLength()); out.close(); } public static void writeFile(String fileName, String data, String charset) { writeFile(new File(fileName), data, charset); } public static void writeFile(File file, String data, String charset) { File parent = file.getParentFile(); if (parent != null) createDirectory(parent); PrintWriter out; try { out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), charset))); } catch (IOException ex) { throw new RuntimeException(ex); } out.print(data); out.close(); } public static void writeText(OutputStream out, String text, String charset) { PrintWriter writer; try { writer = new PrintWriter(new OutputStreamWriter(out, charset)); } catch (UnsupportedEncodingException ex) { throw new RuntimeException(ex); } writer.write(text); writer.flush(); } public static void writeFile(String file, Collection<String> lines) throws IOException { File f = new File(file); createDirectory(f.getParentFile()); BufferedWriter out = new BufferedWriter(new FileWriter(f)); for (String s : lines) { out.write(s); out.write("\n"); } out.close(); } public static List<String> readLines(BufferedReader in) { List<String> ret = new ArrayList<String>(); String line; try { while ((line = in.readLine()) != null) ret.add(line); } catch (IOException ex) { throw new RuntimeException(ex); } return ret; } public static String readToString(InputStream is, String encoding) { try { return readToString(new InputStreamReader(is, encoding)); } catch (UnsupportedEncodingException ex) { throw new RuntimeException(ex); } } public static String readToString(Reader reader) { StringBuffer sb = new StringBuffer(); BufferedReader in; in = new BufferedReader(reader); int ch; try { while ((ch = in.read()) >= 0) { sb.append((char) ch); } } catch (IOException ex) { throw new RuntimeException(ex); } return sb.toString(); } public static byte[] readFileToByteArray(File file) { ByteArrayOutputStream out = new ByteArrayOutputStream(); copyData(file, out); close(out); return out.toByteArray(); } public static String readFile(File file, String encoding) { try { return readToString(new FileInputStream(file), encoding); } catch (FileNotFoundException ex) { throw new RuntimeException(ex); } } public static String readFile(String fileName, String encoding) { return readFile(new File(fileName), encoding); } public static void touch(File f) { File parent = f.getParentFile(); if (parent != null && !parent.exists()) { if (!parent.mkdirs()) throw new RuntimeException("Creating directory failed: " + parent.getPath()); } FileOutputStream out; try { out = new FileOutputStream(f, true); out.close(); } catch (Exception ex) { throw new RuntimeException(ex); } } /** * Loads the contents of a properties file (which has to be in a directory that is in the classpath) into * a Properties-object and returns that. * * @param filename the name of the properties file (e.g. "myname.properties") * @return an object encapsulating the content of the properties file */ public static Properties loadPropertiesFromClasspath(String filename) { Properties p = new Properties(); InputStream in = IO.class.getResourceAsStream("/" + filename); try { p.load(in); } catch (IOException ex) { throw new RuntimeException(ex); } finally { close(in); } return p; } public static Properties loadProperties(String content) { return loadProperties(new StringReader(content)); } public static Properties loadProperties(File f, String encoding) { BufferedInputStream in; try { in = new BufferedInputStream(new FileInputStream(f)); Properties p = loadProperties(in, encoding); in.close(); properties.add(p); propertiesFiles.add(f); return p; } catch (Exception ex) { throw new RuntimeException(ex); } } public static Properties loadProperties(InputStream is, String encoding) { InputStreamReader in; try { in = new InputStreamReader(is, encoding); } catch (UnsupportedEncodingException ex) { throw new RuntimeException(ex); } try { return loadProperties(in); } finally { close(in); } } public static Properties loadProperties(Reader in) { Properties p = new Properties(); try { p.load(in); } catch (IOException ex) { throw new RuntimeException(ex); } return p; } public static Properties loadProperties(URL url, String encoding) throws IOException { if (url == null) { return new Properties(); } URLConnection connection = url.openConnection(); InputStream in = connection.getInputStream(); Properties p = loadProperties(in, encoding); in.close(); return p; } public static void saveLoadedProperties(Properties p, String header) { int index = properties.indexOf(p); File f = index < 0 ? null : (File) propertiesFiles.get(properties.indexOf(p)); if (f == null) throw new RuntimeException("Properties were not loaded via IOTools.loadProperties(File)"); saveProperties(p, header, f); } public static void saveProperties(Properties p, String header, String filepath) { saveProperties(p, header, new File(filepath)); } public static void saveProperties(Properties p, String header, File f) { File parent = f.getParentFile(); if (parent != null) { createDirectory(parent); } try { saveProperties(p, header, new FileOutputStream(f)); } catch (FileNotFoundException ex) { throw new RuntimeException(ex); } } public static void saveProperties(Properties p, String header, OutputStream os) { BufferedOutputStream out; try { out = new BufferedOutputStream(os); p.store(out, header); out.close(); } catch (Exception ex) { throw new RuntimeException(ex); } } public static String toString(Properties p) { ByteArrayOutputStream out = new ByteArrayOutputStream(); saveProperties(p, null, out); return new String(out.toByteArray()); } public static String detectEncoding(byte[] data) { String encoding = UTF_8; BufferedReader in = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(data)), 100); String line; try { line = in.readLine(); } catch (IOException ex) { throw new RuntimeException(ex); } if (line != null) { int idx = line.indexOf("encoding=\""); if (idx > 0) { idx += 10; int endIdx = line.indexOf('"', idx); if (endIdx >= idx) { encoding = line.substring(idx, endIdx); } } } close(in); return encoding; } public static String toString(byte[] data, String encoding) { BufferedReader in; try { in = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(data), encoding)); } catch (UnsupportedEncodingException ex) { throw new RuntimeException(ex); } String s = readToString(in); try { in.close(); } catch (IOException ex) { throw new RuntimeException(ex); } return s; } public static String downloadUrlToString(String url) { return downloadUrlToString(url, null, null); } public static String downloadUrlToString(String url, String username, String password) { BufferedReader in = new BufferedReader(openUrlReader(url, username, password)); String s = IO.readToString(in); close(in); return s; } public static byte[] downloadUrlToByteArray(String url, String username, String password) { BufferedInputStream in = new BufferedInputStream(openUrlInputStream(url, username, password)); byte[] data = readToByteArray(in); close(in); return data; } public static byte[] downloadUrl(String url, String username, String password) { ByteArrayOutputStream out = new ByteArrayOutputStream(); BufferedInputStream in = new BufferedInputStream(openUrlInputStream(url, username, password)); copyData(in, out); close(in); return out.toByteArray(); } public static URLConnection openUrlConnection(String url, String username, String password) { URLConnection connection; try { connection = new URL(url).openConnection(); } catch (Throwable ex) { throw new RuntimeException(ex); } if (username != null) { connection.setRequestProperty("Authorization", "Basic " + Base64.encodeBytes((username + ":" + password).getBytes())); } if (connection instanceof HttpsURLConnection) { HttpsURLConnection sconnection = (HttpsURLConnection) connection; sconnection.setHostnameVerifier(new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }); } return connection; } public static InputStream openUrlInputStream(String url, String username, String password) { try { return openUrlConnection(url, username, password).getInputStream(); } catch (Throwable ex) { throw new RuntimeException(ex); } } public static Reader openUrlReader(String url, String username, String password) { URLConnection connection = openUrlConnection(url, username, password); String encoding = connection.getContentEncoding(); if (encoding == null) encoding = UTF_8; try { return new InputStreamReader(connection.getInputStream(), encoding); } catch (UnsupportedEncodingException ex) { throw new RuntimeException(ex); } catch (IOException ex) { throw new RuntimeException(ex); } } public static void downloadUrlToFile(String url, String file) { downloadUrlToFile(url, file, null); } public static void downloadUrlToFile(String url, String file, CopyObserver observer) { downloadUrlToFile(url, file, null, null, observer); } public static void downloadUrlToFile(String url, String file, String username, String password, CopyObserver observer) { InputStream in; try { URLConnection connection = new URL(url).openConnection(); if (username != null) { connection.setRequestProperty("Authorization", "Basic " + Base64.encodeBytes((username + ":" + password).getBytes())); } connection.connect(); int length = connection.getContentLength(); if (observer != null && length > -1) observer.totalSizeDetermined(length); in = connection.getInputStream(); } catch (Throwable ex) { throw new RuntimeException(ex); } try { copyDataToFile(in, new File(file), observer); } finally { close(in); } } public static class StringInputStream extends InputStream { String s; int len; int index; public StringInputStream(String s) { this.s = s; len = s.length(); } @Override public int read() { return index >= len ? -1 : s.charAt(index++); } } public static class FileList extends ArrayList { public File getFile(int index) { return (File) get(index); } } private static File workDir; public static File getWorkDir() { if (workDir == null) workDir = new File("dummy").getAbsoluteFile().getParentFile(); return workDir; } private static File tempDir; public static File getTempDir() { if (tempDir == null) { try { tempDir = File.createTempFile("dummy", ".tmp").getParentFile(); } catch (IOException ex) { throw new RuntimeException(ex); } } return tempDir; } public static boolean isDirWritable(String dir) { File testfile = new File(dir + "/.writetest.deleteme"); try { touch(testfile); } catch (Throwable ex) { return false; } finally { testfile.delete(); } return true; } public static boolean isFileWritable(File file) { if (file.exists()) return file.canWrite(); try { touch(file); } catch (Throwable ex) { return false; } finally { file.delete(); } return true; } }