package org.docbag.template; import java.io.IOException; import java.io.InputStream; import java.nio.channels.Channels; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; import org.docbag.stream.ChannelUtil; import org.docbag.stream.CloseableUtil; import org.docbag.stream.MemoryInputStream; import org.docbag.stream.MemoryOutputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Implementation of {@link DocumentTemplateStream} that reads another DocumentTemplateStream into memory * and caches it for the later use. * * <p>This behavior is particularly useful for {@link org.docbag.template.repo.DocumentTemplateRepository}</p> * * @author Jakub Torbicki */ public class CachedDocumentTemplateStream implements DocumentTemplateStream { private MemoryInputStream memory; private final String name; private int count; public static final CachedDocumentTemplateStream newInstance(DocumentTemplateStream templateStream) throws IOException { return new CachedDocumentTemplateStream(templateStream.getName()).cacheTemplate(templateStream); } private CachedDocumentTemplateStream(String name) { this.name = name; } private CachedDocumentTemplateStream cacheTemplate(DocumentTemplateStream templateStream) throws IOException { final ReadableByteChannel inputChannel = Channels.newChannel(templateStream.getStream()); MemoryOutputStream output = new MemoryOutputStream(); final WritableByteChannel outputChannel = Channels.newChannel(output); try { ChannelUtil.copyChannel(inputChannel, outputChannel); memory = new MemoryInputStream(output); count = output.getCount(); } finally { CloseableUtil.close(inputChannel); CloseableUtil.close(outputChannel); } return this; } /** * @see DocumentTemplateStream#getStream() */ public InputStream getStream() { // Wrap memory up with new object, so the "position" attribute is reset, thus allowing stream to be reused across different threads return new MemoryInputStream(memory); } /** * @see DocumentTemplateStream#getName() */ public String getName() { return name; } /** * Size of the stream in bytes */ public int getCount() { return count; } }