001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.resource.adapter.jdbc.remote;
023:
024: import java.io.IOException;
025: import java.io.InputStream;
026: import java.io.Serializable;
027: import java.util.ArrayList;
028: import java.util.List;
029: import java.util.Iterator;
030:
031: /**
032: * @author <a href="mailto:telrod@e2technologies.net">Tom Elrod</a>
033: * @version $Revision: 57189 $
034: */
035: public class SerializableInputStream extends InputStream implements
036: Serializable {
037: /** @since 1.2 */
038: static final long serialVersionUID = 3364193722688048342L;
039:
040: private byte[] data = null;
041:
042: protected byte buf[];
043: protected int pos;
044: protected int mark = 0;
045: protected int count;
046:
047: public SerializableInputStream(InputStream ins) throws IOException {
048: List byteList = new ArrayList();
049: int dat = ins.read();
050: while (dat != -1) {
051: byteList.add(new Byte((byte) dat));
052: dat = ins.read();
053: }
054:
055: data = new byte[byteList.size()];
056: int counter = 0;
057: Iterator itr = byteList.iterator();
058: while (itr.hasNext()) {
059: data[counter++] = ((Byte) itr.next()).byteValue();
060: }
061: ins.close();
062: this .buf = this .data;
063: this .pos = 0;
064: this .count = this .buf.length;
065:
066: }
067:
068: /**
069: * Returns the number of bytes that can be read (or skipped over) from
070: * this input stream without blocking by the next caller of a method for
071: * this input stream. The next caller might be the same thread or or
072: * another thread.
073: * <p/>
074: * <p> The <code>available</code> method for class <code>InputStream</code>
075: * always returns <code>0</code>.
076: * <p/>
077: * <p> This method should be overridden by subclasses.
078: *
079: * @return the number of bytes that can be read from this input stream
080: * without blocking.
081: */
082: public synchronized int available() {
083: return count - pos;
084: }
085:
086: /**
087: * Closes this input stream and releases any system resources associated
088: * with the stream.
089: * <p/>
090: * <p> The <code>close</code> method of <code>InputStream</code> does
091: * nothing.
092: *
093: * @throws java.io.IOException if an I/O error occurs.
094: */
095: public void close() throws IOException {
096: System.err.println("close()");
097: }
098:
099: /**
100: * Repositions this stream to the position at the time the
101: * <code>mark</code> method was last called on this input stream.
102: * <p/>
103: * <p> The general contract of <code>reset</code> is:
104: * <p/>
105: * <p><ul>
106: * <p/>
107: * <li> If the method <code>markSupported</code> returns
108: * <code>true</code>, then:
109: * <p/>
110: * <ul><li> If the method <code>mark</code> has not been called since
111: * the stream was created, or the number of bytes read from the stream
112: * since <code>mark</code> was last called is larger than the argument
113: * to <code>mark</code> at that last call, then an
114: * <code>IOException</code> might be thrown.
115: * <p/>
116: * <li> If such an <code>IOException</code> is not thrown, then the
117: * stream is reset to a state such that all the bytes read since the
118: * most recent call to <code>mark</code> (or since the start of the
119: * file, if <code>mark</code> has not been called) will be resupplied
120: * to subsequent callers of the <code>read</code> method, followed by
121: * any bytes that otherwise would have been the next input data as of
122: * the time of the call to <code>reset</code>. </ul>
123: * <p/>
124: * <li> If the method <code>markSupported</code> returns
125: * <code>false</code>, then:
126: * <p/>
127: * <ul><li> The call to <code>reset</code> may throw an
128: * <code>IOException</code>.
129: * <p/>
130: * <li> If an <code>IOException</code> is not thrown, then the stream
131: * is reset to a fixed state that depends on the particular type of the
132: * input stream and how it was created. The bytes that will be supplied
133: * to subsequent callers of the <code>read</code> method depend on the
134: * particular type of the input stream. </ul></ul>
135: * <p/>
136: * <p> The method <code>reset</code> for class <code>InputStream</code>
137: * does nothing and always throws an <code>IOException</code>.
138: *
139: * @throws java.io.IOException if this stream has not been marked or if the
140: * mark has been invalidated.
141: * @see java.io.InputStream#mark(int)
142: * @see java.io.IOException
143: */
144: public synchronized void reset() throws IOException {
145: System.err.println("reset()");
146: }
147:
148: /**
149: * Tests if this input stream supports the <code>mark</code> and
150: * <code>reset</code> methods. Whether or not <code>mark</code> and
151: * <code>reset</code> are supported is an invariant property of a
152: * particular input stream instance. The <code>markSupported</code> method
153: * of <code>InputStream</code> returns <code>false</code>.
154: *
155: * @return <code>true</code> if this stream instance supports the mark
156: * and reset methods; <code>false</code> otherwise.
157: * @see java.io.InputStream#mark(int)
158: * @see java.io.InputStream#reset()
159: */
160: public boolean markSupported() {
161: System.err.println("markSupported()");
162: return false;
163: }
164:
165: /**
166: * Marks the current position in this input stream. A subsequent call to
167: * the <code>reset</code> method repositions this stream at the last marked
168: * position so that subsequent reads re-read the same bytes.
169: * <p/>
170: * <p> The <code>readlimit</code> arguments tells this input stream to
171: * allow that many bytes to be read before the mark position gets
172: * invalidated.
173: * <p/>
174: * <p> The general contract of <code>mark</code> is that, if the method
175: * <code>markSupported</code> returns <code>true</code>, the stream somehow
176: * remembers all the bytes read after the call to <code>mark</code> and
177: * stands ready to supply those same bytes again if and whenever the method
178: * <code>reset</code> is called. However, the stream is not required to
179: * remember any data at all if more than <code>readlimit</code> bytes are
180: * read from the stream before <code>reset</code> is called.
181: * <p/>
182: * <p> The <code>mark</code> method of <code>InputStream</code> does
183: * nothing.
184: *
185: * @param readlimit the maximum limit of bytes that can be read before
186: * the mark position becomes invalid.
187: * @see java.io.InputStream#reset()
188: */
189: public synchronized void mark(int readlimit) {
190: System.err.println("mark(int readlimit)");
191: }
192:
193: /**
194: * Skips over and discards <code>n</code> bytes of data from this input
195: * stream. The <code>skip</code> method may, for a variety of reasons, end
196: * up skipping over some smaller number of bytes, possibly <code>0</code>.
197: * This may result from any of a number of conditions; reaching end of file
198: * before <code>n</code> bytes have been skipped is only one possibility.
199: * The actual number of bytes skipped is returned. If <code>n</code> is
200: * negative, no bytes are skipped.
201: * <p/>
202: * <p> The <code>skip</code> method of <code>InputStream</code> creates a
203: * byte array and then repeatedly reads into it until <code>n</code> bytes
204: * have been read or the end of the stream has been reached. Subclasses are
205: * encouraged to provide a more efficient implementation of this method.
206: *
207: * @param n the number of bytes to be skipped.
208: * @return the actual number of bytes skipped.
209: * @throws java.io.IOException if an I/O error occurs.
210: */
211: public long skip(long n) throws IOException {
212: System.err.println("skip(long n)");
213: return 0;
214: }
215:
216: /**
217: * Reads some number of bytes from the input stream and stores them into
218: * the buffer array <code>b</code>. The number of bytes actually read is
219: * returned as an integer. This method blocks until input data is
220: * available, end of file is detected, or an exception is thrown.
221: * <p/>
222: * <p> If <code>b</code> is <code>null</code>, a
223: * <code>NullPointerException</code> is thrown. If the length of
224: * <code>b</code> is zero, then no bytes are read and <code>0</code> is
225: * returned; otherwise, there is an attempt to read at least one byte. If
226: * no byte is available because the stream is at end of file, the value
227: * <code>-1</code> is returned; otherwise, at least one byte is read and
228: * stored into <code>b</code>.
229: * <p/>
230: * <p> The first byte read is stored into element <code>b[0]</code>, the
231: * next one into <code>b[1]</code>, and so on. The number of bytes read is,
232: * at most, equal to the length of <code>b</code>. Let <i>k</i> be the
233: * number of bytes actually read; these bytes will be stored in elements
234: * <code>b[0]</code> through <code>b[</code><i>k</i><code>-1]</code>,
235: * leaving elements <code>b[</code><i>k</i><code>]</code> through
236: * <code>b[b.length-1]</code> unaffected.
237: * <p/>
238: * <p> If the first byte cannot be read for any reason other than end of
239: * file, then an <code>IOException</code> is thrown. In particular, an
240: * <code>IOException</code> is thrown if the input stream has been closed.
241: * <p/>
242: * <p> The <code>read(b)</code> method for class <code>InputStream</code>
243: * has the same effect as: <pre><code> read(b, 0, b.length) </code></pre>
244: *
245: * @param b the buffer into which the data is read.
246: * @return the total number of bytes read into the buffer, or
247: * <code>-1</code> is there is no more data because the end of
248: * the stream has been reached.
249: * @throws java.io.IOException if an I/O error occurs.
250: * @throws NullPointerException if <code>b</code> is <code>null</code>.
251: * @see java.io.InputStream#read(byte[], int, int)
252: */
253: public int read(byte b[]) throws IOException {
254: System.err.println("read(byte b[])");
255: return read(b, 0, data.length);
256: }
257:
258: /**
259: * Reads up to <code>len</code> bytes of data from the input stream into
260: * an array of bytes. An attempt is made to read as many as
261: * <code>len</code> bytes, but a smaller number may be read, possibly
262: * zero. The number of bytes actually read is returned as an integer.
263: * <p/>
264: * <p> This method blocks until input data is available, end of file is
265: * detected, or an exception is thrown.
266: * <p/>
267: * <p> If <code>b</code> is <code>null</code>, a
268: * <code>NullPointerException</code> is thrown.
269: * <p/>
270: * <p> If <code>off</code> is negative, or <code>len</code> is negative, or
271: * <code>off+len</code> is greater than the length of the array
272: * <code>b</code>, then an <code>IndexOutOfBoundsException</code> is
273: * thrown.
274: * <p/>
275: * <p> If <code>len</code> is zero, then no bytes are read and
276: * <code>0</code> is returned; otherwise, there is an attempt to read at
277: * least one byte. If no byte is available because the stream is at end of
278: * file, the value <code>-1</code> is returned; otherwise, at least one
279: * byte is read and stored into <code>b</code>.
280: * <p/>
281: * <p> The first byte read is stored into element <code>b[off]</code>, the
282: * next one into <code>b[off+1]</code>, and so on. The number of bytes read
283: * is, at most, equal to <code>len</code>. Let <i>k</i> be the number of
284: * bytes actually read; these bytes will be stored in elements
285: * <code>b[off]</code> through <code>b[off+</code><i>k</i><code>-1]</code>,
286: * leaving elements <code>b[off+</code><i>k</i><code>]</code> through
287: * <code>b[off+len-1]</code> unaffected.
288: * <p/>
289: * <p> In every case, elements <code>b[0]</code> through
290: * <code>b[off]</code> and elements <code>b[off+len]</code> through
291: * <code>b[b.length-1]</code> are unaffected.
292: * <p/>
293: * <p> If the first byte cannot be read for any reason other than end of
294: * file, then an <code>IOException</code> is thrown. In particular, an
295: * <code>IOException</code> is thrown if the input stream has been closed.
296: * <p/>
297: * <p> The <code>read(b,</code> <code>off,</code> <code>len)</code> method
298: * for class <code>InputStream</code> simply calls the method
299: * <code>read()</code> repeatedly. If the first such call results in an
300: * <code>IOException</code>, that exception is returned from the call to
301: * the <code>read(b,</code> <code>off,</code> <code>len)</code> method. If
302: * any subsequent call to <code>read()</code> results in a
303: * <code>IOException</code>, the exception is caught and treated as if it
304: * were end of file; the bytes read up to that point are stored into
305: * <code>b</code> and the number of bytes read before the exception
306: * occurred is returned. Subclasses are encouraged to provide a more
307: * efficient implementation of this method.
308: *
309: * @param b the buffer into which the data is read.
310: * @param off the start offset in array <code>b</code>
311: * at which the data is written.
312: * @param len the maximum number of bytes to read.
313: * @return the total number of bytes read into the buffer, or
314: * <code>-1</code> if there is no more data because the end of
315: * the stream has been reached.
316: * @throws NullPointerException if <code>b</code> is <code>null</code>.
317: * @see java.io.InputStream#read()
318: */
319: public synchronized int read(byte b[], int off, int len) {
320: if (b == null) {
321: throw new NullPointerException();
322: } else if ((off < 0) || (off > b.length) || (len < 0)
323: || ((off + len) > b.length) || ((off + len) < 0)) {
324: throw new IndexOutOfBoundsException();
325: }
326: if (pos >= count) {
327: return -1;
328: }
329: if (pos + len > count) {
330: len = count - pos;
331: }
332: if (len <= 0) {
333: return 0;
334: }
335: System.arraycopy(buf, pos, b, off, len);
336: pos += len;
337: return len;
338: }
339:
340: /**
341: * Reads the next byte of data from the input stream. The value byte is
342: * returned as an <code>int</code> in the range <code>0</code> to
343: * <code>255</code>. If no byte is available because the end of the stream
344: * has been reached, the value <code>-1</code> is returned. This method
345: * blocks until input data is available, the end of the stream is detected,
346: * or an exception is thrown.
347: * <p/>
348: * <p> A subclass must provide an implementation of this method.
349: *
350: * @return the next byte of data, or <code>-1</code> if the end of the
351: * stream is reached.
352: */
353: public synchronized int read() {
354: return (pos < count) ? (buf[pos++] & 0xff) : -1;
355: }
356: }
|