001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.ejb.plugins.cmp.jdbc;
023:
024: import java.io.ByteArrayInputStream;
025: import java.io.ByteArrayOutputStream;
026: import java.io.InputStream;
027: import java.io.IOException;
028: import java.io.OutputStream;
029: import java.io.ObjectInputStream;
030: import java.io.ObjectOutputStream;
031: import java.io.Reader;
032:
033: import java.lang.reflect.Field;
034: import java.lang.reflect.Method;
035: import java.lang.reflect.InvocationTargetException;
036:
037: import java.rmi.MarshalledObject;
038: import java.rmi.RemoteException;
039:
040: import java.sql.Connection;
041: import java.sql.ResultSet;
042: import java.sql.Statement;
043: import java.sql.SQLException;
044: import java.sql.Types;
045: import java.sql.CallableStatement;
046:
047: import java.util.Map;
048: import java.util.HashMap;
049: import java.math.BigDecimal;
050:
051: import javax.ejb.EJBObject;
052: import javax.ejb.Handle;
053:
054: import org.jboss.invocation.MarshalledValue;
055: import org.jboss.logging.Logger;
056:
057: /**
058: * JDBCUtil takes care of some of the more anoying JDBC tasks.
059: * It hanles safe closing of jdbc resources, setting statement
060: * parameters and loading query results.
061: *
062: * @author <a href="mailto:dain@daingroup.com">Dain Sundstrom</a>
063: * @author <a href="mailto:alex@jboss.org">Alex Loubyansky</a>
064: * @author Steve Coy
065: * @version $Revision: 57209 $
066: */
067: public final class JDBCUtil {
068: private static final Logger log = Logger.getLogger(JDBCUtil.class
069: .getName());
070:
071: public static void safeClose(Connection con) {
072: if (con != null) {
073: try {
074: con.close();
075: } catch (Exception e) {
076: log.error(SQL_ERROR, e);
077: }
078: }
079: }
080:
081: public static void safeClose(ResultSet rs) {
082: if (rs != null) {
083: try {
084: rs.close();
085: } catch (Exception e) {
086: log.error(SQL_ERROR, e);
087: }
088: }
089: }
090:
091: public static void safeClose(Statement statement) {
092: if (statement != null) {
093: try {
094: statement.close();
095: } catch (Exception e) {
096: log.error(SQL_ERROR, e);
097: }
098: }
099: }
100:
101: public static void safeClose(InputStream in) {
102: if (in != null) {
103: try {
104: in.close();
105: } catch (Exception e) {
106: log.error(SQL_ERROR, e);
107: }
108: }
109: }
110:
111: public static void safeClose(OutputStream out) {
112: if (out != null) {
113: try {
114: out.close();
115: } catch (Exception e) {
116: log.error(SQL_ERROR, e);
117: }
118: }
119: }
120:
121: public static void safeClose(Reader reader) {
122: if (reader != null) {
123: try {
124: reader.close();
125: } catch (Exception e) {
126: log.error(SQL_ERROR, e);
127: }
128: }
129: }
130:
131: /**
132: * Coerces the input value into the correct type for the specified
133: * jdbcType.
134: *
135: * @param jdbcType the jdbc type to which the value will be assigned
136: * @param value the value to coerce
137: * @return the corrected object
138: */
139: public static Object coerceToSQLType(int jdbcType, Object value) {
140: if (value.getClass() == java.util.Date.class) {
141: if (jdbcType == Types.DATE) {
142: return new java.sql.Date(((java.util.Date) value)
143: .getTime());
144: } else if (jdbcType == Types.TIME) {
145: return new java.sql.Time(((java.util.Date) value)
146: .getTime());
147: } else if (jdbcType == Types.TIMESTAMP) {
148: return new java.sql.Timestamp(((java.util.Date) value)
149: .getTime());
150: }
151: } else if (value.getClass() == Character.class
152: && jdbcType == Types.VARCHAR) {
153: value = value.toString();
154: }
155: return value;
156: }
157:
158: /**
159: * Coverts the value into a byte array.
160: * @param value the value to convert into a byte array
161: * @return the byte representation of the value
162: * @throws SQLException if a problem occures in the conversion
163: */
164: public static byte[] convertObjectToByteArray(Object value)
165: throws SQLException {
166: // Do we already have a byte array?
167: if (value instanceof byte[]) {
168: return (byte[]) value;
169: }
170:
171: ByteArrayOutputStream baos = null;
172: ObjectOutputStream oos = null;
173: try {
174: // ejb-reference: store the handle
175: if (value instanceof EJBObject) {
176: value = ((EJBObject) value).getHandle();
177: }
178:
179: // Marshall the object using MashalledValue to handle classloaders
180: value = new MarshalledValue(value);
181:
182: // return the serialize the value
183: baos = new ByteArrayOutputStream();
184: oos = new ObjectOutputStream(baos);
185: oos.writeObject(value);
186: return baos.toByteArray();
187: } catch (RemoteException e) {
188: throw new SQLException("Cannot get Handle of EJBObject: "
189: + e);
190: } catch (IOException e) {
191: throw new SQLException("Can't serialize binary object: "
192: + e);
193: } finally {
194: safeClose(oos);
195: safeClose(baos);
196: }
197: }
198:
199: /**
200: * Coverts the input into an object.
201: * @param input the bytes to convert
202: * @return the object repsentation of the input stream
203: * @throws SQLException if a problem occures in the conversion
204: */
205: public static Object convertToObject(byte[] input)
206: throws SQLException {
207: ByteArrayInputStream bais = new ByteArrayInputStream(input);
208: try {
209: return convertToObject(bais);
210: } finally {
211: safeClose(bais);
212: }
213: }
214:
215: /**
216: * Coverts the input into an object.
217: * @param input the bytes to convert
218: * @return the object repsentation of the input stream
219: * @throws SQLException if a problem occures in the conversion
220: */
221: public static Object convertToObject(InputStream input)
222: throws SQLException {
223: Object value = null;
224: if (input != null) {
225: ObjectInputStream ois = null;
226: try {
227: // deserialize result
228: ois = new ObjectInputStream(input);
229: value = ois.readObject();
230:
231: // de-marshall value if possible
232: if (value instanceof MarshalledValue) {
233: value = ((MarshalledValue) value).get();
234: } else if (value instanceof MarshalledObject) {
235: value = ((MarshalledObject) value).get();
236: }
237:
238: // ejb-reference: get the object back from the handle
239: if (value instanceof Handle) {
240: value = ((Handle) value).getEJBObject();
241: }
242:
243: } catch (RemoteException e) {
244: throw new SQLException(
245: "Unable to load EJBObject back from Handle: "
246: + e);
247: } catch (IOException e) {
248: throw new SQLException(
249: "Unable to load to deserialize result: " + e);
250: } catch (ClassNotFoundException e) {
251: throw new SQLException(
252: "Unable to load to deserialize result: " + e);
253: } finally {
254: // ois will close the input stream it wraps
255: safeClose(ois);
256: }
257: }
258: return value;
259: }
260:
261: /**
262: * Get the indicated result set parameter as a character stream and return
263: * it's entire content as a String.
264: *
265: * @param rs the <code>ResultSet</code> from which a result is
266: * being retrieved.
267: * @param index index of the result column.
268: * @return a String containing the content of the result column
269: */
270: public static String getLongString(ResultSet rs, int index)
271: throws SQLException {
272: String value;
273: Reader textData = rs.getCharacterStream(index);
274: if (textData != null) {
275: try {
276: // Use a modest buffer here to reduce function call overhead
277: // when reading extremely large data.
278: StringBuffer textBuffer = new StringBuffer();
279: char[] tmpBuffer = new char[1000];
280: int charsRead;
281: while ((charsRead = textData.read(tmpBuffer)) != -1)
282: textBuffer.append(tmpBuffer, 0, charsRead);
283: value = textBuffer.toString();
284: } catch (java.io.IOException ioException) {
285: throw new SQLException(ioException.getMessage());
286: } finally {
287: safeClose(textData);
288: }
289: } else
290: value = null;
291: return value;
292: }
293:
294: /**
295: * Read the entire input stream provided and return its content as a byte
296: * array.
297: * The method closes the passed in input stream!
298: *
299: * @param input the <code>InputStream</code> from which a result is
300: * being retrieved.
301: * @return a byte array containing the content of the input stream
302: */
303: public static byte[] getByteArray(InputStream input)
304: throws SQLException {
305: ByteArrayOutputStream baos = new ByteArrayOutputStream();
306: try {
307: // Use a modest buffer here to reduce function call overhead
308: // when reading extremely large data.
309: byte[] tmpBuffer = new byte[1000];
310: int bytesRead;
311: while ((bytesRead = input.read(tmpBuffer)) != -1)
312: baos.write(tmpBuffer, 0, bytesRead);
313: return baos.toByteArray();
314: } catch (java.io.IOException ioException) {
315: throw new SQLException(ioException.getMessage());
316: } finally {
317: safeClose(baos);
318: safeClose(input);
319: }
320: }
321:
322: // Inner
323:
324: public static JDBCResultSetReader getResultSetReader(int jdbcType,
325: Class destination) {
326: JDBCResultSetReader reader;
327: switch (jdbcType) {
328: case Types.CLOB:
329: reader = JDBCResultSetReader.CLOB_READER;
330: break;
331: case Types.LONGVARCHAR:
332: reader = JDBCResultSetReader.LONGVARCHAR_READER;
333: break;
334: case Types.BINARY:
335: reader = JDBCResultSetReader.BINARY_READER;
336: break;
337: case Types.VARBINARY:
338: reader = JDBCResultSetReader.VARBINARY_READER;
339: break;
340: case Types.BLOB:
341: reader = JDBCResultSetReader.BLOB_READER;
342: break;
343: case Types.LONGVARBINARY:
344: reader = JDBCResultSetReader.LONGVARBINARY_READER;
345: break;
346: case Types.JAVA_OBJECT:
347: reader = JDBCResultSetReader.JAVA_OBJECT_READER;
348: break;
349: case Types.STRUCT:
350: reader = JDBCResultSetReader.STRUCT_READER;
351: break;
352: case Types.ARRAY:
353: reader = JDBCResultSetReader.ARRAY_READER;
354: break;
355: case Types.OTHER:
356: reader = JDBCResultSetReader.OTHER_READER;
357: break;
358: default: {
359: reader = getResultReaderByType(destination);
360: }
361: }
362: return reader;
363: }
364:
365: public static JDBCResultSetReader getResultReaderByType(
366: Class destination) {
367: JDBCResultSetReader reader;
368: if (destination == java.util.Date.class) {
369: reader = JDBCResultSetReader.JAVA_UTIL_DATE_READER;
370: } else if (destination == java.sql.Date.class) {
371: reader = JDBCResultSetReader.JAVA_SQL_DATE_READER;
372: } else if (destination == java.sql.Time.class) {
373: reader = JDBCResultSetReader.JAVA_SQL_TIME_READER;
374: } else if (destination == java.sql.Timestamp.class) {
375: reader = JDBCResultSetReader.JAVA_SQL_TIMESTAMP_READER;
376: } else if (destination == BigDecimal.class) {
377: reader = JDBCResultSetReader.BIGDECIMAL_READER;
378: } else if (destination == java.sql.Ref.class) {
379: reader = JDBCResultSetReader.REF_READER;
380: } else if (destination == String.class) {
381: reader = JDBCResultSetReader.STRING_READER;
382: } else if (destination == Boolean.class
383: || destination == Boolean.TYPE) {
384: reader = JDBCResultSetReader.BOOLEAN_READER;
385: } else if (destination == Byte.class
386: || destination == Byte.TYPE) {
387: reader = JDBCResultSetReader.BYTE_READER;
388: } else if (destination == Character.class
389: || destination == Character.TYPE) {
390: reader = JDBCResultSetReader.CHARACTER_READER;
391: } else if (destination == Short.class
392: || destination == Short.TYPE) {
393: reader = JDBCResultSetReader.SHORT_READER;
394: } else if (destination == Integer.class
395: || destination == Integer.TYPE) {
396: reader = JDBCResultSetReader.INT_READER;
397: } else if (destination == Long.class
398: || destination == Long.TYPE) {
399: reader = JDBCResultSetReader.LONG_READER;
400: } else if (destination == Float.class
401: || destination == Float.TYPE) {
402: reader = JDBCResultSetReader.FLOAT_READER;
403: } else if (destination == Double.class
404: || destination == Double.TYPE) {
405: reader = JDBCResultSetReader.DOUBLE_READER;
406: } else {
407: reader = JDBCResultSetReader.OBJECT_READER;
408: }
409: return reader;
410: }
411:
412: public static JDBCParameterSetter getParameterSetter(int jdbcType,
413: Class javaType) {
414: JDBCParameterSetter ps;
415:
416: switch (jdbcType) {
417: case Types.CLOB:
418: case Types.LONGVARCHAR:
419: ps = JDBCParameterSetter.CLOB;
420: break;
421:
422: case Types.BINARY:
423: case Types.VARBINARY:
424: ps = JDBCParameterSetter.BINARY;
425: break;
426:
427: case Types.BLOB:
428: case Types.LONGVARBINARY:
429: ps = JDBCParameterSetter.BLOB;
430: break;
431:
432: case Types.DECIMAL:
433: case Types.NUMERIC:
434: ps = JDBCParameterSetter.NUMERIC;
435: break;
436:
437: case Types.JAVA_OBJECT:
438: case Types.OTHER:
439: case Types.STRUCT:
440:
441: default:
442: ps = JDBCParameterSetter.OBJECT;
443: break;
444: }
445:
446: return ps;
447: }
448:
449: //
450: // All the above is used only for Oracle specific entity create command
451: // and could be refactored/optimized.
452: //
453:
454: private static final Map jdbcTypeNames;
455: private final static Map csTypes;
456:
457: /**
458: * Gets the JDBC type name corresponding to the given type code.
459: * Only used in debug log messages.
460: *
461: * @param jdbcType the integer JDBC type code.
462: * @return the JDBC type name.
463: * @see Types
464: */
465: public static String getJDBCTypeName(int jdbcType) {
466: return (String) jdbcTypeNames.get(new Integer(jdbcType));
467: }
468:
469: private static final String SQL_ERROR = "SQL error";
470: private static final String GET_TIMESTAMP = "getTimestamp";
471: private static final String GET_DATE = "getDate";
472: private static final String GET_TIME = "getTime";
473: private static final String GET_BIGDECIMAL = "getBigDecimal";
474: private static final String GET_REF = "getRef";
475: private static final String GET_STRING = "getString";
476: private static final String GET_BOOLEAN = "getBoolean";
477: private static final String GET_BYTE = "getByte";
478: private static final String GET_SHORT = "getShort";
479: private static final String GET_INT = "getInt";
480: private static final String GET_LONG = "getLong";
481: private static final String GET_FLOAT = "getFloat";
482: private static final String GET_DOUBLE = "getDouble";
483: private static final String GET_BYTES = "getBytes";
484:
485: static {
486: Class[] arg = new Class[] { Integer.TYPE };
487:
488: // Initialize the mapping between non-binary java result set
489: // types and the method on CallableStatement that is used to retrieve
490: // a value of the java type.
491: csTypes = new HashMap();
492: try {
493: // java.util.Date
494: csTypes.put(java.util.Date.class.getName(),
495: CallableStatement.class.getMethod(GET_TIMESTAMP,
496: arg));
497: // java.sql.Date
498: csTypes.put(java.sql.Date.class.getName(),
499: CallableStatement.class.getMethod(GET_DATE, arg));
500: // Time
501: csTypes.put(java.sql.Time.class.getName(),
502: CallableStatement.class.getMethod(GET_TIME, arg));
503: // Timestamp
504: csTypes.put(java.sql.Timestamp.class.getName(),
505: CallableStatement.class.getMethod(GET_TIMESTAMP,
506: arg));
507: // BigDecimal
508: csTypes.put(java.math.BigDecimal.class.getName(),
509: CallableStatement.class.getMethod(GET_BIGDECIMAL,
510: arg));
511: // java.sql.Ref Does this really work?
512: csTypes.put(java.sql.Ref.class.getName(),
513: CallableStatement.class.getMethod(GET_REF, arg));
514: // String
515: csTypes.put(java.lang.String.class.getName(),
516: CallableStatement.class.getMethod(GET_STRING, arg));
517: // Boolean
518: csTypes
519: .put(java.lang.Boolean.class.getName(),
520: CallableStatement.class.getMethod(
521: GET_BOOLEAN, arg));
522: // boolean
523: csTypes.put(Boolean.TYPE.getName(), CallableStatement.class
524: .getMethod(GET_BOOLEAN, arg));
525: // Byte
526: csTypes.put(java.lang.Byte.class.getName(),
527: CallableStatement.class.getMethod(GET_BYTE, arg));
528: // byte
529: csTypes.put(Byte.TYPE.getName(), CallableStatement.class
530: .getMethod(GET_BYTE, arg));
531: // Character
532: csTypes.put(java.lang.Character.class.getName(),
533: CallableStatement.class.getMethod(GET_STRING, arg));
534: // char
535: csTypes.put(Character.TYPE.getName(),
536: CallableStatement.class.getMethod(GET_STRING, arg));
537: // Short
538: csTypes.put(java.lang.Short.class.getName(),
539: CallableStatement.class.getMethod(GET_SHORT, arg));
540: // short
541: csTypes.put(Short.TYPE.getName(), CallableStatement.class
542: .getMethod(GET_SHORT, arg));
543: // Integer
544: csTypes.put(java.lang.Integer.class.getName(),
545: CallableStatement.class.getMethod(GET_INT, arg));
546: // int
547: csTypes.put(Integer.TYPE.getName(), CallableStatement.class
548: .getMethod(GET_INT, arg));
549: // Long
550: csTypes.put(java.lang.Long.class.getName(),
551: CallableStatement.class.getMethod(GET_LONG, arg));
552: // long
553: csTypes.put(Long.TYPE.getName(), CallableStatement.class
554: .getMethod(GET_LONG, arg));
555: // Float
556: csTypes.put(java.lang.Float.class.getName(),
557: CallableStatement.class.getMethod(GET_FLOAT, arg));
558: // float
559: csTypes.put(Float.TYPE.getName(), CallableStatement.class
560: .getMethod(GET_FLOAT, arg));
561: // Double
562: csTypes.put(java.lang.Double.class.getName(),
563: CallableStatement.class.getMethod(GET_DOUBLE, arg));
564: // double
565: csTypes.put(Double.TYPE.getName(), CallableStatement.class
566: .getMethod(GET_DOUBLE, arg));
567: // byte[] (scoy: I expect that this will no longer be invoked)
568: csTypes.put("[B", CallableStatement.class.getMethod(
569: GET_BYTES, arg));
570: } catch (NoSuchMethodException e) {
571: // Should never happen
572: log.error(SQL_ERROR, e);
573: }
574:
575: // Initializes the map between jdbcType (int) and the name of the type.
576: // This map is used to print meaningful debug and error messages.
577: jdbcTypeNames = new HashMap();
578: Field[] fields = Types.class.getFields();
579: for (int i = 0; i < fields.length; i++) {
580: try {
581: jdbcTypeNames.put(fields[i].get(null), fields[i]
582: .getName());
583: } catch (IllegalAccessException e) {
584: // Should never happen
585: log.error(SQL_ERROR, e);
586: }
587: }
588: }
589:
590: /**
591: * Used for all retrieval of parameters from <code>CallableStatement</code>s.
592: * Implements tracing, and allows some tweaking of returned types.
593: *
594: * @param log where to log to
595: * @param cs the <code>CallableStatement</code> from which an out parameter is being retrieved
596: * @param index index of the result column.
597: * @param jdbcType a {@link java.sql.Types} constant used to determine the
598: * most appropriate way to extract the data from rs.
599: * @param destination The class of the variable this is going into
600: * @return the value
601: */
602: public static Object getParameter(Logger log, CallableStatement cs,
603: int index, int jdbcType, Class destination)
604: throws SQLException {
605: Object value = null;
606: switch (jdbcType) {
607: //
608: // Large types
609: //
610: case Types.CLOB:
611: case Types.LONGVARCHAR:
612: case Types.BLOB:
613: case Types.LONGVARBINARY:
614: throw new UnsupportedOperationException();
615:
616: //
617: // Small binary types
618: //
619: case Types.BINARY:
620: case Types.VARBINARY: {
621: byte[] bytes = cs.getBytes(index);
622: if (!cs.wasNull()) {
623: if (destination == byte[].class)
624: value = bytes;
625: else
626: value = convertToObject(bytes);
627: }
628: if (log.isTraceEnabled()) {
629: log.trace("Get result: index=" + index + ", javaType="
630: + destination.getName() + ", Binary, value="
631: + value);
632: }
633: }
634: break;
635:
636: //
637: // Specialist types that the
638: // driver should handle
639: //
640: case Types.JAVA_OBJECT:
641: case Types.STRUCT:
642: case Types.ARRAY:
643: case Types.OTHER: {
644: value = cs.getObject(index);
645: if (log.isTraceEnabled()) {
646: log.trace("Get result: index=" + index + ", javaType="
647: + destination.getName() + ", Object, value="
648: + value);
649: }
650: }
651: break;
652:
653: //
654: // Non-binary types
655: //
656: default:
657: Method method = (Method) csTypes.get(destination.getName());
658: if (method != null) {
659: try {
660: value = method.invoke(cs,
661: new Object[] { new Integer(index) });
662: if (cs.wasNull()) {
663: value = null;
664: }
665:
666: if (log.isTraceEnabled()) {
667: log.trace("Get result: index=" + index
668: + ", javaType=" + destination.getName()
669: + ", Simple, value=" + value);
670: }
671: } catch (IllegalAccessException e) {
672: // Whatever, I guess non-binary will not work for this field.
673: } catch (InvocationTargetException e) {
674: // Whatever, I guess non-binary will not work for this field.
675: }
676: } else {
677: value = cs.getObject(index);
678: if (log.isTraceEnabled()) {
679: log.trace("Get result: index=" + index
680: + ", javaType=" + destination.getName()
681: + ", Object, value=" + value);
682: }
683: }
684: }
685: return coerceToJavaType(value, destination);
686: }
687:
688: private static Object coerceToJavaType(Object value,
689: Class destination) throws SQLException {
690: try {
691: //
692: // null
693: //
694: if (value == null) {
695: return null;
696: }
697:
698: //
699: // java.rmi.MarshalledObject
700: //
701: // get unmarshalled value
702: if (value instanceof MarshalledObject
703: && !destination.equals(MarshalledObject.class)) {
704: value = ((MarshalledObject) value).get();
705: }
706:
707: //
708: // javax.ejb.Handle
709: //
710: // get the object back from the handle
711: if (value instanceof Handle) {
712: value = ((Handle) value).getEJBObject();
713: }
714:
715: //
716: // Primitive wrapper classes
717: //
718: // We have a primitive wrapper and we want a real primitive
719: // just return the wrapper and the vm will convert it at the proxy
720: if (destination.isPrimitive()) {
721: if (value == null)
722: throw new IllegalStateException(
723: "Loaded NULL value for a field of a primitive type.");
724: if ((destination.equals(Byte.TYPE) && value instanceof Byte)
725: || (destination.equals(Short.TYPE) && value instanceof Short)
726: || (destination.equals(Character.TYPE) && value instanceof Character)
727: || (destination.equals(Boolean.TYPE) && value instanceof Boolean)
728: || (destination.equals(Integer.TYPE) && value instanceof Integer)
729: || (destination.equals(Long.TYPE) && value instanceof Long)
730: || (destination.equals(Float.TYPE) && value instanceof Float)
731: || (destination.equals(Double.TYPE) && value instanceof Double)) {
732: return value;
733: }
734: }
735:
736: //
737: // java.util.Date
738: //
739: // make new copy as sub types have problems in comparions
740: if (destination == java.util.Date.class
741: && value instanceof java.util.Date) {
742: // handle timestamp special becauses it hoses the milisecond values
743: if (value instanceof java.sql.Timestamp) {
744: java.sql.Timestamp ts = (java.sql.Timestamp) value;
745:
746: // Timestamp returns whole seconds from getTime and partial
747: // seconds are retrieved from getNanos()
748: // Adrian Brock: Not in 1.4 it doesn't
749: long temp = ts.getTime();
750: if (temp % 1000 == 0)
751: temp += ts.getNanos() / 1000000;
752: return new java.util.Date(temp);
753: } else {
754: return new java.util.Date(((java.util.Date) value)
755: .getTime());
756: }
757: }
758:
759: //
760: // java.sql.Time
761: //
762: // make a new copy object; you never know what a driver will return
763: if (destination == java.sql.Time.class
764: && value instanceof java.sql.Time) {
765: return new java.sql.Time(((java.sql.Time) value)
766: .getTime());
767: }
768:
769: //
770: // java.sql.Date
771: //
772: // make a new copy object; you never know what a driver will return
773: if (destination == java.sql.Date.class
774: && value instanceof java.sql.Date) {
775: return new java.sql.Date(((java.sql.Date) value)
776: .getTime());
777: }
778:
779: //
780: // java.sql.Timestamp
781: //
782: // make a new copy object; you never know what a driver will return
783: if (destination == java.sql.Timestamp.class
784: && value instanceof java.sql.Timestamp) {
785: // make a new Timestamp object; you never know
786: // what a driver will return
787: java.sql.Timestamp orignal = (java.sql.Timestamp) value;
788: java.sql.Timestamp copy = new java.sql.Timestamp(
789: orignal.getTime());
790: copy.setNanos(orignal.getNanos());
791: return copy;
792: }
793:
794: //
795: // java.lang.String --> java.lang.Character or char
796: //
797: // just grab first character
798: if (value instanceof String
799: && (destination == Character.class || destination == Character.TYPE)) {
800: return new Character(((String) value).charAt(0));
801: }
802:
803: // Did we get the desired result?
804: if (destination.isAssignableFrom(value.getClass())) {
805: return value;
806: }
807:
808: if (destination == java.math.BigInteger.class
809: && value.getClass() == java.math.BigDecimal.class) {
810: return ((java.math.BigDecimal) value).toBigInteger();
811: }
812:
813: // oops got the wrong type - nothing we can do
814: throw new SQLException("Got a "
815: + value.getClass().getName()
816: + "[cl="
817: + System.identityHashCode(value.getClass()
818: .getClassLoader()) + ", value=" + value
819: + "] while looking for a " + destination.getName()
820: + "[cl=" + System.identityHashCode(destination)
821: + "]");
822: } catch (RemoteException e) {
823: throw new SQLException(
824: "Unable to load EJBObject back from Handle: " + e);
825: } catch (IOException e) {
826: throw new SQLException(
827: "Unable to load to deserialize result: " + e);
828: } catch (ClassNotFoundException e) {
829: throw new SQLException(
830: "Unable to load to deserialize result: " + e);
831: }
832: }
833: }
|