001: /*
002: Derby - Class org.apache.derby.impl.drda.EXTDTAReaderInputStream
003:
004: Licensed to the Apache Software Foundation (ASF) under one
005: or more contributor license agreements. See the NOTICE file
006: distributed with this work for additional information
007: regarding copyright ownership. The ASF licenses this file
008: to you under the Apache License, Version 2.0 (the
009: "License"); you may not use this file except in compliance
010: with the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing,
015: software distributed under the License is distributed on an
016: "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: KIND, either express or implied. See the License for the
018: specific language governing permissions and limitations
019: under the License.
020: */
021: package org.apache.derby.impl.drda;
022:
023: import java.io.InputStream;
024: import java.io.ByteArrayInputStream;
025: import java.io.IOException;
026:
027: /**
028: * Implementation of InputStream which get EXTDTA from the DDMReader.
029: * This class can be used to stream LOBs from Network client to the
030: * Network server.
031: */
032: final class EXTDTAReaderInputStream extends InputStream {
033: /**
034: * Constructor
035: * @param reader The reader to get data from
036: * @exception DRDAProtocolException if thrown while initializing current
037: * buffer.
038: */
039: EXTDTAReaderInputStream(final DDMReader reader)
040: throws DRDAProtocolException {
041: super ();
042: this .reader = reader;
043: this .length = reader.getDdmLength();
044: this .remainingBytes = length;
045: this .currentBuffer = reader.readLOBInitStream(remainingBytes);
046: }
047:
048: /**
049: * Reads the next byte of data from the input stream.
050: *
051: * <p> This subclass of InputStream implements this method by reading
052: * the next byte from the current buffer. If there is more data,
053: * it will be requested a new buffer from the DDMReader.
054: *
055: * @return the next byte of data, or <code>-1</code> if the end of the
056: * stream is reached.
057: * @exception IOException if an I/O error occurs.
058: * @see java.io.InputStream#read()
059: */
060: public final int read() throws IOException {
061: if (remainingBytes <= 0) {
062: return -1;
063: }
064: int val = (currentBuffer == null) ? -1 : currentBuffer.read();
065: if (val < 0) {
066: val = refreshCurrentBuffer();
067: }
068: remainingBytes--;
069: return val;
070: }
071:
072: /**
073: * Reads up to <code>len</code> bytes of data from the input stream into
074: * an array of bytes. An attempt is made to read as many as
075: * <code>len</code> bytes, but a smaller number may be read, possibly
076: * zero. The number of bytes actually read is returned as an integer.
077: *
078: * This subclass implements this method by calling this method on the
079: * current buffer, which is an instance of ByteArrayInputStream. If the
080: * current buffer does not have any data, it will be requested a new
081: * buffer from the DDMReader.
082: *
083: * @param b the buffer into which the data is read.
084: * @param off the start offset in array <code>b</code>
085: * at which the data is written.
086: * @param len the maximum number of bytes to read.
087: * @return the total number of bytes read into the buffer, or
088: * <code>-1</code> if there is no more data because the end of
089: * the stream has been reached.
090: * @exception IOException if an I/O error occurs.
091: * @exception NullPointerException if <code>b</code> is <code>null</code>.
092: * @see java.io.InputStream#read(byte[], int, int)
093: */
094: public final int read(final byte[] b, final int off, final int len)
095: throws IOException {
096: if (remainingBytes <= 0) {
097: return -1;
098: }
099: int val = currentBuffer.read(b, off, len);
100: if (val < 0) {
101: currentBuffer = reader
102: .readLOBContinuationStream(remainingBytes);
103: val = currentBuffer.read(b, off, len);
104: }
105: remainingBytes -= val;
106: return val;
107: }
108:
109: /**
110: * Returns the number of bytes that can be read (or skipped over) from
111: * this input stream without blocking by the next caller of a method for
112: * this input stream.
113: *
114: * <p> This subclass implements this method by calling available on
115: * the current buffer, which is a ByteInputStreamReader.
116: *
117: * @return the number of bytes that can be read from this input stream
118: * without blocking.
119: */
120: public final int available() {
121: if (remainingBytes <= 0) {
122: return 0;
123: }
124: return currentBuffer.available();
125: }
126:
127: /**
128: * Return the length if this stream. The length includes data which has
129: * been read.
130: * @return length of this stream.
131: */
132: final long getLength() {
133: return length;
134: }
135:
136: /**
137: * Refresh the current buffer from the DDMReader
138: * @exception IOException if there is a IOException when
139: * refreshing the buffer from DDMReader
140: * @return the next byte of data, or <code>-1</code> if the end of the
141: * stream is reached.
142: */
143: private int refreshCurrentBuffer() throws IOException {
144: if (remainingBytes > 0) {
145: currentBuffer = reader
146: .readLOBContinuationStream(remainingBytes);
147: return currentBuffer.read();
148: } else {
149: return -1;
150: }
151: }
152:
153: /** Length of stream */
154: private final long length;
155:
156: /** DDMReader. Used to get more data. */
157: private final DDMReader reader;
158:
159: /** Remaining bytes in stream */
160: private long remainingBytes;
161:
162: /** Current data buffer */
163: private ByteArrayInputStream currentBuffer;
164:
165: }
|