/* * (c) Rob Gordon 2005 */ package org.oddjob.io; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.OutputStream; import java.io.PrintStream; import java.io.Serializable; import java.util.ArrayList; import java.util.List; import org.oddjob.arooa.ArooaValue; import org.oddjob.arooa.convert.ConversionProvider; import org.oddjob.arooa.convert.ConversionRegistry; import org.oddjob.arooa.convert.Convertlet; import org.oddjob.arooa.deploy.annotations.ArooaText; import org.oddjob.arooa.life.ArooaLifeAware; /** * @oddjob.description A buffer can be used to accumulate output from * one or more jobs which can then be used as input to another job. * <p> * A buffer can be used wherever input or output can be specified. A job * <p> * A buffer can be initialised with text, or lines of text and will can * also provide it's contents as text. * <p> * * @oddjob.example * * Capturing the contents of a file in a buffer. * * {@oddjob.xml.resource org/oddjob/io/BufferFileCaptureExample.xml} * * @oddjob.example * * Accumulate output in a buffer. * * {@oddjob.xml.resource org/oddjob/io/BufferAppendExample.xml} * * @oddjob.example * * Write the contents of a buffer to file. This example also shows * initialising the buffer with a list. * * {@oddjob.xml.resource org/oddjob/io/BufferToFileExample.xml} * * @oddjob.example * * Using the contents of a buffer as lines. This also shows how a buffer * can be initialised with text. * * {@oddjob.xml.resource org/oddjob/io/BufferAsLinesExample.xml} * */ public class BufferType implements ArooaValue, ArooaLifeAware, Serializable { private static final long serialVersionUID = 2013042500L; public static class Conversions implements ConversionProvider { public void registerWith(ConversionRegistry registry) { registry.register(BufferType.class, String.class, new Convertlet<BufferType, String>() { public String convert(BufferType from) { return from.getText(); } }); registry.register(BufferType.class, InputStream.class, new Convertlet<BufferType, InputStream>() { public InputStream convert(BufferType from) { return from.toInputStream(); } }); registry.register(BufferType.class, OutputStream.class, new Convertlet<BufferType, OutputStream>() { public OutputStream convert(BufferType from) { return from.toOutputStream(); } }); registry.register(BufferType.class, String[].class, new Convertlet<BufferType, String[]>() { public String[] convert(BufferType from) { return from.getLines(); } }); } } private volatile ByteArrayOutputStream buffer; private volatile transient String text; private volatile transient String[] lines; public InputStream toInputStream() { if (buffer == null) { return null; } else { final byte[] bytes = buffer.toByteArray(); return new ByteArrayInputStream(bytes) { public String toString() { return BufferType.class.getSimpleName() + " InputStream: " + bytes.length + " bytes"; } }; } } public OutputStream toOutputStream() { return buffer; } /** * @oddjob.property text * @oddjob.description The buffer as a text property. Either set the * buffer contents from text or get the buffer contents as text. * @oddjob.required No. * * @param text * * @throws IOException */ @ArooaText public void setText(String text) throws IOException { this.text = text; } public String getText() { if (buffer == null) { return null; } else { return new String(buffer.toByteArray()); } } public String[] getLines() { try { InputStream inputStream = toInputStream(); if (inputStream == null) { return null; } BufferedReader reader = new BufferedReader( new InputStreamReader(inputStream)); List<String> lines = new ArrayList<String>(); while (true) { String line = reader.readLine(); if (line == null) { break; } lines.add(line); } return lines.toArray(new String[lines.size()]); } catch (IOException e) { throw new RuntimeException(e); } } /** * @oddjob.property lines * @oddjob.description The buffer contents as an array of lines. Either set the contents to be the array * or read the contents of the buffer as an array. * @oddjob.required No. * */ public void setLines(String[] lines) { this.lines = lines; } @Override public void initialised() { } @Override public void configured() { buffer = new BufferTypeOutputStream(); if (text != null) { try { buffer.write(text.getBytes()); } catch (IOException e) { throw new RuntimeException(e); } } if (lines != null) { PrintStream print = new PrintStream(buffer); for (String line: lines) { print.println(line); } print.flush(); } } @Override public void destroy() { buffer = null; } public String toString() { return "BufferType: " + (buffer == null ? "unconfigured" : buffer.size() + " bytes"); } static class BufferTypeOutputStream extends ByteArrayOutputStream implements Serializable { private static final long serialVersionUID = 2013042500L; /** * Custom serialisation. */ private void writeObject(ObjectOutputStream s) throws IOException { s.defaultWriteObject(); byte[] bytes = this.toByteArray(); s.writeInt(bytes.length); s.write(bytes); } /** * Custom serialisation. */ private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { s.defaultReadObject(); int size = s.readInt(); byte[] bytes = new byte[size]; s.read(bytes); write(bytes); } @Override public synchronized String toString() { return BufferType.class.getSimpleName() + " OutputStream: " + size() + " bytes"; } } }