net.sourceforge.javadpkg.io.Streams Maven / Gradle / Ivy
Show all versions of dpkg Show documentation
/*
* dpkg - Debian Package library and the Debian Package Maven plugin
* (c) Copyright 2016 Gerrit Hohl
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package net.sourceforge.javadpkg.io;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
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.OutputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
import org.apache.commons.compress.compressors.gzip.GzipParameters;
import net.sourceforge.javadpkg.io.impl.DataStreamConsumer;
import net.sourceforge.javadpkg.io.impl.DataStreamProducer;
import net.sourceforge.javadpkg.io.impl.DataStreamSource;
/**
*
* A utility class for handling standard operations using streams.
*
*
* @author Gerrit Hohl ([email protected])
* @version 1.0, 27.04.2016 by Gerrit Hohl
*/
public class Streams {
/** The default block size. */
private static final int DEFAULT_BLOCK_SIZE = 65536;
/** The default file buffer size. */
private static final int DEFAULT_FILE_BUFFER_SIZE = 1048576;
/**
*
* Private constructor prevents the instantiation of this utility class.
*
*/
private Streams() {
super();
}
/**
*
* Copies the content of the input stream to the output stream until the end
* of the input stream is reached.
*
*
* @param in
* The input stream.
* @param out
* The output stream.
* @throws IllegalArgumentException
* If any of the parameters are null
.
* @throws IOException
* If an I/O error occurs.
*/
public static void copy(InputStream in, OutputStream out) throws IOException {
if (in == null)
throw new IllegalArgumentException("Argument in is null.");
if (out == null)
throw new IllegalArgumentException("Argument out is null.");
copy(in, out, DEFAULT_BLOCK_SIZE, -1);
}
/**
*
* Copies the content of the input stream to the output stream until the end
* of the input stream is reached.
*
*
* @param in
* The input stream.
* @param out
* The output stream.
* @param blockSize
* The block size of data which will be read at once.
* @param length
* The (maximum) length of the data which should be read from the
* input stream. If the length is negative the method will read
* from the input stream until the end is reached. If the
* end-of-stream is reached before the specified length could be
* read the method will exit without an exception.
* @throws IllegalArgumentException
* If any of the parameters are null
or the block
* size is less than 1
.
* @throws IOException
* If an I/O error occurs.
*/
public static void copy(InputStream in, OutputStream out, int blockSize, long length) throws IOException {
DataProducer producer;
DataConsumer consumer;
// ROADMAP Implement listener for progress and cancellation.
if (in == null)
throw new IllegalArgumentException("Argument in is null.");
if (out == null)
throw new IllegalArgumentException("Argument out is null.");
if (blockSize < 1)
throw new IllegalArgumentException("Argument blockSize is less than 1: " + blockSize);
producer = new DataStreamProducer(in, "input stream");
consumer = new DataStreamConsumer(out, "output stream");
transfer(producer, consumer, blockSize, length);
}
/**
*
* Transfers data from a producer to a consumer.
*
*
* @param producer
* The producer which offers the data.
* @param consumer
* The consumer which handles the data.
* @throws IllegalArgumentException
* If any of the parameters are null
or the block
* size is less than 1
.
* @throws IOException
* If an I/O error occurs.
*/
public static void transfer(DataProducer producer, DataConsumer consumer) throws IOException {
if (producer == null)
throw new IllegalArgumentException("Argument producer is null.");
if (consumer == null)
throw new IllegalArgumentException("Argument out is null.");
transfer(producer, consumer, DEFAULT_BLOCK_SIZE, -1);
}
/**
*
* Transfers data from a producer to a consumer.
*
*
* @param producer
* The producer which offers the data.
* @param consumer
* The consumer which handles the data.
* @param blockSize
* The block size of data which will be read at once.
* @param length
* The (maximum) length of the data which should be read from the
* producer. If the length is negative the method will read from
* the producer until the end is reached. If the end is reached
* before the specified length could be read the method will exit
* without an exception.
* @throws IllegalArgumentException
* If any of the parameters are null
or the block
* size is less than 1
.
* @throws IOException
* If an I/O error occurs.
*/
public static void transfer(DataProducer producer, DataConsumer consumer, int blockSize, long length) throws IOException {
boolean limited;
long remainingLength;
byte[] buffer;
int readLength;
// ROADMAP Implement listener for progress and cancellation.
if (producer == null)
throw new IllegalArgumentException("Argument producer is null.");
if (consumer == null)
throw new IllegalArgumentException("Argument out is null.");
if (blockSize < 1)
throw new IllegalArgumentException("Argument blockSize is less than 1: " + blockSize);
// --- Is the length limited? ---
if (length < 0) {
limited = false;
} else {
limited = true;
}
// --- Do we have some length to read? ---
remainingLength = length;
if (!limited || (remainingLength > 0)) {
buffer = new byte[blockSize];
do {
// --- Unlimited uses the full block size, limited the remaining ---
readLength = blockSize;
if (limited && (readLength > remainingLength)) {
readLength = (int) remainingLength;
}
try {
readLength = producer.produce(buffer);
} catch (IOException e) {
throw new IOException("Couldn't read data from " + producer.getName() + " and pass to " + consumer.getName()
+ ": " + e.getMessage(), e);
}
if (readLength > 0) {
try {
consumer.consume(buffer, readLength);
} catch (IOException e) {
throw new IOException("Couldn't read data from " + producer.getName() + " and pass to "
+ consumer.getName() + ": " + e.getMessage(), e);
}
// --- If we're limited we have to count ---
if (limited) {
remainingLength -= readLength;
}
}
/*
* --- Exit if the End-of-Stream is reached in any case.
* For limited copy actions also the rest length is important. ---
*/
} while ((readLength >= 0) && (!limited || (remainingLength > 0)));
}
}
/**
*
* Copies the content of the source to the target until the complete content
* is copied.
*
*
* The source as well as the target is not closed by this method.
*
*
* @param source
* The source.
* @param target
* The target.
* @throws IllegalArgumentException
* If any of the parameters are null
.
* @throws IOException
* If an I/O error occurs.
*/
public static void copy(DataSource source, DataTarget target) throws IOException {
if (source == null)
throw new IllegalArgumentException("Argument source is null.");
if (target == null)
throw new IllegalArgumentException("Argument target is null.");
copy(source, target, DEFAULT_BLOCK_SIZE, -1);
}
/**
*
* Copies the content of the source to the target until the complete content
* is copied.
*
*
* The source as well as the target is not closed by this method.
*
*
* @param source
* The source.
* @param target
* The target.
* @param blockSize
* The block size of data which will be read at once.
* @param length
* The (maximum) length of the data which should be read from the
* input stream. If the length is negative the method will read
* from the input stream until the end is reached. If the
* end-of-stream is reached before the specified length could be
* read the method will exit without an exception.
* @throws IllegalArgumentException
* If any of the parameters are null
or the block
* size is less than 1
.
* @throws IOException
* If an I/O error occurs.
*/
public static void copy(DataSource source, DataTarget target, int blockSize, long length) throws IOException {
DataProducer producer;
DataConsumer consumer;
// ROADMAP Implement listener for progress and cancellation.
if (source == null)
throw new IllegalArgumentException("Argument source is null.");
if (target == null)
throw new IllegalArgumentException("Argument target is null.");
if (blockSize < 1)
throw new IllegalArgumentException("Argument blockSize is less than 1: " + blockSize);
producer = createProducer(source);
consumer = createConsumer(target);
transfer(producer, consumer, blockSize, length);
}
/**
*
* Compresses the content of the source to the target using GZIP until the
* complete content is compressed.
*
*
* The source as well as the target is not closed by this method.
*
*
* @param source
* The source.
* @param target
* The target.
* @param compressionLevel
* The compression level, a number from -1
to
* 9
. -1
is the default compression,
* 0
is no compression and 9
is the
* best compression.
* @throws IllegalArgumentException
* If any of the parameters are null
or the block
* size is less than 1
.
* @throws IOException
* If an I/O error occurs.
*/
public static void compressGzip(DataSource source, DataTarget target, int compressionLevel) throws IOException {
if (source == null)
throw new IllegalArgumentException("Argument source is null.");
if (target == null)
throw new IllegalArgumentException("Argument target is null.");
if ((compressionLevel < -1) || (compressionLevel > 9))
throw new IllegalArgumentException(
"Argument compressionLevel is out of bound. Lower limit: -1; upper limit: 9; compressionLevel: "
+ compressionLevel);
compressGzip(source, target, DEFAULT_BLOCK_SIZE, -1, compressionLevel);
}
/**
*
* Compresses the content of the source to the target using GZIP until the
* complete content is compressed.
*
*
* The source as well as the target is not closed by this method.
*
*
* @param source
* The source.
* @param target
* The target.
* @param blockSize
* The block size of data which will be read at once.
* @param length
* The (maximum) length of the data which should be read from the
* input stream. If the length is negative the method will read
* from the input stream until the end is reached. If the
* end-of-stream is reached before the specified length could be
* read the method will exit without an exception.
* @param compressionLevel
* The compression level, a number from -1
to
* 9
. -1
is the default compression,
* 0
is no compression and 9
is the
* best compression.
* @throws IllegalArgumentException
* If any of the parameters are null
or the block
* size is less than 1
.
* @throws IOException
* If an I/O error occurs.
*/
@SuppressWarnings("resource")
public static void compressGzip(DataSource source, DataTarget target, int blockSize, long length, int compressionLevel)
throws IOException {
DataProducer producer;
OutputStream out = null;
GzipCompressorOutputStream gzipOut;
GzipParameters gzipParameters;
DataConsumer consumer;
// ROADMAP Implement listener for progress and cancellation.
if (source == null)
throw new IllegalArgumentException("Argument source is null.");
if (target == null)
throw new IllegalArgumentException("Argument target is null.");
if (blockSize < 1)
throw new IllegalArgumentException("Argument blockSize is less than 1: " + blockSize);
if ((compressionLevel < -1) || (compressionLevel > 9))
throw new IllegalArgumentException(
"Argument compressionLevel is out of bound. Lower limit: -1; upper limit: 9; compressionLevel: "
+ compressionLevel);
producer = createProducer(source);
try {
out = target.getOutputStream();
gzipParameters = new GzipParameters();
gzipParameters.setCompressionLevel(compressionLevel);
gzipOut = new GzipCompressorOutputStream(out, gzipParameters);
consumer = new DataStreamConsumer(gzipOut, target.getName());
} catch (IOException e) {
throw new IOException("Couldn't open GZIP stream on target |" + target.getName() + "|: " + e.getMessage(), e);
}
transfer(producer, consumer, blockSize, length);
// --- Use finish() as it flushes the GZIP stream. flush() only flushes the underlying stream. ---
try {
gzipOut.finish();
} catch (IOException e) {
throw new IOException("Couldn't finish GZIP stream on target |" + target.getName() + "|: " + e.getMessage(), e);
}
}
/**
*
* Creates a producer which gets its data from the specified source.
*
*
* @param source
* The source.
* @return The producer.
* @throws IllegalArgumentException
* If the source is null
.
* @throws IOException
* If an I/O error occurs while obtaining the
* {@link InputStream} of the source.
*/
@SuppressWarnings("resource")
public static DataProducer createProducer(DataSource source) throws IOException {
InputStream in;
DataProducer producer;
if (source == null)
throw new IllegalArgumentException("Argument source is null.");
try {
in = source.getInputStream();
} catch (IOException e) {
throw new IOException("Couldn't obtain input stream from source |" + source + "|: " + e.getMessage(), e);
}
producer = new DataStreamProducer(in, "source |" + source.getName() + "|");
return producer;
}
/**
*
* Creates a consumer which puts its data into the specified target.
*
*
* @param target
* The target.
* @return The consumer.
* @throws IllegalArgumentException
* If the target is null
.
* @throws IOException
* If an I/O error occurs while obtaining the
* {@link OutputStream} of the target.
*/
@SuppressWarnings("resource")
public static DataConsumer createConsumer(DataTarget target) throws IOException {
OutputStream out;
DataConsumer consumer;
if (target == null)
throw new IllegalArgumentException("Argument target is null.");
try {
out = target.getOutputStream();
} catch (IOException e) {
throw new IOException("Couldn't obtain output stream from target |" + target + "|: " + e.getMessage(), e);
}
consumer = new DataStreamConsumer(out, "target |" + target + "|");
return consumer;
}
/**
*
* Creates a buffered stream for reading from the specified file.
*
*
* @param file
* The file.
* @return The buffered stream.
* @throws IllegalArgumentException
* If the file is null
.
* @throws FileNotFoundException
* If the file does not exist, is a directory rather than a
* regular file, or for some other reason cannot be opened for
* reading.
*/
public static InputStream createBufferedFileInputStream(File file) throws FileNotFoundException {
InputStream in;
if (file == null)
throw new IllegalArgumentException("Argument file is null.");
in = createBufferedFileInputStream(file, DEFAULT_FILE_BUFFER_SIZE);
return in;
}
/**
*
* Creates a buffered stream for reading from the specified file.
*
*
* @param file
* The file.
* @param fileBufferSize
* The size of the buffer for reading from the file.
* @return The buffered stream.
* @throws IllegalArgumentException
* If the file is null
or the file buffer size is
* less than 1
.
* @throws FileNotFoundException
* If the file does not exist, is a directory rather than a
* regular file, or for some other reason cannot be opened for
* reading.
*/
public static InputStream createBufferedFileInputStream(File file, int fileBufferSize) throws FileNotFoundException {
InputStream in;
if (file == null)
throw new IllegalArgumentException("Argument file is null.");
if (fileBufferSize < 1)
throw new IllegalArgumentException("Argument fileBufferSize is less than 1: " + fileBufferSize);
in = new BufferedInputStream(new FileInputStream(file), fileBufferSize);
return in;
}
/**
*
* Creates a buffered stream for writing into the specified file.
*
*
* @param file
* The file.
* @return The buffered stream.
* @throws IllegalArgumentException
* If the file is null
.
* @throws FileNotFoundException
* If the file exists but is a directory rather than a regular
* file, does not exist but cannot be created, or cannot be
* opened for any other reason.
*/
public static OutputStream createBufferedFileOutputStream(File file) throws FileNotFoundException {
OutputStream out;
if (file == null)
throw new IllegalArgumentException("Argument file is null.");
out = createBufferedFileOutputStream(file, DEFAULT_FILE_BUFFER_SIZE);
return out;
}
/**
*
* Creates a buffered stream for writing into the specified file.
*
*
* @param file
* The file.
* @param fileBufferSize
* The size of the buffer for writing into the file.
* @return The buffered stream.
* @throws IllegalArgumentException
* If the file is null
or the file buffer size is
* less than 1
.
* @throws FileNotFoundException
* If the file exists but is a directory rather than a regular
* file, does not exist but cannot be created, or cannot be
* opened for any other reason.
*/
public static OutputStream createBufferedFileOutputStream(File file, int fileBufferSize) throws FileNotFoundException {
OutputStream out;
if (file == null)
throw new IllegalArgumentException("Argument file is null.");
if (fileBufferSize < 1)
throw new IllegalArgumentException("Argument fileBufferSize is less than 1: " + fileBufferSize);
out = new BufferedOutputStream(new FileOutputStream(file), fileBufferSize);
return out;
}
/**
*
* Creates a stream on a resource.
*
*
* @param pkg
* The package in which the resource resides.
* @param loader
* The class loader which should be used.
* @param name
* The name of the resource.
* @return The stream.
* @throws IllegalArgumentException
* If any of the parameters are null
.
* @throws FileNotFoundException
* If the resource couldn't be found.
*/
@SuppressWarnings("resource")
public static InputStream createResourceInputStream(Package pkg, ClassLoader loader, String name)
throws FileNotFoundException {
StringBuilder sb;
InputStream in;
String resourceName;
File file;
if (pkg == null)
throw new IllegalArgumentException("Argument pkg is null.");
if (loader == null)
throw new IllegalArgumentException("Argument loader is null.");
if (name == null)
throw new IllegalArgumentException("Argument name is null.");
sb = new StringBuilder();
sb.append(pkg.getName().replace('.', '/'));
sb.append('/');
sb.append(name);
resourceName = sb.toString();
in = loader.getResourceAsStream(resourceName);
if (in == null) {
file = new File("src/" + resourceName);
if (file.exists() && file.isFile()) {
in = createBufferedFileInputStream(file);
} else
throw new FileNotFoundException("Couldn't find resource |" + resourceName + "|.");
}
return in;
}
/**
*
* Creates a stream on a resource.
*
*
* @param clazz
* The class which provides the package and the class loader used
* to load the resource. The package of the class is the package
* in which the resource resides.
* @param name
* The name of the resource.
* @return The stream.
* @throws IllegalArgumentException
* If any of the parameters are null
.
* @throws FileNotFoundException
* If the resource couldn't be found.
*/
public static InputStream createResourceInputStream(Class> clazz, String name) throws FileNotFoundException {
InputStream in;
if (clazz == null)
throw new IllegalArgumentException("Argument clazz is null.");
if (name == null)
throw new IllegalArgumentException("Argument name is null.");
in = createResourceInputStream(clazz.getPackage(), clazz.getClassLoader(), name);
return in;
}
/**
*
* Creates a source on a resource.
*
*
* @param pkg
* The package in which the resource resides.
* @param loader
* The class loader which should be used.
* @param name
* The name of the resource.
* @return The source.
* @throws IllegalArgumentException
* If any of the parameters are null
.
* @throws FileNotFoundException
* If the resource couldn't be found.
*/
@SuppressWarnings("resource")
public static DataSource createResourceDataSource(Package pkg, ClassLoader loader, String name)
throws FileNotFoundException {
DataSource source;
InputStream in;
if (pkg == null)
throw new IllegalArgumentException("Argument pkg is null.");
if (loader == null)
throw new IllegalArgumentException("Argument loader is null.");
if (name == null)
throw new IllegalArgumentException("Argument name is null.");
in = createResourceInputStream(pkg, loader, name);
source = new DataStreamSource(in, name, true);
return source;
}
/**
*
* Creates a source on a resource.
*
*
* @param clazz
* The class which provides the package and the class loader used
* to load the resource. The package of the class is the package
* in which the resource resides.
* @param name
* The name of the resource.
* @return The stream.
* @throws IllegalArgumentException
* If any of the parameters are null
.
* @throws FileNotFoundException
* If the resource couldn't be found.
*/
@SuppressWarnings("resource")
public static DataSource createResourceDataSource(Class> clazz, String name) throws FileNotFoundException {
DataSource source;
InputStream in;
if (clazz == null)
throw new IllegalArgumentException("Argument clazz is null.");
if (name == null)
throw new IllegalArgumentException("Argument name is null.");
in = createResourceInputStream(clazz, name);
source = new DataStreamSource(in, name, true);
return source;
}
}