1 22 package org.jboss.ejb.plugins.cmp.jdbc; 23 24 import java.io.ByteArrayInputStream ; 25 import java.io.ByteArrayOutputStream ; 26 import java.io.InputStream ; 27 import java.io.IOException ; 28 import java.io.OutputStream ; 29 import java.io.ObjectInputStream ; 30 import java.io.ObjectOutputStream ; 31 import java.io.Reader ; 32 33 import java.lang.reflect.Field ; 34 import java.lang.reflect.Method ; 35 import java.lang.reflect.InvocationTargetException ; 36 37 import java.rmi.MarshalledObject ; 38 import java.rmi.RemoteException ; 39 40 import java.sql.Connection ; 41 import java.sql.ResultSet ; 42 import java.sql.Statement ; 43 import java.sql.SQLException ; 44 import java.sql.Types ; 45 import java.sql.CallableStatement ; 46 47 import java.util.Map ; 48 import java.util.HashMap ; 49 import java.math.BigDecimal ; 50 51 import javax.ejb.EJBObject ; 52 import javax.ejb.Handle ; 53 54 import org.jboss.invocation.MarshalledValue; 55 import org.jboss.logging.Logger; 56 57 67 public final class JDBCUtil 68 { 69 private static final Logger log = Logger.getLogger(JDBCUtil.class.getName()); 70 71 public static void safeClose(Connection con) 72 { 73 if(con != null) 74 { 75 try 76 { 77 con.close(); 78 } 79 catch(Exception e) 80 { 81 log.error(SQL_ERROR, e); 82 } 83 } 84 } 85 86 public static void safeClose(ResultSet rs) 87 { 88 if(rs != null) 89 { 90 try 91 { 92 rs.close(); 93 } 94 catch(Exception e) 95 { 96 log.error(SQL_ERROR, e); 97 } 98 } 99 } 100 101 public static void safeClose(Statement statement) 102 { 103 if(statement != null) 104 { 105 try 106 { 107 statement.close(); 108 } 109 catch(Exception e) 110 { 111 log.error(SQL_ERROR, e); 112 } 113 } 114 } 115 116 public static void safeClose(InputStream in) 117 { 118 if(in != null) 119 { 120 try 121 { 122 in.close(); 123 } 124 catch(Exception e) 125 { 126 log.error(SQL_ERROR, e); 127 } 128 } 129 } 130 131 public static void safeClose(OutputStream out) 132 { 133 if(out != null) 134 { 135 try 136 { 137 out.close(); 138 } 139 catch(Exception e) 140 { 141 log.error(SQL_ERROR, e); 142 } 143 } 144 } 145 146 public static void safeClose(Reader reader) 147 { 148 if(reader != null) 149 { 150 try 151 { 152 reader.close(); 153 } 154 catch(Exception e) 155 { 156 log.error(SQL_ERROR, e); 157 } 158 } 159 } 160 161 169 public static Object coerceToSQLType(int jdbcType, Object value) 170 { 171 if(value.getClass() == java.util.Date .class) 172 { 173 if(jdbcType == Types.DATE) 174 { 175 return new java.sql.Date (((java.util.Date )value).getTime()); 176 } 177 else if(jdbcType == Types.TIME) 178 { 179 return new java.sql.Time (((java.util.Date )value).getTime()); 180 } 181 else if(jdbcType == Types.TIMESTAMP) 182 { 183 return new java.sql.Timestamp (((java.util.Date )value).getTime()); 184 } 185 } 186 else if(value.getClass() == Character .class && jdbcType == Types.VARCHAR) 187 { 188 value = value.toString(); 189 } 190 return value; 191 } 192 193 199 public static byte[] convertObjectToByteArray(Object value) 200 throws SQLException 201 { 202 if(value instanceof byte[]) 204 { 205 return (byte[])value; 206 } 207 208 ByteArrayOutputStream baos = null; 209 ObjectOutputStream oos = null; 210 try 211 { 212 if(value instanceof EJBObject ) 214 { 215 value = ((EJBObject )value).getHandle(); 216 } 217 218 value = new MarshalledValue(value); 220 221 baos = new ByteArrayOutputStream (); 223 oos = new ObjectOutputStream (baos); 224 oos.writeObject(value); 225 return baos.toByteArray(); 226 } 227 catch(RemoteException e) 228 { 229 throw new SQLException ("Cannot get Handle of EJBObject: " + e); 230 } 231 catch(IOException e) 232 { 233 throw new SQLException ("Can't serialize binary object: " + e); 234 } 235 finally 236 { 237 safeClose(oos); 238 safeClose(baos); 239 } 240 } 241 242 248 public static Object convertToObject(byte[] input) 249 throws SQLException 250 { 251 ByteArrayInputStream bais = new ByteArrayInputStream (input); 252 try 253 { 254 return convertToObject(bais); 255 } 256 finally 257 { 258 safeClose(bais); 259 } 260 } 261 262 263 269 public static Object convertToObject(InputStream input) 270 throws SQLException 271 { 272 Object value = null; 273 if(input != null) 274 { 275 ObjectInputStream ois = null; 276 try 277 { 278 ois = new ObjectInputStream (input); 280 value = ois.readObject(); 281 282 if(value instanceof MarshalledValue) 284 { 285 value = ((MarshalledValue)value).get(); 286 } 287 else if(value instanceof MarshalledObject ) 288 { 289 value = ((MarshalledObject )value).get(); 290 } 291 292 if(value instanceof Handle ) 294 { 295 value = ((Handle )value).getEJBObject(); 296 } 297 298 } 299 catch(RemoteException e) 300 { 301 throw new SQLException ("Unable to load EJBObject back from Handle: " + e); 302 } 303 catch(IOException e) 304 { 305 throw new SQLException ("Unable to load to deserialize result: " + e); 306 } 307 catch(ClassNotFoundException e) 308 { 309 throw new SQLException ("Unable to load to deserialize result: " + e); 310 } 311 finally 312 { 313 safeClose(ois); 315 } 316 } 317 return value; 318 } 319 320 329 public static String getLongString(ResultSet rs, int index) 330 throws SQLException 331 { 332 String value; 333 Reader textData = rs.getCharacterStream(index); 334 if(textData != null) 335 { 336 try 337 { 338 StringBuffer textBuffer = new StringBuffer (); 341 char[] tmpBuffer = new char[1000]; 342 int charsRead; 343 while((charsRead = textData.read(tmpBuffer)) != -1) 344 textBuffer.append(tmpBuffer, 0, charsRead); 345 value = textBuffer.toString(); 346 } 347 catch(java.io.IOException ioException) 348 { 349 throw new SQLException (ioException.getMessage()); 350 } 351 finally 352 { 353 safeClose(textData); 354 } 355 } 356 else 357 value = null; 358 return value; 359 } 360 361 362 371 public static byte[] getByteArray(InputStream input) 372 throws SQLException 373 { 374 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 375 try 376 { 377 byte[] tmpBuffer = new byte[1000]; 380 int bytesRead; 381 while((bytesRead = input.read(tmpBuffer)) != -1) 382 baos.write(tmpBuffer, 0, bytesRead); 383 return baos.toByteArray(); 384 } 385 catch(java.io.IOException ioException) 386 { 387 throw new SQLException (ioException.getMessage()); 388 } 389 finally 390 { 391 safeClose(baos); 392 safeClose(input); 393 } 394 } 395 396 398 public static JDBCResultSetReader getResultSetReader(int jdbcType, Class destination) 399 { 400 JDBCResultSetReader reader; 401 switch(jdbcType) 402 { 403 case Types.CLOB: 404 reader = JDBCResultSetReader.CLOB_READER; 405 break; 406 case Types.LONGVARCHAR: 407 reader = JDBCResultSetReader.LONGVARCHAR_READER; 408 break; 409 case Types.BINARY: 410 reader = JDBCResultSetReader.BINARY_READER; 411 break; 412 case Types.VARBINARY: 413 reader = JDBCResultSetReader.VARBINARY_READER; 414 break; 415 case Types.BLOB: 416 reader = JDBCResultSetReader.BLOB_READER; 417 break; 418 case Types.LONGVARBINARY: 419 reader = JDBCResultSetReader.LONGVARBINARY_READER; 420 break; 421 case Types.JAVA_OBJECT: 422 reader = JDBCResultSetReader.JAVA_OBJECT_READER; 423 break; 424 case Types.STRUCT: 425 reader = JDBCResultSetReader.STRUCT_READER; 426 break; 427 case Types.ARRAY: 428 reader = JDBCResultSetReader.ARRAY_READER; 429 break; 430 case Types.OTHER: 431 reader = JDBCResultSetReader.OTHER_READER; 432 break; 433 default: 434 { 435 reader = getResultReaderByType(destination); 436 } 437 } 438 return reader; 439 } 440 441 public static JDBCResultSetReader getResultReaderByType(Class destination) 442 { 443 JDBCResultSetReader reader; 444 if(destination == java.util.Date .class) 445 { 446 reader = JDBCResultSetReader.JAVA_UTIL_DATE_READER; 447 } 448 else if(destination == java.sql.Date .class) 449 { 450 reader = JDBCResultSetReader.JAVA_SQL_DATE_READER; 451 } 452 else if(destination == java.sql.Time .class) 453 { 454 reader = JDBCResultSetReader.JAVA_SQL_TIME_READER; 455 } 456 else if(destination == java.sql.Timestamp .class) 457 { 458 reader = JDBCResultSetReader.JAVA_SQL_TIMESTAMP_READER; 459 } 460 else if(destination == BigDecimal .class) 461 { 462 reader = JDBCResultSetReader.BIGDECIMAL_READER; 463 } 464 else if(destination == java.sql.Ref .class) 465 { 466 reader = JDBCResultSetReader.REF_READER; 467 } 468 else if(destination == String .class) 469 { 470 reader = JDBCResultSetReader.STRING_READER; 471 } 472 else if(destination == Boolean .class || destination == Boolean.TYPE) 473 { 474 reader = JDBCResultSetReader.BOOLEAN_READER; 475 } 476 else if(destination == Byte .class || destination == Byte.TYPE) 477 { 478 reader = JDBCResultSetReader.BYTE_READER; 479 } 480 else if(destination == Character .class || destination == Character.TYPE) 481 { 482 reader = JDBCResultSetReader.CHARACTER_READER; 483 } 484 else if(destination == Short .class || destination == Short.TYPE) 485 { 486 reader = JDBCResultSetReader.SHORT_READER; 487 } 488 else if(destination == Integer .class || destination == Integer.TYPE) 489 { 490 reader = JDBCResultSetReader.INT_READER; 491 } 492 else if(destination == Long .class || destination == Long.TYPE) 493 { 494 reader = JDBCResultSetReader.LONG_READER; 495 } 496 else if(destination == Float .class || destination == Float.TYPE) 497 { 498 reader = JDBCResultSetReader.FLOAT_READER; 499 } 500 else if(destination == Double .class || destination == Double.TYPE) 501 { 502 reader = JDBCResultSetReader.DOUBLE_READER; 503 } 504 else 505 { 506 reader = JDBCResultSetReader.OBJECT_READER; 507 } 508 return reader; 509 } 510 511 public static JDBCParameterSetter getParameterSetter(int jdbcType, Class javaType) 512 { 513 JDBCParameterSetter ps; 514 515 switch(jdbcType) 516 { 517 case Types.CLOB: 518 case Types.LONGVARCHAR: 519 ps = JDBCParameterSetter.CLOB; 520 break; 521 522 case Types.BINARY: 523 case Types.VARBINARY: 524 ps = JDBCParameterSetter.BINARY; 525 break; 526 527 case Types.BLOB: 528 case Types.LONGVARBINARY: 529 ps = JDBCParameterSetter.BLOB; 530 break; 531 532 case Types.DECIMAL: 533 case Types.NUMERIC: 534 ps = JDBCParameterSetter.NUMERIC; 535 break; 536 537 case Types.JAVA_OBJECT: 538 case Types.OTHER: 539 case Types.STRUCT: 540 541 default: 542 ps = JDBCParameterSetter.OBJECT; 543 break; 544 } 545 546 return ps; 547 } 548 549 554 private static final Map jdbcTypeNames; 555 private final static Map csTypes; 556 557 565 public static String getJDBCTypeName(int jdbcType) 566 { 567 return (String )jdbcTypeNames.get(new Integer (jdbcType)); 568 } 569 570 private static final String SQL_ERROR = "SQL error"; 571 private static final String GET_TIMESTAMP = "getTimestamp"; 572 private static final String GET_DATE = "getDate"; 573 private static final String GET_TIME = "getTime"; 574 private static final String GET_BIGDECIMAL = "getBigDecimal"; 575 private static final String GET_REF = "getRef"; 576 private static final String GET_STRING = "getString"; 577 private static final String GET_BOOLEAN = "getBoolean"; 578 private static final String GET_BYTE = "getByte"; 579 private static final String GET_SHORT = "getShort"; 580 private static final String GET_INT = "getInt"; 581 private static final String GET_LONG = "getLong"; 582 private static final String GET_FLOAT = "getFloat"; 583 private static final String GET_DOUBLE = "getDouble"; 584 private static final String GET_BYTES = "getBytes"; 585 586 static 587 { 588 Class [] arg = new Class []{Integer.TYPE}; 589 590 csTypes = new HashMap (); 594 try 595 { 596 csTypes.put(java.util.Date .class.getName(), 598 CallableStatement .class.getMethod(GET_TIMESTAMP, arg)); 599 csTypes.put(java.sql.Date .class.getName(), 601 CallableStatement .class.getMethod(GET_DATE, arg)); 602 csTypes.put(java.sql.Time .class.getName(), 604 CallableStatement .class.getMethod(GET_TIME, arg)); 605 csTypes.put(java.sql.Timestamp .class.getName(), 607 CallableStatement .class.getMethod(GET_TIMESTAMP, arg)); 608 csTypes.put(java.math.BigDecimal .class.getName(), 610 CallableStatement .class.getMethod(GET_BIGDECIMAL, arg)); 611 csTypes.put(java.sql.Ref .class.getName(), 613 CallableStatement .class.getMethod(GET_REF, arg)); 614 csTypes.put(java.lang.String .class.getName(), 616 CallableStatement .class.getMethod(GET_STRING, arg)); 617 csTypes.put(java.lang.Boolean .class.getName(), 619 CallableStatement .class.getMethod(GET_BOOLEAN, arg)); 620 csTypes.put(Boolean.TYPE.getName(), 622 CallableStatement .class.getMethod(GET_BOOLEAN, arg)); 623 csTypes.put(java.lang.Byte .class.getName(), 625 CallableStatement .class.getMethod(GET_BYTE, arg)); 626 csTypes.put(Byte.TYPE.getName(), 628 CallableStatement .class.getMethod(GET_BYTE, arg)); 629 csTypes.put(java.lang.Character .class.getName(), 631 CallableStatement .class.getMethod(GET_STRING, arg)); 632 csTypes.put(Character.TYPE.getName(), 634 CallableStatement .class.getMethod(GET_STRING, arg)); 635 csTypes.put(java.lang.Short .class.getName(), 637 CallableStatement .class.getMethod(GET_SHORT, arg)); 638 csTypes.put(Short.TYPE.getName(), 640 CallableStatement .class.getMethod(GET_SHORT, arg)); 641 csTypes.put(java.lang.Integer .class.getName(), 643 CallableStatement .class.getMethod(GET_INT, arg)); 644 csTypes.put(Integer.TYPE.getName(), 646 CallableStatement .class.getMethod(GET_INT, arg)); 647 csTypes.put(java.lang.Long .class.getName(), 649 CallableStatement .class.getMethod(GET_LONG, arg)); 650 csTypes.put(Long.TYPE.getName(), 652 CallableStatement .class.getMethod(GET_LONG, arg)); 653 csTypes.put(java.lang.Float .class.getName(), 655 CallableStatement .class.getMethod(GET_FLOAT, arg)); 656 csTypes.put(Float.TYPE.getName(), 658 CallableStatement .class.getMethod(GET_FLOAT, arg)); 659 csTypes.put(java.lang.Double .class.getName(), 661 CallableStatement .class.getMethod(GET_DOUBLE, arg)); 662 csTypes.put(Double.TYPE.getName(), 664 CallableStatement .class.getMethod(GET_DOUBLE, arg)); 665 csTypes.put("[B", 667 CallableStatement .class.getMethod(GET_BYTES, arg)); 668 } 669 catch(NoSuchMethodException e) 670 { 671 log.error(SQL_ERROR, e); 673 } 674 675 jdbcTypeNames = new HashMap (); 678 Field [] fields = Types .class.getFields(); 679 for(int i = 0; i < fields.length; i++) 680 { 681 try 682 { 683 jdbcTypeNames.put(fields[i].get(null), fields[i].getName()); 684 } 685 catch(IllegalAccessException e) 686 { 687 log.error(SQL_ERROR, e); 689 } 690 } 691 } 692 693 705 public static Object getParameter(Logger log, CallableStatement cs, int index, int jdbcType, Class destination) throws SQLException 706 { 707 Object value = null; 708 switch(jdbcType) 709 { 710 case Types.CLOB: 714 case Types.LONGVARCHAR: 715 case Types.BLOB: 716 case Types.LONGVARBINARY: 717 throw new UnsupportedOperationException (); 718 719 case Types.BINARY: 723 case Types.VARBINARY: 724 { 725 byte[] bytes = cs.getBytes(index); 726 if(!cs.wasNull()) 727 { 728 if(destination == byte[].class) 729 value = bytes; 730 else 731 value = convertToObject(bytes); 732 } 733 if(log.isTraceEnabled()) 734 { 735 log.trace("Get result: index=" + index + 736 ", javaType=" + destination.getName() + 737 ", Binary, value=" + value); 738 } 739 } 740 break; 741 742 case Types.JAVA_OBJECT: 747 case Types.STRUCT: 748 case Types.ARRAY: 749 case Types.OTHER: 750 { 751 value = cs.getObject(index); 752 if(log.isTraceEnabled()) 753 { 754 log.trace("Get result: index=" + index + 755 ", javaType=" + destination.getName() + 756 ", Object, value=" + value); 757 } 758 } 759 break; 760 761 default: 765 Method method = (Method )csTypes.get(destination.getName()); 766 if(method != null) 767 { 768 try 769 { 770 value = method.invoke(cs, new Object []{new Integer (index)}); 771 if(cs.wasNull()) 772 { 773 value = null; 774 } 775 776 if(log.isTraceEnabled()) 777 { 778 log.trace("Get result: index=" + index + 779 ", javaType=" + destination.getName() + 780 ", Simple, value=" + value); 781 } 782 } 783 catch(IllegalAccessException e) 784 { 785 } 787 catch(InvocationTargetException e) 788 { 789 } 791 } 792 else 793 { 794 value = cs.getObject(index); 795 if(log.isTraceEnabled()) 796 { 797 log.trace("Get result: index=" + index + 798 ", javaType=" + destination.getName() + 799 ", Object, value=" + value); 800 } 801 } 802 } 803 return coerceToJavaType(value, destination); 804 } 805 806 private static Object coerceToJavaType( 807 Object value, 808 Class destination) throws SQLException 809 { 810 try 811 { 812 if(value == null) 816 { 817 return null; 818 } 819 820 if(value instanceof MarshalledObject && !destination.equals(MarshalledObject .class)) 825 { 826 value = ((MarshalledObject )value).get(); 827 } 828 829 if(value instanceof Handle ) 834 { 835 value = ((Handle )value).getEJBObject(); 836 } 837 838 if(destination.isPrimitive()) 844 { 845 if(value == null) 846 throw new IllegalStateException ("Loaded NULL value for a field of a primitive type."); 847 if((destination.equals(Byte.TYPE) && value instanceof Byte ) || 848 (destination.equals(Short.TYPE) && value instanceof Short ) || 849 (destination.equals(Character.TYPE) && value instanceof Character ) || 850 (destination.equals(Boolean.TYPE) && value instanceof Boolean ) || 851 (destination.equals(Integer.TYPE) && value instanceof Integer ) || 852 (destination.equals(Long.TYPE) && value instanceof Long ) || 853 (destination.equals(Float.TYPE) && value instanceof Float ) || 854 (destination.equals(Double.TYPE) && value instanceof Double ) 855 ) 856 { 857 return value; 858 } 859 } 860 861 if(destination == java.util.Date .class && value instanceof java.util.Date ) 866 { 867 if(value instanceof java.sql.Timestamp ) 869 { 870 java.sql.Timestamp ts = (java.sql.Timestamp )value; 871 872 long temp = ts.getTime(); 876 if(temp % 1000 == 0) 877 temp += ts.getNanos() / 1000000; 878 return new java.util.Date (temp); 879 } 880 else 881 { 882 return new java.util.Date (((java.util.Date )value).getTime()); 883 } 884 } 885 886 if(destination == java.sql.Time .class && value instanceof java.sql.Time ) 891 { 892 return new java.sql.Time (((java.sql.Time )value).getTime()); 893 } 894 895 if(destination == java.sql.Date .class && value instanceof java.sql.Date ) 900 { 901 return new java.sql.Date (((java.sql.Date )value).getTime()); 902 } 903 904 if(destination == java.sql.Timestamp .class && value instanceof java.sql.Timestamp ) 909 { 910 java.sql.Timestamp orignal = (java.sql.Timestamp )value; 913 java.sql.Timestamp copy = new java.sql.Timestamp (orignal.getTime()); 914 copy.setNanos(orignal.getNanos()); 915 return copy; 916 } 917 918 if(value instanceof String && (destination == Character .class || destination == Character.TYPE)) 923 { 924 return new Character (((String )value).charAt(0)); 925 } 926 927 if(destination.isAssignableFrom(value.getClass())) 929 { 930 return value; 931 } 932 933 if(destination == java.math.BigInteger .class && value.getClass() == java.math.BigDecimal .class) 934 { 935 return ((java.math.BigDecimal )value).toBigInteger(); 936 } 937 938 throw new SQLException ("Got a " + value.getClass().getName() + "[cl=" + 940 System.identityHashCode(value.getClass().getClassLoader()) + 941 ", value=" + value + "] while looking for a " + 942 destination.getName() + "[cl=" + 943 System.identityHashCode(destination) + "]"); 944 } 945 catch(RemoteException e) 946 { 947 throw new SQLException ("Unable to load EJBObject back from Handle: " 948 + e); 949 } 950 catch(IOException e) 951 { 952 throw new SQLException ("Unable to load to deserialize result: " + e); 953 } 954 catch(ClassNotFoundException e) 955 { 956 throw new SQLException ("Unable to load to deserialize result: " + e); 957 } 958 } 959 } 960 | Popular Tags |