--- /dev/null
+/*\r
+ Derby - Class org.apache.derby.impl.drda.StandardEXTDTAReaderInputStream\r
+\r
+ Licensed to the Apache Software Foundation (ASF) under one\r
+ or more contributor license agreements. See the NOTICE file\r
+ distributed with this work for additional information\r
+ regarding copyright ownership. The ASF licenses this file\r
+ to you under the Apache License, Version 2.0 (the\r
+ "License"); you may not use this file except in compliance\r
+ with the License. You may obtain a copy of the License at\r
+ \r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+ \r
+ Unless required by applicable law or agreed to in writing,\r
+ software distributed under the License is distributed on an\r
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY\r
+ KIND, either express or implied. See the License for the\r
+ specific language governing permissions and limitations\r
+ under the License.\r
+*/\r
+package org.apache.derby.impl.drda;\r
+import java.io.InputStream;\r
+import java.io.ByteArrayInputStream;\r
+import java.io.IOException;\r
+\r
+/**\r
+ * Implementation of InputStream which get EXTDTA from the DDMReader.\r
+ * This class can be used to stream LOBs from Network client to the\r
+ * Network server.\r
+ */\r
+final class StandardEXTDTAReaderInputStream extends EXTDTAReaderInputStream \r
+{\r
+ /**\r
+ * Constructor\r
+ * @param reader The reader to get data from\r
+ * @exception DRDAProtocolException if thrown while initializing current \r
+ * buffer.\r
+ */\r
+ StandardEXTDTAReaderInputStream(final DDMReader reader) \r
+ throws DRDAProtocolException\r
+ {\r
+ super();\r
+ this.reader = reader;\r
+ this.length = reader.getDdmLength(); \r
+ this.remainingBytes = length;\r
+ this.currentBuffer = \r
+ reader.readLOBInitStream(remainingBytes);\r
+ }\r
+\r
+ /**\r
+ * Reads the next byte of data from the input stream.\r
+ * \r
+ * <p> This subclass of InputStream implements this method by reading\r
+ * the next byte from the current buffer. If there is more data,\r
+ * it will be requested a new buffer from the DDMReader.\r
+ *\r
+ * @return the next byte of data, or <code>-1</code> if the end of the\r
+ * stream is reached.\r
+ * @exception IOException if an I/O error occurs.\r
+ * @see java.io.InputStream#read()\r
+ */\r
+ public final int read() \r
+ throws IOException\r
+ {\r
+ if (remainingBytes <= 0) {\r
+ return -1;\r
+ }\r
+ int val = (currentBuffer == null) ? -1 : currentBuffer.read();\r
+ if (val < 0) {\r
+ val = refreshCurrentBuffer();\r
+ }\r
+ remainingBytes--;\r
+ return val;\r
+ }\r
+ \r
+ /**\r
+ * Reads up to <code>len</code> bytes of data from the input stream into\r
+ * an array of bytes. An attempt is made to read as many as\r
+ * <code>len</code> bytes, but a smaller number may be read, possibly\r
+ * zero. The number of bytes actually read is returned as an integer.\r
+ *\r
+ * This subclass implements this method by calling this method on the \r
+ * current buffer, which is an instance of ByteArrayInputStream. If the\r
+ * current buffer does not have any data, it will be requested a new\r
+ * buffer from the DDMReader.\r
+ *\r
+ * @param b the buffer into which the data is read.\r
+ * @param off the start offset in array <code>b</code>\r
+ * at which the data is written.\r
+ * @param len the maximum number of bytes to read.\r
+ * @return the total number of bytes read into the buffer, or\r
+ * <code>-1</code> if there is no more data because the end of\r
+ * the stream has been reached.\r
+ * @exception IOException if an I/O error occurs.\r
+ * @exception NullPointerException if <code>b</code> is <code>null</code>.\r
+ * @see java.io.InputStream#read(byte[], int, int)\r
+ */\r
+ public final int read(final byte[] b,\r
+ final int off,\r
+ final int len) \r
+ throws IOException\r
+ {\r
+ if (remainingBytes <= 0) {\r
+ return -1;\r
+ }\r
+ int val = currentBuffer.read(b, off, len);\r
+ if (val < 0) {\r
+ currentBuffer = \r
+ reader.readLOBContinuationStream(remainingBytes);\r
+ val = currentBuffer.read(b, off, len);\r
+ }\r
+ remainingBytes -= val;\r
+ return val;\r
+ }\r
+\r
+ /**\r
+ * Returns the number of bytes that can be read (or skipped over) from\r
+ * this input stream without blocking by the next caller of a method for\r
+ * this input stream. \r
+ *\r
+ * <p> This subclass implements this method by calling available on \r
+ * the current buffer, which is a ByteInputStreamReader.\r
+ *\r
+ * @return the number of bytes that can be read from this input stream\r
+ * without blocking. \r
+ */\r
+ public final int available() \r
+ {\r
+ if (remainingBytes <= 0) {\r
+ return 0;\r
+ }\r
+ return currentBuffer.available();\r
+ }\r
+\r
+ /**\r
+ * Return the length if this stream. The length includes data which has \r
+ * been read.\r
+ * @return length of this stream.\r
+ */\r
+ final long getLength() \r
+ {\r
+ return length;\r
+ }\r
+ \r
+ /**\r
+ * Refresh the current buffer from the DDMReader\r
+ * @exception IOException if there is a IOException when\r
+ * refreshing the buffer from DDMReader\r
+ * @return the next byte of data, or <code>-1</code> if the end of the\r
+ * stream is reached.\r
+ */\r
+ private int refreshCurrentBuffer() \r
+ throws IOException\r
+ {\r
+ if (remainingBytes > 0) {\r
+ currentBuffer = \r
+ reader.readLOBContinuationStream(remainingBytes);\r
+ return currentBuffer.read();\r
+ } else {\r
+ return -1;\r
+ }\r
+ }\r
+ \r
+ /** Length of stream */\r
+ private final long length;\r
+ \r
+ /** DDMReader. Used to get more data. */\r
+ private final DDMReader reader;\r
+ \r
+ /** Remaining bytes in stream */\r
+ private long remainingBytes;\r
+ \r
+ /** Current data buffer */\r
+ private ByteArrayInputStream currentBuffer;\r
+\r
+}\r