Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/mysql/jdbc/Buffer.java


1   /*
2    Copyright (C) 2002-2004 MySQL AB
3   
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of version 2 of the GNU General Public License as
6    published by the Free Software Foundation.
7    
8   
9    There are special exceptions to the terms and conditions of the GPL 
10   as it is applied to this software. View the full text of the 
11   exception exception in file EXCEPTIONS-CONNECTOR-J in the directory of this 
12   software distribution.
13  
14   This program is distributed in the hope that it will be useful,
15   but WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   GNU General Public License for more details.
18  
19   You should have received a copy of the GNU General Public License
20   along with this program; if not, write to the Free Software
21   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22  
23   */
24  package com.mysql.jdbc;
25  
26  import java.io.UnsupportedEncodingException;
27  import java.sql.SQLException;
28  
29  
30  /**
31   * Buffer contains code to read and write packets from/to the MySQL server.
32   *
33   * @version $Id: Buffer.java,v 1.15.2.18 2004/10/21 19:31:04 mmatthew Exp $
34   * @author Mark Matthews
35   */
36  class Buffer {
37      static final int NO_LENGTH_LIMIT = -1;
38      static final long NULL_LENGTH = -1;
39      private byte[] byteBuffer;
40      private boolean wasMultiPacket = false;
41      private int bufLength = 0;
42      private int position = 0;
43      private int sendLength = 0;
44  
45      Buffer(byte[] buf) {
46          this.byteBuffer = buf;
47          setBufLength(buf.length);
48      }
49  
50      Buffer(int size) {
51          this.byteBuffer = new byte[size];
52          setBufLength(this.byteBuffer.length);
53          this.position = MysqlIO.HEADER_LENGTH;
54      }
55  
56      /**
57       * Sets the array of bytes to use as a buffer to read from.
58       *
59       * @param byteBuffer the array of bytes to use as a buffer
60       */
61      public void setByteBuffer(byte[] byteBuffer) {
62          this.byteBuffer = byteBuffer;
63      }
64  
65      /**
66       * Returns the array of bytes this Buffer is using to read from.
67       *
68       * @return byte array being read from
69       */
70      public byte[] getByteBuffer() {
71          return this.byteBuffer;
72      }
73  
74      /**
75       * Set the current position to write to/ read from
76       *
77       * @param position the position (0-based index)
78       */
79      public void setPosition(int position) {
80          this.position = position;
81      }
82  
83      /**
84       * Returns the current position to write to/ read from
85       *
86       * @return the current position to write to/ read from
87       */
88      public int getPosition() {
89          return this.position;
90      }
91  
92      /**
93       * Sets whether this packet was part of a multipacket
94       *
95       * @param flag was this packet part of a multipacket?
96       */
97      public void setWasMultiPacket(boolean flag) {
98          wasMultiPacket = flag;
99      }
100 
101     /**
102      * Skip over a length-encoded string
103      *
104      * @return The position past the end of the string
105      */
106     public int fastSkipLenString() {
107         long len = this.readFieldLength();
108 
109         position += len;
110 
111         return (int) len; // this is safe, as this is only
112     }
113 
114     /**
115      * Was this packet part of a multipacket?
116      *
117      * @return was this packet part of a multipacket?
118      */
119     public boolean wasMultiPacket() {
120         return wasMultiPacket;
121     }
122 
123     protected final byte[] getBufferSource() {
124         return byteBuffer;
125     }
126 
127     final byte[] getBytes(int len) {
128         byte[] b = new byte[len];
129         System.arraycopy(this.byteBuffer, this.position, b, 0, len);
130         this.position += len; // update cursor
131 
132         return b;
133     }
134 
135     // 2000-06-05 Changed
136     final boolean isLastDataPacket() {
137         return ((getBufLength() < 9) && ((this.byteBuffer[0] & 0xff) == 254));
138     }
139 
140     final void clear() {
141         this.position = MysqlIO.HEADER_LENGTH;
142     }
143 
144     final void dump() {
145       StringUtils.dumpAsHex(this.byteBuffer, getBufLength());
146     }
147 
148     final void dumpHeader() {
149         for (int i = 0; i < MysqlIO.HEADER_LENGTH; i++) {
150             String hexVal = Integer.toHexString((int) this.byteBuffer[i] & 0xff);
151 
152             if (hexVal.length() == 1) {
153                 hexVal = "0" + hexVal;
154             }
155 
156             System.out.print(hexVal + " ");
157         }
158     }
159 
160     final void dumpNBytes(int start, int nBytes) {
161         StringBuffer asciiBuf = new StringBuffer();
162 
163         for (int i = start;
164                 (i < (start + nBytes)) && (i < this.byteBuffer.length); i++) {
165             String hexVal = Integer.toHexString((int) this.byteBuffer[i] & 0xff);
166 
167             if (hexVal.length() == 1) {
168                 hexVal = "0" + hexVal;
169             }
170 
171             System.out.print(hexVal + " ");
172 
173             if ((this.byteBuffer[i] > 32) && (this.byteBuffer[i] < 127)) {
174                 asciiBuf.append((char) this.byteBuffer[i]);
175             } else {
176                 asciiBuf.append(".");
177             }
178 
179             asciiBuf.append(" ");
180         }
181 
182         System.out.println("    " + asciiBuf.toString());
183     }
184 
185     final void ensureCapacity(int additionalData) throws SQLException {
186         if ((this.position + additionalData) > getBufLength()) {
187             if ((this.position + additionalData) < this.byteBuffer.length) {
188                 // byteBuffer.length is != getBufLength() all of the time
189                 // due to re-using of packets (we don't shrink them)
190                 //
191                 // If we can, don't re-alloc, just set buffer length 
192                 // to size of current buffer
193                 setBufLength(this.byteBuffer.length);
194             } else {
195                 //
196                 // Otherwise, re-size, and pad so we can avoid
197                 // allocing again in the near future
198                 //
199                 int newLength = (int) (this.byteBuffer.length * 1.25);
200 
201                 if (newLength < (this.byteBuffer.length + additionalData)) {
202                     newLength = this.byteBuffer.length
203                         + (int) (additionalData * 1.25);
204                 }
205 
206                 if (newLength < this.byteBuffer.length) {
207                     newLength = this.byteBuffer.length + additionalData;
208                 }
209 
210                 byte[] newBytes = new byte[newLength];
211 
212                 System.arraycopy(this.byteBuffer, 0, newBytes, 0,
213                     this.byteBuffer.length);
214                 this.byteBuffer = newBytes;
215                 setBufLength(this.byteBuffer.length);
216             }
217         }
218     }
219 
220     final long newReadLength() {
221         int sw = this.byteBuffer[this.position++] & 0xff;
222 
223         switch (sw) {
224         case 251:
225             return (long) 0;
226 
227         case 252:
228             return (long) readInt();
229 
230         case 253:
231             return (long) readLongInt();
232 
233         case 254: // changed for 64 bit lengths
234             return (long) readLongLong();
235 
236         default:
237             return (long) sw;
238         }
239     }
240 
241     final byte readByte() {
242         return this.byteBuffer[this.position++];
243     }
244 
245     final long readFieldLength() {
246         int sw = this.byteBuffer[this.position++] & 0xff;
247 
248         switch (sw) {
249         case 251:
250             return NULL_LENGTH;
251 
252         case 252:
253             return (long) readInt();
254 
255         case 253:
256             return (long) readLongInt();
257 
258         case 254:
259             return readLongLong();
260 
261         default:
262             return (long) sw;
263         }
264     }
265 
266     // 2000-06-05 Changed
267     final int readInt() {
268         byte[] b = this.byteBuffer; // a little bit optimization
269 
270         return (b[this.position++] & 0xff) | ((b[this.position++] & 0xff) << 8);
271     }
272 
273     final byte[] readLenByteArray(int offset) {
274         long len = this.readFieldLength();
275 
276         if (len == NULL_LENGTH) {
277             return null;
278         }
279 
280         if (len == 0) {
281             return new byte[0];
282         }
283 
284         this.position += offset;
285 
286         return getBytes((int) len);
287     }
288 
289     final long readLength() {
290         int sw = this.byteBuffer[this.position++] & 0xff;
291 
292         switch (sw) {
293         case 251:
294             return (long) 0;
295 
296         case 252:
297             return (long) readInt();
298 
299         case 253:
300             return (long) readLongInt();
301 
302         case 254:
303             return (long) readLong();
304 
305         default:
306             return (long) sw;
307         }
308     }
309 
310     // 2000-06-05 Fixed
311     final long readLong() {
312         byte[] b = this.byteBuffer;
313 
314         return (b[this.position++] & 0xff) | ((b[this.position++] & 0xff) << 8)
315         | ((b[this.position++] & 0xff) << 16)
316         | ((b[this.position++] & 0xff) << 24);
317     }
318 
319     // 2000-06-05 Changed
320     final int readLongInt() {
321         byte[] b = this.byteBuffer;
322 
323         return (b[this.position++] & 0xff) | ((b[this.position++] & 0xff) << 8)
324         | ((b[this.position++] & 0xff) << 16);
325     }
326 
327     // 2000-06-05 Fixed
328     final long readLongLong() {
329         byte[] b = this.byteBuffer;
330 
331         return (long) (b[this.position++] & 0xff)
332         | ((long) (b[this.position++] & 0xff) << 8)
333         | ((long) (b[this.position++] & 0xff) << 16)
334         | ((long) (b[this.position++] & 0xff) << 24)
335         | ((long) (b[this.position++] & 0xff) << 32)
336         | ((long) (b[this.position++] & 0xff) << 40)
337         | ((long) (b[this.position++] & 0xff) << 48)
338         | ((long) (b[this.position++] & 0xff) << 56);
339     }
340 
341     //
342     // Read a null-terminated string
343     //
344     // To avoid alloc'ing a new byte array, we
345     // do this by hand, rather than calling getNullTerminatedBytes()
346     //
347     final String readString() {
348         int i = this.position;
349         int len = 0;
350     int maxLen = getBufLength();
351     
352         while ((i < maxLen) && (this.byteBuffer[i] != 0)) {
353             len++;
354             i++;
355         }
356 
357         String s = new String(this.byteBuffer, this.position, len);
358         this.position += (len + 1); // update cursor
359 
360         return s;
361     }
362     
363     final String readString(String encoding) throws SQLException {
364     int i = this.position;
365     int len = 0;
366     int maxLen = getBufLength();
367     
368     while ((i < maxLen) && (this.byteBuffer[i] != 0)) {
369       len++;
370       i++;
371     }
372 
373     try {
374       return new String(this.byteBuffer, this.position, len, encoding);
375       
376     } catch (UnsupportedEncodingException uEE) {
377       throw new SQLException("Unsupported character encoding '" + encoding + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT);
378     } finally {
379       this.position += (len + 1); // update cursor
380     }
381     }
382 
383     final int readnBytes() {
384         int sw = this.byteBuffer[this.position++] & 0xff;
385 
386         switch (sw) {
387         case 1:
388             return this.byteBuffer[this.position++] & 0xff;
389 
390         case 2:
391             return this.readInt();
392 
393         case 3:
394             return this.readLongInt();
395 
396         case 4:
397             return (int) this.readLong();
398 
399         default:
400             return 255;
401         }
402     }
403 
404     final void writeByte(byte b) throws SQLException {
405         ensureCapacity(1);
406 
407         this.byteBuffer[this.position++] = b;
408     }
409 
410     // Write a byte array
411     final void writeBytesNoNull(byte[] bytes) throws SQLException {
412         int len = bytes.length;
413         ensureCapacity(len);
414         System.arraycopy(bytes, 0, this.byteBuffer, this.position, len);
415         this.position += len;
416     }
417 
418     // Write a byte array with the given offset and length
419     final void writeBytesNoNull(byte[] bytes, int offset, int length)
420         throws SQLException {
421         ensureCapacity(length);
422         System.arraycopy(bytes, offset, this.byteBuffer, this.position, length);
423         this.position += length;
424     }
425 
426     final void writeDouble(double d) {
427         long l = Double.doubleToLongBits(d);
428         writeLongLong(l);
429     }
430 
431     final void writeFloat(float f) {
432         int i = Float.floatToIntBits(f);
433         byte[] b = this.byteBuffer;
434         b[this.position++] = (byte) (i & 0xff);
435         b[this.position++] = (byte) (i >>> 8);
436         b[this.position++] = (byte) (i >>> 16);
437         b[this.position++] = (byte) (i >>> 24);
438     }
439 
440     // 2000-06-05 Changed
441     final void writeInt(int i) {
442         byte[] b = this.byteBuffer;
443         b[this.position++] = (byte) (i & 0xff);
444         b[this.position++] = (byte) (i >>> 8);
445     }
446 
447     // 2000-06-05 Changed
448     final void writeLong(long i) {
449         byte[] b = this.byteBuffer;
450         b[this.position++] = (byte) (i & 0xff);
451         b[this.position++] = (byte) (i >>> 8);
452         b[this.position++] = (byte) (i >>> 16);
453         b[this.position++] = (byte) (i >>> 24);
454     }
455 
456     // 2000-06-05 Changed
457     final void writeLongInt(int i) {
458         byte[] b = this.byteBuffer;
459         b[this.position++] = (byte) (i & 0xff);
460         b[this.position++] = (byte) (i >>> 8);
461         b[this.position++] = (byte) (i >>> 16);
462     }
463 
464     final void writeLongLong(long i) {
465         byte[] b = this.byteBuffer;
466         b[this.position++] = (byte) (i & 0xff);
467         b[this.position++] = (byte) (i >>> 8);
468         b[this.position++] = (byte) (i >>> 16);
469         b[this.position++] = (byte) (i >>> 24);
470         b[this.position++] = (byte) (i >>> 32);
471         b[this.position++] = (byte) (i >>> 40);
472         b[this.position++] = (byte) (i >>> 48);
473         b[this.position++] = (byte) (i >>> 56);
474     }
475 
476     // Write null-terminated string
477     final void writeString(String s) throws SQLException {
478       ensureCapacity(s.length() + 1);
479       
480         writeStringNoNull(s);
481         this.byteBuffer[this.position++] = 0;
482     }
483 
484     // Write string, with no termination
485     final void writeStringNoNull(String s) throws SQLException {
486         int len = s.length();
487         ensureCapacity(len);
488         System.arraycopy(s.getBytes(), 0, byteBuffer, position, len);
489         position += len;
490 
491         //         for (int i = 0; i < len; i++)
492         //         {
493         //             this.byteBuffer[this.position++] = (byte)s.charAt(i);
494         //         }
495     }
496 
497     // Write a String using the specified character
498     // encoding
499     final void writeStringNoNull(String s, String encoding, String serverEncoding, 
500         SingleByteCharsetConverter converter, boolean parserKnowsUnicode)
501         throws UnsupportedEncodingException, SQLException {
502         byte[] b = null;
503         
504         if (converter != null) {
505             b = converter.toBytes(s);
506         } else {
507             b = StringUtils.getBytes(s, encoding, serverEncoding, parserKnowsUnicode);
508         }
509 
510         int len = b.length;
511         ensureCapacity(len);
512         System.arraycopy(b, 0, this.byteBuffer, this.position, len);
513         this.position += len;
514     }
515 
516     void setBufLength(int bufLength) {
517         this.bufLength = bufLength;
518     }
519 
520     int getBufLength() {
521         return bufLength;
522     }
523 
524     void setSendLength(int sendLength) {
525         this.sendLength = sendLength;
526     }
527 }