You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by ba...@apache.org on 2005/04/28 21:05:45 UTC
svn commit: r165178 [8/26] - in /incubator/derby/code/trunk: ./ java/client/
java/client/org/ java/client/org/apache/ java/client/org/apache/derby/
java/client/org/apache/derby/client/ java/client/org/apache/derby/client/am/
java/client/org/apache/derby/client/net/
java/client/org/apache/derby/client/resources/
java/client/org/apache/derby/jdbc/ tools/ant/properties/
Added: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/DateTime.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/client/org/apache/derby/client/am/DateTime.java?rev=165178&view=auto
==============================================================================
--- incubator/derby/code/trunk/java/client/org/apache/derby/client/am/DateTime.java (added)
+++ incubator/derby/code/trunk/java/client/org/apache/derby/client/am/DateTime.java Thu Apr 28 12:05:42 2005
@@ -0,0 +1,639 @@
+/*
+
+ Derby - Class org.apache.derby.client.am.DateTime
+
+ Copyright (c) 2001, 2005 The Apache Software Foundation or its licensors, where applicable.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+package org.apache.derby.client.am;
+
+
+/**
+ * High performance converters from date/time byte encodings to JDBC Date, Time and Timestamp objects.
+ * <p>
+ * Using this class for direct date/time conversions from bytes offers
+ * superior performance over the alternative method of first constructing
+ * a Java String from the encoded bytes, and then using
+ * {@link java.sql.Date#valueOf java.sql.Date.valueOf()},
+ * {@link java.sql.Time#valueOf java.sql.Time.valueOf()} or
+ * {@link java.sql.Timestamp#valueOf java.sql.Timestamp.valueOf()}.
+ * <p>
+ */
+public class DateTime
+{
+
+ // Hide the default constructor
+ private DateTime () {}
+
+ private static final int dateRepresentationLength = 10;
+ private static final int timeRepresentationLength = 8;
+ private static final int timestampRepresentationLength = 26;
+
+ // *********************************************************
+ // ********** Output converters (byte[] -> class) **********
+ // *********************************************************
+
+ /**
+ * Expected character representation is DERBY string representation
+ * of a date, which is in one of the following format.
+ */
+ public static final java.sql.Date dateBytesToDate (byte[] buffer,
+ int offset,
+ java.sql.Date recyclableDate)
+ {
+ int year, month, day;
+
+ String date = new String (buffer, offset, DateTime.dateRepresentationLength);
+ int yearIndx, monthIndx, dayIndx;
+ if (date.charAt (4) == '-') {
+ // JIS format: yyyy-mm-dd.
+ yearIndx = 0;
+ monthIndx = 5;
+ dayIndx = 8;
+ }
+ else throw new java.lang.IllegalArgumentException ("Unsupported date format!");
+
+ int zeroBase = ((int) '0');
+ // Character arithmetic is used rather than
+ // the less efficient Integer.parseInt (date.substring()).
+ year =
+ 1000*(((int) date.charAt (yearIndx)) - zeroBase) +
+ 100*(((int) date.charAt (yearIndx+1)) - zeroBase) +
+ 10*(((int) date.charAt (yearIndx+2)) - zeroBase) +
+ (((int) date.charAt (yearIndx+3)) - zeroBase) -
+ 1900;
+ month =
+ 10*(((int) date.charAt (monthIndx)) - zeroBase) +
+ (((int) date.charAt (monthIndx+1)) - zeroBase) -
+ 1;
+ day =
+ 10*(((int) date.charAt (dayIndx)) - zeroBase) +
+ (((int) date.charAt (dayIndx+1)) - zeroBase);
+
+ if (recyclableDate == null)
+ return new java.sql.Date (year, month, day);
+ else {
+ recyclableDate.setYear (year);
+ recyclableDate.setMonth (month);
+ recyclableDate.setDate (day);
+ return recyclableDate;
+ }
+ }
+
+ /**
+ * Expected character representation is DERBY string representation
+ * of a time, which is in one of the following format: hh.mm.ss.
+ */
+ public static final java.sql.Time timeBytesToTime (byte[] buffer,
+ int offset,
+ java.sql.Time recyclableTime)
+ {
+ int hour, minute, second;
+
+ String time = new String (buffer, offset, DateTime.timeRepresentationLength);
+ int zeroBase = ((int) '0');
+
+ // compute hour.
+ hour =
+ 10*(((int) time.charAt (0)) - zeroBase) +
+ (((int) time.charAt (1)) - zeroBase);
+ // compute minute.
+ minute =
+ 10*(((int) time.charAt (3)) - zeroBase) +
+ (((int) time.charAt (4)) - zeroBase);
+ // compute second.
+ second =
+ 10*(((int) time.charAt (6)) - zeroBase) +
+ (((int) time.charAt (7)) - zeroBase);
+
+ if (recyclableTime == null)
+ return new java.sql.Time (hour, minute, second);
+ else {
+ recyclableTime.setHours (hour);
+ recyclableTime.setMinutes (minute);
+ recyclableTime.setSeconds (second);
+ return recyclableTime;
+ }
+ }
+
+ /**
+ * Expected character representation is DERBY string representation
+ * of a timestamp: <code>yyyy-mm-dd-hh.mm.ss.ffffff</code>.
+ *
+ */
+ public static final java.sql.Timestamp timestampBytesToTimestamp (byte[] buffer,
+ int offset,
+ java.sql.Timestamp recyclableTimestamp)
+ {
+ int year, month, day, hour, minute, second, fraction;
+
+ String timestamp = new String (buffer, offset, DateTime.timestampRepresentationLength);
+ int zeroBase = ((int) '0');
+
+ year =
+ 1000*(((int) timestamp.charAt (0)) - zeroBase) +
+ 100*(((int) timestamp.charAt (1)) - zeroBase) +
+ 10*(((int) timestamp.charAt (2)) - zeroBase) +
+ (((int) timestamp.charAt (3)) - zeroBase) -
+ 1900;
+ month =
+ 10*(((int) timestamp.charAt (5)) - zeroBase) +
+ (((int) timestamp.charAt (6)) - zeroBase) -
+ 1;
+ day =
+ 10*(((int) timestamp.charAt (8)) - zeroBase) +
+ (((int) timestamp.charAt (9)) - zeroBase);
+ hour =
+ 10*(((int) timestamp.charAt (11)) - zeroBase) +
+ (((int) timestamp.charAt (12)) - zeroBase);
+ minute =
+ 10*(((int) timestamp.charAt (14)) - zeroBase) +
+ (((int) timestamp.charAt (15)) - zeroBase);
+ second =
+ 10*(((int) timestamp.charAt (17)) - zeroBase) +
+ (((int) timestamp.charAt (18)) - zeroBase);
+ fraction =
+ 100000*(((int) timestamp.charAt (20)) - zeroBase) +
+ 10000*(((int) timestamp.charAt (21)) - zeroBase) +
+ 1000*(((int) timestamp.charAt (22)) - zeroBase) +
+ 100*(((int) timestamp.charAt (23)) - zeroBase) +
+ 10*(((int) timestamp.charAt (24)) - zeroBase) +
+ (((int) timestamp.charAt (25)) - zeroBase);
+
+ if (recyclableTimestamp == null)
+ return new java.sql.Timestamp (year, month, day, hour, minute, second, fraction*1000);
+ else {
+ recyclableTimestamp.setYear (year);
+ recyclableTimestamp.setMonth (month);
+ recyclableTimestamp.setDate (day);
+ recyclableTimestamp.setHours (hour);
+ recyclableTimestamp.setMinutes (minute);
+ recyclableTimestamp.setSeconds (second);
+ recyclableTimestamp.setNanos (fraction*1000);
+ return recyclableTimestamp;
+ }
+ }
+
+ // ********************************************************
+ // ********** Input converters (class -> byte[]) **********
+ // ********************************************************
+
+ /**
+ * The returned character representation is in JDBC date format:
+ * <code>yyyy-mm-dd</code> date format in
+ * DERBY string representation of a date.
+ *
+ */
+ public static final int dateToDateBytes (byte[] buffer,
+ int offset,
+ java.sql.Date date
+ ) throws ConversionException
+ {
+ int year = date.getYear () + 1900;
+ if (year > 9999) throw new ConversionException ("Year exceeds the maximum \"9999\".");
+ int month = date.getMonth () + 1;
+ int day = date.getDate ();
+
+ char[] dateChars = new char[DateTime.dateRepresentationLength];
+ int zeroBase = (int) '0';
+ dateChars[0] = (char) (year/1000 + zeroBase);
+ dateChars[1] = (char) ((year%1000)/100 + zeroBase);
+ dateChars[2] = (char) ((year%100)/10 + zeroBase);
+ dateChars[3] = (char) (year%10 + + zeroBase);
+ dateChars[4] = '-';
+ dateChars[5] = (char) (month/10 + zeroBase);
+ dateChars[6] = (char) (month%10 + zeroBase);
+ dateChars[7] = '-';
+ dateChars[8] = (char) (day/10 + zeroBase);
+ dateChars[9] = (char) (day%10 + zeroBase);
+ byte[] dateBytes = (new String(dateChars)).getBytes ();
+ System.arraycopy(dateBytes, 0, buffer, offset, DateTime.dateRepresentationLength);
+
+ return DateTime.dateRepresentationLength;
+ }
+
+ /**
+ * The returned character representation is in JDBC time escape format:
+ * <code>hh:mm:ss</code>, which is the same as JIS time format in
+ * DERBY string representation of a time.
+ *
+ */
+ public static final int timeToTimeBytes (byte[] buffer,
+ int offset,
+ java.sql.Time time)
+ {
+ int hour = time.getHours();
+ int minute = time.getMinutes();
+ int second = time.getSeconds();
+
+ char[] timeChars = new char[DateTime.timeRepresentationLength];
+ int zeroBase = (int) '0';
+ timeChars[0] = (char) (hour/10 + zeroBase);
+ timeChars[1] = (char) (hour%10 + + zeroBase);
+ timeChars[2] = ':';
+ timeChars[3] = (char) (minute/10 + zeroBase);
+ timeChars[4] = (char) (minute%10 + zeroBase);
+ timeChars[5] = ':';
+ timeChars[6] = (char) (second/10 + zeroBase);
+ timeChars[7] = (char) (second%10 + zeroBase);
+ byte[] timeBytes = (new String(timeChars)).getBytes ();
+ System.arraycopy(timeBytes, 0, buffer, offset, DateTime.timeRepresentationLength);
+
+ return DateTime.timeRepresentationLength;
+ }
+
+ /**
+ * The returned character representation is in DERBY string representation of
+ * a timestamp: <code>yyyy-mm-dd-hh.mm.ss.ffffff</code>.
+ */
+ public static final int timestampToTimestampBytes (byte[] buffer,
+ int offset,
+ java.sql.Timestamp timestamp
+ ) throws ConversionException
+ {
+ int year = timestamp.getYear () + 1900;
+ if (year > 9999) throw new ConversionException ("Year exceeds the maximum \"9999\".");
+ int month = timestamp.getMonth () + 1;
+ int day = timestamp.getDate ();
+ int hour = timestamp.getHours();
+ int minute = timestamp.getMinutes();
+ int second = timestamp.getSeconds();
+ int microsecond = timestamp.getNanos()/1000;
+
+ char[] timestampChars = new char[DateTime.timestampRepresentationLength];
+ int zeroBase = (int) '0';
+ timestampChars[0] = (char) (year/1000 + zeroBase);
+ timestampChars[1] = (char) ((year%1000)/100 + zeroBase);
+ timestampChars[2] = (char) ((year%100)/10 + zeroBase);
+ timestampChars[3] = (char) (year%10 + + zeroBase);
+ timestampChars[4] = '-';
+ timestampChars[5] = (char) (month/10 + zeroBase);
+ timestampChars[6] = (char) (month%10 + zeroBase);
+ timestampChars[7] = '-';
+ timestampChars[8] = (char) (day/10 + zeroBase);
+ timestampChars[9] = (char) (day%10 + zeroBase);
+ timestampChars[10] = '-';
+ timestampChars[11] = (char) (hour/10 + zeroBase);
+ timestampChars[12] = (char) (hour%10 + zeroBase);
+ timestampChars[13] = '.';
+ timestampChars[14] = (char) (minute/10 + zeroBase);
+ timestampChars[15] = (char) (minute%10 + zeroBase);
+ timestampChars[16] = '.';
+ timestampChars[17] = (char) (second/10 + zeroBase);
+ timestampChars[18] = (char) (second%10 + zeroBase);
+ timestampChars[19] = '.';
+ timestampChars[20] = (char) (microsecond/100000 + zeroBase);
+ timestampChars[21] = (char) ((microsecond%100000)/10000 + zeroBase);
+ timestampChars[22] = (char) ((microsecond%10000)/1000 + zeroBase);
+ timestampChars[23] = (char) ((microsecond%1000)/100 + zeroBase);
+ timestampChars[24] = (char) ((microsecond%100)/10 + zeroBase);
+ timestampChars[25] = (char) (microsecond%10 + zeroBase);
+
+ byte[] timestampBytes = (new String(timestampChars)).getBytes ();
+ System.arraycopy(timestampBytes, 0, buffer, offset, DateTime.timestampRepresentationLength);
+
+ return DateTime.timestampRepresentationLength;
+ }
+
+ // *********************************************************
+ // ******* CROSS output converters (byte[] -> class) *******
+ // *********************************************************
+
+ /**
+ * Expected character representation is DERBY string representation
+ * of a date, which is in one of the following format.
+ */
+ public static final java.sql.Timestamp dateBytesToTimestamp (byte[] buffer,
+ int offset,
+ java.sql.Timestamp recyclableTimestamp)
+ {
+ int year, month, day;
+
+ String date = new String (buffer, offset, DateTime.dateRepresentationLength);
+ int yearIndx, monthIndx, dayIndx;
+
+ yearIndx = 0;
+ monthIndx = 5;
+ dayIndx = 8;
+
+ int zeroBase = ((int) '0');
+ // Character arithmetic is used rather than
+ // the less efficient Integer.parseInt (date.substring()).
+ year =
+ 1000*(((int) date.charAt (yearIndx)) - zeroBase) +
+ 100*(((int) date.charAt (yearIndx+1)) - zeroBase) +
+ 10*(((int) date.charAt (yearIndx+2)) - zeroBase) +
+ (((int) date.charAt (yearIndx+3)) - zeroBase) -
+ 1900;
+ month =
+ 10*(((int) date.charAt (monthIndx)) - zeroBase) +
+ (((int) date.charAt (monthIndx+1)) - zeroBase) -
+ 1;
+ day =
+ 10*(((int) date.charAt (dayIndx)) - zeroBase) +
+ (((int) date.charAt (dayIndx+1)) - zeroBase);
+
+ if (recyclableTimestamp == null)
+ return new java.sql.Timestamp (year, month, day, 0, 0, 0, 0);
+ else {
+ recyclableTimestamp.setYear (year);
+ recyclableTimestamp.setMonth (month);
+ recyclableTimestamp.setDate (day);
+ recyclableTimestamp.setHours (0);
+ recyclableTimestamp.setMinutes (0);
+ recyclableTimestamp.setSeconds (0);
+ recyclableTimestamp.setNanos (0);
+ return recyclableTimestamp;
+ }
+ }
+
+ /**
+ * Expected character representation is DERBY string representation
+ * of a time, which is in one of the following format.
+ */
+ public static final java.sql.Timestamp timeBytesToTimestamp (byte[] buffer,
+ int offset,
+ java.sql.Timestamp recyclableTimestamp)
+ {
+ int hour, minute, second;
+
+ String time = new String (buffer, offset, DateTime.timeRepresentationLength);
+ int zeroBase = ((int) '0');
+
+ // compute hour.
+ hour =
+ 10*(((int) time.charAt (0)) - zeroBase) +
+ (((int) time.charAt (1)) - zeroBase);
+ // compute minute.
+ minute =
+ 10*(((int) time.charAt (3)) - zeroBase) +
+ (((int) time.charAt (4)) - zeroBase);
+ // compute second JIS format: hh:mm:ss.
+ second =
+ 10*(((int) time.charAt (6)) - zeroBase) +
+ (((int) time.charAt (7)) - zeroBase);
+
+ if (recyclableTimestamp == null)
+ return new java.sql.Timestamp (0, 0, 1, hour, minute, second, 0);
+ else {
+ recyclableTimestamp.setYear (0);
+ recyclableTimestamp.setMonth (0);
+ recyclableTimestamp.setDate (1);
+ recyclableTimestamp.setHours (hour);
+ recyclableTimestamp.setMinutes (minute);
+ recyclableTimestamp.setSeconds (second);
+ recyclableTimestamp.setNanos (0);
+ return recyclableTimestamp;
+ }
+ }
+
+ /**
+ * Expected character representation is DERBY string representation
+ * of a timestamp: <code>yyyy-mm-dd-hh.mm.ss.ffffff</code>.
+ */
+ public static final java.sql.Date timestampBytesToDate (byte[] buffer,
+ int offset,
+ java.sql.Date recyclableDate)
+ {
+ int year, month, day;
+
+ String timestamp = new String (buffer, offset, DateTime.timestampRepresentationLength);
+ int zeroBase = ((int) '0');
+
+ year =
+ 1000*(((int) timestamp.charAt (0)) - zeroBase) +
+ 100*(((int) timestamp.charAt (1)) - zeroBase) +
+ 10*(((int) timestamp.charAt (2)) - zeroBase) +
+ (((int) timestamp.charAt (3)) - zeroBase) -
+ 1900;
+ month =
+ 10*(((int) timestamp.charAt (5)) - zeroBase) +
+ (((int) timestamp.charAt (6)) - zeroBase) -
+ 1;
+ day =
+ 10*(((int) timestamp.charAt (8)) - zeroBase) +
+ (((int) timestamp.charAt (9)) - zeroBase);
+
+ if (recyclableDate == null)
+ return new java.sql.Date (year, month, day);
+ else {
+ recyclableDate.setYear (year);
+ recyclableDate.setMonth (month);
+ recyclableDate.setDate (day);
+ return recyclableDate;
+ }
+ }
+
+ /**
+ * Expected character representation is DERBY string representation
+ * of a timestamp: <code>yyyy-mm-dd-hh.mm.ss.ffffff</code>.
+ */
+ public static final java.sql.Time timestampBytesToTime (byte[] buffer,
+ int offset,
+ java.sql.Time recyclableTime)
+ {
+ int hour, minute, second;
+
+ String timestamp = new String (buffer, offset, DateTime.timestampRepresentationLength);
+ int zeroBase = ((int) '0');
+
+ hour =
+ 10*(((int) timestamp.charAt (11)) - zeroBase) +
+ (((int) timestamp.charAt (12)) - zeroBase);
+ minute =
+ 10*(((int) timestamp.charAt (14)) - zeroBase) +
+ (((int) timestamp.charAt (15)) - zeroBase);
+ second =
+ 10*(((int) timestamp.charAt (17)) - zeroBase) +
+ (((int) timestamp.charAt (18)) - zeroBase);
+
+ if (recyclableTime == null)
+ return new java.sql.Time (hour, minute, second);
+ else {
+ recyclableTime.setYear (hour);
+ recyclableTime.setMonth (minute);
+ recyclableTime.setDate (second);
+ return recyclableTime;
+ }
+ }
+
+ // *********************************************************
+ // ******* CROSS input converters (class -> byte[]) ********
+ // *********************************************************
+
+ /**
+ * The returned character representation is in JDBC date escape format:
+ * <code>yyyy-mm-dd</code>, which is the same as JIS date format in
+ * DERBY string representation of a date.
+ *
+ */
+ public static final int timestampToDateBytes (byte[] buffer,
+ int offset,
+ java.sql.Timestamp timestamp
+ ) throws ConversionException
+ {
+ int year = timestamp.getYear () + 1900;
+ if (year > 9999) throw new ConversionException ("Year exceeds the maximum \"9999\".");
+ int month = timestamp.getMonth () + 1;
+ int day = timestamp.getDate ();
+
+ char[] dateChars = new char[DateTime.dateRepresentationLength];
+ int zeroBase = (int) '0';
+ dateChars[0] = (char) (year/1000 + zeroBase);
+ dateChars[1] = (char) ((year%1000)/100 + zeroBase);
+ dateChars[2] = (char) ((year%100)/10 + zeroBase);
+ dateChars[3] = (char) (year%10 + + zeroBase);
+ dateChars[4] = '-';
+ dateChars[5] = (char) (month/10 + zeroBase);
+ dateChars[6] = (char) (month%10 + zeroBase);
+ dateChars[7] = '-';
+ dateChars[8] = (char) (day/10 + zeroBase);
+ dateChars[9] = (char) (day%10 + zeroBase);
+ byte[] dateBytes = (new String(dateChars)).getBytes ();
+ System.arraycopy(dateBytes, 0, buffer, offset, DateTime.dateRepresentationLength);
+
+ return DateTime.dateRepresentationLength;
+ }
+
+ /**
+ * The returned character representation is in JDBC time escape format:
+ * <code>hh:mm:ss</code>, which is the same as JIS time format in
+ * DERBY string representation of a time.
+ *
+ */
+ public static final int timestampToTimeBytes (byte[] buffer,
+ int offset,
+ java.sql.Timestamp timestamp)
+ {
+ int hour = timestamp.getHours();
+ int minute = timestamp.getMinutes();
+ int second = timestamp.getSeconds();
+
+ char[] timeChars = new char[DateTime.timeRepresentationLength];
+ int zeroBase = (int) '0';
+ timeChars[0] = (char) (hour/10 + zeroBase);
+ timeChars[1] = (char) (hour%10 + + zeroBase);
+ timeChars[2] = ':';
+ timeChars[3] = (char) (minute/10 + zeroBase);
+ timeChars[4] = (char) (minute%10 + zeroBase);
+ timeChars[5] = ':';
+ timeChars[6] = (char) (second/10 + zeroBase);
+ timeChars[7] = (char) (second%10 + zeroBase);
+ byte[] timeBytes = (new String(timeChars)).getBytes ();
+ System.arraycopy(timeBytes, 0, buffer, offset, DateTime.timeRepresentationLength);
+
+ return DateTime.timeRepresentationLength;
+ }
+
+ /**
+ * The returned character representation is in DERBY string representation of
+ * a timestamp: <code>yyyy-mm-dd-hh.mm.ss.ffffff</code>.
+ *
+ */
+ public static final int dateToTimestampBytes (byte[] buffer,
+ int offset,
+ java.sql.Date date
+ ) throws ConversionException
+ {
+ int year = date.getYear () + 1900;
+ if (year > 9999) throw new ConversionException ("Year exceeds the maximum \"9999\".");
+ int month = date.getMonth () + 1;
+ int day = date.getDate ();
+
+ char[] timestampChars = new char[DateTime.timestampRepresentationLength];
+ int zeroBase = (int) '0';
+ timestampChars[0] = (char) (year/1000 + zeroBase);
+ timestampChars[1] = (char) ((year%1000)/100 + zeroBase);
+ timestampChars[2] = (char) ((year%100)/10 + zeroBase);
+ timestampChars[3] = (char) (year%10 + + zeroBase);
+ timestampChars[4] = '-';
+ timestampChars[5] = (char) (month/10 + zeroBase);
+ timestampChars[6] = (char) (month%10 + zeroBase);
+ timestampChars[7] = '-';
+ timestampChars[8] = (char) (day/10 + zeroBase);
+ timestampChars[9] = (char) (day%10 + zeroBase);
+ timestampChars[10] = '-';
+ timestampChars[11] = '0';
+ timestampChars[12] = '0';
+ timestampChars[13] = '.';
+ timestampChars[14] = '0';
+ timestampChars[15] = '0';
+ timestampChars[16] = '.';
+ timestampChars[17] = '0';
+ timestampChars[18] = '0';
+ timestampChars[19] = '.';
+ timestampChars[20] = '0';
+ timestampChars[21] = '0';
+ timestampChars[22] = '0';
+ timestampChars[23] = '0';
+ timestampChars[24] = '0';
+ timestampChars[25] = '0';
+
+ byte[] timestampBytes = (new String(timestampChars)).getBytes ();
+ System.arraycopy(timestampBytes, 0, buffer, offset, DateTime.timestampRepresentationLength);
+
+ return DateTime.timestampRepresentationLength;
+ }
+
+ /**
+ * The returned character representation is in DERBY string representation of
+ * a timestamp: <code>yyyy-mm-dd-hh.mm.ss.ffffff</code>.
+ *
+ */
+ public static final int timeToTimestampBytes (byte[] buffer,
+ int offset,
+ java.sql.Time time
+ )
+ {
+ int hour = time.getHours();
+ int minute = time.getMinutes();
+ int second = time.getSeconds();
+
+ char[] timestampChars = new char[DateTime.timestampRepresentationLength];
+ int zeroBase = (int) '0';
+ timestampChars[0] = '1';
+ timestampChars[1] = '9';
+ timestampChars[2] = '0';
+ timestampChars[3] = '0';
+ timestampChars[4] = '-';
+ timestampChars[5] = '0';
+ timestampChars[6] = '1';
+ timestampChars[7] = '-';
+ timestampChars[8] = '0';
+ timestampChars[9] = '1';
+ timestampChars[10] = '-';
+ timestampChars[11] = (char) (hour/10 + zeroBase);
+ timestampChars[12] = (char) (hour%10 + zeroBase);
+ timestampChars[13] = '.';
+ timestampChars[14] = (char) (minute/10 + zeroBase);
+ timestampChars[15] = (char) (minute%10 + zeroBase);
+ timestampChars[16] = '.';
+ timestampChars[17] = (char) (second/10 + zeroBase);
+ timestampChars[18] = (char) (second%10 + zeroBase);
+ timestampChars[19] = '.';
+ timestampChars[20] = '0';
+ timestampChars[21] = '0';
+ timestampChars[22] = '0';
+ timestampChars[23] = '0';
+ timestampChars[24] = '0';
+ timestampChars[25] = '0';
+
+ byte[] timestampBytes = (new String(timestampChars)).getBytes ();
+ System.arraycopy(timestampBytes, 0, buffer, offset, DateTime.timestampRepresentationLength);
+
+ return DateTime.timestampRepresentationLength;
+ }
+}
+
Propchange: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/DateTime.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Decimal.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Decimal.java?rev=165178&view=auto
==============================================================================
--- incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Decimal.java (added)
+++ incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Decimal.java Thu Apr 28 12:05:42 2005
@@ -0,0 +1,489 @@
+/*
+
+ Derby - Class org.apache.derby.client.am.Decimal
+
+ Copyright (c) 2001, 2005 The Apache Software Foundation or its licensors, where applicable.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+package org.apache.derby.client.am;
+
+/**
+ * Converters from fixed point decimal bytes to <code>java.math.BigDecimal</code>,
+ * <code>double</code>, or <code>long</code>.
+ */
+public class Decimal
+{
+ /**
+ * Packed Decimal representation
+ */
+ public final static int PACKED_DECIMAL = 0x30;
+
+ //--------------------------private constants---------------------------------
+
+ private static final int[][] tenRadixMagnitude = {
+ { 0x3b9aca00 }, // 10^9
+ { 0x0de0b6b3, 0xa7640000 }, // 10^18
+ { 0x033b2e3c, 0x9fd0803c, 0xe8000000 }, // 10^27
+ };
+
+ //--------------------------constructors--------------------------------------
+
+ // Hide the default constructor, this is a static class.
+ private Decimal() {}
+
+ //--------------------------private helper methods----------------------------
+
+ /**
+ * Convert a range of packed nybbles (up to 9 digits without overflow) to an int.
+ * Note that for performance purpose, it does not do array-out-of-bound checking.
+ */
+ private static final int packedNybblesToInt (byte[] buffer,
+ int offset,
+ int startNybble,
+ int numberOfNybbles)
+ {
+ int value = 0;
+
+ int i = startNybble / 2;
+ if ((startNybble % 2) != 0) {
+ // process low nybble of the first byte if necessary.
+ value += buffer[offset+i] & 0x0F;
+ i++;
+ }
+
+ int endNybble = startNybble + numberOfNybbles -1;
+ for (; i<(endNybble+1)/2; i++) {
+ value = value*10 + ((buffer[offset+i] & 0xF0) >>> 4); // high nybble.
+ value = value*10 + (buffer[offset+i] & 0x0F); // low nybble.
+ }
+
+ if ((endNybble % 2) == 0) {
+ // process high nybble of the last byte if necessary.
+ value = value*10 + ((buffer[offset+i] & 0xF0) >>> 4);
+ }
+
+ return value;
+ }
+
+ /**
+ * Convert a range of packed nybbles (up to 18 digits without overflow) to a long.
+ * Note that for performance purpose, it does not do array-out-of-bound checking.
+ */
+ private static final long packedNybblesToLong (byte[] buffer,
+ int offset,
+ int startNybble,
+ int numberOfNybbles)
+ {
+ long value = 0;
+
+ int i = startNybble / 2;
+ if ((startNybble % 2) != 0) {
+ // process low nybble of the first byte if necessary.
+ value += buffer[offset+i] & 0x0F;
+ i++;
+ }
+
+ int endNybble = startNybble + numberOfNybbles -1;
+ for (; i<(endNybble+1)/2; i++) {
+ value = value*10 + ((buffer[offset+i] & 0xF0) >>> 4); // high nybble.
+ value = value*10 + (buffer[offset+i] & 0x0F); // low nybble.
+ }
+
+ if ((endNybble % 2) == 0) {
+ // process high nybble of the last byte if necessary.
+ value = value*10 + ((buffer[offset+i] & 0xF0) >>> 4);
+ }
+
+ return value;
+ }
+
+ /**
+ * Compute the int array of magnitude from input value segments.
+ */
+ private static final int[] computeMagnitude(int[] input)
+ {
+ int length = input.length;
+ int[] mag = new int[length];
+
+ mag[length-1] = input[length-1];
+ for (int i=0; i<length-1; i++) {
+ int carry = 0;
+ int j = tenRadixMagnitude[i].length-1;
+ int k = length-1;
+ for (; j>=0; j--, k--) {
+ long product = (input[length-2-i] & 0xFFFFFFFFL) * (tenRadixMagnitude[i][j] & 0xFFFFFFFFL)
+ + (mag[k] & 0xFFFFFFFFL) // add previous value
+ + (carry & 0xFFFFFFFFL); // add carry
+ carry = (int) (product >>> 32);
+ mag[k] = (int) (product & 0xFFFFFFFFL);
+ }
+ mag[k] = (int) carry;
+ }
+ return mag;
+ }
+
+ //--------------entry points for runtime representation-----------------------
+
+ /**
+ * Build a <code>java.math.BigDecimal</code> from a fixed point decimal byte representation.
+ *
+ * @exception IllegalArgumentException if the specified representation is not recognized.
+ */
+ public static final java.math.BigDecimal getBigDecimal (byte[] buffer,
+ int offset,
+ int precision,
+ int scale
+ ) throws java.io.UnsupportedEncodingException
+ {
+ // The byte-length of a packed decimal with precision <code>p</code> is always <code>p/2 + 1</code>
+ int length = precision / 2 + 1;
+
+ // check for sign.
+ int signum;
+ if ((buffer[offset+length-1] & 0x0F) == 0x0D)
+ signum = -1;
+ else
+ signum = 1;
+
+ if (precision <= 9) {
+ // can be handled by int without overflow.
+ int value = packedNybblesToInt(buffer, offset, 0, length*2-1);
+
+ // convert value to a byte array of magnitude.
+ byte[] magnitude = new byte[4];
+ magnitude[0] = (byte)(value >>> 24);
+ magnitude[1] = (byte)(value >>> 16);
+ magnitude[2] = (byte)(value >>> 8);
+ magnitude[3] = (byte)(value);
+
+ return new java.math.BigDecimal (new java.math.BigInteger(signum, magnitude), scale);
+ }
+ else if (precision <= 18) {
+ // can be handled by long without overflow.
+ long value = packedNybblesToLong(buffer, offset, 0, length*2-1);
+
+ // convert value to a byte array of magnitude.
+ byte[] magnitude = new byte[8];
+ magnitude[0] = (byte)(value >>> 56);
+ magnitude[1] = (byte)(value >>> 48);
+ magnitude[2] = (byte)(value >>> 40);
+ magnitude[3] = (byte)(value >>> 32);
+ magnitude[4] = (byte)(value >>> 24);
+ magnitude[5] = (byte)(value >>> 16);
+ magnitude[6] = (byte)(value >>> 8);
+ magnitude[7] = (byte)(value);
+
+ return new java.math.BigDecimal (new java.math.BigInteger(signum, magnitude), scale);
+ }
+ else if (precision <= 27) {
+ // get the value of last 9 digits (5 bytes).
+ int lo = packedNybblesToInt(buffer, offset, (length-5)*2, 9);
+ // get the value of another 9 digits (5 bytes).
+ int me = packedNybblesToInt(buffer, offset, (length-10)*2+1, 9);
+ // get the value of the rest digits.
+ int hi = packedNybblesToInt(buffer, offset, 0, (length-10)*2+1);
+
+ // compute the int array of magnitude.
+ int[] value = computeMagnitude(new int[] {hi, me, lo});
+
+ // convert value to a byte array of magnitude.
+ byte[] magnitude = new byte[12];
+ magnitude[0] = (byte)(value[0] >>> 24);
+ magnitude[1] = (byte)(value[0] >>> 16);
+ magnitude[2] = (byte)(value[0] >>> 8);
+ magnitude[3] = (byte)(value[0]);
+ magnitude[4] = (byte)(value[1] >>> 24);
+ magnitude[5] = (byte)(value[1] >>> 16);
+ magnitude[6] = (byte)(value[1] >>> 8);
+ magnitude[7] = (byte)(value[1]);
+ magnitude[8] = (byte)(value[2] >>> 24);
+ magnitude[9] = (byte)(value[2] >>> 16);
+ magnitude[10] = (byte)(value[2] >>> 8);
+ magnitude[11] = (byte)(value[2]);
+
+ return new java.math.BigDecimal (new java.math.BigInteger(signum, magnitude), scale);
+ }
+ else if (precision <= 31) {
+ // get the value of last 9 digits (5 bytes).
+ int lo = packedNybblesToInt(buffer, offset, (length-5)*2, 9);
+ // get the value of another 9 digits (5 bytes).
+ int meLo = packedNybblesToInt(buffer, offset, (length-10)*2+1, 9);
+ // get the value of another 9 digits (5 bytes).
+ int meHi = packedNybblesToInt(buffer, offset, (length-14)*2, 9);
+ // get the value of the rest digits.
+ int hi = packedNybblesToInt(buffer, offset, 0, (length-14)*2);
+
+ // compute the int array of magnitude.
+ int[] value = computeMagnitude(new int[] {hi, meHi, meLo, lo});
+
+ // convert value to a byte array of magnitude.
+ byte[] magnitude = new byte[16];
+ magnitude[0] = (byte)(value[0] >>> 24);
+ magnitude[1] = (byte)(value[0] >>> 16);
+ magnitude[2] = (byte)(value[0] >>> 8);
+ magnitude[3] = (byte)(value[0]);
+ magnitude[4] = (byte)(value[1] >>> 24);
+ magnitude[5] = (byte)(value[1] >>> 16);
+ magnitude[6] = (byte)(value[1] >>> 8);
+ magnitude[7] = (byte)(value[1]);
+ magnitude[8] = (byte)(value[2] >>> 24);
+ magnitude[9] = (byte)(value[2] >>> 16);
+ magnitude[10] = (byte)(value[2] >>> 8);
+ magnitude[11] = (byte)(value[2]);
+ magnitude[12] = (byte)(value[3] >>> 24);
+ magnitude[13] = (byte)(value[3] >>> 16);
+ magnitude[14] = (byte)(value[3] >>> 8);
+ magnitude[15] = (byte)(value[3]);
+
+ return new java.math.BigDecimal (new java.math.BigInteger(signum, magnitude), scale);
+ }
+ else {
+ // throw an exception here if nibbles is greater than 31
+ throw new java.lang.IllegalArgumentException("Decimal may only be up to 31 digits!");
+ }
+ }
+
+ /**
+ * Build a Java <code>double</code> from a fixed point decimal byte representation.
+ *
+ * @exception IllegalArgumentException if the specified representation is not recognized.
+ */
+ public static final double getDouble (byte[] buffer,
+ int offset,
+ int precision,
+ int scale
+ ) throws java.io.UnsupportedEncodingException
+ {
+ // The byte-length of a packed decimal with precision <code>p</code> is always <code>p/2 + 1</code>
+ int length = precision / 2 + 1;
+
+ // check for sign.
+ int signum;
+ if ((buffer[offset+length-1] & 0x0F) == 0x0D)
+ signum = -1;
+ else
+ signum = 1;
+
+ if (precision <= 9) {
+ // can be handled by int without overflow.
+ int value = packedNybblesToInt(buffer, offset, 0, length*2-1);
+
+ return signum * value / Math.pow(10, scale);
+ }
+ else if (precision <= 18) {
+ // can be handled by long without overflow.
+ long value = packedNybblesToLong(buffer, offset, 0, length*2-1);
+
+ return signum * value / Math.pow(10, scale);
+ }
+ else if (precision <= 27) {
+ // get the value of last 9 digits (5 bytes).
+ int lo = packedNybblesToInt(buffer, offset, (length-5)*2, 9);
+ // get the value of another 9 digits (5 bytes).
+ int me = packedNybblesToInt(buffer, offset, (length-10)*2+1, 9);
+ // get the value of the rest digits.
+ int hi = packedNybblesToInt(buffer, offset, 0, (length-10)*2+1);
+
+ return signum * (lo / Math.pow(10, scale) +
+ me * Math.pow(10, 9-scale) +
+ hi * Math.pow(10, 18-scale));
+ }
+ else if (precision <= 31) {
+ // get the value of last 9 digits (5 bytes).
+ int lo = packedNybblesToInt(buffer, offset, (length-5)*2, 9);
+ // get the value of another 9 digits (5 bytes).
+ int meLo = packedNybblesToInt(buffer, offset, (length-10)*2+1, 9);
+ // get the value of another 9 digits (5 bytes).
+ int meHi = packedNybblesToInt(buffer, offset, (length-14)*2, 9);
+ // get the value of the rest digits.
+ int hi = packedNybblesToInt(buffer, offset, 0, (length-14)*2);
+
+ return signum * (lo / Math.pow(10, scale) +
+ meLo * Math.pow(10, 9-scale) +
+ meHi * Math.pow(10, 18-scale) +
+ hi * Math.pow(10, 27-scale));
+ }
+ else {
+ // throw an exception here if nibbles is greater than 31
+ throw new java.lang.IllegalArgumentException ("Decimal may only be up to 31 digits!");
+ }
+ }
+
+ /**
+ * Build a Java <code>long</code> from a fixed point decimal byte representation.
+ *
+ * @exception IllegalArgumentException if the specified representation is not recognized.
+ */
+ public static final long getLong (byte[] buffer,
+ int offset,
+ int precision,
+ int scale
+ ) throws java.io.UnsupportedEncodingException
+ {
+ if (precision > 31) {
+ // throw an exception here if nibbles is greater than 31
+ throw new java.lang.IllegalArgumentException ("Decimal may only be up to 31 digits!");
+ }
+
+ // The byte-length of a packed decimal with precision <code>p</code> is always <code>p/2 + 1</code>
+ int length = precision / 2 + 1;
+
+ // check for sign.
+ int signum;
+ if ((buffer[offset+length-1] & 0x0F) == 0x0D)
+ signum = -1;
+ else
+ signum = 1;
+
+ // compute the integer part only.
+ int leftOfDecimalPoint = length*2-1-scale;
+ long integer = 0;
+ if (leftOfDecimalPoint > 0) {
+ int i = 0;
+ for (; i<leftOfDecimalPoint/2; i++) {
+ integer = integer*10 + signum*((buffer[offset+i] & 0xF0) >>> 4); // high nybble.
+ integer = integer*10 + signum* (buffer[offset+i] & 0x0F); // low nybble.
+ }
+ if ((leftOfDecimalPoint % 2) == 1) {
+ // process high nybble of the last byte if necessary.
+ integer = integer*10 + signum*((buffer[offset+i] & 0xF0) >>> 4);
+ }
+ }
+
+ return integer;
+ }
+
+ //--------------entry points for runtime representation-----------------------
+
+ /**
+ Write a Java <code>java.math.BigDecimal</code> to packed decimal bytes.
+ */
+ public static final int bigDecimalToPackedDecimalBytes (byte[] buffer,
+ int offset,
+ java.math.BigDecimal b,
+ int declaredPrecision,
+ int declaredScale)
+ throws ConversionException
+ {
+ // packed decimal may only be up to 31 digits.
+ if (declaredPrecision > 31)
+ throw new ConversionException ("Packed decimal may only be up to 31 digits!");
+
+ // get absolute unscaled value of the BigDecimal as a String.
+ String unscaledStr = b.unscaledValue().abs().toString();
+
+ // get precision of the BigDecimal.
+ int bigPrecision = unscaledStr.length();
+
+ if (bigPrecision > 31)
+ throw new ConversionException ("The numeric literal \"" +
+ b.toString() +
+ "\" is not valid because its value is out of range.",
+ "42820",
+ -405);
+
+ int bigScale = b.scale();
+ int bigWholeIntegerLength = bigPrecision - bigScale;
+ if ( (bigWholeIntegerLength > 0) && (!unscaledStr.equals ("0")) ) {
+ // if whole integer part exists, check if overflow.
+ int declaredWholeIntegerLength = declaredPrecision - declaredScale;
+ if (bigWholeIntegerLength > declaredWholeIntegerLength)
+ throw new ConversionException ("Overflow occurred during numeric data type conversion of \"" +
+ b.toString() +
+ "\".",
+ "22003",
+ -413);
+ }
+
+ // convert the unscaled value to a packed decimal bytes.
+
+ // get unicode '0' value.
+ int zeroBase = '0';
+
+ // start index in target packed decimal.
+ int packedIndex = declaredPrecision-1;
+
+ // start index in source big decimal.
+ int bigIndex;
+
+ if (bigScale >= declaredScale) {
+ // If target scale is less than source scale,
+ // discard excessive fraction.
+
+ // set start index in source big decimal to ignore excessive fraction.
+ bigIndex = bigPrecision-1-(bigScale-declaredScale);
+
+ if (bigIndex < 0) {
+ // all digits are discarded, so only process the sign nybble.
+ buffer[offset+(packedIndex+1)/2] =
+ (byte) ( (b.signum()>=0)?12:13 ); // sign nybble
+ }
+ else {
+ // process the last nybble together with the sign nybble.
+ buffer[offset+(packedIndex+1)/2] =
+ (byte) ( ( (unscaledStr.charAt(bigIndex)-zeroBase) << 4 ) + // last nybble
+ ( (b.signum()>=0)?12:13 ) ); // sign nybble
+ }
+ packedIndex-=2;
+ bigIndex-=2;
+ }
+ else {
+ // If target scale is greater than source scale,
+ // pad the fraction with zero.
+
+ // set start index in source big decimal to pad fraction with zero.
+ bigIndex = declaredScale-bigScale-1;
+
+ // process the sign nybble.
+ buffer[offset+(packedIndex+1)/2] =
+ (byte) ( (b.signum()>=0)?12:13 ); // sign nybble
+
+ for (packedIndex-=2, bigIndex-=2; bigIndex>=0; packedIndex-=2, bigIndex-=2)
+ buffer[offset+(packedIndex+1)/2] = (byte) 0;
+
+ if (bigIndex == -1) {
+ buffer[offset+(packedIndex+1)/2] =
+ (byte) ( (unscaledStr.charAt(bigPrecision-1)-zeroBase) << 4 ); // high nybble
+
+ packedIndex-=2;
+ bigIndex = bigPrecision-3;
+ }
+ else {
+ bigIndex = bigPrecision-2;
+ }
+ }
+
+ // process the rest.
+ for (; bigIndex>=0; packedIndex-=2, bigIndex-=2) {
+ buffer[offset+(packedIndex+1)/2] =
+ (byte) ( ( (unscaledStr.charAt(bigIndex)-zeroBase) << 4 ) + // high nybble
+ ( unscaledStr.charAt(bigIndex+1)-zeroBase ) ); // low nybble
+ }
+
+ // process the first nybble when there is one left.
+ if (bigIndex == -1) {
+ buffer[offset+(packedIndex+1)/2] =
+ (byte) (unscaledStr.charAt(0) - zeroBase);
+
+ packedIndex-=2;
+ }
+
+ // pad zero in front of the big decimal if necessary.
+ for (; packedIndex>=-1; packedIndex-=2)
+ buffer[offset+(packedIndex+1)/2] = (byte) 0;
+
+ return declaredPrecision/2 + 1;
+ }
+}
Propchange: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Decimal.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Diagnosable.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Diagnosable.java?rev=165178&view=auto
==============================================================================
--- incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Diagnosable.java (added)
+++ incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Diagnosable.java Thu Apr 28 12:05:42 2005
@@ -0,0 +1,28 @@
+/*
+
+ Derby - Class org.apache.derby.client.am.Diagnosable
+
+ Copyright (c) 2001, 2005 The Apache Software Foundation or its licensors, where applicable.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.apache.derby.client.am;
+
+public interface Diagnosable
+{
+ public Sqlca getSqlca();
+ public java.lang.Throwable getThrowable ();
+ public void printTrace (java.io.PrintWriter printWriter, String messageHeader);
+}
Propchange: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/Diagnosable.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/DisconnectException.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/client/org/apache/derby/client/am/DisconnectException.java?rev=165178&view=auto
==============================================================================
--- incubator/derby/code/trunk/java/client/org/apache/derby/client/am/DisconnectException.java (added)
+++ incubator/derby/code/trunk/java/client/org/apache/derby/client/am/DisconnectException.java Thu Apr 28 12:05:42 2005
@@ -0,0 +1,72 @@
+/*
+
+ Derby - Class org.apache.derby.client.am.DisconnectException
+
+ Copyright (c) 2001, 2005 The Apache Software Foundation or its licensors, where applicable.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.apache.derby.client.am;
+
+public class DisconnectException extends SqlException
+{
+
+ public DisconnectException (Agent agent, String reason, SqlState sqlstate, SqlCode sqlcode)
+ {
+ super (agent.logWriter_, reason, sqlstate, sqlcode);
+ }
+
+ public DisconnectException (Agent agent, String reason, SqlState sqlstate)
+ {
+ super (agent.logWriter_, reason, sqlstate, SqlCode.disconnectError);
+ // make the call to close the streams and socket.
+ if (agent != null) agent.disconnectEvent();
+ }
+
+ public DisconnectException (java.lang.Throwable throwable, Agent agent, String reason, SqlState sqlstate)
+ {
+ super (agent.logWriter_, throwable, reason, sqlstate, SqlCode.disconnectError);
+ // make the call to close the streams and socket.
+ if (agent != null) agent.disconnectEvent();
+ }
+
+ public DisconnectException (Agent agent)
+ {
+ this (agent, null, SqlState.undefined);
+ }
+
+ public DisconnectException (java.lang.Throwable throwable, Agent agent)
+ {
+ this (throwable, agent, null, SqlState.undefined);
+ }
+
+ public DisconnectException (Agent agent, String reason)
+ {
+ this (agent, reason, SqlState.undefined);
+ }
+
+ public DisconnectException (Throwable throwable, Agent agent, String reason)
+ {
+ this (throwable, agent, reason, SqlState.undefined);
+ }
+
+ public DisconnectException (Agent agent, SqlException e)
+ {
+ this (agent, e.getMessage());
+ setNextException (e);
+ }
+}
+
+
Propchange: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/DisconnectException.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/EncryptionManager.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/client/org/apache/derby/client/am/EncryptionManager.java?rev=165178&view=auto
==============================================================================
--- incubator/derby/code/trunk/java/client/org/apache/derby/client/am/EncryptionManager.java (added)
+++ incubator/derby/code/trunk/java/client/org/apache/derby/client/am/EncryptionManager.java Thu Apr 28 12:05:42 2005
@@ -0,0 +1,528 @@
+/*
+
+ Derby - Class org.apache.derby.client.am.EncryptionManager
+
+ Copyright (c) 2001, 2005 The Apache Software Foundation or its licensors, where applicable.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.apache.derby.client.am;
+import java.security.Security;
+import java.security.Provider;
+
+// This class is get used when using encrypted password and/or userid mechanism.
+// The <b>EncryptionManager</b> classs uses Diffie_Hellman algorithm to get the publick key and
+// secret key, and then DES encryption is done using certain token (based on security
+// mechanism) and server side's public key. Basically, this class is called when using
+// security mechanism User ID and encrypted password (usrencpwd) and Encrypted user ID and password
+// (eusridpwd).
+// This class uses JCE provider to do Diffie_Hellman algorithm and DES encryption,
+// obtainPublicKey(), calculateEncryptionToken(int, byte[]) and encryptData(byte[], int, byte[], byte[])
+// The agreed public value for the Diffie-Hellman prime is 256 bits
+// and hence the encrytion will work only if the jce provider supports a 256 bits prime
+
+public class EncryptionManager
+{
+ transient Agent agent_; // for obtaining an exception log writer only
+
+ // PROTOCOL's Diffie-Hellman agreed public value: prime.
+ private static final byte modulusBytes__[] = {
+ (byte)0xC6, (byte)0x21, (byte)0x12, (byte)0xD7,
+ (byte)0x3E, (byte)0xE6, (byte)0x13, (byte)0xF0,
+ (byte)0x94, (byte)0x7A, (byte)0xB3, (byte)0x1F,
+ (byte)0x0F, (byte)0x68, (byte)0x46, (byte)0xA1,
+ (byte)0xBF, (byte)0xF5, (byte)0xB3, (byte)0xA4,
+ (byte)0xCA, (byte)0x0D, (byte)0x60, (byte)0xBC,
+ (byte)0x1E, (byte)0x4C, (byte)0x7A, (byte)0x0D,
+ (byte)0x8C, (byte)0x16, (byte)0xB3, (byte)0xE3
+ };
+
+ //the prime value in BigInteger form. It has to be in BigInteger form because this
+ //is the form used in JCE library.
+ private static final java.math.BigInteger modulus__
+ = new java.math.BigInteger (1, modulusBytes__);
+
+ // PROTOCOL's Diffie-Hellman agreed public value: base.
+ private static final byte baseBytes__[] = {
+ (byte)0x46, (byte)0x90, (byte)0xFA, (byte)0x1F,
+ (byte)0x7B, (byte)0x9E, (byte)0x1D, (byte)0x44,
+ (byte)0x42, (byte)0xC8, (byte)0x6C, (byte)0x91,
+ (byte)0x14, (byte)0x60, (byte)0x3F, (byte)0xDE,
+ (byte)0xCF, (byte)0x07, (byte)0x1E, (byte)0xDC,
+ (byte)0xEC, (byte)0x5F, (byte)0x62, (byte)0x6E,
+ (byte)0x21, (byte)0xE2, (byte)0x56, (byte)0xAE,
+ (byte)0xD9, (byte)0xEA, (byte)0x34, (byte)0xE4
+ };
+
+ // The base value in BigInteger form.
+ private static final java.math.BigInteger base__ =
+ new java.math.BigInteger (1, baseBytes__);
+
+ //PROTOCOL's Diffie-Hellman agreed exponential length
+ private static final int exponential_length__ = 255;
+
+ private javax.crypto.spec.DHParameterSpec paramSpec_;
+ private java.security.KeyPairGenerator keyPairGenerator_;
+ private java.security.KeyPair keyPair_;
+ private javax.crypto.KeyAgreement keyAgreement_;
+
+ private byte[] token_; // init vector
+ private byte[] secKey_; // security key
+ private javax.crypto.SecretKeyFactory secretKeyFactory_ = null;
+ private String providerName; // security provider name
+ private Provider provider;
+
+ // EncryptionManager constructor. In this constructor,DHParameterSpec,
+ // KeyPairGenerator, KeyPair, and KeyAgreement are initialized.
+ public EncryptionManager (Agent agent) throws SqlException
+ {
+ agent_ = agent;
+ try
+ {
+ // get a security provider that supports the diffie helman key agreement algorithm
+ Provider[] list = Security.getProviders("KeyAgreement.DH");
+ if(list == null)
+ throw new java.security.NoSuchProviderException();
+ provider = list[0];
+ providerName = provider.getName();
+
+ java.security.Security.addProvider ((java.security.Provider) provider);
+
+ paramSpec_ = new javax.crypto.spec.DHParameterSpec (modulus__, base__, exponential_length__);
+ keyPairGenerator_ = java.security.KeyPairGenerator.getInstance ("DH", providerName);
+ keyPairGenerator_.initialize (paramSpec_);
+ keyPair_ = keyPairGenerator_.generateKeyPair();
+ keyAgreement_ = javax.crypto.KeyAgreement.getInstance ("DH", providerName);
+ keyAgreement_.init (keyPair_.getPrivate());
+ }
+ catch (java.security.NoSuchProviderException e) {
+ throw new SqlException (agent_.logWriter_, e, "java.security.NoSuchProviderException is caught" +
+ " when initializing EncryptionManager '" + e.getMessage() + "'");
+ }
+ catch (java.security.NoSuchAlgorithmException e) {
+ throw new SqlException (agent_.logWriter_, e, "java.security.NoSuchAlgorithmException is caught" +
+ " when initializing EncryptionManager '" + e.getMessage() + "'");
+ }
+ catch (java.security.InvalidAlgorithmParameterException e) {
+ throw new SqlException (agent_.logWriter_, e, "java.security.InvalidAlgorithmParameterException is caught" +
+ " when initializing EncryptionManager '" + e.getMessage() + "'");
+ }
+
+ catch (java.security.InvalidKeyException e) {
+ throw new SqlException (agent_.logWriter_, e, "java.security.InvalidKeyException is caught" +
+ " when initializing EncryptionManager '" + e.getMessage() + "'");
+ }
+ }
+
+ // This method generates the public key and returns it. This
+ // shared public key is the application requester's connection key and will
+ // be exchanged with the application server's connection key. This connection
+ // key will be put in the sectkn in ACCSEC command and send to the application
+ // server.
+ // @param null
+ // @return a byte array that is the application requester's public key
+ public byte[] obtainPublicKey ()
+ {
+
+ //we need to get the plain form public key because PROTOCOL accepts plain form
+ //public key only.
+ java.math.BigInteger aPub = ((javax.crypto.interfaces.DHPublicKey) keyPair_.getPublic()).getY();
+ byte[] aPubKey = aPub.toByteArray();
+
+ //the following lines of code is to adjust the length of the key. PublicKey
+ //in JCE is in the form of BigInteger and it's a signed value. When tranformed
+ //to a Byte array form, normally this array is 32 bytes. However, if the
+ //value happens to take up all 32 X 8 bits and it is positive, an extra
+ //bit is needed and then a 33 byte array will be returned. Since PROTOCOL can't
+ //recogize the 33 byte key, we check the length here, if the length is 33,
+ //we will just trim off the first byte (0) and get the rest of 32 bytes.
+ if (aPubKey.length == 33 && aPubKey[0]==0) {
+ //System.out.println ("Adjust length");
+ byte[] newKey = new byte[32];
+ for (int i=0; i < newKey.length; i++)
+ newKey[i] = aPubKey[i+1];
+ return newKey;
+ }
+
+ //the following lines of code is to adjust the length of the key. Occasionally,
+ //the length of the public key is less than 32, the reason of this is that the 0 byte
+ //in the beginning is somehow not returned. So we check the length here, if the length
+ //is less than 32, we will pad 0 in the beginning to make the public key 32 bytes
+ if (aPubKey.length < 32) {
+ byte[] newKey = new byte[32];
+ int i;
+ for (i=0; i < 32-aPubKey.length; i++) {
+ newKey[i] = 0;
+ }
+ for (int j=i; j<newKey.length; j++)
+ newKey[j] = aPubKey[j-i];
+ return newKey;
+ }
+ return aPubKey;
+ }
+
+ // This method is used to calculate the encryption token. DES encrypts the
+ // data using a token and the generated shared private key. The token used
+ // depends on the type of security mechanism being used:
+ // USRENCPWD - The userid is used as the token. The USRID is zero-padded to
+ // 8 bytes if less than 8 bytes or truncated to 8 bytes if greater than 8 bytes.
+ // EUSRIDPWD - The middle 8 bytes of the server's connection key is used as
+ // the token.
+ // @param int securityMechanism
+ // @param byte[] userid or server's connection key
+ // @return byte[] the encryption token
+ private byte[] calculateEncryptionToken (int securityMechanism, byte[] initVector)
+ {
+ byte[] token = new byte[8];
+
+ //USRENCPWD, the userid is used as token
+ if (securityMechanism == 7) {
+ if (initVector.length < 8) { //shorter than 8 bytes, zero padded to 8 bytes
+ for (int i=0; i<initVector.length; i++)
+ token[i] = initVector[i];
+ for (int i=initVector.length; i<8; i++)
+ token[i] = 0;
+ }
+ else { //longer than 8 bytes, truncated to 8 bytes
+ for (int i=0; i<8; i++)
+ token[i] = initVector[i];
+ }
+ }
+ //EUSRIDPWD - The middle 8 bytes of the server's connection key is used as
+ //the token.
+ else if (securityMechanism == 9) {
+ for (int i = 0; i < 8; i++) {
+ token[i] = initVector[i + 12];
+ }
+ }
+ return token;
+ }
+
+ //JDK 1.4 has a parity check on the DES encryption key. Each byte needs to have an odd number
+ //of "1"s in it, and this is required by DES. Otherwise JDK 1.4 throws InvalidKeyException.
+ //Older JDK doesn't check this. In order to make encryption work with JDK1.4, we are going to
+ //check each of the 8 byte of our key and flip the last bit if it has even number of 1s.
+ private void keyParityCheck(byte[] key) throws SqlException
+ {
+ byte temp;
+ int changeParity;
+ if (key.length!=8)
+ throw new SqlException (agent_.logWriter_, "DES key has the wrong length");
+ for (int i=0; i<8; i++)
+ {
+ temp = key[i];
+ changeParity = 1;
+ for (int j=0; j<8; j++)
+ {
+ if (temp < 0)
+ changeParity = 1 - changeParity;
+ temp = (byte) (temp << 1);
+ }
+ if (changeParity == 1)
+ {
+ if ((key[i] & 1) != 0)
+ key[i] &= 0xfe;
+ else
+ key[i] |= 1;
+ }
+ }
+ }
+
+ // This method generates a secret key using the application server's
+ // public key
+ private byte[] generatePrivateKey (byte[] targetPublicKey) throws SqlException
+ {
+ try {
+
+ //initiate a Diffie_Hellman KeyFactory object.
+ java.security.KeyFactory keyFac = java.security.KeyFactory.getInstance ("DH", provider);
+
+ //Use server's public key to initiate a DHPublicKeySpec and then use
+ //this DHPublicKeySpec to initiate a publicKey object
+ java.math.BigInteger publicKey = new java.math.BigInteger (1, targetPublicKey);
+ javax.crypto.spec.DHPublicKeySpec dhKeySpec =
+ new javax.crypto.spec.DHPublicKeySpec (publicKey, modulus__, base__);
+ java.security.PublicKey pubKey = keyFac.generatePublic (dhKeySpec);
+
+ //Execute the first phase of DH keyagreement protocal.
+ keyAgreement_.doPhase (pubKey, true);
+
+ //generate the shared secret key. The application requestor's shared secret
+ //key should be exactly the same as the application server's shared secret
+ //key
+ byte[] sharedSecret = keyAgreement_.generateSecret();
+ byte[] newKey = new byte[32];
+
+ //We adjust the length here. If the length of secret key is 33 and the first byte is 0,
+ //we trim off the frist byte. If the length of secret key is less than 32, we will
+ //pad 0 to the beginning of the byte array tho make the secret key 32 bytes.
+ if (sharedSecret.length == 33 && sharedSecret[0] == 0) {
+ for (int i=0; i<newKey.length; i++)
+ newKey[i] = sharedSecret[i+1];
+
+ }
+ if (sharedSecret.length < 32) {
+ int i;
+ for (i=0; i<(32 - sharedSecret.length); i++) {
+ newKey[i] = 0;
+ }
+ for (int j=i; j<sharedSecret.length; j++)
+ newKey[j] = sharedSecret[j-i];
+ }
+
+ //The Data Encryption Standard (DES) is going to be used to encrypt userid
+ //and password. DES is a block cipher; it encrypts data in 64-bit blocks.
+ //PROTOCOL encryption uses DES CBC mode as defined by the FIPS standard
+ //DES CBC requires an encryption key and an 8 byte token to encrypt the data.
+ //The middle 8 bytes of Diffie-Hellman shared private key is used as the
+ //encryption key. The following code retrieves middle 8 bytes of the shared
+ //private key.
+ byte[] key = new byte[8];
+
+ //if secret key is not 32, we will use the adjust length secret key
+ if (sharedSecret.length==32) {
+ for (int i=0; i< 8;i++)
+ key[i] = sharedSecret[i+12];
+ }
+ else if (sharedSecret.length==33 || sharedSecret.length < 32) {
+ for (int i=0; i< 8;i++)
+ key[i] = newKey[i+12];
+ }
+ else
+ throw new SqlException (agent_.logWriter_, "sharedSecret key length error " + sharedSecret.length);
+
+ //we do parity check here and flip the parity bit if the byte has even number of 1s
+ keyParityCheck(key);
+ return key;
+ }/*
+ catch (java.security.NoSuchProviderException e) {
+ throw new SqlException (agent_.logWriter_, e, "java.security.NoSuchProviderException is caught "
+ + "when encrypting data '" + e.getMessage() + "'");
+ }*/
+ catch (java.security.NoSuchAlgorithmException e) {
+ throw new SqlException (agent_.logWriter_, e, "java.security.NoSuchAlgorithmException is caught "
+ + "when encrypting data '" + e.getMessage() + "'");
+ }
+ catch (java.security.spec.InvalidKeySpecException e) {
+ throw new SqlException (agent_.logWriter_, e, "java.security.InvalidKeySpecException is caught "
+ + "when encrypting data");
+ }
+ catch (java.security.InvalidKeyException e) {
+ throw new SqlException (agent_.logWriter_, e, "java.security.InvalidKeyException is caught "
+ + "when encrypting data '" + e.getMessage() + "'");
+ }
+
+
+ }
+
+ // This method encrypts the usreid/password with the middle 8 bytes of
+ // the generated secret key and an encryption token. Then it returns the
+ // encrypted data in a byte array.
+ // plainText The byte array form userid/password to encrypt.
+ // initVector The byte array which is used to calculate the
+ // encryption token.
+ // targetPublicKey DERBY' public key.
+ // Returns the encrypted data in a byte array.
+ public byte[] encryptData (byte[] plainText,
+ int securityMechanism,
+ byte[] initVector,
+ byte[] targetPublicKey) throws SqlException
+ {
+
+ byte[] cipherText = null;
+ java.security.Key key = null;
+
+ if (token_ == null)
+ token_ = calculateEncryptionToken (securityMechanism, initVector);
+
+ try{
+ if (secKey_ == null)
+ {
+ //use this encryption key to initiate a SecretKeySpec object
+ secKey_ = generatePrivateKey (targetPublicKey);
+ javax.crypto.spec.SecretKeySpec desKey = new javax.crypto.spec.SecretKeySpec (secKey_, "DES");
+ key = desKey;
+ }
+ else
+ {
+ //use this encryption key to initiate a SecretKeySpec object
+ javax.crypto.spec.DESKeySpec desKey = new javax.crypto.spec.DESKeySpec (secKey_);
+ if (secretKeyFactory_ == null)
+ secretKeyFactory_ = javax.crypto.SecretKeyFactory.getInstance("DES", providerName);
+ key = secretKeyFactory_.generateSecret(desKey);
+ }
+
+ //We use DES in CBC mode because this is the mode used in PROTOCOL. The
+ //encryption mode has to be consistent for encryption and decryption.
+ //CBC mode requires an initialization vector(IV) parameter. In CBC mode
+ //we need to initialize the Cipher object with an IV, which can be supplied
+ // using the javax.crypto.spec.IvParameterSpec class.
+ javax.crypto.Cipher cipher= javax.crypto.Cipher.getInstance ("DES/CBC/PKCS5Padding", providerName);
+
+ //generate a IVParameterSpec object and use it to initiate the
+ //Cipher object.
+ javax.crypto.spec.IvParameterSpec ivParam = new javax.crypto.spec.IvParameterSpec (token_);
+
+ //initiate the Cipher using encryption mode, encryption key and the
+ //IV parameter.
+ cipher.init (javax.crypto.Cipher.ENCRYPT_MODE, key, ivParam);
+
+ //Execute the final phase of encryption
+ cipherText = cipher.doFinal (plainText);
+ }
+ catch (java.security.NoSuchProviderException e) {
+ throw new SqlException (agent_.logWriter_, e, "java.security.NoSuchProviderException is caught "
+ + "when encrypting data '" + e.getMessage() + "'");
+ }
+ catch (java.security.NoSuchAlgorithmException e) {
+ throw new SqlException (agent_.logWriter_, e, "java.security.NoSuchAlgorithmException is caught "
+ + "when encrypting data '" + e.getMessage() + "'");
+ }
+ catch (java.security.InvalidKeyException e) {
+ throw new SqlException (agent_.logWriter_, e, "java.security.InvalidKeyException is caught "
+ + "when encrypting data '" + e.getMessage() + "'");
+ }
+ catch (javax.crypto.NoSuchPaddingException e) {
+ throw new SqlException (agent_.logWriter_, e, "javax.crypto.NoSuchPaddingException is caught "
+ + "when encrypting data '" + e.getMessage() + "'");
+ }
+ catch (javax.crypto.BadPaddingException e) {
+ throw new SqlException (agent_.logWriter_, e, "javax.crypto.BadPaddingException is caught "
+ + "when encrypting data '" + e.getMessage() + "'");
+ }
+ catch (java.security.InvalidAlgorithmParameterException e) {
+ throw new SqlException (agent_.logWriter_, e, "java.security.InvalidAlgorithmParameterException is caught "
+ + "when encrypting data '" + e.getMessage() + "'");
+ }
+ catch (javax.crypto.IllegalBlockSizeException e) {
+ throw new SqlException (agent_.logWriter_, e, "javax.crypto.IllegalBlockSizeException is caught "
+ + "when encrypting data '" + e.getMessage() + "'");
+ }
+ catch (java.security.spec.InvalidKeySpecException e) {
+ throw new SqlException (agent_.logWriter_, e, "javax.crypto.IllegalBlockSizeException is caught "
+ + "when encrypting data '" + e.getMessage() + "'");
+ }
+ return cipherText;
+ }
+
+
+ // This method decrypts the usreid/password with the middle 8 bytes of
+ // the generated secret key and an encryption token. Then it returns the
+ // decrypted data in a byte array.
+ // plainText The byte array form userid/password to encrypt.
+ // initVector The byte array which is used to calculate the
+ // encryption token.
+ // targetPublicKey DERBY' public key.
+ // Returns the decrypted data in a byte array.
+ public byte[] decryptData (byte[] cipherText,
+ int securityMechanism,
+ byte[] initVector,
+ byte[] targetPublicKey) throws SqlException
+ {
+
+ byte[] plainText = null;
+ java.security.Key key = null;
+
+ if (token_ == null)
+ token_ = calculateEncryptionToken (securityMechanism, initVector);
+
+ try{
+ if (secKey_ == null)
+ {
+ //use this encryption key to initiate a SecretKeySpec object
+ secKey_ = generatePrivateKey (targetPublicKey);
+ javax.crypto.spec.SecretKeySpec desKey = new javax.crypto.spec.SecretKeySpec (secKey_, "DES");
+ key = desKey;
+ }
+ else
+ {
+ //use this encryption key to initiate a SecretKeySpec object
+ javax.crypto.spec.DESKeySpec desKey = new javax.crypto.spec.DESKeySpec (secKey_);
+ if (secretKeyFactory_ == null)
+ secretKeyFactory_ = javax.crypto.SecretKeyFactory.getInstance("DES", providerName);
+ key = secretKeyFactory_.generateSecret(desKey);
+ }
+
+ //We use DES in CBC mode because this is the mode used in PROTOCOL. The
+ //encryption mode has to be consistent for encryption and decryption.
+ //CBC mode requires an initialization vector(IV) parameter. In CBC mode
+ //we need to initialize the Cipher object with an IV, which can be supplied
+ // using the javax.crypto.spec.IvParameterSpec class.
+ javax.crypto.Cipher cipher= javax.crypto.Cipher.getInstance ("DES/CBC/PKCS5Padding", providerName);
+
+ //generate a IVParameterSpec object and use it to initiate the
+ //Cipher object.
+ javax.crypto.spec.IvParameterSpec ivParam = new javax.crypto.spec.IvParameterSpec (token_);
+
+ //initiate the Cipher using encryption mode, encryption key and the
+ //IV parameter.
+ cipher.init (javax.crypto.Cipher.DECRYPT_MODE, key,ivParam);
+
+ //Execute the final phase of encryption
+ plainText = cipher.doFinal (cipherText);
+ }
+ catch (java.security.NoSuchProviderException e) {
+ throw new SqlException (agent_.logWriter_, e, "java.security.NoSuchProviderException is caught "
+ + "when encrypting data '" + e.getMessage() + "'");
+ }
+ catch (java.security.NoSuchAlgorithmException e) {
+ throw new SqlException (agent_.logWriter_, e, "java.security.NoSuchAlgorithmException is caught "
+ + "when encrypting data '" + e.getMessage() + "'");
+ }
+ catch (java.security.InvalidKeyException e) {
+ throw new SqlException (agent_.logWriter_, e, "java.security.InvalidKeyException is caught "
+ + "when encrypting data '" + e.getMessage() + "'");
+ }
+ catch (javax.crypto.NoSuchPaddingException e) {
+ throw new SqlException (agent_.logWriter_, e, "javax.crypto.NoSuchPaddingException is caught "
+ + "when encrypting data '" + e.getMessage() + "'");
+ }
+ catch (javax.crypto.BadPaddingException e) {
+ throw new SqlException (agent_.logWriter_, e, "javax.crypto.BadPaddingException is caught "
+ + "when encrypting data '" + e.getMessage() + "'");
+ }
+ catch (java.security.InvalidAlgorithmParameterException e) {
+ throw new SqlException (agent_.logWriter_, e, "java.security.InvalidAlgorithmParameterException is caught "
+ + "when encrypting data '" + e.getMessage() + "'");
+ }
+ catch (javax.crypto.IllegalBlockSizeException e) {
+ throw new SqlException (agent_.logWriter_, e, "javax.crypto.IllegalBlockSizeException is caught "
+ + "when encrypting data '" + e.getMessage() + "'");
+ }
+ catch (java.security.spec.InvalidKeySpecException e) {
+ throw new SqlException (agent_.logWriter_, e, "javax.crypto.IllegalBlockSizeException is caught "
+ + "when encrypting data '" + e.getMessage() + "'");
+ }
+ return plainText;
+ }
+
+ public void setInitVector(byte[] initVector)
+ {
+ token_ = initVector;
+ }
+
+ public void setSecKey(byte[] secKey)
+ {
+ secKey_ = secKey;
+ }
+
+ public void resetSecurityKeys()
+ {
+ token_ = null;
+ secKey_ = null;
+ }
+
+}
+
Propchange: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/EncryptionManager.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/ErrorKey.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/client/org/apache/derby/client/am/ErrorKey.java?rev=165178&view=auto
==============================================================================
--- incubator/derby/code/trunk/java/client/org/apache/derby/client/am/ErrorKey.java (added)
+++ incubator/derby/code/trunk/java/client/org/apache/derby/client/am/ErrorKey.java Thu Apr 28 12:05:42 2005
@@ -0,0 +1,49 @@
+/*
+
+ Derby - Class org.apache.derby.client.am.ErrorKey
+
+ Copyright (c) 2001, 2005 The Apache Software Foundation or its licensors, where applicable.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+
+package org.apache.derby.client.am;
+
+
+// This class associates the SQL states and error codes with every possible exception
+// as distinguished by a unique resourceKey.
+public class ErrorKey
+{
+ private String resourceKey_;
+ private String sqlState_;
+ private int errorCode_;
+
+
+ String getResourceKey ()
+ {
+ return resourceKey_;
+ }
+
+ String getSQLState ()
+ {
+ return sqlState_;
+ }
+
+ int getErrorCode ()
+ {
+ return errorCode_;
+ }
+}
+
+
Propchange: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/ErrorKey.java
------------------------------------------------------------------------------
svn:eol-style = native
Added: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/ExceptionFormatter.java
URL: http://svn.apache.org/viewcvs/incubator/derby/code/trunk/java/client/org/apache/derby/client/am/ExceptionFormatter.java?rev=165178&view=auto
==============================================================================
--- incubator/derby/code/trunk/java/client/org/apache/derby/client/am/ExceptionFormatter.java (added)
+++ incubator/derby/code/trunk/java/client/org/apache/derby/client/am/ExceptionFormatter.java Thu Apr 28 12:05:42 2005
@@ -0,0 +1,214 @@
+/*
+
+ Derby - Class org.apache.derby.client.am.ExceptionFormatter
+
+ Copyright (c) 2001, 2005 The Apache Software Foundation or its licensors, where applicable.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+*/
+package org.apache.derby.client.am;
+
+public class ExceptionFormatter
+{
+ // returnTokensOnly is true only when exception tracing is enabled so
+ // that we don't try to go to the server for a message while we're in
+ // the middle of parsing an Sqlca reply.
+ // Without this, if e.getMessage() fails, we would have infinite recursion
+ // when TRACE_DIAGNOSTICS is on because tracing occurs within the exception constructor.
+ static public void printTrace (java.sql.SQLException e,
+ java.io.PrintWriter printWriter,
+ String messageHeader,
+ boolean returnTokensOnly)
+ {
+ String header;
+ synchronized (printWriter) {
+ while (e != null) {
+ if (e instanceof java.sql.DataTruncation) {
+ header = messageHeader + "[" + "DataTruncation@" + Integer.toHexString (e.hashCode()) + "]";
+ printWriter.println (header + " java.sql.DataTruncation");
+ }
+ else if (e instanceof java.sql.SQLWarning) {
+ header = messageHeader + "[" + "SQLWarning@" + Integer.toHexString (e.hashCode()) + "]";
+ printWriter.println (header + " java.sql.SQLWarning");
+ }
+ else if (e instanceof java.sql.BatchUpdateException) {
+ header = messageHeader + "[" + "BatchUpdateException@" + Integer.toHexString (e.hashCode()) + "]";
+ printWriter.println (header + " java.sql.BatchUpdateException");
+ }
+ else { // e instanceof java.sql.SQLException
+ header = messageHeader + "[" + "SQLException@" + Integer.toHexString (e.hashCode()) + "]";
+ printWriter.println (header + " java.sql.SQLException");
+ }
+
+ if (e instanceof Diagnosable) {
+ java.lang.Throwable throwable = null;
+ try {
+ throwable = ((Diagnosable) e).getThrowable();
+ }
+ catch (java.lang.NoSuchMethodError doNothing) {
+ }
+ if (throwable != null) {
+ printTrace (throwable, printWriter, header);
+ }
+ Sqlca sqlca = ((Diagnosable) e).getSqlca();
+ if (sqlca != null) {
+ printTrace (sqlca, printWriter, header);
+ // JDK stack trace calls e.getMessage(), so we must set some state on the sqlca that says return tokens only.
+ ((Sqlca) sqlca).returnTokensOnlyInMessageText (returnTokensOnly);
+ }
+ }
+
+ printWriter.println (header + " SQL state = " + e.getSQLState ());
+ printWriter.println (header + " Error code = " + String.valueOf (e.getErrorCode ()));
+ if (!(e instanceof Diagnosable)) {
+ printWriter.println (header + " Message = " + e.getMessage());
+ }
+ else {
+ if (((Diagnosable) e).getSqlca() == null)
+ { // Too much has changed, so escape out here.
+ printWriter.println (header + " Message = " + e.getMessage());
+ }
+ else { // This is server-side error.
+ Sqlca sqlca = (Sqlca) ((Diagnosable) e).getSqlca();
+ if (returnTokensOnly) {
+ // print message tokens directly.
+ printWriter.println (header + " Tokens = " + sqlca.getSqlErrmc()); // a string containing error tokens only
+ }
+ else {
+ // Try to get message text from server.
+ String message = e.getMessage();
+ if (!sqlca.messageTextRetrievedContainsTokensOnly_) { // got the message text.
+ printWriter.println (header + " Message = " + message);
+ }
+ else { // got only message tokens.
+ java.sql.SQLException mysteryException = sqlca.exceptionThrownOnStoredProcInvocation_;
+ if (mysteryException != null &&
+ (mysteryException.getErrorCode() == -440 || mysteryException.getErrorCode() == -444)) {
+ printWriter.println (header + " Unable to obtain message text from server." +
+ " Only message tokens are available." +
+ " The stored procedure SYSIBM.SQLCAMESSAGE is not installed on server." +
+ " Contact your DBA.");
+ }
+ else {
+ printWriter.println (header + " Error occurred while trying to obtain message text from server. " +
+ "Only message tokens are available.");
+ }
+ printWriter.println (header + " Tokens = " + message);
+ }
+ }
+ }
+ }
+
+ if (e instanceof java.sql.DataTruncation) {
+ printWriter.println (header + " Index = " + ((java.sql.DataTruncation) e).getIndex());
+ printWriter.println (header + " Parameter = " + ((java.sql.DataTruncation) e).getParameter());
+ printWriter.println (header + " Read = " + ((java.sql.DataTruncation) e).getRead());
+ printWriter.println (header + " Data size = " + ((java.sql.DataTruncation) e).getDataSize());
+ printWriter.println (header + " Transfer size = " + ((java.sql.DataTruncation) e).getTransferSize());
+ }
+
+ if (e instanceof java.sql.BatchUpdateException) {
+ printWriter.println (header + " Update counts = " + Utils.getStringFromInts (((java.sql.BatchUpdateException) e).getUpdateCounts()));
+ }
+
+ printWriter.println (header + " Stack trace follows");
+ e.printStackTrace (printWriter);
+
+ if (e instanceof Diagnosable) {
+ Sqlca sqlca = (Sqlca) ((Diagnosable) e).getSqlca();
+ if (sqlca != null) {
+ // JDK stack trace calls e.getMessage(), now that it is finished,
+ // we can reset the state on the sqlca that says return tokens only.
+ sqlca.returnTokensOnlyInMessageText (false);
+ }
+ }
+
+ e = e.getNextException ();
+ }
+
+ printWriter.flush();
+ }
+ }
+
+ static public void printTrace (Sqlca sqlca,
+ java.io.PrintWriter printWriter,
+ String messageHeader)
+ {
+ String header = messageHeader + "[" + "Sqlca@" + Integer.toHexString (sqlca.hashCode()) + "]";
+ synchronized (printWriter) {
+ printWriter.println (header + " DERBY SQLCA from server");
+ printWriter.println (header + " SqlCode = " + sqlca.getSqlCode());
+ printWriter.println (header + " SqlErrd = " + Utils.getStringFromInts (sqlca.getSqlErrd()));
+ printWriter.println (header + " SqlErrmc = " + sqlca.getSqlErrmc());
+ printWriter.println (header + " SqlErrmcTokens = " + Utils.getStringFromStrings (sqlca.getSqlErrmcTokens()));
+ printWriter.println (header + " SqlErrp = " + sqlca.getSqlErrp());
+ printWriter.println (header + " SqlState = " + sqlca.getSqlState());
+ printWriter.println (header + " SqlWarn = " + new String (sqlca.getSqlWarn()));
+ }
+ }
+
+ static public void printTrace (java.lang.Throwable e,
+ java.io.PrintWriter printWriter,
+ String messageHeader)
+ {
+ String header = messageHeader + "[" + "Throwable@" + Integer.toHexString (e.hashCode()) + "]";
+ synchronized (printWriter) {
+ printWriter.println (header + " " + e.getClass().getName());
+ printWriter.println (header + " Message = " + e.getMessage ());
+ printWriter.println (header + " Stack trace follows");
+ e.printStackTrace (printWriter);
+ }
+ }
+
+ static public void printTrace (javax.transaction.xa.XAException e,
+ java.io.PrintWriter printWriter,
+ String messageHeader)
+ {
+ String header = messageHeader + "[" + "XAException@" + Integer.toHexString (e.hashCode()) + "]";
+ synchronized (printWriter) {
+ printWriter.println (header + " javax.transaction.xa.XAException");
+ printWriter.println (header + " Message = " + e.getMessage ());
+ printWriter.println (header + " Stack trace follows");
+
+ e.printStackTrace (printWriter);
+
+ if(! ((org.apache.derby.client.am.Configuration.jreLevelMajor == 1) &&
+ (org.apache.derby.client.am.Configuration.jreLevelMinor >= 4)) ||
+ (org.apache.derby.client.am.Configuration.jreLevelMajor > 1) )
+ { // If not jre 1.4 or above, we need to print the cause if there is one
+ // For jre 1.4 or above, e.printStackTrace() will print the cause automatically
+ if (e instanceof Diagnosable) {
+ java.lang.Throwable throwable = null;
+ try {
+ throwable = ((Diagnosable) e).getThrowable();
+ }
+ catch (java.lang.NoSuchMethodError doNothing) {
+ }
+ if (throwable != null)
+ {
+ printWriter.print ("Caused by: ");
+ if (throwable instanceof java.sql.SQLException)
+ {
+ throwable.printStackTrace (printWriter);
+ }
+ else
+ {
+ printTrace (throwable, printWriter, header);
+ }
+ }
+ }
+ }
+ }
+ }
+}
Propchange: incubator/derby/code/trunk/java/client/org/apache/derby/client/am/ExceptionFormatter.java
------------------------------------------------------------------------------
svn:eol-style = native