1 7 package org.jboss.cache.loader; 8 9 import org.apache.commons.logging.Log; 10 import org.apache.commons.logging.LogFactory; 11 import org.jboss.cache.Fqn; 12 import org.jboss.cache.Modification; 13 import org.jboss.cache.config.CacheLoaderConfig.IndividualCacheLoaderConfig; 14 15 import javax.naming.InitialContext ; 16 import javax.naming.NamingException ; 17 import javax.sql.DataSource ; 18 import java.io.ByteArrayInputStream ; 19 import java.io.ByteArrayOutputStream ; 20 import java.io.IOException ; 21 import java.io.InputStream ; 22 import java.io.ObjectInputStream ; 23 import java.io.ObjectOutputStream ; 24 import java.sql.Connection ; 25 import java.sql.DatabaseMetaData ; 26 import java.sql.DriverManager ; 27 import java.sql.PreparedStatement ; 28 import java.sql.ResultSet ; 29 import java.sql.SQLException ; 30 import java.sql.Statement ; 31 import java.sql.Types ; 32 import java.util.ArrayList ; 33 import java.util.Collection ; 34 import java.util.Collections ; 35 import java.util.HashMap ; 36 import java.util.HashSet ; 37 import java.util.List ; 38 import java.util.Map ; 39 import java.util.Properties ; 40 import java.util.Set ; 41 42 84 public class JDBCCacheLoader extends AbstractCacheLoader 85 { 86 private static final Log log = LogFactory.getLog(JDBCCacheLoader.class); 87 88 private static final ThreadLocal connection = new ThreadLocal (); 89 90 private JDBCCacheLoaderConfig config; 91 private ConnectionFactory cf; 92 private String driverName; 93 94 public void setConfig(IndividualCacheLoaderConfig base) 95 { 96 if (config instanceof JDBCCacheLoaderConfig) 97 { 98 config = (JDBCCacheLoaderConfig) base; 99 } 100 else 101 { 102 config = new JDBCCacheLoaderConfig(base); 103 } 104 105 if (config.getDatasourceName() == null) 106 { 107 this.cf = new NonManagedConnectionFactory(config.getJdbcURL(), config.getJdbcUser(), config.getJdbcPassword()); 108 } 109 } 112 113 public IndividualCacheLoaderConfig getConfig() 114 { 115 return config; 116 } 117 118 125 public Set <String > getChildrenNames(Fqn fqn) throws Exception 126 { 127 Set children = null; 128 Connection con = null; 129 PreparedStatement ps = null; 130 ResultSet rs = null; 131 try 132 { 133 if (log.isDebugEnabled()) 134 { 135 log.debug("executing sql: " + config.getSelectChildNamesSql() + " (" + fqn + ")"); 136 } 137 138 con = cf.getConnection(); 139 ps = con.prepareStatement(config.getSelectChildNamesSql()); 140 ps.setString(1, fqn.toString()); 141 rs = ps.executeQuery(); 142 if (rs.next()) 143 { 144 children = new HashSet (); 145 do 146 { 147 String child = rs.getString(1); 148 int slashInd = child.lastIndexOf('/'); 149 String name = child.substring(slashInd + 1); 150 children.add(name); 153 } 154 while (rs.next()); 155 } 156 } 157 catch (SQLException e) 158 { 159 log.error("Failed to get children names for fqn " + fqn, e); 160 throw new IllegalStateException ("Failed to get children names for fqn " + fqn + ": " + e.getMessage()); 161 } 162 finally 163 { 164 safeClose(rs); 165 safeClose(ps); 166 cf.close(con); 167 } 168 169 return children == null ? null : Collections.unmodifiableSet(children); 170 } 171 172 174 187 193 200 public Map get(Fqn name) throws Exception 201 { 202 final Map node = loadNode(name); 203 return node == NULL_NODE_IN_ROW ? new HashMap (0) : node; 204 } 205 206 213 public boolean exists(Fqn name) throws Exception 214 { 215 final Map node = loadNode(name); 216 return node != null; } 218 219 231 public Object put(Fqn name, Object key, Object value) throws Exception 232 { 233 Map oldNode = loadNode(name); 234 Object oldValue; 235 Map node; 236 237 if (oldNode == null || oldNode == NULL_NODE_IN_ROW) 238 { 239 node = new HashMap (); 240 } 241 else 242 { 243 node = oldNode; 244 } 245 oldValue = node.put(key, value); 246 247 if (oldNode != null) 248 { 249 updateNode(name, node); 250 } 251 else 252 { 253 if (name.size() > 1) 254 { 255 for (int i = 1; i < name.size(); ++i) 256 { 257 final Fqn parent = name.getFqnChild(i); 258 if (!exists(parent)) 259 { 260 insertNode(parent, null); 261 } 262 } 263 } 264 insertNode(name, node); 265 } 266 267 return oldValue; 268 } 269 270 278 public void put(Fqn name, Map attributes) throws Exception 279 { 280 put(name, attributes, false); 281 } 282 283 291 public Object remove(Fqn name, Object key) throws Exception 292 { 293 Object removedValue = null; 294 Map node = loadNode(name); 295 if (node != null && node != NULL_NODE_IN_ROW) 296 { 297 removedValue = node.remove(key); 298 if (node.isEmpty()) 299 { 300 updateNode(name, null); 301 } 302 else 303 { 304 updateNode(name, node); 305 } 306 } 307 return removedValue; 308 } 309 310 317 public void remove(Fqn name) throws Exception 318 { 319 Connection con = null; 320 PreparedStatement ps = null; 321 try 322 { 323 if (name.size() == 0) 324 { 325 if (log.isDebugEnabled()) 326 { 327 log.debug("executing sql: " + config.getDeleteAllSql()); 328 } 329 330 con = cf.getConnection(); 331 ps = con.prepareStatement(config.getDeleteAllSql()); 332 int deletedRows = ps.executeUpdate(); 333 334 if (log.isDebugEnabled()) 335 { 336 log.debug("total rows deleted: " + deletedRows); 337 } 338 } 339 else 340 { 341 StringBuffer sql = new StringBuffer (300); 342 sql.append("delete from ").append(config.getTable()).append(" where fqn in ("); 343 List fqns = new ArrayList (); 345 346 addChildrenToDeleteSql(name.toString(), sql, fqns); 347 348 sql.append(')'); 349 350 if (fqns.size() == 1) 351 { 352 if (log.isDebugEnabled()) 353 { 354 log.debug("executing sql: " + config.getDeleteNodeSql() + "(" + name + ")"); 355 } 356 357 con = cf.getConnection(); 358 ps = con.prepareStatement(config.getDeleteNodeSql()); 359 ps.setString(1, name.toString()); 360 } 361 else 362 { 363 if (log.isDebugEnabled()) 364 { 365 log.debug("executing sql: " + sql + " " + fqns); 366 } 367 368 con = cf.getConnection(); 369 ps = con.prepareStatement(sql.toString()); 370 for (int i = 0; i < fqns.size(); ++i) 371 { 372 ps.setString(i + 1, (String ) fqns.get(i)); 373 } 374 } 375 376 int deletedRows = ps.executeUpdate(); 377 378 if (log.isDebugEnabled()) 379 { 380 log.debug("total rows deleted: " + deletedRows); 381 } 382 } 383 } 384 catch (SQLException e) 385 { 386 log.error("Failed to remove node " + name, e); 387 throw new IllegalStateException ("Failed to remove node " + name + ": " + e.getMessage()); 388 } 389 finally 390 { 391 safeClose(ps); 392 cf.close(con); 393 } 394 } 395 396 402 public void removeData(Fqn name) throws Exception 403 { 404 updateNode(name, null); 405 } 406 407 416 public void prepare(Object tx, List <Modification> modifications, boolean one_phase) throws Exception 417 { 418 if (cf instanceof NonManagedConnectionFactory) 421 { 422 Connection con = cf.prepare(tx); 423 if (log.isTraceEnabled()) 424 { 425 log.trace("openned tx connection: tx=" + tx + ", con=" + con); 426 } 427 } 428 429 try 430 { 431 put(modifications); 432 433 if (one_phase) 435 { 436 commit(tx); 437 } 438 } 439 catch (Exception e) 440 { 441 rollback(tx); 443 throw e; 445 } 446 } 447 448 454 public void commit(Object tx) throws Exception 455 { 456 cf.commit(tx); 457 } 458 459 464 public void rollback(Object tx) 465 { 466 cf.rollback(tx); 467 } 468 469 471 public void create() throws Exception 472 { 473 } 474 475 public void start() throws Exception 476 { 477 if (config.getDriverClass() != null) 478 { 479 loadDriver(config.getDriverClass()); 480 } 481 else 482 { 483 InitialContext ctx = null; 486 try 487 { 488 ctx = new InitialContext (); 489 DataSource dataSource = (DataSource ) ctx.lookup(config.getDatasourceName()); 490 this.cf = new ManagedConnectionFactory(dataSource); 491 } 492 catch (NamingException e) 493 { 494 log.error("Failed to lookup datasource " + config.getDatasourceName() + ": " + e.getMessage(), e); 495 throw new IllegalStateException ("Failed to lookup datasource " + config.getDatasourceName() + ": " + e.getMessage()); 496 } 497 finally 498 { 499 if (ctx != null) 500 { 501 try 502 { 503 ctx.close(); 504 } 505 catch (NamingException e) 506 { 507 log.warn("Failed to close naming context.", e); 508 } 509 } 510 } 511 } 512 513 Connection con = null; 514 Statement st = null; 515 516 try 517 { 518 con = cf.getConnection(); 519 driverName = getDriverName(con); 520 if (config.getCreateTable()) 521 { 522 if (!tableExists(config.getTable(), con)) 523 { 524 if (log.isDebugEnabled()) 525 { 526 log.debug("executing ddl: " + config.getCreateTableDDL()); 527 } 528 st = con.createStatement(); 529 st.executeUpdate(config.getCreateTableDDL()); 530 } 531 } 532 } 533 finally 534 { 535 safeClose(st); 536 cf.close(con); 537 } 538 } 539 540 public void stop() 541 { 542 if (config.getDropTable()) 543 { 544 Connection con = null; 545 Statement st = null; 546 try 547 { 548 if (log.isDebugEnabled()) 549 { 550 log.debug("executing ddl: " + config.getDropTableDDL()); 551 } 552 553 con = cf.getConnection(); 554 st = con.createStatement(); 555 st.executeUpdate(config.getDropTableDDL()); 556 safeClose(st); 557 } 558 catch (SQLException e) 559 { 560 log.error("Failed to drop table: " + e.getMessage(), e); 561 } 562 finally 563 { 564 safeClose(st); 565 cf.close(con); 566 } 567 } 568 } 569 570 public void destroy() 571 { 572 } 573 574 576 private void addChildrenToDeleteSql(String name, StringBuffer sql, List fqns) 577 throws SQLException 578 { 579 Connection con = null; 582 PreparedStatement selChildrenPs = null; 583 ResultSet rs = null; 584 try 585 { 586 if (log.isDebugEnabled()) 587 { 588 log.debug("executing sql: " + config.getSelectChildFqnsSql() + "(" + name + ")"); 589 } 590 591 con = cf.getConnection(); 592 selChildrenPs = con.prepareStatement(config.getSelectChildFqnsSql()); 593 selChildrenPs.setString(1, name); 594 rs = selChildrenPs.executeQuery(); 595 596 if (rs.next()) 597 { 598 do 599 { 600 String childStr = rs.getString(1); 601 addChildrenToDeleteSql(childStr, sql, fqns); 602 } 603 while (rs.next()); 604 } 605 606 if (fqns.size() == 0) 607 { 608 sql.append("?"); 609 } 610 else 611 { 612 sql.append(", ?"); 613 } 614 fqns.add(name); 615 } 616 finally 617 { 618 safeClose(rs); 619 safeClose(selChildrenPs); 620 cf.close(con); 621 } 622 } 623 624 public void put(Fqn name, Map attributes, boolean override) throws Exception 625 { 626 Map attrs = (attributes == null ? null : new HashMap (attributes)); 628 629 Map oldNode = loadNode(name); 630 if (oldNode != null) 631 { 632 if (!override && oldNode != NULL_NODE_IN_ROW && attrs != null) 633 { 634 attrs.putAll(oldNode); 635 } 636 updateNode(name, attrs); 637 } 638 else 639 { 640 if (name.size() > 1) 641 { 642 for (int i = 1; i < name.size(); ++i) 643 { 644 final Fqn parent = name.getFqnChild(i); 645 if (!exists(parent)) 646 { 647 insertNode(parent, null); 648 } 649 } 650 } 651 insertNode(name, attrs); 652 } 653 } 654 655 661 private void insertNode(Fqn name, Map node) 662 { 663 Connection con = null; 664 PreparedStatement ps = null; 665 try 666 { 667 if (log.isDebugEnabled()) 668 { 669 log.debug("executing sql: " + config.getInsertNodeSql() + " (" + name + ")"); 670 } 671 672 con = cf.getConnection(); 673 ps = con.prepareStatement(config.getInsertNodeSql()); 674 675 ps.setString(1, name.toString()); 676 677 if (node != null) 678 { 679 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 681 ObjectOutputStream oos = new ObjectOutputStream (baos); 682 oos.writeObject(node); 685 686 ByteArrayInputStream bais = new ByteArrayInputStream (baos.toByteArray()); 687 ps.setBinaryStream(2, bais, baos.size()); 688 } 689 else 690 { 691 if (driverName != null && (driverName.contains("SQLSERVER") 693 || driverName.contains("POSTGRESQL"))) 694 { 695 ps.setNull(2, Types.LONGVARBINARY); 696 } 697 else 698 { 699 ps.setNull(2, Types.BLOB); 700 } 701 } 703 704 if (name.size() == 0) 705 { 706 ps.setNull(3, Types.VARCHAR); 707 } 708 else 709 { 710 ps.setString(3, name.getFqnChild(name.size() - 1).toString()); 711 } 712 713 int rows = ps.executeUpdate(); 714 if (rows != 1) 715 { 716 throw new IllegalStateException ("Expected one insert row but got " + rows); 717 } 718 } 719 catch (RuntimeException e) 720 { 721 throw e; 722 } 723 catch (Exception e) 724 { 725 log.error("Failed to insert node: " + e.getMessage(), e); 726 throw new IllegalStateException ("Failed to insert node: " + e.getMessage()); 727 } 728 finally 729 { 730 safeClose(ps); 731 cf.close(con); 732 } 733 } 734 735 741 private void updateNode(Fqn name, Map node) 742 { 743 Connection con = null; 744 PreparedStatement ps = null; 745 try 746 { 747 if (log.isDebugEnabled()) 748 { 749 log.debug("executing sql: " + config.getUpdateNodeSql()); 750 } 751 752 con = cf.getConnection(); 753 ps = con.prepareStatement(config.getUpdateNodeSql()); 754 755 if (node == null) 756 { 757 node = new HashMap (0); 761 } 762 ByteArrayOutputStream baos = new ByteArrayOutputStream (); 766 ObjectOutputStream oos = new ObjectOutputStream (baos); 767 oos.writeObject(node); 769 770 ByteArrayInputStream bais = new ByteArrayInputStream (baos.toByteArray()); 771 ps.setBinaryStream(1, bais, baos.size()); 772 774 ps.setString(2, name.toString()); 775 776 int rows = ps.executeUpdate(); 777 } 782 catch (Exception e) 783 { 784 log.error("Failed to update node for fqn " + name + ": " + e.getMessage(), e); 785 throw new IllegalStateException ("Failed to update node for fqn " + name + ": " + e.getMessage()); 786 } 787 finally 788 { 789 safeClose(ps); 790 cf.close(con); 791 } 792 } 793 794 802 private Map loadNode(Fqn name) 803 { 804 boolean rowExists = false; 805 Map oldNode = null; 806 Connection con = null; 807 PreparedStatement ps = null; 808 ResultSet rs = null; 809 try 810 { 811 if (log.isDebugEnabled()) 812 { 813 log.debug("executing sql: " + config.getSelectNodeSql() + " (" + name + ")"); 814 } 815 816 con = cf.getConnection(); 817 ps = con.prepareStatement(config.getSelectNodeSql()); 818 ps.setString(1, name.toString()); 819 820 rs = ps.executeQuery(); 821 822 if (rs.next()) 823 { 824 rowExists = true; 825 InputStream is = rs.getBinaryStream(1); 826 if (is != null && !rs.wasNull()) 827 { 828 ObjectInputStream ois = null; 829 try 830 { 831 ois = new ObjectInputStream (is); 833 Object marshalledNode = ois.readObject(); 834 835 oldNode = (Map ) marshalledNode; 845 } 846 catch (IOException e) 847 { 848 throw new SQLException ("Unable to load to deserialize result: " + e); 849 } 850 catch (ClassNotFoundException e) 851 { 852 throw new SQLException ("Unable to load to deserialize result: " + e); 853 } 854 finally 855 { 856 safeClose(ois); 857 } 858 } 859 } 860 } 861 catch (SQLException e) 862 { 863 log.error("Failed to load node for fqn " + name + ": " + e.getMessage(), e); 864 throw new IllegalStateException ("Failed to load node for fqn " + name + ": " + e.getMessage()); 865 } 866 finally 867 { 868 safeClose(rs); 869 safeClose(ps); 870 cf.close(con); 871 } 872 873 return oldNode == null ? (rowExists ? NULL_NODE_IN_ROW : null) : oldNode; 874 } 875 876 private static void safeClose(InputStream is) 877 { 878 if (is != null) 879 { 880 try 881 { 882 is.close(); 883 } 884 catch (IOException e) 885 { 886 log.warn("Failed to close input stream: " + e.getMessage()); 887 } 888 } 889 } 890 891 private static void safeClose(Connection con) 892 { 893 if (con != null) 894 { 895 try 896 { 897 con.close(); 898 } 899 catch (SQLException e) 900 { 901 log.warn("Failed to close connection: " + e.getMessage()); 902 } 903 } 904 } 905 906 private static void safeClose(Statement st) 907 { 908 if (st != null) 909 { 910 try 911 { 912 st.close(); 913 } 914 catch (SQLException e) 915 { 916 log.warn("Failed to close statement: " + e.getMessage()); 917 } 918 } 919 } 920 921 private static void safeClose(ResultSet rs) 922 { 923 if (rs != null) 924 { 925 try 926 { 927 rs.close(); 928 } 929 catch (SQLException e) 930 { 931 log.warn("Failed to close result set: " + e.getMessage()); 932 } 933 } 934 } 935 936 private static void loadDriver(String drv) 937 { 938 try 939 { 940 Class.forName(drv).newInstance(); 941 } 942 catch (Exception e) 943 { 944 log.error("Failed to load driver " + drv, e); 945 throw new IllegalStateException ("Failed to load driver " + drv + ": " + e.getMessage()); 946 } 947 } 948 949 private static String getDriverName(Connection con) 950 { 951 if (con == null) return null; 952 try 953 { 954 DatabaseMetaData dmd = con.getMetaData(); 955 return dmd.getDriverName().toUpperCase(); 956 } 957 catch (SQLException e) 958 { 959 throw new IllegalStateException ( 962 "Error while getting the driver name " + ": " + e.getMessage()); 963 } 964 } 965 966 static String getRequiredProperty(Properties props, String name) 967 { 968 String value = props.getProperty(name); 969 if (value == null) 970 { 971 throw new IllegalStateException ("Missing required property: " + name); 972 } 973 return value; 974 } 975 976 private static boolean tableExists(String tableName, Connection con) 977 { 978 ResultSet rs = null; 979 try 980 { 981 DatabaseMetaData dmd = con.getMetaData(); 984 String catalog = con.getCatalog(); 985 String schema = null; 986 String quote = dmd.getIdentifierQuoteString(); 987 if (tableName.startsWith(quote)) 988 { 989 if (!tableName.endsWith(quote)) 990 { 991 throw new IllegalStateException ("Mismatched quote in table name: " + tableName); 992 } 993 int quoteLength = quote.length(); 994 tableName = tableName.substring(quoteLength, tableName.length() - quoteLength); 995 if (dmd.storesLowerCaseQuotedIdentifiers()) 996 { 997 tableName = tableName.toLowerCase(); 998 } 999 else if (dmd.storesUpperCaseQuotedIdentifiers()) 1000 { 1001 tableName = tableName.toUpperCase(); 1002 } 1003 } 1004 else 1005 { 1006 if (dmd.storesLowerCaseIdentifiers()) 1007 { 1008 tableName = tableName.toLowerCase(); 1009 } 1010 else if (dmd.storesUpperCaseIdentifiers()) 1011 { 1012 tableName = tableName.toUpperCase(); 1013 } 1014 } 1015 1016 int dotIndex; 1017 if ((dotIndex = tableName.indexOf('.')) != -1) 1018 { 1019 schema = tableName.substring(0, dotIndex); 1021 tableName = tableName.substring(dotIndex + 1); 1022 } 1023 1024 rs = dmd.getTables(catalog, schema, tableName, null); 1025 return rs.next(); 1026 } 1027 catch (SQLException e) 1028 { 1029 throw new IllegalStateException ( 1032 "Error while checking if table aleady exists " + tableName + ": " + e.getMessage()); 1033 } 1034 finally 1035 { 1036 safeClose(rs); 1037 } 1038 } 1039 1040 1042 private static final Map NULL_NODE_IN_ROW = new Map () 1043 { 1044 public int size() 1045 { 1046 throw new UnsupportedOperationException (); 1047 } 1048 1049 public void clear() 1050 { 1051 throw new UnsupportedOperationException (); 1052 } 1053 1054 public boolean isEmpty() 1055 { 1056 throw new UnsupportedOperationException (); 1057 } 1058 1059 public boolean containsKey(Object key) 1060 { 1061 throw new UnsupportedOperationException (); 1062 } 1063 1064 public boolean containsValue(Object value) 1065 { 1066 throw new UnsupportedOperationException (); 1067 } 1068 1069 public Collection values() 1070 { 1071 throw new UnsupportedOperationException (); 1072 } 1073 1074 public void putAll(Map t) 1075 { 1076 throw new UnsupportedOperationException (); 1077 } 1078 1079 public Set entrySet() 1080 { 1081 throw new UnsupportedOperationException (); 1082 } 1083 1084 public Set keySet() 1085 { 1086 throw new UnsupportedOperationException (); 1087 } 1088 1089 public Object get(Object key) 1090 { 1091 throw new UnsupportedOperationException (); 1092 } 1093 1094 public Object remove(Object key) 1095 { 1096 throw new UnsupportedOperationException (); 1097 } 1098 1099 public Object put(Object key, Object value) 1100 { 1101 throw new UnsupportedOperationException (); 1102 } 1103 }; 1104 1105 interface ConnectionFactory 1106 { 1107 Connection getConnection() throws SQLException ; 1108 1109 Connection prepare(Object tx); 1110 1111 void commit(Object tx); 1112 1113 void rollback(Object tx); 1114 1115 void close(Connection con); 1116 } 1117 1118 private final class NonManagedConnectionFactory implements ConnectionFactory 1119 { 1120 private final String url; 1121 private final String usr; 1122 private final String pwd; 1123 1124 public NonManagedConnectionFactory(String url, String usr, String pwd) 1125 { 1126 this.url = url; 1127 this.usr = usr; 1128 this.pwd = pwd; 1129 } 1130 1131 public Connection prepare(Object tx) 1132 { 1133 Connection con = getConnection(); 1134 try 1135 { 1136 if (con.getAutoCommit()) 1137 { 1138 con.setAutoCommit(false); 1139 } 1140 } 1141 catch (Exception e) 1142 { 1143 log.error("Failed to set auto-commit: " + e.getMessage(), e); 1144 throw new IllegalStateException ("Failed to set auto-commit: " + e.getMessage()); 1145 } 1146 connection.set(con); 1147 return con; 1148 } 1149 1150 public Connection getConnection() 1151 { 1152 Connection con = (Connection ) connection.get(); 1153 if (con == null) 1154 { 1155 try 1156 { 1157 con = DriverManager.getConnection(url, usr, pwd); 1158 } 1160 catch (SQLException e) 1161 { 1162 log.error("Failed to get connection for url=" + url + ", user=" + usr + ", password=" + pwd, e); 1163 throw new IllegalStateException ("Failed to get connection for url=" + 1164 url + 1165 ", user=" + 1166 usr + 1167 ", password=" + 1168 pwd + 1169 ": " + 1170 e.getMessage()); 1171 } 1172 } 1173 1174 if (log.isTraceEnabled()) 1175 { 1176 log.debug("using connection: " + con); 1177 } 1178 1179 return con; 1180 } 1181 1182 public void commit(Object tx) 1183 { 1184 Connection con = (Connection ) connection.get(); 1185 if (con == null) 1186 { 1187 throw new IllegalStateException ("Failed to commit: thread is not associated with the connection!"); 1188 } 1189 1190 try 1191 { 1192 con.commit(); 1193 if (log.isTraceEnabled()) 1194 { 1195 log.trace("committed tx=" + tx + ", con=" + con); 1196 } 1197 } 1198 catch (SQLException e) 1199 { 1200 log.error("Failed to commit", e); 1201 throw new IllegalStateException ("Failed to commit: " + e.getMessage()); 1202 } 1203 finally 1204 { 1205 closeTxConnection(con); 1206 } 1207 } 1208 1209 public void rollback(Object tx) 1210 { 1211 Connection con = (Connection ) connection.get(); 1212 if (con == null) 1213 { 1214 throw new IllegalStateException ("Failed to rollback: thread is not associated with the connection!"); 1216 } 1217 1218 try 1219 { 1220 con.rollback(); 1221 if (log.isTraceEnabled()) 1222 { 1223 log.trace("rolledback tx=" + tx + ", con=" + con); 1224 } 1225 } 1226 catch (SQLException e) 1227 { 1228 log.error("Failed to rollback", e); 1229 throw new IllegalStateException ("Failed to rollback: " + e.getMessage()); 1230 } 1231 finally 1232 { 1233 closeTxConnection(con); 1234 } 1235 } 1236 1237 public void close(Connection con) 1238 { 1239 if (con != null && con != connection.get()) 1240 { 1241 try 1242 { 1243 con.close(); 1244 if (log.isTraceEnabled()) 1245 { 1246 } 1248 } 1249 catch (SQLException e) 1250 { 1251 log.warn("Failed to close connection: " + e.getMessage()); 1252 } 1253 } 1254 } 1255 1256 private void closeTxConnection(Connection con) 1257 { 1258 safeClose(con); 1259 connection.set(null); 1260 } 1261 } 1262 1263 private final class ManagedConnectionFactory 1264 implements ConnectionFactory 1265 { 1266 private final DataSource dataSource; 1267 1268 public ManagedConnectionFactory(DataSource dataSource) 1269 { 1270 if (dataSource == null) 1274 { 1275 throw new IllegalArgumentException ("dataSource cannot be null"); 1276 } 1277 1278 this.dataSource = dataSource; 1279 } 1280 1281 public Connection prepare(Object tx) 1282 { 1283 1287 try 1288 { 1289 return getConnection(); 1290 } 1291 catch (SQLException e) 1292 { 1293 log.error("Failed to get connection: " + e.getMessage(), e); 1294 throw new IllegalStateException ("Failed to get connection: " + e.getMessage()); 1295 } 1296 } 1297 1298 public Connection getConnection() 1299 throws SQLException 1300 { 1301 return dataSource.getConnection(); 1302 } 1303 1304 public void commit(Object tx) 1305 { 1306 } 1307 1308 public void rollback(Object tx) 1309 { 1310 } 1311 1312 public void close(Connection con) 1313 { 1314 safeClose(con); 1315 } 1316 } 1317} 1318 | Popular Tags |