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 26 package com.sun.xml.internal.org.jvnet.staxex; 27 28 import javax.activation.DataHandler; 29 import javax.activation.DataSource; 30 import java.io.BufferedInputStream; 31 import java.io.Closeable; 32 import java.io.File; 33 import java.io.IOException; 34 import java.io.InputStream; 35 import 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 */ 53 public 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 — 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 }