1/*
2 * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.xml.internal.org.jvnet.staxex;
27
28import javax.activation.DataHandler;
29import javax.activation.DataSource;
30import java.io.BufferedInputStream;
31import java.io.Closeable;
32import java.io.File;
33import java.io.IOException;
34import java.io.InputStream;
35import java.net.URL;
36
37/**
38 * {@link DataHandler} extended to offer better buffer management
39 * in a streaming environment.
40 *
41 * <p>
42 * {@link DataHandler} is used commonly as a data format across
43 * multiple systems (such as JAXB/WS.) Unfortunately, {@link DataHandler}
44 * has the semantics of "read as many times as you want", so this makes
45 * it difficult for involving parties to handle a BLOB in a streaming fashion.
46 *
47 * <p>
48 * {@link StreamingDataHandler} solves this problem by offering methods
49 * that enable faster bulk "consume once" read operation.
50 *
51 * @author Jitendra Kotamraju
52 */
53public abstract class StreamingDataHandler extends DataHandler implements Closeable {
54
55    private String hrefCid;
56
57    public StreamingDataHandler(Object o, String s) {
58        super(o, s);
59    }
60
61    public StreamingDataHandler(URL url) {
62        super(url);
63    }
64
65    public StreamingDataHandler(DataSource dataSource) {
66        super(dataSource);
67    }
68
69    /**
70     * Works like {@link #getInputStream()} except that this method
71     * can be invoked only once.
72     *
73     * <p>
74     * This is used as a signal from the caller that there will
75     * be no further {@link #getInputStream()} invocation nor
76     * {@link #readOnce()} invocation on this object (which would
77     * result in {@link IOException}.)
78     *
79     * <p>
80     * When {@link DataHandler} is backed by a streaming BLOB
81     * (such as an attachment in a web service read from the network),
82     * this allows the callee to avoid unnecessary buffering.
83     *
84     * <p>
85     * Note that it is legal to call {@link #getInputStream()}
86     * multiple times and then call {@link #readOnce()} afterward.
87     * Streams created such a way can be read in any order &mdash;
88     * there's no requirement that streams created earlier must be read
89     * first.
90     *
91     * @return
92     *      always non-null. Represents the content of this BLOB.
93     *      The returned stream is generally not buffered, so for
94     *      better performance read in a big batch or wrap this into
95     *      {@link BufferedInputStream}.
96     * @throws IOException
97     *      if any i/o error
98     */
99    public abstract InputStream readOnce() throws IOException;
100
101    /**
102     * Obtains the BLOB into a specified file.
103     *
104     * <p>
105     * Semantically, this method is roughly equivalent to the following
106     * code, except that the actual implementation is likely to be a lot faster.
107     *
108     * <pre>
109     * InputStream i = getInputStream();
110     * OutputStream o = new FileOutputStream(dst);
111     * int ch;
112     * while((ch=i.read())!=-1)  o.write(ch);
113     * i.close();
114     * o.close();
115     * </pre>
116     *
117     * <p>
118     * The main motivation behind this method is that often
119     * {@link DataHandler} that reads data from a streaming source
120     * will use a temporary file as a data store to hold data
121     * (think of commons-fileupload.) In such case this method
122     * can be as fast as calling {@link File#renameTo(File)}.
123     *
124     * <p>
125     * This method shouldn't be called when there are any
126     * open streams.
127     *
128     * <p>
129     * After this method is invoked, {@link #readOnce()} and
130     * {@link #getInputStream()} will simply open the destination
131     * file you've specified as an argument. So if you further
132     * move the file or delete this file, those methods will
133     * behave in undefined fashion. For a simliar reason,
134     * calling this method multiple times will cause
135     * undefined behavior.
136     */
137    public abstract void moveTo(File dst) throws IOException;
138
139    /**
140     * Releases any resources associated with this DataHandler.
141     * (such as an attachment in a web service read from a temp
142     * file will be deleted.) After calling this method, it is
143     * illegal to call any other methods.
144     */
145    public abstract void close() throws IOException;
146
147    public String getHrefCid() {
148        return hrefCid;
149    }
150
151    public void setHrefCid(final String cid) {
152        this.hrefCid = cid;
153    }
154}
155