Adding JMCR-Stable version
[Benchmarks_CSolver.git] / JMCR-Stable / real-world application / MyDerby-10.3 / java / engine / org / apache / derby / impl / jdbc / UTF8Reader.java
diff --git a/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/impl/jdbc/UTF8Reader.java b/JMCR-Stable/real-world application/MyDerby-10.3/java/engine/org/apache/derby/impl/jdbc/UTF8Reader.java
new file mode 100644 (file)
index 0000000..e522f69
--- /dev/null
@@ -0,0 +1,448 @@
+/*\r
+\r
+   Derby - Class org.apache.derby.impl.jdbc.UTF8Reader\r
+\r
+   Licensed to the Apache Software Foundation (ASF) under one or more\r
+   contributor license agreements.  See the NOTICE file distributed with\r
+   this work for additional information regarding copyright ownership.\r
+   The ASF licenses this file to you under the Apache License, Version 2.0\r
+   (the "License"); you may not use this file except in compliance with\r
+   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, software\r
+   distributed under the License is distributed on an "AS IS" BASIS,\r
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+   See the License for the specific language governing permissions and\r
+   limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.impl.jdbc;\r
+\r
+import java.io.BufferedInputStream;\r
+import java.io.InputStream;\r
+import java.io.Reader;\r
+import java.io.IOException;\r
+import java.io.UTFDataFormatException;\r
+import java.io.EOFException;\r
+import java.sql.SQLException;\r
+\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+import org.apache.derby.iapi.types.Resetable;\r
+\r
+/**\r
+*/\r
+public final class UTF8Reader extends Reader\r
+{\r
+\r
+    private InputStream in;\r
+    /** Stream store that can reposition itself on request. */\r
+    private final PositionedStoreStream positionedIn;\r
+    /** Store last visited position in the store stream. */\r
+    private long rawStreamPos = 0L;\r
+    private final long utfLen;          // bytes\r
+    private long       utfCount;        // bytes\r
+    private long       readerCharCount; // characters\r
+    private long       maxFieldSize;    // characeters\r
+\r
+    private char[]         buffer = new char[8 * 1024];\r
+    private int            charactersInBuffer; // within buffer\r
+    private int            readPositionInBuffer;\r
+\r
+    private boolean noMoreReads;\r
+\r
+    // maintain a reference to the parent object so that it can't get\r
+    // garbage collected until we are done with the stream.\r
+    private ConnectionChild parent;\r
+\r
+    public UTF8Reader(\r
+        InputStream in,\r
+        long maxFieldSize,\r
+        ConnectionChild parent,\r
+        Object synchronization)\r
+            throws IOException, SQLException\r
+    {\r
+        super(synchronization);\r
+        this.maxFieldSize = maxFieldSize;\r
+        this.parent = parent;\r
+\r
+        parent.setupContextStack();\r
+        try {\r
+            synchronized (lock) { // Synchronize access to store.\r
+                if (in instanceof PositionedStoreStream) {\r
+                    this.positionedIn = (PositionedStoreStream)in;\r
+                    // This stream is already buffered, and buffering it again\r
+                    // this high up complicates the handling a lot. Must\r
+                    // implement a special buffered reader to buffer again.\r
+                    // Note that buffering this UTF8Reader again, does not\r
+                    // cause any trouble...\r
+                    this.in = in;\r
+                    try {\r
+                        this.positionedIn.resetStream();\r
+                    } catch (StandardException se) {\r
+                        IOException ioe = new IOException(se.getMessage());\r
+                        ioe.initCause(se);\r
+                        throw ioe;\r
+                    }\r
+                } else {\r
+                    this.positionedIn = null;\r
+                    // Buffer this for improved performance.\r
+                    this.in = new BufferedInputStream (in);\r
+                }\r
+                this.utfLen = readUnsignedShort();\r
+                // Even if we are reading the encoded length, the stream may\r
+                // not be a positioned stream. This is currently true when a\r
+                // stream is passed in after a ResetSet.getXXXStream method.\r
+                if (this.positionedIn != null) {\r
+                    this.rawStreamPos = this.positionedIn.getPosition();\r
+                }\r
+            } // End synchronized block\r
+        } finally {\r
+            parent.restoreContextStack();\r
+        }\r
+    }\r
+\r
+    /**\r
+     * Constructs a <code>UTF8Reader</code> using a stream.\r
+     * <p>\r
+     * This consturctor accepts the stream size as parameter and doesn't\r
+     * attempt to read the length from the stream.\r
+     *\r
+     * @param in the underlying stream\r
+     * @param maxFieldSize the maximum allowed length for the associated column\r
+     * @param streamSize size of the underlying stream in bytes\r
+     * @param parent the connection child this stream is associated with\r
+     * @param synchronization object to synchronize on\r
+     */\r
+    public UTF8Reader(\r
+            InputStream in,\r
+            long maxFieldSize,\r
+            long streamSize,\r
+            ConnectionChild parent,\r
+            Object synchronization)\r
+                throws IOException {\r
+        super(synchronization);\r
+        this.maxFieldSize = maxFieldSize;\r
+        this.parent = parent;\r
+        this.utfLen = streamSize;\r
+        this.positionedIn = null;\r
+\r
+        if (SanityManager.DEBUG) {\r
+            // Do not allow the inputstream here to be a Resetable, as this\r
+            // means (currently, not by design...) that the length is encoded in\r
+            // the stream and we can't pass that out as data to the user.\r
+            SanityManager.ASSERT(!(in instanceof Resetable));\r
+        }\r
+        // Buffer this for improved performance.\r
+        this.in = new BufferedInputStream(in);\r
+    }\r
+\r
+    /*\r
+    ** Reader implemention.\r
+    */\r
+    public int read() throws IOException\r
+    {\r
+        synchronized (lock) {\r
+\r
+            // check if closed..\r
+            if (noMoreReads)\r
+                throw new IOException();\r
+\r
+            if (readPositionInBuffer >= charactersInBuffer) {\r
+                if (fillBuffer()) {\r
+                    return -1;\r
+                }\r
+                readPositionInBuffer = 0;\r
+            }\r
+\r
+            return buffer[readPositionInBuffer++];\r
+        }\r
+    }\r
+\r
+    public int read(char[] cbuf, int off, int len) throws IOException\r
+    {\r
+        synchronized (lock) {\r
+            // check if closed..\r
+            if (noMoreReads)\r
+                throw new IOException();\r
+\r
+            if (readPositionInBuffer >= charactersInBuffer) {\r
+                if (fillBuffer()) {\r
+                    return -1;\r
+                }\r
+                readPositionInBuffer = 0;\r
+            }\r
+\r
+            int remainingInBuffer = charactersInBuffer - readPositionInBuffer;\r
+\r
+            if (len > remainingInBuffer)\r
+                len = remainingInBuffer;\r
+\r
+            System.arraycopy(buffer, readPositionInBuffer, cbuf, off, len);\r
+            readPositionInBuffer += len;\r
+\r
+            return len;\r
+        }\r
+    }\r
+\r
+    public long skip(long len) throws IOException {\r
+        if (len < 0) {\r
+            throw new IllegalArgumentException(\r
+                "Number of characters to skip must be positive: " + len);\r
+        }\r
+        synchronized (lock) {\r
+            // check if closed..\r
+            if (noMoreReads)\r
+                throw new IOException();\r
+\r
+            if (readPositionInBuffer >= charactersInBuffer) {\r
+                // do somthing\r
+                if (fillBuffer()) {\r
+                    return 0L;\r
+                }\r
+                readPositionInBuffer = 0;\r
+            }\r
+\r
+            int remainingInBuffer = charactersInBuffer - readPositionInBuffer;\r
+\r
+            if (len > remainingInBuffer)\r
+                len = remainingInBuffer;\r
+\r
+            readPositionInBuffer += len;\r
+\r
+            return len;\r
+        }\r
+\r
+    }\r
+\r
+    public void close()\r
+    {\r
+        synchronized (lock) {\r
+            closeIn();\r
+            parent  = null;\r
+            noMoreReads = true;\r
+        }\r
+    }\r
+\r
+    /*\r
+    ** Methods just for Derby's JDBC driver\r
+    */\r
+    public int readInto(StringBuffer sb, int len) throws IOException {\r
+\r
+        synchronized (lock) {\r
+            if (readPositionInBuffer >= charactersInBuffer) {\r
+                if (fillBuffer()) {\r
+                    return -1;\r
+                }\r
+                readPositionInBuffer = 0;\r
+            }\r
+\r
+            int remainingInBuffer = charactersInBuffer - readPositionInBuffer;\r
+\r
+            if (len > remainingInBuffer)\r
+                len = remainingInBuffer;\r
+            sb.append(buffer, readPositionInBuffer, len);\r
+\r
+            readPositionInBuffer += len;\r
+\r
+            return len;\r
+        }\r
+    }\r
+\r
+    int readAsciiInto(byte[] abuf, int off, int len) throws IOException {\r
+\r
+        synchronized (lock) {\r
+            if (readPositionInBuffer >= charactersInBuffer) {\r
+                if (fillBuffer()) {\r
+                    return -1;\r
+                }\r
+                readPositionInBuffer = 0;\r
+            }\r
+\r
+            int remainingInBuffer = charactersInBuffer - readPositionInBuffer;\r
+\r
+            if (len > remainingInBuffer)\r
+                len = remainingInBuffer;\r
+\r
+            char[] lbuffer = buffer;\r
+            for (int i = 0; i < len; i++) {\r
+                char c = lbuffer[readPositionInBuffer + i];\r
+                byte cb;\r
+                if (c <= 255)\r
+                    cb = (byte) c;\r
+                else\r
+                    cb = (byte) '?'; // Question mark - out of range character.\r
+\r
+                abuf[off + i] = cb;\r
+            }\r
+\r
+            readPositionInBuffer += len;\r
+\r
+            return len;\r
+        }\r
+    }\r
+\r
+    /*\r
+    ** internal implementation\r
+    */\r
+\r
+    private void closeIn() {\r
+        if (in != null) {\r
+            try {\r
+                in.close();\r
+            } catch (IOException ioe) {\r
+            } finally {\r
+                in = null;\r
+            }\r
+        }\r
+    }\r
+\r
+    private IOException utfFormatException(String s) {\r
+        noMoreReads = true;\r
+        closeIn();\r
+        return new UTFDataFormatException(s);\r
+    }\r
+\r
+    private IOException utfFormatException() {\r
+        noMoreReads = true;\r
+        closeIn();\r
+        return new UTFDataFormatException();\r
+    }\r
+\r
+    /**\r
+        Fill the buffer, return true if eof has been reached.\r
+    */\r
+    //@GuardedBy("lock")\r
+    private boolean fillBuffer() throws IOException\r
+    {\r
+        if (in == null)\r
+            return true;\r
+\r
+        charactersInBuffer = 0;\r
+\r
+        try {\r
+        try {\r
+            parent.setupContextStack();\r
+            // If we are operating on a positioned stream, reposition it to\r
+            // continue reading at the position we stopped last time.\r
+            if (this.positionedIn != null) {\r
+                try {\r
+                    this.positionedIn.reposition(this.rawStreamPos);\r
+                } catch (StandardException se) {\r
+                    throw Util.generateCsSQLException(se);\r
+                }\r
+            }\r
+readChars:\r
+        while (\r
+                (charactersInBuffer < buffer.length) &&\r
+                ((utfCount < utfLen) || (utfLen == 0)) &&\r
+                ((maxFieldSize == 0) || (readerCharCount < maxFieldSize))\r
+              )\r
+        {\r
+            int c = in.read();\r
+            if (c == -1) {\r
+                if (utfLen == 0) {\r
+                    closeIn();\r
+                    break readChars;\r
+                }\r
+                throw utfFormatException();\r
+            }\r
+\r
+            int finalChar;\r
+            switch (c >> 4) {\r
+                case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:\r
+                    // 0xxxxxxx\r
+                    utfCount++;\r
+                    finalChar = c;\r
+                    break;\r
+\r
+                case 12: case 13:\r
+                    {\r
+                    // 110x xxxx   10xx xxxx\r
+                    utfCount += 2;\r
+                    int char2 = in.read();\r
+                    if (char2 == -1)\r
+                        throw utfFormatException();\r
+\r
+                    if ((char2 & 0xC0) != 0x80)\r
+                        throw utfFormatException();\r
+                    finalChar = (((c & 0x1F) << 6) | (char2 & 0x3F));\r
+                    break;\r
+                    }\r
+\r
+                case 14:\r
+                    {\r
+                    // 1110 xxxx  10xx xxxx  10xx xxxx\r
+                    utfCount += 3;\r
+                    int char2 = in.read();\r
+                    int char3 = in.read();\r
+                    if (char2 == -1 || char3 == -1)\r
+                        throw utfFormatException();\r
+\r
+                    if ((c == 0xE0) && (char2 == 0) && (char3 == 0))\r
+                    {\r
+                        if (utfLen == 0) {\r
+                            // we reached the end of a long string,\r
+                            // that was terminated with\r
+                            // (11100000, 00000000, 00000000)\r
+                            closeIn();\r
+                            break readChars;\r
+                        }\r
+                        throw utfFormatException();\r
+                    }\r
+\r
+                    if (((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))\r
+                        throw utfFormatException();\r
+\r
+                    finalChar = (((c & 0x0F) << 12) |\r
+                               ((char2 & 0x3F) << 6) |\r
+                               ((char3 & 0x3F) << 0));\r
+                    }\r
+                    break;\r
+\r
+                default:\r
+                    // 10xx xxxx,  1111 xxxx\r
+                    throw utfFormatException();\r
+            }\r
+\r
+            buffer[charactersInBuffer++] = (char) finalChar;\r
+            readerCharCount++;\r
+        }\r
+        if (utfLen != 0 && utfCount > utfLen)\r
+            throw utfFormatException("utfCount " + utfCount + " utfLen " + utfLen);\r
+\r
+        if (charactersInBuffer != 0) {\r
+            if (this.positionedIn != null) {\r
+                // Save the last visisted position so we can start reading where\r
+                // we let go the next time we fill the buffer.\r
+                this.rawStreamPos = this.positionedIn.getPosition();\r
+            }\r
+            return false;\r
+        }\r
+\r
+        closeIn();\r
+        return true;\r
+        } finally {\r
+            parent.restoreContextStack();\r
+        }\r
+        } catch (SQLException sqle) {\r
+            IOException ioe =\r
+                new IOException(sqle.getSQLState() + ": " + sqle.getMessage());\r
+            ioe.initCause(sqle);\r
+            throw ioe;\r
+        }\r
+    }\r
+\r
+    // this method came from java.io.DataInputStream\r
+    private final int readUnsignedShort() throws IOException {\r
+        int ch1 = in.read();\r
+        int ch2 = in.read();\r
+        if ((ch1 | ch2) < 0)\r
+            throw new EOFException();\r
+\r
+        return (ch1 << 8) + (ch2 << 0);\r
+    }\r
+}\r