All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.databene.commons.IOUtil Maven / Gradle / Ivy

Go to download

'databene commons' is an open source Java library by Volker Bergmann. It provides extensions to the Java core library by utility classes, abstract concepts and concrete implementations.

There is a newer version: 1.0.11
Show newest version
/*
 * Copyright (C) 2004-2014 Volker Bergmann ([email protected]).
 * All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * http://www.apache.org/licenses/LICENSE-2.0
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.databene.commons;

import org.databene.commons.collection.MapEntry;
import org.databene.commons.converter.ToStringConverter;
import org.databene.commons.file.FileByNameFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.MalformedURLException;
import java.net.URLConnection;
import java.net.URLDecoder;
import java.util.Collection;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import javax.imageio.ImageIO;
import javax.swing.ImageIcon;

/**
 * Provides stream operations.
*
* Created: 17.07.2006 22:17:42 * @since 0.1 * @author Volker Bergmann */ public final class IOUtil { /** The logger. */ private static final Logger LOGGER = LoggerFactory.getLogger(IOUtil.class); private static final String USER_AGENT = "Mozilla/5.0 (Windows; U; Windows NT 5.1; de-DE; rv:1.7.5) Gecko/20041122 Firefox/1.0"; // convenience unchecked-exception operations ---------------------------------------------------------------------- /** * Convenience method that closes a {@link Closeable} if it is not null * and logs possible exceptions without disturbing program execution. * @param closeable the stream to close */ public static void close(Closeable closeable) { if (closeable != null) { try { closeable.close(); } catch (IOException e) { LOGGER.error("Error closing " + closeable, e); } } } public static void closeAll(T... closeables) { if (closeables != null) { Throwable t = null; for (Closeable closeable : closeables) { try { closeable.close(); } catch (IOException e) { LOGGER.error("Error closing " + closeable, e); } catch (Throwable e) { t = e; } } if (t != null) throw new RuntimeException("Error closing resources", t); } } public static > void closeAll(T closeables) { if (closeables != null) { Throwable t = null; for (Closeable closeable : closeables) { try { closeable.close(); } catch (IOException e) { LOGGER.error("Error closing " + closeable, e); } catch (Throwable e) { t = e; } } if (t != null) throw new RuntimeException("Error closing resources", t); } } public static void flush(Flushable flushable) { if (flushable != null) { try { flushable.flush(); } catch (IOException e) { LOGGER.error("Error flushing " + flushable, e); } } } // URI operations -------------------------------------------------------------------------------------------------- public static String localFilename(String uri) { String[] path = uri.split("/"); return path[path.length - 1]; } public static boolean isURIAvailable(String uri) { LOGGER.debug("isURIAvailable({})", uri); boolean available; if (uri.startsWith("string://")) { available = true; } else if (uri.startsWith("http://")) { available = httpUrlAvailable(uri); } else { InputStream stream = null; try { if (uri.startsWith("file:") && !uri.startsWith("file://")) { stream = getFileOrResourceAsStream(uri.substring("file:".length()), false); } else { if (!uri.contains("://")) uri = "file://" + uri; if (uri.startsWith("file://")) stream = getFileOrResourceAsStream(uri.substring("file://".length()), false); } available = (stream != null); } catch (FileNotFoundException e) { available = false; } finally { close(stream); } } LOGGER.debug("isURIAvailable({}) returns {}", uri, available); return available; } public static String getContentOfURI(String uri) throws IOException { return getContentOfURI(uri, SystemInfo.getFileEncoding()); } public static String getContentOfURI(String uri, String encoding) throws IOException { Reader reader = getReaderForURI(uri, encoding); StringWriter writer = new StringWriter(); transfer(reader, writer); return writer.toString(); } public static String[] readTextLines(String uri, boolean includeEmptyLines) throws IOException { ArrayBuilder builder = new ArrayBuilder(String.class, 100); BufferedReader reader = getReaderForURI(uri); String line; while ((line = reader.readLine()) != null) if (line.length() > 0 || includeEmptyLines) builder.add(line); return builder.toArray(); } public static BufferedReader getReaderForURI(String uri) throws IOException { return getReaderForURI(uri, SystemInfo.getFileEncoding()); } public static BufferedReader getReaderForURI(String uri, String defaultEncoding) throws IOException { if (uri.startsWith("string://")) return new BufferedReader(new StringReader(uri.substring("string://".length()))); else if (uri.startsWith("http://")) return getHttpReader(new URL(uri), defaultEncoding); else return getFileReader(uri, defaultEncoding); } public static InputStream getInputStreamForURI(String uri) throws IOException { Assert.notNull(uri, "uri"); return getInputStreamForURI(uri, true); } /** * Creates an InputStream from a url in String representation. * @param uri the source url * @return an InputStream that reads the url. * @throws IOException if the url cannot be read. */ public static InputStream getInputStreamForURI(String uri, boolean required) throws IOException { LOGGER.debug("getInputStreamForURI({}, {})", uri, required); if (uri.startsWith("string://")) { String content = uri.substring("string://".length()); return new ByteArrayInputStream(content.getBytes(SystemInfo.getCharset())); } if (isFileUri(uri)) return getFileOrResourceAsStream(stripOffProtocolFromUri(uri), true); else if (uri.startsWith("file:")) return getFileOrResourceAsStream(uri.substring("file:".length()), true); else if (uri.contains("://")) { return getInputStreamForURL(new URL(uri)); } else return getFileOrResourceAsStream(uri, required); } public static String stripOffProtocolFromUri(String uri) { int index = uri.indexOf("://"); if (index >= 0) return uri.substring(index + 3); index = uri.indexOf(":"); if (index > 1 || (!SystemInfo.isWindows() && index > 0)) return uri.substring(index + 1); return uri; } public static boolean isFileUri(String uri) { return (uri.startsWith("file:") || !uri.contains("://")); } public static InputStream getInputStreamForURL(URL url) throws IOException { try { URLConnection connection = getConnection(url); return connection.getInputStream(); } catch (MalformedURLException e) { throw new IllegalArgumentException(e); } } public static InputStream getInputStreamForUriReference(String localUri, String contextUri, boolean required) throws IOException { LOGGER.debug("getInputStreamForUriReference({}, {})", localUri, contextUri); // do not resolve context for absolute URLs or missing contexts if (StringUtil.isEmpty(contextUri) || getProtocol(localUri) != null) return getInputStreamForURI(localUri, required); // now resolve the relative uri String uri = resolveRelativeUri(localUri, contextUri); if (localUri.startsWith("http://")) { return getInputStreamForURL(new URL(uri)); } if (localUri.startsWith("file:") && !localUri.startsWith("file://")) return getFileOrResourceAsStream(localUri.substring("file:".length()), true); if (!localUri.contains("://")) localUri = "file://" + localUri; if (localUri.startsWith("file://")) return getFileOrResourceAsStream(localUri.substring("file://".length()), true); else throw new ConfigurationError("Can't to handle URL " + localUri); } /** * Returns an InputStream to a file resource on the class path. * @param name the file's name * @return an InputStream to the resource */ public static InputStream getResourceAsStream(String name, boolean required) { LOGGER.debug("getResourceAsStream({}, {})", name, required); InputStream stream = null; ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader(); if (contextClassLoader != null) stream = contextClassLoader.getResourceAsStream(name); if (stream == null) { String searchedName = (name.startsWith("/") ? name : '/' + name); stream = IOUtil.class.getResourceAsStream(searchedName); } if (required && stream == null) throw new ConfigurationError("Resource not found: " + name); return stream; } public static String resolveRelativeUri(String relativeUri, String contextUri) { LOGGER.debug("resolveRelativeUri({}, {})", relativeUri, contextUri); if (contextUri == null) return relativeUri; if (isAbsoluteRef(relativeUri, contextUri)) return relativeUri; String contextProtocol = getProtocol(contextUri); if (contextProtocol == null || contextProtocol.equals("file")) return resolveRelativeFile(getPath(contextUri), getPath(relativeUri)); else return resolveRelativeURL(contextUri, relativeUri); } public static boolean isAbsoluteRef(String uri, String contextUri) { if (StringUtil.isEmpty(contextUri)) // if there is no context, the URI must be absolute return true; // recognize Windows drive letter formats like C:\ if (uri.length() >= 3 && Character.isLetter(uri.charAt(0)) && uri.charAt(1) == ':' && uri.charAt(2) == '\\') return true; String refProtocol = getProtocol(uri); String ctxProtocol = getProtocol(contextUri); if (ctxProtocol == null) // if no context protocol is given, assume 'file' ctxProtocol = "file"; if (!ctxProtocol.equals(refProtocol) && refProtocol != null) // if the ref has a different protocol declared than the context, its absolute return true; // if the protocols are 'file' and the URI starts with '/' or '~' its an absolute file URI return ("file".equals(ctxProtocol) && ((uri.startsWith("/") || uri.startsWith("~")))); } private static String resolveRelativeFile(String contextPath, String relativePath) { char firstChar = relativePath.charAt(0); boolean isAbsolutePath = firstChar == '/' || firstChar == File.separatorChar; if (isAbsolutePath || isURIAvailable(relativePath)) return relativePath; else return new File(contextPath, relativePath).getPath(); } private static String resolveRelativeURL(String contextUri, String relativeUri) { try { URL contextUrl = new URL(contextUri); URL absoluteUrl = new URL(contextUrl, relativeUri); String result = absoluteUrl.toString(); return result; } catch (MalformedURLException e) { throw new IllegalArgumentException(e); } } public static String getParentUri(String uri) { if (StringUtil.isEmpty(uri)) return null; String protocol = getProtocol(uri); if (protocol != null) uri = uri.substring(protocol.length()); char systemSeparator = SystemInfo.getFileSeparator(); char uriSeparator = (uri.indexOf(systemSeparator) >= 0 ? systemSeparator : '/'); String parentUri = StringUtil.splitOnLastSeparator(uri, uriSeparator)[0]; if (parentUri == null) parentUri = "."; parentUri += uriSeparator; if (protocol != null) parentUri = protocol + parentUri; return parentUri; } public static String getProtocol(String uri) { if (uri == null) return null; int sep = uri.indexOf("://"); if (sep > 0) return uri.substring(0, sep); return (uri.startsWith("file:") ? "file" : null); } private static String getPath(String uri) { if (uri == null || ".".equals(uri)) return null; int sep = uri.indexOf("://"); if (sep > 0) return uri.substring(sep + 3); return (uri.startsWith("file:") ? uri.substring(5) : uri); } public static PrintWriter getPrinterForURI(String uri, String encoding) throws FileNotFoundException, UnsupportedEncodingException { return getPrinterForURI(uri, encoding, false, SystemInfo.getLineSeparator(), false); } @SuppressWarnings("resource") public static PrintWriter getPrinterForURI(String uri, String encoding, boolean append, final String lineSeparator, boolean autoCreateFolder) throws FileNotFoundException, UnsupportedEncodingException { File file = new File(uri); if (autoCreateFolder) FileUtil.ensureDirectoryExists(file.getParentFile()); return new PrintWriter(new OutputStreamWriter(new FileOutputStream(uri, append), encoding)) { @Override public void println() { print(lineSeparator); } }; } // piping streams -------------------------------------------------------------------------------------------------- public static int transfer(Reader reader, Writer writer) throws IOException { int totalChars = 0; char[] buffer = new char[16384]; int charsRead; while ((charsRead = reader.read(buffer, 0, buffer.length)) > 0) { writer.write(buffer, 0, charsRead); totalChars += charsRead; } return totalChars; } public static int transfer(InputStream in, OutputStream out) throws IOException { int totalChars = 0; byte[] buffer = new byte[16384]; int charsRead; while ((charsRead = in.read(buffer, 0, buffer.length)) != -1) { out.write(buffer, 0, charsRead); totalChars += charsRead; } return totalChars; } public static void copyFile(String srcUri, String targetUri) throws IOException { LOGGER.debug("copying " + srcUri + " --> " + targetUri); InputStream in = null; OutputStream out = null; try { in = getInputStreamForURI(srcUri); out = openOutputStreamForURI(targetUri); IOUtil.transfer(in, out); } finally { close(out); close(in); } } public static OutputStream openOutputStreamForURI(String uri) throws IOException { if (uri.startsWith("file:")) { uri = uri.substring(5); if (uri.startsWith("//")) uri = uri.substring(2); return new FileOutputStream(uri); } else if (uri.contains("://")) { try { URL url = new URL(uri); URLConnection urlc = url.openConnection(); return urlc.getOutputStream(); } catch (MalformedURLException e) { throw new IllegalArgumentException(e); } } return new FileOutputStream(uri); } // Properties I/O -------------------------------------------------------------------------------------------------- public static Map readProperties(String filename) throws IOException { return readProperties(filename, SystemInfo.getFileEncoding()); } @SuppressWarnings({ "unchecked", "rawtypes" }) public static Map readProperties(String filename, String encoding) throws IOException { return readProperties(new OrderedMap(), filename, null, encoding); } @SuppressWarnings("rawtypes") public static Map readProperties( String filename, Converter converter) throws IOException { return readProperties(filename, converter, SystemInfo.getFileEncoding()); } @SuppressWarnings("rawtypes") public static Map readProperties( String filename, Converter converter, String encoding) throws IOException { return readProperties(new OrderedMap(), filename, converter, encoding); } @SuppressWarnings({ "unchecked", "rawtypes" }) private static M readProperties(M target, String filename, Converter converter, String encoding) throws IOException { Reader reader = null; ReaderLineIterator iterator = null; try { reader = IOUtil.getReaderForURI(filename, encoding); iterator = new ReaderLineIterator(reader); String key = null; String value = ""; while (iterator.hasNext()) { String line = iterator.next(); line = line.trim(); if (line.startsWith("#")) continue; boolean incomplete = (line.endsWith("\\") && line.charAt(line.length() - 2) != '\\'); if (incomplete) line = line.substring(0, line.length() - 1); line = StringUtil.unescape(line); if (key != null) { value += line; } else { String[] assignment = ParseUtil.parseAssignment(line, "=", false); if (assignment != null && assignment[1] != null) { key = assignment[0]; value = assignment[1]; } else continue; } if (!incomplete) { if (converter != null) { Map.Entry entry = new MapEntry(key, value); entry = converter.convert(entry); target.put(entry.getKey(), entry.getValue()); } else target.put(key, value); key = null; value = ""; } } } finally { if (iterator != null) iterator.close(); else IOUtil.close(reader); } return target; } public static void writeProperties(Map properties, String filename) throws IOException { writeProperties(properties, filename, SystemInfo.getFileEncoding()); } public static void writeProperties(Map properties, String filename, String encoding) throws IOException { PrintWriter stream = null; try { stream = IOUtil.getPrinterForURI(filename, encoding); for (Map.Entry entry : properties.entrySet()) stream.println(entry.getKey() + "=" + ToStringConverter.convert(entry.getValue(), "")); } finally { IOUtil.close(stream); } } // text file im/export --------------------------------------------------------------------------------------------- /* public static String readTextResource(String filename) throws FileNotFoundException, IOException { InputStreamReader reader = new InputStreamReader(getFileOrResourceAsStream(filename)); String text = read(reader); reader.close(); return text; } public static String readTextFile(File file) throws FileNotFoundException, IOException { FileReader reader = new FileReader(file); return read(reader); } */ public static void writeTextFile(String filename, String content) throws IOException { writeTextFile(filename, content, SystemInfo.getFileEncoding()); } public static void writeTextFile(String filename, String content, String encoding) throws IOException { if (encoding == null) encoding = SystemInfo.getCharset().name(); Writer writer = null; try { writer = new OutputStreamWriter(openOutputStreamForURI(filename), encoding); transfer(new StringReader(content), writer); } finally { close(writer); } } // private helpers ------------------------------------------------------------------------------------------------- /** * Returns an InputStream that reads a file. The file is first searched on the disk directories * then in the class path. * @param filename the name of the file to be searched. * @return an InputStream that accesses the file. * @throws FileNotFoundException if the file cannot be found. */ private static InputStream getFileOrResourceAsStream(String filename, boolean required) throws FileNotFoundException { LOGGER.debug("getFileOrResourceAsStream({}, {})", filename, required); File file = new File(filename); if (file.exists()) { return new FileInputStream(filename); } else return getResourceAsStream(filename, required); } private static boolean httpUrlAvailable(String urlString) { try { URL url = new URL(urlString); URLConnection urlConnection = url.openConnection(); urlConnection.connect(); return true; } catch (IOException e) { return false; } } private static URLConnection getConnection(URL url) throws IOException { URLConnection connection = url.openConnection(); connection.setRequestProperty("User-Agent", USER_AGENT); connection.connect(); return connection; } public static byte[] getBinaryContentOfUri(String uri) throws IOException { InputStream in = getInputStreamForURI(uri); ByteArrayOutputStream out = new ByteArrayOutputStream(25000); transfer(in, out); return out.toByteArray(); } public static void writeBytes(byte[] bytes, File file) throws IOException { ByteArrayInputStream in = new ByteArrayInputStream(bytes); OutputStream out = new FileOutputStream(file); try { transfer(in, out); } finally { IOUtil.close(out); IOUtil.close(in); } } public static void copyDirectory(URL srcUrl, File targetDirectory, Filter filenameFilter) throws IOException { LOGGER.debug("copyDirectory({}, {}, {})", new Object[] { srcUrl, targetDirectory, filenameFilter }); String protocol = srcUrl.getProtocol(); if (protocol.equals("file")) { try { FileUtil.copy(new File(srcUrl.toURI()), targetDirectory, true, new FileByNameFilter(filenameFilter)); } catch (URISyntaxException e) { throw new RuntimeException("Unexpected exception", e); } } else if (protocol.equals("jar")) { String path = srcUrl.getPath(); int separatorIndex = path.indexOf("!"); String jarPath = path.substring(5, separatorIndex); // extract jar file name String relativePath = path.substring(separatorIndex + 2); // extract path inside jar file if (!relativePath.endsWith("/")) relativePath += "/"; extractFolderFromJar(jarPath, relativePath, targetDirectory, filenameFilter); } else throw new UnsupportedOperationException("Protocol not supported: "+ protocol + " (URL: " + srcUrl + ")"); } public static void extractFolderFromJar(String jarPath, String directory, File targetDirectory, Filter filenameFilter) throws IOException { LOGGER.debug("extractFolderFromJar({}, {}, {}, {})", new Object[] { jarPath, directory, targetDirectory, filenameFilter}); JarFile jar = new JarFile(URLDecoder.decode(jarPath, "UTF-8")); Enumeration entries = jar.entries(); while (entries.hasMoreElements()) { JarEntry entry = entries.nextElement(); String name = entry.getName(); if (name.startsWith(directory) && !directory.equals(name) && (filenameFilter == null || filenameFilter.accept(name))) { String relativeName = name.substring(directory.length()); if (entry.isDirectory()) { File subDir = new File(targetDirectory, relativeName); LOGGER.debug("creating sub directory {}", subDir); subDir.mkdir(); } else { File targetFile = new File(targetDirectory, relativeName); LOGGER.debug("copying file {} to {}", name, targetFile); InputStream in = jar.getInputStream(entry); OutputStream out = new FileOutputStream(targetFile); transfer(in, out); out.close(); in.close(); } } } } public static String[] listResources(URL url) throws IOException { LOGGER.debug("listResources({})", url); String protocol = url.getProtocol(); if (protocol.equals("file")) { try { String[] result = new File(url.toURI()).list(); if (result == null) result = new String[0]; LOGGER.debug("found file resources: {}", result); return result; } catch (URISyntaxException e) { throw new RuntimeException("Unexpected exception", e); } } else if (protocol.equals("jar")) { String path = url.getPath(); int separatorIndex = path.indexOf("!"); String jarPath = path.substring(5, separatorIndex); // extract jar file name String relativePath = path.substring(separatorIndex + 2); // extract path inside jar file JarFile jar = new JarFile(URLDecoder.decode(jarPath, "UTF-8")); Enumeration entries = jar.entries(); Set result = new HashSet(); while (entries.hasMoreElements()) { String name = entries.nextElement().getName(); if (name.startsWith(relativePath)) { String entry = name.substring(relativePath.length()); int checkSubdir = entry.indexOf("/"); if (checkSubdir >= 0) // return only the top directory name of all sub directory entries entry = entry.substring(0, checkSubdir); result.add(entry); } } LOGGER.debug("found jar resources: {}", result); return result.toArray(new String[result.size()]); } else throw new UnsupportedOperationException("Protocol not supported: "+ protocol + " (URL: " + url + ")"); } public static void download(URL url, File targetFile) throws IOException { LOGGER.info("downloading {}", url); FileUtil.ensureDirectoryExists(targetFile.getParentFile()); InputStream in = getInputStreamForURL(url); try { OutputStream out = new FileOutputStream(targetFile); try { IOUtil.transfer(in, out); } finally { IOUtil.close(out); } } finally { IOUtil.close(in); } } public static ImageIcon readImageIcon(String resourceName) { try { InputStream in = getInputStreamForURI(resourceName); if (in == null) throw new FileNotFoundException("Resource not found: " + resourceName); return new ImageIcon(ImageIO.read(in)); } catch (Exception e) { throw new ConfigurationError(e); } } // helpers --------------------------------------------------------------------------------------------------------- private static BufferedReader getFileReader(String filename, String defaultEncoding) throws IOException, UnsupportedEncodingException { if (defaultEncoding == null) defaultEncoding = SystemInfo.getFileEncoding(); InputStream is = getInputStreamForURI(filename); PushbackInputStream in = new PushbackInputStream(is, 4); defaultEncoding = bomEncoding(in, defaultEncoding); return new BufferedReader(new InputStreamReader(in, defaultEncoding)); } private static BufferedReader getHttpReader(URL url, String defaultEncoding) throws IOException, UnsupportedEncodingException { try { URLConnection connection = getConnection(url); connection.connect(); String encoding = encoding(connection, defaultEncoding); InputStream inputStream = connection.getInputStream(); return new BufferedReader(new InputStreamReader(inputStream, encoding)); } catch (MalformedURLException e) { throw new IllegalArgumentException(e); } } static String encoding(URLConnection connection, String defaultEncoding) { String encoding = connection.getContentEncoding(); if (StringUtil.isEmpty(encoding)) { String ct = connection.getHeaderField("Content-Type"); if (!StringUtil.isEmpty(ct)) { int i = ct.indexOf("charset"); if (i >= 0) encoding = ct.substring(i + "charset".length() + 1).trim(); } } if (StringUtil.isEmpty(encoding)) encoding = defaultEncoding; if (StringUtil.isEmpty(encoding)) encoding = SystemInfo.getFileEncoding(); return encoding; } private static String bomEncoding(PushbackInputStream in, String defaultEncoding) throws IOException { int b1 = in.read(); if (b1 == -1) return defaultEncoding; if (b1 != 0xEF) { in.unread(b1); return defaultEncoding; } int b2 = in.read(); if (b2 == -1) { in.unread(b1); return defaultEncoding; } if (b2 != 0xBB) { in.unread(b2); in.unread(b1); return defaultEncoding; } int b3 = in.read(); if (b3 == -1) { in.unread(b2); in.unread(b1); return defaultEncoding; } if (b3 != 0xBF) { in.unread(b3); in.unread(b2); in.unread(b1); return defaultEncoding; } return Encodings.UTF_8; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy