/* * Copyright [1999-2015] Wellcome Trust Sanger Institute and the EMBL-European Bioinformatics Institute * Copyright [2016-2017] EMBL-European Bioinformatics Institute * * 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.ensembl.healthcheck.util; import java.io.BufferedInputStream; import java.io.Closeable; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.io.StringReader; import java.io.Writer; import java.util.List; import java.util.zip.GZIPInputStream; import org.apache.commons.io.IOUtils; /** * Contains useful methods for dealing with Input/Output opertations * * @author ayates * @author dstaines */ public class InputOutputUtils { public static void close(Closeable closeable) { if (null != closeable) { try { closeable.close(); } catch (IOException e) { // don't log error } } } /** * Performs the same function as the commons io version but also performs * logging of readers which threw an exception when trying to close them and * logs them at error level */ public static void closeQuietly(Reader reader) { close(reader); } /** * Equivalent of {@link #closeQuietly(Writer)} but for {@link Writer} * extending classes */ public static void closeQuietly(Writer writer) { close(writer); } /** * Performs the same function as the commons io version but also performs * logging of streams which threw an exception when trying to close them and * logs them at error level */ public static void closeQuietly(InputStream is) { close(is); } /** * Equivalent of {@link #closeQuietly(InputStream)} but for * {@link OutputStream} extending classes */ public static void closeQuietly(OutputStream os) { close(os); } /** * Similar to {@link #openClasspathResource(String)} but this uses the given * class to base the package name off. The resource should be just the * resource name */ public static InputStream openClasspathResource(Class<?> clazz, String resource) throws UtilUncheckedException { String target = getResourceAsStreamCompatibleName( clazz, resource); return openClasspathResource(target); } /** * Attempts to return a classpath resource. It is the responsibility of the * calling class to correctly close this input stream. Use * {@link #closeQuietly(InputStream)} for an easy implementation of closing * input streams. * * @param resource * The resource to find. Must be '/package/file.name' * @return The input stream found * @throws UtilUncheckedException * Thrown if the input stream was null i.e. the resource name * looked for did not exist */ public static InputStream openClasspathResource(String resource) throws UtilUncheckedException { return openClasspathResource(resource, true); } /** * Allows optional opening of a resource with or without buffering */ private static InputStream openClasspathResource(String resource, boolean buffered) { InputStream is = InputOutputUtils.class.getResourceAsStream(resource); if (is == null) { throw new UtilUncheckedException("Could not find resource " + resource); } return (buffered) ? new BufferedInputStream(is) : is; } /** * Attempts to return a gzipped classpath resource. It is the responsibility * of the calling class to correctly close this input stream. Use * {@link #closeQuietly(InputStream)} for an easy implementation of closing * input streams. * * @param resource * The resource to find. Must be '/package/file.name' * @return The input stream found * @throws UtilUncheckedException * Thrown if the input stream was null i.e. the resource name * looked for did not exist */ public static InputStream openGzippedClasspathResource(String resource) throws UtilUncheckedException { try { return new GZIPInputStream(openClasspathResource(resource, false)); } catch (IOException e) { throw new UtilUncheckedException("Could not unzip resource " + resource); } } /** * Provides an easy resource to String slurp method */ public static String slurpTextClasspathResourceToString(String resource) throws UtilUncheckedException { return slurpTextClasspathResourceToString(resource, false); } /** * Provides an easy resource to String slurp method */ public static String slurpGzippedTextClasspathResourceToString( String resource) throws UtilUncheckedException { return slurpTextClasspathResourceToString(resource, true); } private static String slurpTextClasspathResourceToString(String resource, boolean gzipped) throws UtilUncheckedException { String output = ""; InputStream is = null; try { if (!gzipped) { is = openClasspathResource(resource); } else { is = openGzippedClasspathResource(resource); } output = IOUtils.toString(is); } catch (IOException e) { throw new UtilUncheckedException( "IOException detected whilst streaming resource " + resource, e); } finally { closeQuietly(is); } return output; } /** * For the given resource path this method will stream the resource from the * current class path and pass back a StringReader holding the content of * the resource. */ public static StringReader slurpTextClasspathResourceToStringReader( String resource) throws UtilUncheckedException { String slurp = slurpTextClasspathResourceToString(resource); return new StringReader(slurp); } public static StringReader slurpGzippedTextClasspathResourceToStringReader( String resource) throws UtilUncheckedException { String slurp = slurpGzippedTextClasspathResourceToString(resource); return new StringReader(slurp); } /** * Takes a resource on the classpath and copies it out to the file system * * @param classpathResource * The classpath resource as defined as /path * @param outputFile * The output location for the file */ public static void copyFromClasspathToFileSystem(String classpathResource, File outputFile) { InputStream classpathInputStream = openClasspathResource(classpathResource); try { copyInputStreamToFileSystem(classpathInputStream, outputFile); } finally { closeQuietly(classpathInputStream); } } /** * Takes a gzipped resource on the classpath, unzips and copies it out to * the file system * * @param classpathResource * The classpath resource as defined as /path * @param outputFile * The output location for the file */ public static void copyFromGzippedClasspathToFileSystem( String classpathResource, File outputFile) { InputStream classpathInputStream = openGzippedClasspathResource(classpathResource); try { copyInputStreamToFileSystem(classpathInputStream, outputFile); } finally { closeQuietly(classpathInputStream); } } /** * Takes an already open input stream and copies to content to the file * system at the specified point * * @param stream * The stream to copy from * @param outputFile * The file output location */ public static void copyInputStreamToFileSystem(InputStream stream, File outputFile) { OutputStream output = null; try { output = new FileOutputStream(outputFile); IOUtils.copy(stream, output); } catch (IOException e) { throw new UtilUncheckedException( "Could not copy contents out to file " + outputFile, e); } finally { closeQuietly(output); } } /** * Attempts to read a list of strings from the resource, which is first * checked as a file and then as a classpath resource * * @param resource * filename or classpath resource * @return list of strings read from resource */ public static List<String> resourceToList(String resource) { List<String> l = CollectionUtils.createArrayList(); try { File res = new File(resource); if (!res.exists()) { res = null; if (resourceExists(resource)) { res = File.createTempFile("resource", ".tmp"); InputOutputUtils.copyFromClasspathToFileSystem(resource, res); } } if (res != null) l.addAll(org.apache.commons.io.FileUtils.readLines(res, null)); } catch (IOException e) { throw new UtilUncheckedException("Could not read from resource " + resource, e); } return l; } /** * @param resource * classpath resource * @return true if resource exists and can be read */ public static boolean resourceExists(String resource) { return InputOutputUtils.class.getResourceAsStream(resource) != null; } public static String getResourceAsStreamCompatibleName(Class<?> clazz, String resourceName) { String output = "/" + clazz.getPackage().getName(); output = output.replaceAll("\\.", "/"); return output + "/" + resourceName; } }