/*
* Copyright 2008-2014 the original author or authors
*
* 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.kaleidofoundry.core.io;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Iterator;
import org.kaleidofoundry.core.lang.Charsets;
import org.kaleidofoundry.core.system.JavaSystemHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* IO helper tools
*
* @author jraduget
*/
public abstract class IOHelper {
/**
* default buffer size for reading data
*/
public static final int DefaultBufferSize = 512;
private final static Logger LOGGER = LoggerFactory.getLogger(IOHelper.class);
/**
* @param reader
* @return Returns the entire contents of a text reader
* @throws IOException
*/
public static StringBuilder getFullText(final Reader reader) throws IOException {
if (reader == null) { return null; }
BufferedReader buff = null;
if (reader instanceof BufferedReader) {
buff = (BufferedReader) reader;
} else {
buff = new BufferedReader(reader);
}
final StringBuilder str = new StringBuilder();
String line = null;
try {
while ((line = buff.readLine()) != null) {
str.append(line);
}
} finally {
buff.close();
}
return str;
}
/**
* @param in
* @param bufferSize
* @return data input stream
* @throws IOException
*/
public static ByteArrayOutputStream toByteArrayOutputStream(final InputStream in, final int bufferSize) throws IOException {
final ByteArrayOutputStream bout = new ByteArrayOutputStream();
final byte[] data = new byte[bufferSize];
int dataBuffLenght = 0;
while ((dataBuffLenght = in.read(data)) > 0) {
bout.write(data, 0, dataBuffLenght);
}
return bout;
}
/**
* @param in
* @param bufferSize
* @return byte[] of data input stream
* @throws IOException
*/
public static byte[] toByteArray(final InputStream in, final int bufferSize) throws IOException {
return toByteArrayOutputStream(in, bufferSize).toByteArray();
}
/**
* @param in
* @return byte[] of data input stream, buffered reading is {@link #DefaultBufferSize}
* @throws IOException
*/
public static byte[] toByteArray(final InputStream in) throws IOException {
return toByteArray(in, DefaultBufferSize);
}
/**
* The resource file will be searched as follows:
* <ul>
* <li>1. URL connection (without authentification)</li>
* <li>1. System file</li>
* <li>2. Java classpath</li>
* <li>3. Jar classpath</li>
* </ul>
* <br/>
*
* @param resourcePath Name of the resource
* @return inputStream for reading resource (null if no resource found)
*/
public static InputStream getResourceInputStream(final String resourcePath) {
return getResourceInputStream(resourcePath, IOHelper.class.getClassLoader());
}
/**
* @param in
* @return string conversion of the given input stream
* @throws IOException
*/
public static String toString(final InputStream in) throws IOException {
return toString(in, Charsets.UTF_8.getCode());
}
/**
* Convert an {@link InputStream} to {@link String}<br/>
* It is a helper method, uses it only for small inpustream entry
*
* @param in inputstream
* @param charset charset to used
* @return string representation of the inputstream. if input is null, return null
* @throws IOException
*/
public static String toString(final InputStream in, final String charset) throws IOException {
if (in == null) { return null; }
BufferedReader reader = null;
StringBuilder str = null;
try {
reader = new BufferedReader(new InputStreamReader(in, charset));
String inputLine;
while ((inputLine = reader.readLine()) != null) {
if (str == null) {
str = new StringBuilder();
}
str.append(inputLine);
str.append("\n");
}
return str != null ? str.substring(0, str.length() - 1) : null;
} finally {
if (reader != null) {
reader.close();
}
}
}
/**
* Helper method to quick iterate on line of a text file<br/>
* <br/>
* Simple sample :
*
* <pre>
*
* for (String line : IOHelper.readlines("/foo.txt")) {
* System.out.println(line);
* }
* </pre>
*
* Or better to free io resource :
*
* <pre>
* try {
* IoIterable<String> lines = IOHelper.readlines("/foo.txt");
* for (String line : IOHelper.readlines("/foo.txt")) {
* System.out.println(line);
* }
* } finally {
* if (lines != null) {
* lines.close();
* }
* }
*
* </pre>
*
* @param filename
* @return {@link Iterable} on line of a file content. You have to call {@link IoIterable#close()} when you have finish to use it
* @throws IOException
*/
public static IoIterable<String> readlines(final String filename) throws IOException {
final FileReader fileReader = new FileReader(filename);
final BufferedReader bufferReader = new BufferedReader(fileReader);
return new IoIterable<String>() {
@Override
public Iterator<String> iterator() {
return new Iterator<String>() {
private String currentLine = getNextLine();
@Override
public boolean hasNext() {
return currentLine != null;
}
@Override
public String next() {
String retval = currentLine;
currentLine = getNextLine();
return retval;
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
private String getNextLine() {
String currentLine = null;
try {
currentLine = bufferReader.readLine();
} catch (IOException ioe) {
currentLine = null;
}
return currentLine;
}
};
}
@Override
public void close() throws IOException {
bufferReader.close();
fileReader.close();
}
};
}
/**
* The resource file will be searched as follows:
* <ul>
* <li>1. URL connection (without authentification)</li>
* <li>1. System file</li>
* <li>2. Java classpath</li>
* <li>3. Jar classpath</li>
* </ul>
* <br/>
*
* @param resourcePath Name of the resource
* @param classLoader class loader to use
* @return inputStream for reading resource (null if no resource found)
*/
public static InputStream getResourceInputStream(final String resourcePath, final ClassLoader classLoader) {
// 1. try to get resource from url connection (without authentification)
try {
LOGGER.debug("try getResourceInputStream from url : {}", resourcePath);
final URL configUrl = new URL(resourcePath);
final URLConnection configConnection = configUrl.openConnection();
configConnection.connect();
return configConnection.getInputStream();
} catch (final MalformedURLException e) {
LOGGER.debug("malform url : {}", resourcePath);
} catch (final IOException e) {
LOGGER.debug("ioexception from url : {}", resourcePath);
}
File fconf = null;
InputStream fconfIn = null;
// 2. try to get resource from file system (if full path is given)
LOGGER.debug("try getResourceInputStream from system file : {}", resourcePath);
fconf = new File(resourcePath);
if (!fconf.exists()) {
// 3. search file in java classpath
LOGGER.debug("try getResourceInputStream from java classpath : {}", resourcePath);
fconf = JavaSystemHelper.getResourceAsFile(classLoader, resourcePath);
}
if (fconf != null) {
try {
fconfIn = new FileInputStream(fconf);
} catch (final FileNotFoundException fne) {
LOGGER.debug("FileNotFoundException from java classpath : {}", resourcePath);
}
}
// 4. if still not found, search it in classpath jars
LOGGER.debug("try getResourceInputStream from java jar classpath: {}", resourcePath);
if (fconf == null || !fconf.exists()) { return JavaSystemHelper.getResourceAsStream(classLoader, resourcePath); }
return fconfIn;
}
}