source: Ballon/out/artifacts/geisa_artifact/WEB-INF/lib/mysql-connector-java-5.1.21/src/com/mysql/jdbc/Buffer.java @ 848

Last change on this file since 848 was 766, checked in by npipsl, 11 years ago
File size: 17.3 KB
Line 
1/*
2 Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
3 
4
5  The MySQL Connector/J is licensed under the terms of the GPLv2
6  <http://www.gnu.org/licenses/old-licenses/gpl-2.0.html>, like most MySQL Connectors.
7  There are special exceptions to the terms and conditions of the GPLv2 as it is applied to
8  this software, see the FLOSS License Exception
9  <http://www.mysql.com/about/legal/licensing/foss-exception.html>.
10
11  This program is free software; you can redistribute it and/or modify it under the terms
12  of the GNU General Public License as published by the Free Software Foundation; version 2
13  of the License.
14
15  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
16  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17  See the GNU General Public License for more details.
18
19  You should have received a copy of the GNU General Public License along with this
20  program; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth
21  Floor, Boston, MA 02110-1301  USA
22
23
24
25 */
26package com.mysql.jdbc;
27
28import java.io.UnsupportedEncodingException;
29import java.nio.ByteBuffer;
30import java.sql.SQLException;
31
32/**
33 * Buffer contains code to read and write packets from/to the MySQL server.
34 *
35 * @version $Id$
36 * @author Mark Matthews
37 */
38public class Buffer {
39        static final int MAX_BYTES_TO_DUMP = 512;
40
41        static final int NO_LENGTH_LIMIT = -1;
42
43        static final long NULL_LENGTH = -1;
44
45        private int bufLength = 0;
46
47        private byte[] byteBuffer;
48
49        private int position = 0;
50
51        protected boolean wasMultiPacket = false;
52
53        public Buffer(byte[] buf) {
54                this.byteBuffer = buf;
55                setBufLength(buf.length);
56        }
57
58        Buffer(int size) {
59                this.byteBuffer = new byte[size];
60                setBufLength(this.byteBuffer.length);
61                this.position = MysqlIO.HEADER_LENGTH;
62        }
63
64        final void clear() {
65                this.position = MysqlIO.HEADER_LENGTH;
66        }
67
68        final void dump() {
69                dump(getBufLength());
70        }
71
72        final String dump(int numBytes) {
73                return StringUtils.dumpAsHex(getBytes(0,
74                                numBytes > getBufLength() ? getBufLength() : numBytes),
75                                numBytes > getBufLength() ? getBufLength() : numBytes);
76        }
77
78        final String dumpClampedBytes(int numBytes) {
79                int numBytesToDump = numBytes < MAX_BYTES_TO_DUMP ? numBytes
80                                : MAX_BYTES_TO_DUMP;
81
82                String dumped = StringUtils.dumpAsHex(getBytes(0,
83                                numBytesToDump > getBufLength() ? getBufLength()
84                                                : numBytesToDump),
85                                numBytesToDump > getBufLength() ? getBufLength()
86                                                : numBytesToDump);
87
88                if (numBytesToDump < numBytes) {
89                        return dumped + " ....(packet exceeds max. dump length)";
90                }
91
92                return dumped;
93        }
94
95        final void dumpHeader() {
96                for (int i = 0; i < MysqlIO.HEADER_LENGTH; i++) {
97                        String hexVal = Integer.toHexString(readByte(i) & 0xff);
98
99                        if (hexVal.length() == 1) {
100                                hexVal = "0" + hexVal; //$NON-NLS-1$
101                        }
102
103                        System.out.print(hexVal + " "); //$NON-NLS-1$
104                }
105        }
106
107        final void dumpNBytes(int start, int nBytes) {
108                StringBuffer asciiBuf = new StringBuffer();
109
110                for (int i = start; (i < (start + nBytes)) && (i < getBufLength()); i++) {
111                        String hexVal = Integer.toHexString(readByte(i) & 0xff);
112
113                        if (hexVal.length() == 1) {
114                                hexVal = "0" + hexVal; //$NON-NLS-1$
115                        }
116
117                        System.out.print(hexVal + " "); //$NON-NLS-1$
118
119                        if ((readByte(i) > 32) && (readByte(i) < 127)) {
120                                asciiBuf.append((char) readByte(i));
121                        } else {
122                                asciiBuf.append("."); //$NON-NLS-1$
123                        }
124
125                        asciiBuf.append(" "); //$NON-NLS-1$
126                }
127
128                System.out.println("    " + asciiBuf.toString()); //$NON-NLS-1$
129        }
130
131        final void ensureCapacity(int additionalData) throws SQLException {
132                if ((this.position + additionalData) > getBufLength()) {
133                        if ((this.position + additionalData) < this.byteBuffer.length) {
134                                // byteBuffer.length is != getBufLength() all of the time
135                                // due to re-using of packets (we don't shrink them)
136                                //
137                                // If we can, don't re-alloc, just set buffer length
138                                // to size of current buffer
139                                setBufLength(this.byteBuffer.length);
140                        } else {
141                                //
142                                // Otherwise, re-size, and pad so we can avoid
143                                // allocing again in the near future
144                                //
145                                int newLength = (int) (this.byteBuffer.length * 1.25);
146
147                                if (newLength < (this.byteBuffer.length + additionalData)) {
148                                        newLength = this.byteBuffer.length
149                                                        + (int) (additionalData * 1.25);
150                                }
151
152                                if (newLength < this.byteBuffer.length) {
153                                        newLength = this.byteBuffer.length + additionalData;
154                                }
155
156                                byte[] newBytes = new byte[newLength];
157
158                                System.arraycopy(this.byteBuffer, 0, newBytes, 0,
159                                                this.byteBuffer.length);
160                                this.byteBuffer = newBytes;
161                                setBufLength(this.byteBuffer.length);
162                        }
163                }
164        }
165
166        /**
167         * Skip over a length-encoded string
168         *
169         * @return The position past the end of the string
170         */
171        public int fastSkipLenString() {
172                long len = this.readFieldLength();
173
174                this.position += len;
175
176                return (int) len;
177        }
178
179        public void fastSkipLenByteArray() {
180                long len = this.readFieldLength();
181
182                if (len == NULL_LENGTH || len == 0) {
183                        return;
184                }
185               
186                this.position += len;
187        }
188       
189        protected final byte[] getBufferSource() {
190                return this.byteBuffer;
191        }
192
193        public int getBufLength() {
194                return this.bufLength;
195        }
196
197        /**
198         * Returns the array of bytes this Buffer is using to read from.
199         *
200         * @return byte array being read from
201         */
202        public byte[] getByteBuffer() {
203                return this.byteBuffer;
204        }
205
206        final byte[] getBytes(int len) {
207                byte[] b = new byte[len];
208                System.arraycopy(this.byteBuffer, this.position, b, 0, len);
209                this.position += len; // update cursor
210
211                return b;
212        }
213
214        /*
215         * (non-Javadoc)
216         *
217         * @see com.mysql.jdbc.Buffer#getBytes(int, int)
218         */
219        byte[] getBytes(int offset, int len) {
220                byte[] dest = new byte[len];
221                System.arraycopy(this.byteBuffer, offset, dest, 0, len);
222
223                return dest;
224        }
225
226        int getCapacity() {
227                return this.byteBuffer.length;
228        }
229
230        public ByteBuffer getNioBuffer() {
231                throw new IllegalArgumentException(Messages
232                                .getString("ByteArrayBuffer.0")); //$NON-NLS-1$
233        }
234
235        /**
236         * Returns the current position to write to/ read from
237         *
238         * @return the current position to write to/ read from
239         */
240        public int getPosition() {
241                return this.position;
242        }
243
244        // 2000-06-05 Changed
245        final boolean isLastDataPacket() {
246                return ((getBufLength() < 9) && ((this.byteBuffer[0] & 0xff) == 254));
247        }
248
249        final boolean isAuthMethodSwitchRequestPacket() {
250                return ((this.byteBuffer[0] & 0xff) == 254);
251        }
252
253        final boolean isOKPacket() {
254                return ((this.byteBuffer[0] & 0xff) == 0);
255        }
256
257        final boolean isRawPacket() {
258                return ((this.byteBuffer[0] & 0xff) == 1);
259        }
260
261        final long newReadLength() {
262                int sw = this.byteBuffer[this.position++] & 0xff;
263
264                switch (sw) {
265                case 251:
266                        return 0;
267
268                case 252:
269                        return readInt();
270
271                case 253:
272                        return readLongInt();
273
274                case 254: // changed for 64 bit lengths
275                        return readLongLong();
276
277                default:
278                        return sw;
279                }
280        }
281
282        final byte readByte() {
283                return this.byteBuffer[this.position++];
284        }
285
286        final byte readByte(int readAt) {
287                return this.byteBuffer[readAt];
288        }
289
290        final long readFieldLength() {
291                int sw = this.byteBuffer[this.position++] & 0xff;
292
293                switch (sw) {
294                case 251:
295                        return NULL_LENGTH;
296
297                case 252:
298                        return readInt();
299
300                case 253:
301                        return readLongInt();
302
303                case 254:
304                        return readLongLong();
305
306                default:
307                        return sw;
308                }
309        }
310
311        // 2000-06-05 Changed
312        final int readInt() {
313                byte[] b = this.byteBuffer; // a little bit optimization
314
315                return (b[this.position++] & 0xff) | ((b[this.position++] & 0xff) << 8);
316        }
317
318        final int readIntAsLong() {
319                byte[] b = this.byteBuffer;
320
321                return (b[this.position++] & 0xff) | ((b[this.position++] & 0xff) << 8)
322                                | ((b[this.position++] & 0xff) << 16)
323                                | ((b[this.position++] & 0xff) << 24);
324        }
325
326        final byte[] readLenByteArray(int offset) {
327                long len = this.readFieldLength();
328
329                if (len == NULL_LENGTH) {
330                        return null;
331                }
332
333                if (len == 0) {
334                        return Constants.EMPTY_BYTE_ARRAY;
335                }
336
337                this.position += offset;
338
339                return getBytes((int) len);
340        }
341
342        final long readLength() {
343                int sw = this.byteBuffer[this.position++] & 0xff;
344
345                switch (sw) {
346                case 251:
347                        return 0;
348
349                case 252:
350                        return readInt();
351
352                case 253:
353                        return readLongInt();
354
355                case 254:
356                        return readLong();
357
358                default:
359                        return sw;
360                }
361        }
362
363        // 2000-06-05 Fixed
364        final long readLong() {
365                byte[] b = this.byteBuffer;
366
367                return ((long) b[this.position++] & 0xff)
368                                | (((long) b[this.position++] & 0xff) << 8)
369                                | ((long) (b[this.position++] & 0xff) << 16)
370                                | ((long) (b[this.position++] & 0xff) << 24);
371        }
372
373        // 2000-06-05 Changed
374        final int readLongInt() {
375                byte[] b = this.byteBuffer;
376
377                return (b[this.position++] & 0xff) | ((b[this.position++] & 0xff) << 8)
378                                | ((b[this.position++] & 0xff) << 16);
379        }
380
381        // 2000-06-05 Fixed
382        final long readLongLong() {
383                byte[] b = this.byteBuffer;
384
385                return (b[this.position++] & 0xff)
386                                | ((long) (b[this.position++] & 0xff) << 8)
387                                | ((long) (b[this.position++] & 0xff) << 16)
388                                | ((long) (b[this.position++] & 0xff) << 24)
389                                | ((long) (b[this.position++] & 0xff) << 32)
390                                | ((long) (b[this.position++] & 0xff) << 40)
391                                | ((long) (b[this.position++] & 0xff) << 48)
392                                | ((long) (b[this.position++] & 0xff) << 56);
393        }
394
395        final int readnBytes() {
396                int sw = this.byteBuffer[this.position++] & 0xff;
397
398                switch (sw) {
399                case 1:
400                        return this.byteBuffer[this.position++] & 0xff;
401
402                case 2:
403                        return this.readInt();
404
405                case 3:
406                        return this.readLongInt();
407
408                case 4:
409                        return (int) this.readLong();
410
411                default:
412                        return 255;
413                }
414        }
415
416        //
417        // Read a null-terminated string
418        //
419        // To avoid alloc'ing a new byte array, we
420        // do this by hand, rather than calling getNullTerminatedBytes()
421        //
422        public final String readString() {
423                int i = this.position;
424                int len = 0;
425                int maxLen = getBufLength();
426
427                while ((i < maxLen) && (this.byteBuffer[i] != 0)) {
428                        len++;
429                        i++;
430                }
431
432                String s = StringUtils.toString(this.byteBuffer, this.position, len);
433                this.position += (len + 1); // update cursor
434
435                return s;
436        }
437
438        final String readString(String encoding, ExceptionInterceptor exceptionInterceptor) throws SQLException {
439                int i = this.position;
440                int len = 0;
441                int maxLen = getBufLength();
442
443                while ((i < maxLen) && (this.byteBuffer[i] != 0)) {
444                        len++;
445                        i++;
446                }
447
448                try {
449                        return StringUtils.toString(this.byteBuffer, this.position, len, encoding);
450                } catch (UnsupportedEncodingException uEE) {
451                        throw SQLError.createSQLException(Messages.getString("ByteArrayBuffer.1") //$NON-NLS-1$
452                                        + encoding + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); //$NON-NLS-1$
453                } finally {
454                        this.position += (len + 1); // update cursor
455                }
456        }
457
458        /**
459         * Read a fixed length string
460         */
461        final String readString(String encoding, ExceptionInterceptor exceptionInterceptor, int expectedLength) throws SQLException {
462                int i = this.position;
463                int len = 0;
464                int maxLen = getBufLength();
465
466                while ((i < maxLen) && (len < expectedLength) && (this.byteBuffer[i] != 0)) {
467                        len++;
468                        i++;
469                }
470               
471                if (len < expectedLength) {
472                        throw SQLError.createSQLException(Messages.getString("ByteArrayBuffer.2"),
473                                        SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor);
474                }
475
476                try {
477                        return StringUtils.toString(this.byteBuffer, this.position, len, encoding);
478                } catch (UnsupportedEncodingException uEE) {
479                        throw SQLError.createSQLException(Messages.getString("ByteArrayBuffer.1") //$NON-NLS-1$
480                                        + encoding + "'", SQLError.SQL_STATE_ILLEGAL_ARGUMENT, exceptionInterceptor); //$NON-NLS-1$
481                } finally {
482                        this.position += len; // update cursor
483                }
484        }
485
486        public void setBufLength(int bufLengthToSet) {
487                this.bufLength = bufLengthToSet;
488        }
489
490        /**
491         * Sets the array of bytes to use as a buffer to read from.
492         *
493         * @param byteBuffer
494         *            the array of bytes to use as a buffer
495         */
496        public void setByteBuffer(byte[] byteBufferToSet) {
497                this.byteBuffer = byteBufferToSet;
498        }
499
500        /**
501         * Set the current position to write to/ read from
502         *
503         * @param position
504         *            the position (0-based index)
505         */
506        public void setPosition(int positionToSet) {
507                this.position = positionToSet;
508        }
509
510        /**
511         * Sets whether this packet was part of a multipacket
512         *
513         * @param flag
514         *            was this packet part of a multipacket?
515         */
516        public void setWasMultiPacket(boolean flag) {
517                this.wasMultiPacket = flag;
518        }
519
520        public String toString() {
521                return dumpClampedBytes(getPosition());
522        }
523
524        public String toSuperString() {
525                return super.toString();
526        }
527
528        /**
529         * Was this packet part of a multipacket?
530         *
531         * @return was this packet part of a multipacket?
532         */
533        public boolean wasMultiPacket() {
534                return this.wasMultiPacket;
535        }
536
537        public final void writeByte(byte b) throws SQLException {
538                ensureCapacity(1);
539
540                this.byteBuffer[this.position++] = b;
541        }
542
543        // Write a byte array
544        public final void writeBytesNoNull(byte[] bytes) throws SQLException {
545                int len = bytes.length;
546                ensureCapacity(len);
547                System.arraycopy(bytes, 0, this.byteBuffer, this.position, len);
548                this.position += len;
549        }
550
551        // Write a byte array with the given offset and length
552        final void writeBytesNoNull(byte[] bytes, int offset, int length)
553                        throws SQLException {
554                ensureCapacity(length);
555                System.arraycopy(bytes, offset, this.byteBuffer, this.position, length);
556                this.position += length;
557        }
558
559        final void writeDouble(double d) throws SQLException {
560                long l = Double.doubleToLongBits(d);
561                writeLongLong(l);
562        }
563
564        final void writeFieldLength(long length) throws SQLException {
565                if (length < 251) {
566                        writeByte((byte) length);
567                } else if (length < 65536L) {
568                        ensureCapacity(3);
569                        writeByte((byte) 252);
570                        writeInt((int) length);
571                } else if (length < 16777216L) {
572                        ensureCapacity(4);
573                        writeByte((byte) 253);
574                        writeLongInt((int) length);
575                } else {
576                        ensureCapacity(9);
577                        writeByte((byte) 254);
578                        writeLongLong(length);
579                }
580        }
581
582        final void writeFloat(float f) throws SQLException {
583                ensureCapacity(4);
584
585                int i = Float.floatToIntBits(f);
586                byte[] b = this.byteBuffer;
587                b[this.position++] = (byte) (i & 0xff);
588                b[this.position++] = (byte) (i >>> 8);
589                b[this.position++] = (byte) (i >>> 16);
590                b[this.position++] = (byte) (i >>> 24);
591        }
592
593        // 2000-06-05 Changed
594        final void writeInt(int i) throws SQLException {
595                ensureCapacity(2);
596
597                byte[] b = this.byteBuffer;
598                b[this.position++] = (byte) (i & 0xff);
599                b[this.position++] = (byte) (i >>> 8);
600        }
601
602        // Write a String using the specified character
603        // encoding
604        final void writeLenBytes(byte[] b) throws SQLException {
605                int len = b.length;
606                ensureCapacity(len + 9);
607                writeFieldLength(len);
608                System.arraycopy(b, 0, this.byteBuffer, this.position, len);
609                this.position += len;
610        }
611
612        // Write a String using the specified character
613        // encoding
614        final void writeLenString(String s, String encoding, String serverEncoding,
615                        SingleByteCharsetConverter converter, boolean parserKnowsUnicode,
616                        MySQLConnection conn)
617                        throws UnsupportedEncodingException, SQLException {
618                byte[] b = null;
619
620                if (converter != null) {
621                        b = converter.toBytes(s);
622                } else {
623                        b = StringUtils.getBytes(s, encoding, serverEncoding,
624                                        parserKnowsUnicode, conn, conn.getExceptionInterceptor());
625                }
626
627                int len = b.length;
628                ensureCapacity(len + 9);
629                writeFieldLength(len);
630                System.arraycopy(b, 0, this.byteBuffer, this.position, len);
631                this.position += len;
632        }
633
634        // 2000-06-05 Changed
635        final void writeLong(long i) throws SQLException {
636                ensureCapacity(4);
637
638                byte[] b = this.byteBuffer;
639                b[this.position++] = (byte) (i & 0xff);
640                b[this.position++] = (byte) (i >>> 8);
641                b[this.position++] = (byte) (i >>> 16);
642                b[this.position++] = (byte) (i >>> 24);
643        }
644
645        // 2000-06-05 Changed
646        final void writeLongInt(int i) throws SQLException {
647                ensureCapacity(3);
648                byte[] b = this.byteBuffer;
649                b[this.position++] = (byte) (i & 0xff);
650                b[this.position++] = (byte) (i >>> 8);
651                b[this.position++] = (byte) (i >>> 16);
652        }
653
654        final void writeLongLong(long i) throws SQLException {
655                ensureCapacity(8);
656                byte[] b = this.byteBuffer;
657                b[this.position++] = (byte) (i & 0xff);
658                b[this.position++] = (byte) (i >>> 8);
659                b[this.position++] = (byte) (i >>> 16);
660                b[this.position++] = (byte) (i >>> 24);
661                b[this.position++] = (byte) (i >>> 32);
662                b[this.position++] = (byte) (i >>> 40);
663                b[this.position++] = (byte) (i >>> 48);
664                b[this.position++] = (byte) (i >>> 56);
665        }
666
667        // Write null-terminated string
668        final void writeString(String s) throws SQLException {
669                ensureCapacity((s.length() * 2) + 1);
670                writeStringNoNull(s);
671                this.byteBuffer[this.position++] = 0;
672        }
673       
674        //       Write null-terminated string in the given encoding
675        final void writeString(String s, String encoding, MySQLConnection conn) throws SQLException {
676                ensureCapacity((s.length() * 2) + 1);
677                try {
678                        writeStringNoNull(s, encoding, encoding, false, conn);
679                } catch (UnsupportedEncodingException ue) {
680                        throw new SQLException(ue.toString(), SQLError.SQL_STATE_GENERAL_ERROR);
681                }
682               
683                this.byteBuffer[this.position++] = 0;
684        }
685
686        // Write string, with no termination
687        final void writeStringNoNull(String s) throws SQLException {
688                int len = s.length();
689                ensureCapacity(len * 2);
690                System.arraycopy(StringUtils.getBytes(s), 0, this.byteBuffer, this.position, len);
691                this.position += len;
692
693                // for (int i = 0; i < len; i++)
694                // {
695                // this.byteBuffer[this.position++] = (byte)s.charAt(i);
696                // }
697        }
698
699        // Write a String using the specified character
700        // encoding
701        final void writeStringNoNull(String s, String encoding,
702                        String serverEncoding, boolean parserKnowsUnicode, MySQLConnection conn)
703                        throws UnsupportedEncodingException, SQLException {
704                byte[] b = StringUtils.getBytes(s, encoding, serverEncoding,
705                                parserKnowsUnicode, conn, conn.getExceptionInterceptor());
706
707                int len = b.length;
708                ensureCapacity(len);
709                System.arraycopy(b, 0, this.byteBuffer, this.position, len);
710                this.position += len;
711        }
712}
Note: See TracBrowser for help on using the repository browser.