001: package org.jvnet.staxex;
002:
003: import javax.activation.DataHandler;
004: import javax.activation.DataSource;
005: import java.io.BufferedInputStream;
006: import java.io.File;
007: import java.io.IOException;
008: import java.io.InputStream;
009: import java.net.URL;
010:
011: /**
012: * {@link DataHandler} extended to offer better buffer management
013: * in a streaming environment.
014: *
015: * <p>
016: * {@link DataHandler} is used commonly as a data format across
017: * multiple systems (such as JAXB/WS.) Unfortunately, {@link DataHandler}
018: * has the semantics of "read as many times as you want", so this makes
019: * it difficult for involving parties to handle a BLOB in a streaming fashion.
020: *
021: * <p>
022: * {@link StreamingDataHandler} solves this problem by offering methods
023: * that enable faster bulk "consume once" read operation.
024: *
025: * @author Jitendra Kotamraju
026: */
027: public abstract class StreamingDataHandler extends DataHandler {
028:
029: public StreamingDataHandler(Object o, String s) {
030: super (o, s);
031: }
032:
033: public StreamingDataHandler(URL url) {
034: super (url);
035: }
036:
037: public StreamingDataHandler(DataSource dataSource) {
038: super (dataSource);
039: }
040:
041: /**
042: * Works like {@link #getInputStream()} except that this method
043: * can be invoked only once.
044: *
045: * <p>
046: * This is used as a signal from the caller that there will
047: * be no further {@link #getInputStream()} invocation nor
048: * {@link #readOnce()} invocation on this object (which would
049: * result in {@link IOException}.)
050: *
051: * <p>
052: * When {@link DataHandler} is backed by a streaming BLOB
053: * (such as an attachment in a web service read from the network),
054: * this allows the callee to avoid unnecessary buffering.
055: *
056: * <p>
057: * Note that it is legal to call {@link #getInputStream()}
058: * multiple times and then call {@link #readOnce()} afterward.
059: * Streams created such a way can be read in any order —
060: * there's no requirement that streams created earlier must be read
061: * first.
062: *
063: * @return
064: * always non-null. Represents the content of this BLOB.
065: * The returned stream is generally not buffered, so for
066: * better performance read in a big batch or wrap this into
067: * {@link BufferedInputStream}.
068: * @throws IOException
069: * if any i/o error
070: */
071: public abstract InputStream readOnce() throws IOException;
072:
073: /**
074: * Obtains the BLOB into a specified file.
075: *
076: * <p>
077: * Semantically, this method is roughly equivalent to the following
078: * code, except that the actual implementation is likely to be a lot faster.
079: *
080: * <pre>
081: * InputStream i = getInputStream();
082: * OutputStream o = new FileOutputStream(dst);
083: * int ch;
084: * while((ch=i.read())!=-1) o.write(ch);
085: * i.close();
086: * o.close();
087: * </pre>
088: *
089: * <p>
090: * The main motivation behind this method is that often
091: * {@link DataHandler} that reads data from a streaming source
092: * will use a temporary file as a data store to hold data
093: * (think of commons-fileupload.) In such case this method
094: * can be as fast as calling {@link File#renameTo(File)}.
095: *
096: * <p>
097: * This method shouldn't be called when there are any
098: * open streams.
099: *
100: * <p>
101: * After this method is invoked, {@link #readOnce()} and
102: * {@link #getInputStream()} will simply open the destination
103: * file you've specified as an argument. So if you further
104: * move the file or delete this file, those methods will
105: * behave in undefined fashion. For a simliar reason,
106: * calling this method multiple times will cause
107: * undefined behavior.
108: */
109: public abstract void moveTo(File dst) throws IOException;
110:
111: /**
112: * Releases any resources associated with this DataHandler.
113: * (such as an attachment in a web service read from a temp
114: * file will be deleted.) After calling this method, it is
115: * illegal to call any other methods.
116: */
117: public abstract void close() throws IOException;
118:
119: }
|