CompressedInputStream.java
上传用户:sxlinghang
上传日期:2022-07-20
资源大小:1405k
文件大小:8k
源码类别:

数据库编程

开发平台:

Java

  1. /*
  2.    Copyright (C) 2002 MySQL AB
  3.           This program is free software; you can redistribute it and/or modify
  4.           it under the terms of the GNU General Public License as published by
  5.           the Free Software Foundation; either version 2 of the License, or
  6.           (at your option) any later version.
  7.           This program is distributed in the hope that it will be useful,
  8.           but WITHOUT ANY WARRANTY; without even the implied warranty of
  9.           MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10.           GNU General Public License for more details.
  11.           You should have received a copy of the GNU General Public License
  12.           along with this program; if not, write to the Free Software
  13.           Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  14.  */
  15. package com.mysql.jdbc;
  16. import java.io.EOFException;
  17. import java.io.IOException;
  18. import java.io.InputStream;
  19. import java.util.zip.DataFormatException;
  20. import java.util.zip.Inflater;
  21. /**
  22.  * @author Mark Matthews
  23.  *
  24.  * To change this generated comment edit the template variable "typecomment":
  25.  * Window>Preferences>Java>Templates.
  26.  * To enable and disable the creation of type comments go to
  27.  * Window>Preferences>Java>Code Generation.
  28.  */
  29. class CompressedInputStream extends InputStream {
  30.     //~ Instance fields --------------------------------------------------------
  31.     /**
  32.      * The ZIP inflater used to un-compress packets
  33.      */
  34.     private Inflater inflater;
  35.     /**
  36.      * The stream we are reading from the server
  37.      */
  38.     private InputStream in;
  39.     /**
  40.      * The packet data after it has been un-compressed
  41.      */
  42.     private byte[] uncompressedPacket;
  43.     /**
  44.      * The position we are reading from
  45.      */
  46.     private int pos = 0;
  47.     //~ Constructors -----------------------------------------------------------
  48.     /**
  49.      * Creates a new CompressedInputStream that reads
  50.      * the given stream from the server.
  51.      *
  52.      * @param streamFromServer
  53.      */
  54.     public CompressedInputStream(InputStream streamFromServer) {
  55.         this.in = streamFromServer;
  56.         this.inflater = new Inflater();
  57.     }
  58.     //~ Methods ----------------------------------------------------------------
  59.     /**
  60.      * @see java.io.InputStream#available()
  61.      */
  62.     public int available() throws IOException {
  63.         if (this.uncompressedPacket == null) {
  64.             return this.in.available();
  65.         }
  66.         return this.uncompressedPacket.length - this.pos + this.in.available();
  67.     }
  68.     /**
  69.      * @see java.io.InputStream#close()
  70.      */
  71.     public void close() throws IOException {
  72.         this.in.close();
  73.         this.uncompressedPacket = null;
  74.         this.inflater = null;
  75.     }
  76.     /**
  77.      * @see java.io.InputStream#read()
  78.      */
  79.     public int read() throws IOException {
  80.         try {
  81.             getNextPacketIfRequired(1);
  82.         } catch (IOException ioEx) {
  83.             return -1;
  84.         }
  85.         return this.uncompressedPacket[this.pos++] & 0xff;
  86.     }
  87.     /**
  88.      * @see java.io.InputStream#read(byte, int, int)
  89.      */
  90.     public int read(byte[] b, int off, int len) throws IOException {
  91.         if (b == null) {
  92.             throw new NullPointerException();
  93.         } else if ((off < 0) || (off > b.length) || (len < 0)
  94.                 || ((off + len) > b.length) || ((off + len) < 0)) {
  95.             throw new IndexOutOfBoundsException();
  96.         }
  97.         if (len <= 0) {
  98.             return 0;
  99.         }
  100.         try {
  101.             getNextPacketIfRequired(len);
  102.         } catch (IOException ioEx) {
  103.             return -1;
  104.         }
  105.         System.arraycopy(this.uncompressedPacket, this.pos, b, off, len);
  106.         this.pos += len;
  107.         return len;
  108.     }
  109.     /**
  110.      * @see java.io.InputStream#read(byte)
  111.      */
  112.     public int read(byte[] b) throws IOException {
  113.         return read(b, 0, b.length);
  114.     }
  115.     /**
  116.      * @see java.io.InputStream#skip(long)
  117.      */
  118.     public long skip(long n) throws IOException {
  119.         long count = 0;
  120.         for (long i = 0; i < n; i++) {
  121.             int bytesRead = read();
  122.             if (bytesRead == -1) {
  123.                 break;
  124.             }
  125.             count++;
  126.         }
  127.         return count;
  128.     }
  129.     /**
  130.          * Retrieves and un-compressed (if necessary) the next
  131.          * packet from the server.
  132.          *
  133.          * @throws IOException if an I/O error occurs
  134.          */
  135.     private void getNextPacketFromServer() throws IOException {
  136.         byte[] uncompressedBuffer = null;
  137.         int packetLength = this.in.read() + (this.in.read() << 8)
  138.             + (this.in.read() << 16);
  139.         // -1 for all values through above assembly sequence
  140.         if (packetLength == -65793) {
  141.             throw new IOException("Unexpected end of input stream");
  142.         }
  143.         // we don't look at packet sequence in this case
  144.         this.in.read();
  145.         int compressedLength = this.in.read() + (this.in.read() << 8)
  146.             + (this.in.read() << 16);
  147.         if (compressedLength > 0) {
  148.             uncompressedBuffer = new byte[compressedLength];
  149.             byte[] compressedBuffer = new byte[packetLength];
  150.             readFully(compressedBuffer, 0, packetLength);
  151.             try {
  152.                 this.inflater.reset();
  153.             } catch (NullPointerException npe) {
  154.                 this.inflater = new Inflater();
  155.             }
  156.             this.inflater.setInput(compressedBuffer);
  157.             try {
  158.                 this.inflater.inflate(uncompressedBuffer);
  159.             } catch (DataFormatException dfe) {
  160.                 throw new IOException(
  161.                     "Error while uncompressing packet from server.");
  162.             }
  163.             this.inflater.end();
  164.         } else {
  165.             //
  166.             // Read data, note this this code is reached when using
  167.             //  compressed packets that have not been compressed, as well
  168.             //
  169.             uncompressedBuffer = new byte[packetLength + 1];
  170.             readFully(uncompressedBuffer, 0, packetLength);
  171.         }
  172.         if ((this.uncompressedPacket != null)
  173.                 && (this.pos < this.uncompressedPacket.length)) {
  174.             int remainingLength = this.uncompressedPacket.length - this.pos;
  175.             byte[] combinedBuffer = new byte[remainingLength
  176.                 + uncompressedBuffer.length];
  177.             System.arraycopy(this.uncompressedPacket, this.pos, combinedBuffer, 0,
  178.                 remainingLength);
  179.             System.arraycopy(uncompressedBuffer, 0, combinedBuffer,
  180.                 remainingLength, uncompressedBuffer.length);
  181.             uncompressedBuffer = combinedBuffer;
  182.         }
  183.         this.uncompressedPacket = uncompressedBuffer;
  184.         this.pos = 0;
  185.         return;
  186.     }
  187.     /**
  188.      * Determines if another packet needs to be read from the server
  189.      * to be able to read numBytes from the stream.
  190.      *
  191.      * @param numBytes the number of bytes to be read
  192.      * @throws IOException if an I/O error occors.
  193.      */
  194.     private void getNextPacketIfRequired(int numBytes)
  195.         throws IOException {
  196.         if ((this.uncompressedPacket == null)
  197.                 || ((this.pos + numBytes) > this.uncompressedPacket.length)) {
  198.             getNextPacketFromServer();
  199.         }
  200.     }
  201.     private final int readFully(byte[] b, int off, int len)
  202.         throws IOException {
  203.         if (len < 0) {
  204.             throw new IndexOutOfBoundsException();
  205.         }
  206.         int n = 0;
  207.         while (n < len) {
  208.             int count = this.in.read(b, off + n, len - n);
  209.             if (count < 0) {
  210.                 throw new EOFException();
  211.             }
  212.             n += count;
  213.         }
  214.         return n;
  215.     }
  216. }