net.derquinse.common.io.MemoryByteSourceLoader Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of derquinse-common-base Show documentation
Show all versions of derquinse-common-base Show documentation
Module containing support classes depending on Java SE 6, Guava 11 and Joda-Time 2.0
/*
* Copyright (C) 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 net.derquinse.common.io;
import static com.google.common.base.Preconditions.checkNotNull;
import static net.derquinse.common.io.InternalPreconditions.checkChunkSize;
import static net.derquinse.common.io.InternalPreconditions.checkMaxSize;
import static net.derquinse.common.io.InternalPreconditions.checkSize;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import javax.annotation.concurrent.ThreadSafe;
import com.google.common.base.Objects;
import com.google.common.io.ByteSource;
import com.google.common.io.ByteStreams;
import com.google.common.io.Closer;
import com.google.common.io.Files;
import com.google.common.primitives.Ints;
/**
* Memory byte source loader.
* @author Andres Rodriguez
*/
@ThreadSafe
public final class MemoryByteSourceLoader {
/** Default loader. */
private static final MemoryByteSourceLoader DEFAULT = new MemoryByteSourceLoader(false, Integer.MAX_VALUE, 8192,
false, null);
/** Whether to use direct memory. */
private final boolean direct;
/** Maximum size. */
private final int maxSize;
/** Chunk size. */
private final int chunkSize;
/** Whether to merge after loading. */
private final boolean merge;
/** Transformer to use. */
private final BytesTransformer transformer;
/** Gets the default loader. */
public static MemoryByteSourceLoader get() {
return DEFAULT;
}
/** Constructor. */
private MemoryByteSourceLoader(boolean direct, int maxSize, int chunkSize, boolean merge, BytesTransformer transformer) {
this.direct = direct;
this.maxSize = maxSize;
this.chunkSize = chunkSize;
this.merge = merge;
this.transformer = transformer;
}
/** Returns whether the loader uses direct memory. */
public boolean isDirect() {
return direct;
}
/** Returns the maximum size. */
public int getMaxSize() {
return maxSize;
}
/** Returns the chunk size. */
public int getChunkSize() {
return chunkSize;
}
/** Returns whether the loader merges after loading. */
public boolean isMerge() {
return merge;
}
/** Returns the transformer used. */
public BytesTransformer getTransformer() {
return transformer;
}
/**
* Returns a loader with the same configuration and the use of direct memory specified by the
* argument.
* @param direct True to use direct memory, false to use heap.
*/
public MemoryByteSourceLoader direct(boolean direct) {
if (direct == this.direct) {
return this;
}
return new MemoryByteSourceLoader(direct, maxSize, chunkSize, merge, transformer);
}
/**
* Returns a loader with the same configuration and the maximum allowed size specified by the
* argument.
*/
public MemoryByteSourceLoader maxSize(int maxSize) {
checkMaxSize(maxSize);
if (maxSize == this.maxSize) {
return this;
}
return new MemoryByteSourceLoader(direct, maxSize, chunkSize, merge, transformer);
}
/**
* Returns a loader with the same configuration and the chunk size specified by the argument.
*/
public MemoryByteSourceLoader chunkSize(int chunkSize) {
checkChunkSize(chunkSize);
if (chunkSize == this.chunkSize) {
return this;
}
return new MemoryByteSourceLoader(direct, maxSize, chunkSize, merge, transformer);
}
/**
* Returns a loader with the same configuration and that merges the source after loading according
* to the provided argument.
* @param merge Whether to merge after loading.
*/
public MemoryByteSourceLoader merge(boolean merge) {
if (merge == this.merge) {
return this;
}
return new MemoryByteSourceLoader(direct, maxSize, chunkSize, merge, transformer);
}
/**
* Returns a loader with the same configuration and the transformer specified by the argument.
*/
public MemoryByteSourceLoader transformer(ByteStreamTransformer transformer) {
BytesTransformer v = transformer == null ? null : BytesTransformer.of(transformer);
if (Objects.equal(this.transformer, v)) {
return this;
}
return new MemoryByteSourceLoader(direct, maxSize, chunkSize, merge, v);
}
private MemoryByteSource merged(MemoryByteSource source) {
if (merge) {
return source.merge();
}
return source;
}
/** Opens a new memory output stream. */
public MemoryOutputStream openStream() {
if (direct) {
return DirectByteSource.openStream(this);
}
return HeapByteSource.openStream(this);
}
/**
* Loads the contents of the input stream into a memory byte source.
* @param is Input stream. It is not closed.
* @return The loaded data in a byte source.
*/
public MemoryByteSource load(InputStream is) throws IOException {
checkNotNull(is, "The input stream to load must be provided");
final MemoryOutputStream os = openStream();
if (transformer != null) {
transformer.transform(is, os);
} else {
ByteStreams.copy(is, os);
}
return os.toByteSource();
}
/** Performs a copy of the provided source. */
MemoryByteSource copy(MemoryByteSource source) {
try {
return load(source.openStream());
} catch (IOException e) {
throw new IllegalStateException(e); // should not happen
}
}
/**
* Transform an existing memory byte source.
*/
private MemoryByteSource transform(MemoryByteSource source) {
checkSize(Ints.saturatedCast(source.size()), maxSize);
final MemoryByteSource transformed;
if (direct) {
transformed = source.toDirect(chunkSize);
} else {
transformed = source.toHeap(chunkSize);
}
return merged(transformed);
}
/**
* Loads the contents of an existing source into a memory byte source.
* @return The loaded data in a byte source.
*/
public MemoryByteSource load(ByteSource source) throws IOException {
checkNotNull(source, "The byte source to load must be provided");
if (transformer == null && source instanceof MemoryByteSource) {
return transform((MemoryByteSource) source);
}
Closer closer = Closer.create();
try {
InputStream is = closer.register(source.openStream());
return load(is);
} catch (Throwable t) {
throw closer.rethrow(t);
} finally {
closer.close();
}
}
/**
* Loads the contents of an existing file into a memory byte source.
* @return The loaded data in a byte source.
*/
public MemoryByteSource load(File file) throws IOException {
checkNotNull(file, "The file to load must be provided");
return load(Files.asByteSource(file));
}
@Override
public int hashCode() {
return Objects.hashCode(direct, maxSize, chunkSize, merge, transformer);
}
@Override
public boolean equals(Object obj) {
if (obj instanceof MemoryByteSourceLoader) {
MemoryByteSourceLoader s = (MemoryByteSourceLoader) obj;
return direct == s.direct && merge == s.merge && maxSize == s.maxSize && chunkSize == s.chunkSize
&& transformer.equals(s.transformer);
}
return false;
}
/** Creates a new sink based on this loader. */
public MemoryByteSink newSink() {
return new MemoryByteSink(this);
}
@Override
public String toString() {
return Objects.toStringHelper(this).omitNullValues().add("direct", direct).add("maxSize", maxSize)
.add("chunkSize", chunkSize).add("merge", merge).add("transformer", transformer).toString();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy