KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > mysql > jdbc > CompressedInputStream


1 /*
2    Copyright (C) 2002 MySQL AB
3
4           This program is free software; you can redistribute it and/or modify
5           it under the terms of the GNU General Public License as published by
6           the Free Software Foundation; either version 2 of the License, or
7           (at your option) any later version.
8
9           This program is distributed in the hope that it will be useful,
10           but WITHOUT ANY WARRANTY; without even the implied warranty of
11           MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12           GNU General Public License for more details.
13
14           You should have received a copy of the GNU General Public License
15           along with this program; if not, write to the Free Software
16           Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17
18  */

19 package com.mysql.jdbc;
20
21 import java.io.EOFException JavaDoc;
22 import java.io.IOException JavaDoc;
23 import java.io.InputStream JavaDoc;
24
25 import java.util.zip.DataFormatException JavaDoc;
26 import java.util.zip.Inflater JavaDoc;
27
28
29 /**
30  * @author Mark Matthews
31  *
32  * To change this generated comment edit the template variable "typecomment":
33  * Window>Preferences>Java>Templates.
34  * To enable and disable the creation of type comments go to
35  * Window>Preferences>Java>Code Generation.
36  */

37 class CompressedInputStream extends InputStream JavaDoc {
38     //~ Instance fields --------------------------------------------------------
39

40     /**
41      * The ZIP inflater used to un-compress packets
42      */

43     private Inflater JavaDoc inflater;
44
45     /**
46      * The stream we are reading from the server
47      */

48     private InputStream JavaDoc in;
49
50     /**
51      * The packet data after it has been un-compressed
52      */

53     private byte[] uncompressedPacket;
54
55     /**
56      * The position we are reading from
57      */

58     private int pos = 0;
59
60     //~ Constructors -----------------------------------------------------------
61

62     /**
63      * Creates a new CompressedInputStream that reads
64      * the given stream from the server.
65      *
66      * @param streamFromServer
67      */

68     public CompressedInputStream(InputStream JavaDoc streamFromServer) {
69         this.in = streamFromServer;
70         this.inflater = new Inflater JavaDoc();
71     }
72
73     //~ Methods ----------------------------------------------------------------
74

75     /**
76      * @see java.io.InputStream#available()
77      */

78     public int available() throws IOException JavaDoc {
79         if (this.uncompressedPacket == null) {
80             return this.in.available();
81         }
82
83         return this.uncompressedPacket.length - this.pos + this.in.available();
84     }
85
86     /**
87      * @see java.io.InputStream#close()
88      */

89     public void close() throws IOException JavaDoc {
90         this.in.close();
91         this.uncompressedPacket = null;
92         this.inflater = null;
93     }
94
95     /**
96      * @see java.io.InputStream#read()
97      */

98     public int read() throws IOException JavaDoc {
99         try {
100             getNextPacketIfRequired(1);
101         } catch (IOException JavaDoc ioEx) {
102             return -1;
103         }
104
105         return this.uncompressedPacket[this.pos++] & 0xff;
106     }
107
108     /**
109      * @see java.io.InputStream#read(byte, int, int)
110      */

111     public int read(byte[] b, int off, int len) throws IOException JavaDoc {
112         if (b == null) {
113             throw new NullPointerException JavaDoc();
114         } else if ((off < 0) || (off > b.length) || (len < 0)
115                 || ((off + len) > b.length) || ((off + len) < 0)) {
116             throw new IndexOutOfBoundsException JavaDoc();
117         }
118
119         if (len <= 0) {
120             return 0;
121         }
122
123         try {
124             getNextPacketIfRequired(len);
125         } catch (IOException JavaDoc ioEx) {
126             return -1;
127         }
128
129         System.arraycopy(this.uncompressedPacket, this.pos, b, off, len);
130         this.pos += len;
131
132         return len;
133     }
134
135     /**
136      * @see java.io.InputStream#read(byte)
137      */

138     public int read(byte[] b) throws IOException JavaDoc {
139         return read(b, 0, b.length);
140     }
141
142     /**
143      * @see java.io.InputStream#skip(long)
144      */

145     public long skip(long n) throws IOException JavaDoc {
146         long count = 0;
147
148         for (long i = 0; i < n; i++) {
149             int bytesRead = read();
150
151             if (bytesRead == -1) {
152                 break;
153             }
154
155             count++;
156         }
157
158         return count;
159     }
160
161     /**
162          * Retrieves and un-compressed (if necessary) the next
163          * packet from the server.
164          *
165          * @throws IOException if an I/O error occurs
166          */

167     private void getNextPacketFromServer() throws IOException JavaDoc {
168         byte[] uncompressedBuffer = null;
169
170         int packetLength = this.in.read() + (this.in.read() << 8)
171             + (this.in.read() << 16);
172
173         // -1 for all values through above assembly sequence
174
if (packetLength == -65793) {
175             throw new IOException JavaDoc("Unexpected end of input stream");
176         }
177
178         // we don't look at packet sequence in this case
179
this.in.read();
180
181         int compressedLength = this.in.read() + (this.in.read() << 8)
182             + (this.in.read() << 16);
183
184         if (compressedLength > 0) {
185             uncompressedBuffer = new byte[compressedLength];
186
187             byte[] compressedBuffer = new byte[packetLength];
188
189             readFully(compressedBuffer, 0, packetLength);
190
191             try {
192                 this.inflater.reset();
193             } catch (NullPointerException JavaDoc npe) {
194                 this.inflater = new Inflater JavaDoc();
195             }
196
197             this.inflater.setInput(compressedBuffer);
198
199             try {
200                 this.inflater.inflate(uncompressedBuffer);
201             } catch (DataFormatException JavaDoc dfe) {
202                 throw new IOException JavaDoc(
203                     "Error while uncompressing packet from server.");
204             }
205
206             this.inflater.end();
207         } else {
208             //
209
// Read data, note this this code is reached when using
210
// compressed packets that have not been compressed, as well
211
//
212
uncompressedBuffer = new byte[packetLength + 1];
213             readFully(uncompressedBuffer, 0, packetLength);
214         }
215
216         if ((this.uncompressedPacket != null)
217                 && (this.pos < this.uncompressedPacket.length)) {
218             int remainingLength = this.uncompressedPacket.length - this.pos;
219
220             byte[] combinedBuffer = new byte[remainingLength
221                 + uncompressedBuffer.length];
222             System.arraycopy(this.uncompressedPacket, this.pos, combinedBuffer, 0,
223                 remainingLength);
224             System.arraycopy(uncompressedBuffer, 0, combinedBuffer,
225                 remainingLength, uncompressedBuffer.length);
226             uncompressedBuffer = combinedBuffer;
227         }
228
229         this.uncompressedPacket = uncompressedBuffer;
230         this.pos = 0;
231
232         return;
233     }
234
235     /**
236      * Determines if another packet needs to be read from the server
237      * to be able to read numBytes from the stream.
238      *
239      * @param numBytes the number of bytes to be read
240      * @throws IOException if an I/O error occors.
241      */

242     private void getNextPacketIfRequired(int numBytes)
243         throws IOException JavaDoc {
244         if ((this.uncompressedPacket == null)
245                 || ((this.pos + numBytes) > this.uncompressedPacket.length)) {
246             getNextPacketFromServer();
247         }
248     }
249
250     private final int readFully(byte[] b, int off, int len)
251         throws IOException JavaDoc {
252         if (len < 0) {
253             throw new IndexOutOfBoundsException JavaDoc();
254         }
255
256         int n = 0;
257
258         while (n < len) {
259             int count = this.in.read(b, off + n, len - n);
260
261             if (count < 0) {
262                 throw new EOFException JavaDoc();
263             }
264
265             n += count;
266         }
267
268         return n;
269     }
270 }
271
Popular Tags