1 64 65 package com.jcorporate.expresso.core.db; 66 67 import com.jcorporate.expresso.core.dataobjects.PersistenceManager; 68 import com.jcorporate.expresso.core.db.config.JDBCConfig; 69 import com.jcorporate.expresso.core.db.config.JNDIConfig; 70 import com.jcorporate.expresso.core.db.datasource.DSException; 71 import com.jcorporate.expresso.core.db.datasource.JndiDataSource; 72 import com.jcorporate.expresso.core.db.exception.ConnectionPoolException; 73 import com.jcorporate.expresso.core.db.exception.PoolFullException; 74 import com.jcorporate.expresso.core.misc.ConfigManager; 75 import com.jcorporate.expresso.core.misc.ConfigurationException; 76 import com.jcorporate.expresso.core.misc.DateTime; 77 import com.jcorporate.expresso.core.misc.StringUtil; 78 import com.jcorporate.expresso.kernel.RootContainerInterface; 79 import com.jcorporate.expresso.kernel.management.ExpressoRuntimeMap; 80 import com.jcorporate.expresso.kernel.util.ClassLocator; 81 import com.jcorporate.expresso.kernel.util.LocatorUtils; 82 import org.apache.log4j.Logger; 83 84 import java.util.ArrayList ; 85 import java.util.Date ; 86 import java.util.Enumeration ; 87 import java.util.HashMap ; 88 import java.util.Iterator ; 89 import java.util.LinkedList ; 90 import java.util.List ; 91 import java.util.Map ; 92 93 94 108 public class DBConnectionPool 109 extends Thread { 110 static private int nextConnectionId = 1; 111 112 115 private static Logger log = Logger.getLogger(DBConnectionPool.class); 116 117 121 private boolean supportsTransactions = false; 122 123 126 static private HashMap otherDBPools = new HashMap (); 127 128 131 private static final String THIS_CLASS = DBConnectionPool.class.getName(); 132 133 134 137 private long interval = 30 * 1000; 138 139 143 private long maxttl = interval * 10; 144 145 146 150 private static final int GET_CONNECTION_RETRIES = 30; 151 152 153 private String dbDriverType = null; 154 155 158 private String dbDriver = null; 159 160 163 private String dbURL = null; 164 165 168 private String dbConnectFormat = null; 169 170 173 private String dbLogin = null; 174 175 178 private String dbPassword = null; 179 180 183 private String dbName = ""; 184 185 186 191 private int issuedConnectionsCount = 0; 192 193 196 private static final int CLEAN_POOL_MAX = 50; 197 198 203 private int maxPoolSize = 6; 204 205 209 private boolean initialized = false; 210 211 214 private ArrayList wildCards = new ArrayList (2); 215 216 219 protected LinkedList available = new LinkedList (); 220 221 224 protected Map inUse = new HashMap (3); 225 226 230 protected Object poolLock = new Object (); 231 232 235 protected Object timestampLock = new Object (); 236 237 242 private String testQuery = null; 243 244 245 249 private static String uniqueRowKeyword = "DISTINCT"; 250 251 256 public final static int LIMITATION_DISABLED = 0; 257 258 269 public final static int LIMITATION_AFTER_TABLE = 1; 270 271 282 public final static int LIMITATION_AFTER_WHERE = 2; 283 284 295 public final static int LIMITATION_AFTER_ORDER_BY = 3; 296 297 309 public final static int LIMITATION_AFTER_SELECT = 4; 310 311 327 protected int limitationPosition = LIMITATION_DISABLED; 328 329 349 protected String limitationSyntax = null; 350 351 355 protected boolean checkZeroUpdate = false; 356 357 358 362 protected EscapeHandler escapeHandler = null; 363 364 365 370 protected long lastUsed; 371 372 376 private JndiDataSource jndiDS = null; 377 378 381 public DBConnectionPool() { 382 super(); 383 lastUsed = System.currentTimeMillis(); 384 } 385 386 387 395 protected DBConnection buildNewConnection() throws DBException { 396 DBConnection oneConnection = null; 397 if (dbDriverType.equalsIgnoreCase("datasource")) { 402 JDBCConfig myJdbc = getJDBCConfig(getDataContext()); 403 oneConnection = new DBConnection(myJdbc); 404 } else { 405 oneConnection = new DBConnection(dbDriver, dbURL, dbConnectFormat); 406 oneConnection.connect(dbLogin, dbPassword); 407 } 408 oneConnection.setDataContext(getDataContext()); 409 oneConnection.setId(nextConnectionId); 410 nextConnectionId++; 411 oneConnection.setDescription("New Connection"); 412 return oneConnection; 413 } 414 415 422 protected synchronized DBConnection createNewConnection() throws DBException { 423 DBConnection oneConnection = null; 424 425 int totalConnections = 0; 429 int avail = 0; 430 int inuse = 0; 431 boolean firstConnection = false; 432 synchronized (poolLock) { 433 avail = available.size(); 434 inuse = inUse.size(); 435 totalConnections = avail + inuse; 436 firstConnection = totalConnections == 0; 437 if (avail > 0) { 442 return null; 443 } 444 445 if (totalConnections >= this.maxPoolSize) { 446 return null; 447 } 448 449 } 451 if (log.isInfoEnabled()) { 452 log.info("Creating new connection Total size: " + totalConnections + "In Use Size: " + 453 inuse + " Available: " + avail + " Name: " + this.getDataContext()); 454 } 455 456 oneConnection = buildNewConnection(); 457 oneConnection.setParentPool(this); 458 459 synchronized (poolLock) { 460 int totalPools = available.size() + inUse.size(); 463 if (totalPools >= this.maxPoolSize) { 464 oneConnection.disconnect(); 465 log.warn("Got too many connections... abandoning one: inUse.size()=" + 466 inUse.size() + 467 " available.size()=" + available.size()); 468 return null; 469 } else { 470 oneConnection.setAvailable(false); 474 475 inUse.put(new Integer (oneConnection.getId()), oneConnection); 476 } 477 } 478 479 if (log.isDebugEnabled()) { 480 log.debug("New connection " + oneConnection.getId() + 481 " created successfully. " + "Now " + avail + 482 " connections available in pool '" + getDataContext() + 483 "', " + inuse + " currently connected"); 484 } 485 486 487 if (firstConnection) { 488 initialized = true; 489 supportsTransactions = oneConnection.supportsTransactions(); 490 491 JDBCConfig myConfig = getJDBCConfig(getDataContext()); 492 493 String limPosStr = StringUtil.notNull(myConfig.getLimitationPosition()); 496 497 if (limPosStr.length() > 0) { 498 setLimitationPosition(limPosStr); 499 } 500 501 String limSynStr = StringUtil.notNull(myConfig.getLimitationSyntax()); 504 505 if (limPosStr.length() > 0) { 506 setLimitationSyntax(limSynStr); 507 } 508 509 String keyword = StringUtil.notNull(myConfig.getUniqueRowKeyword()); 512 513 if (keyword.length() < 1) { 514 uniqueRowKeyword = "DISTINCT"; } else { 516 } 519 520 String zeroUpdate = StringUtil.notNull(myConfig.getCheckZeroUpdate()); 523 524 if (zeroUpdate.length() > 0) { 525 checkZeroUpdate = myConfig.checkZeroUpdate(); 526 } 527 528 setWildCards(); 531 532 } 533 oneConnection.setLimitationPosition(this.limitationPosition); 535 oneConnection.setLimitationSyntax(this.limitationSyntax); 536 oneConnection.setEscapeHandler(this.escapeHandler); 537 538 return oneConnection; 539 } 540 541 544 protected void cleanAvailable() throws ConnectionPoolException { 545 if (log.isDebugEnabled()) { 546 log.debug("Checking available pool for connections to remove"); 547 } 548 549 long startTime = System.currentTimeMillis(); 550 boolean removedConnections = false; 551 synchronized (poolLock) { 552 553 for (int i = 0; i < available.size();) { 555 DBConnection dbc = (DBConnection) available.get(i); 556 if (dbc.getCreatedTime() + maxttl < startTime) { 562 try { 563 dbc.disconnect(); 564 } catch (Throwable ex) { 565 log.warn("Error disconnecting", ex); 566 } 567 568 available.remove(i); 569 removedConnections = true; 570 } else { 571 i++; 572 } 573 } 574 575 if (removedConnections) { 576 poolLock.notify(); 577 } 578 } 579 580 } 581 582 591 public void clean() 592 throws ConnectionPoolException, DBException { 593 594 if (log.isDebugEnabled()) { 595 log.debug("Checking connection pool for stale connections"); 596 } 597 598 long now = System.currentTimeMillis(); 599 long lastTouched = 0; 600 DBConnection oneConnection = null; 601 602 ArrayList connectionsToRelease = null; 603 604 605 List connectionsToBeRemoved = new ArrayList (); 606 607 608 synchronized (poolLock) { 609 for (Iterator it = inUse.values().iterator(); it.hasNext();) { 610 oneConnection = (DBConnection) it.next(); 611 if (log.isDebugEnabled()) { 612 log.debug("Checking '" 613 + oneConnection.getDescription() + "'"); 614 } 615 616 lastTouched = oneConnection.getLastTouched(); 617 long timeOutTime = lastTouched + interval; 618 619 if (now > timeOutTime) { 620 621 if (log.isDebugEnabled()) { 622 log.debug("Closing connection"); 623 } 624 625 if (!oneConnection.getImmortal()) { 626 if (log.isDebugEnabled()) { 627 log.debug("Connection " 628 + oneConnection.getDescription() 629 + " was idle more than " + (interval / 1000) 630 + " seconds and was returned to the pool. " 631 + "Last SQL executed was '" 632 + oneConnection.getSQL() + "'"); 633 } 634 635 if (connectionsToRelease == null) { 636 connectionsToRelease = new ArrayList (); 637 } 638 connectionsToRelease.add(oneConnection); 639 640 } else { 641 log.warn("Warning: 'Immortal' Connection " 642 + oneConnection.getDescription() 643 + " was idle more than " + (interval / 1000) 644 + " seconds. " 645 + "Last SQL executed was '" 646 + oneConnection.getSQL() + "'"); 647 } 648 } 649 650 652 653 654 timeOutTime = lastTouched + (interval * 60 * 3); 655 if (now > timeOutTime) { 656 657 log.warn("Connection " 658 + oneConnection.getDescription() 659 + " was idle more than " + (interval / 1000) 660 + " minutes and was disconnected and removed " 661 + "from the pool"); 662 663 665 666 connectionsToBeRemoved.add(oneConnection); 667 668 } 669 } 670 671 673 for (int i = 0; i < connectionsToBeRemoved.size(); i++) { 674 DBConnection dbconn = (DBConnection) connectionsToBeRemoved.get(i); 675 dbconn.disconnect(); 676 dbconn.setAvailable(true); 677 inUse.remove(new Integer (dbconn.getId())); 678 } 679 680 681 DBConnection oneToRelease = null; 682 if (connectionsToRelease != null) { 683 for (Iterator rl = connectionsToRelease.iterator(); 684 rl.hasNext();) { 685 686 oneToRelease = (DBConnection) rl.next(); 687 release(oneToRelease); 688 oneToRelease.clear(); 689 oneToRelease = null; 690 } 691 } 692 } 693 } 694 695 696 699 public synchronized void disconnectAll() 700 throws DBException { 701 DBConnection oneConnection = null; 702 703 for (Iterator it = getPoolList().iterator(); it.hasNext();) { 704 oneConnection = (DBConnection) it.next(); 705 706 if (!oneConnection.isClosed()) { 707 try { 708 oneConnection.disconnect(); 709 } catch (DBException de) { 710 log.error("Unable to disconnect from " + 711 "database successfully when clearing connection pool", 712 de); 713 } 714 } 715 } 716 717 synchronized (poolLock) { 718 available = new LinkedList (); 719 inUse = new HashMap (3); 720 } 721 } 722 723 724 731 public synchronized void executeExclusiveUpdate(String theSQL) 732 throws DBException { 733 this.disconnectAll(); 734 735 try { 736 yield(); 737 sleep(500); 739 } catch (java.lang.InterruptedException ie) { 742 if (log.isDebugEnabled()) { 743 log.debug("Interrupted while sleeping"); 744 } 745 } 746 747 DBConnection dbc = null; 748 749 try { 750 dbc = this.getConnection(); 751 dbc.executeUpdate(theSQL); 752 } finally { 753 if (dbc != null) { 754 this.release(dbc); 755 } 756 } 757 } 758 759 765 private DBConnection findExistingConnection() { 766 DBConnection oneConnection = null; 767 768 try { 769 while (available.size() > 0) { 770 synchronized (poolLock) { 771 if (available.size() == 0) { 772 return null; 773 } 774 oneConnection = (DBConnection) available.removeFirst(); 775 oneConnection.setAvailable(false); 776 777 778 if (testQuery != null) { 779 try { 780 oneConnection.execute(testQuery); 781 } catch (DBException de) { 782 if (log.isDebugEnabled()) { 783 log.debug("Test query '" + testQuery + 784 "' failed:" + de.getMessage() + 785 ", closing connection & trying again"); 786 } 787 try { 788 oneConnection.disconnect(); 789 } catch (Exception e) { 790 log.error("Unable to close connection that failed " + 791 "test query", e); 792 } 793 794 continue; 798 } 799 } 800 801 if (oneConnection.isClosed()) { 802 if (log.isDebugEnabled()) { 803 log.debug("Dead connection removed " + 804 "from pool. Was previously '" + 805 oneConnection.getDescription() + 806 "'. Currently " + available.size() + 807 " connections available, " + inUse.size() + 808 " clients connected"); 809 } 810 try { 811 oneConnection.disconnect(); 812 } catch (Exception e) { 813 log.warn("Error Disconnecting", e); 815 } finally { 816 oneConnection = null; 820 } 821 continue; 822 } 823 824 if (oneConnection.getCreatedTime() 830 + this.maxttl < System.currentTimeMillis()) { 831 if (log.isInfoEnabled()) { 832 log.info("Discarding connection. Timeout since created time reached"); 833 } 834 835 try { 836 oneConnection.disconnect(); 837 } catch (Exception e) { 838 log.warn("Error Disconnecting", e); 840 } finally { 841 oneConnection = null; 845 } 846 continue; 847 848 } 849 850 851 if (log.isDebugEnabled()) { 852 log.debug("Available connection " + 853 oneConnection.getId() + 854 " found. Was previously '" + 855 oneConnection.getDescription() + 856 "'. Currently " + available.size() + 857 " connections available, " + inUse.size() + 858 " clients connected"); 859 } 860 861 inUse.put(new Integer (oneConnection.getId()), 862 oneConnection); 863 } 864 865 return oneConnection; 866 867 } 868 869 } catch (DBException de) { 870 log.error("Unable to test if connection is closed", de); 871 } 872 873 return null; 874 } 875 876 892 public DBConnection getConnection() 893 throws ConnectionPoolException, PoolFullException, DBException { 894 if (!isInitialized()) { 895 throw new ConnectionPoolException("Connection pool '" + getDataContext() + 896 "' is not initialized. Can't get connection."); 897 } 898 899 900 if (dbDriver == null) { 904 throw new ConnectionPoolException("Cannot make new connection - dbDriver is null"); 905 } 906 if (dbURL == null) { 907 throw new ConnectionPoolException("Cannot make new connection - dbURL is null"); 908 } 909 if (dbConnectFormat == null) { 910 throw new ConnectionPoolException("Cannot make new connection - dbConnectFormat is null"); 911 } 912 913 914 DBConnection oneConnection = null; 915 int connectionTries = 0; 916 int numAvail, numInUse; 917 918 while (connectionTries < GET_CONNECTION_RETRIES) { 919 issuedConnectionsCount++; 924 925 926 if (issuedConnectionsCount >= CLEAN_POOL_MAX) { 927 cleanAvailable(); 928 clean(); 929 issuedConnectionsCount = 0; 930 synchronized (timestampLock) { 932 lastUsed = System.currentTimeMillis(); 933 } 934 } 935 940 if (isTimeToClean()) { 941 cleanAvailable(); 942 clean(); 943 issuedConnectionsCount = 0; 944 synchronized (timestampLock) { 946 lastUsed = System.currentTimeMillis(); 947 } 948 } 949 950 951 synchronized (poolLock) { 952 oneConnection = this.findExistingConnection(); 956 if (oneConnection != null) { 957 oneConnection.setDataContext(getDataContext()); 958 return oneConnection; 959 } 960 961 if (isFull()) { 962 clean(); 963 if (isFull()) { 964 if (log.isInfoEnabled()) { 966 log.info("--------------------------------"); 967 log.info("WARNING: DB Connection Pool '" + getDataContext() + 968 "' is " + "full even after clean."); 969 } 970 971 if (log.isDebugEnabled()) { 972 dumpDebugInfo(); 973 } 974 975 long currentTime = System.currentTimeMillis(); 976 long waitInterval = interval / 2; 981 long finaltime = waitInterval + currentTime; 982 try { 983 while (finaltime > currentTime && isFull()) { 984 985 poolLock.wait(waitInterval); 986 987 if (System.currentTimeMillis() >= finaltime && isFull()) { 988 clean(); 992 if (isFull()) { 993 log.error("Pool '" + getDataContext() + "' still full"); 994 throw new PoolFullException("Cannot allocate " + 996 "another database connection. There are already " + 997 "too many connections in use." + 998 " Please report this problem to the System " + 999 "Administrator"); 1000 } 1001 1002 } else { 1003 oneConnection = findExistingConnection(); 1007 } 1008 1009 if (oneConnection != null) { 1010 if (log.isDebugEnabled()) { 1011 log.debug("Found existing connection after sleep"); 1012 } 1013 1014 oneConnection.setDataContext(getDataContext()); 1015 return oneConnection; 1016 } 1017 1018 currentTime = System.currentTimeMillis(); 1019 } 1020 } catch (InterruptedException ie) { 1021 throw new ConnectionPoolException("Interrupted while waiting for available connection"); 1022 } 1023 1024 } 1025 } 1026 1027 numAvail = available.size(); 1029 numInUse = inUse.size(); 1030 } 1031 1032 1033 if (numAvail + numInUse < this.maxPoolSize) { 1038 oneConnection = createNewConnection(); 1040 1041 if (oneConnection != null) { 1042 return oneConnection; 1043 } 1044 } 1045 1046 1047 if (log.isInfoEnabled()) { 1055 log.info("Couldn't find or create a new connection for this iteration."); 1056 } 1057 1058 synchronized (this) { 1059 connectionTries++; 1060 try { 1061 sleep(1); 1062 } catch (InterruptedException ex) { 1063 log.debug("Interrupted while sleeping", ex); 1064 } 1065 } 1066 1067 } 1068 1069 1070 throw new PoolFullException("Unable to get database connection in " 1071 + GET_CONNECTION_RETRIES + " attempts"); 1072 1073 } 1074 1075 private boolean isTimeToClean() { 1076 long now = System.currentTimeMillis(); 1077 boolean isTimeToClean = false; 1078 1079 synchronized (timestampLock) { 1081 isTimeToClean = now > this.lastUsed + this.interval; 1082 } 1083 return isTimeToClean; 1084 } 1085 1086 1087 1091 protected void dumpDebugInfo() { 1092 if (log.isDebugEnabled()) { 1096 synchronized (poolLock) { 1097 int i = 0; 1098 log.debug("Current contents:"); 1099 for (Iterator conns = inUse.values().iterator(); 1100 conns.hasNext();) { 1101 DBConnection oneConn = (DBConnection) conns.next(); 1102 i++; 1103 Date dt = new Date (oneConn.getLastTouched()); 1104 try { 1105 log.debug("Connection " + i + ":" + 1106 oneConn.getDescription() + ":" + 1107 DateTime.getDateTimeForDB(dt)); 1108 } catch (DBException ex) { 1109 log.error("Error rendering date time object", ex); 1110 } 1111 } 1112 1113 log.debug("Waiting " + (interval / 2000) + 1114 " seconds for a connection to free up"); 1115 } 1116 } 1117 1118 } 1119 1120 1125 protected boolean isFull() { 1126 int inuse, avail; 1127 synchronized (poolLock) { 1128 inuse = inUse.size(); 1129 avail = available.size(); 1130 } 1131 if (log.isDebugEnabled()) { 1132 int totalConnections = avail + inuse; 1133 log.debug("Available connections: " + avail 1134 + " In Use Connections: " + inuse + " totalConnections " + totalConnections); 1135 } 1136 return (inuse >= maxPoolSize); 1137 } 1138 1139 1152 public DBConnection getConnection(String connectionDescrip) 1153 throws DBException { 1154 DBConnection oneConnection = getConnection(); 1155 oneConnection.setDescription(connectionDescrip); 1156 1157 if (log.isDebugEnabled()) { 1158 log.debug("Connection for '" + connectionDescrip + 1159 "' established"); 1160 } 1161 1162 return oneConnection; 1163 } 1164 1165 1166 1171 public String getDBName() { 1172 return dbName; 1173 } 1174 1175 1180 public String getDataContext() { 1181 return dbName; 1182 } 1183 1184 1190 static public boolean supportsTransactions(String connName) 1191 throws DBException { 1192 DBConnectionPool myPool = getInstance(connName); 1193 1194 return myPool.supportsTransactions(); 1195 } 1196 1197 1202 public boolean supportsTransactions() 1203 throws DBException { 1204 return supportsTransactions; 1205 } 1206 1207 1215 static synchronized public DBConnectionPool getInstance(String dataContext) 1216 throws DBException { 1217 1218 synchronized (DBConnectionPool.otherDBPools) { 1219 if (dataContext == null || dataContext.length() == 0) { 1220 dataContext = DBConnection.DEFAULT_DB_CONTEXT_NAME; 1221 } 1222 1223 DBConnectionPool altPool = (DBConnectionPool) otherDBPools.get(dataContext); 1224 1225 if (altPool == null) { 1226 DBConnectionPool newPool = new DBConnectionPool(); 1227 newPool.setDataContext(dataContext); 1228 1229 JDBCConfig myConfig = DBConnectionPool.getJDBCConfig(dataContext); 1230 1231 try { 1232 newPool.setParams(myConfig); 1233 } catch (DBException de) { 1234 throw new ConnectionPoolException("Unable to initialize pool for configuration '" + 1235 dataContext + "':" + de.getMessage(), de); 1236 } 1237 1238 otherDBPools.put(dataContext, newPool); 1239 1240 return newPool; 1241 } 1242 1243 return altPool; 1244 } 1245 } 1246 1247 1248 1260 public static synchronized javax.sql.DataSource getDataSource(String dataContext) 1261 throws java.sql.SQLException { 1262 try { 1263 return new SimpleDataSource(DBConnectionPool.getInstance(dataContext)); 1264 } catch (DBException ex) { 1265 log.error("Error getting database connection pool", ex); 1266 throw new java.sql.SQLException (ex.getMessage()); 1267 } 1268 } 1269 1270 1276 public synchronized ArrayList getPoolList() 1277 throws DBException { 1278 ArrayList al; 1279 synchronized (poolLock) { 1280 al = new ArrayList (available); 1281 for (Iterator it = inUse.values().iterator(); it.hasNext();) { 1282 al.add(it.next()); 1283 } 1284 } 1285 1286 return al; 1287 } 1288 1289 public ArrayList getWildCardsList() { 1290 return new ArrayList (wildCards); 1291 } 1292 1293 1299 public boolean isInitialized() { 1300 return initialized; 1301 } 1302 1303 1311 public void release(DBConnection connectionToRelease) { 1312 if (connectionToRelease == null) { 1313 return; 1314 } 1315 1321 try { 1322 if (!connectionToRelease.getAutoCommit()) { 1323 connectionToRelease.setAutoCommit(true); 1324 } 1325 1326 connectionToRelease.clear(); 1327 } catch (DBException dbe) { 1328 if (log.isDebugEnabled()) { 1329 log.debug("Error setting auto-commit to true", dbe); 1330 } 1331 1332 1333 } 1334 if (connectionToRelease.isAvailable()) { 1335 return; 1336 } 1337 if (log.isDebugEnabled()) { 1338 log.debug("Releasing connection " + connectionToRelease.getId() + 1339 " '" + connectionToRelease.getDescription() + "'"); 1340 } 1341 synchronized (poolLock) { 1342 if (inUse.remove(new Integer (connectionToRelease.getId())) == null) { 1343 if (log.isDebugEnabled()) { 1344 log.debug("Connection " + connectionToRelease.getId() + 1345 " was not listed as " + 1346 "in use and could not be released"); 1347 } 1348 1349 return; 1350 } 1351 connectionToRelease.setAvailable(true); 1352 available.add(connectionToRelease); 1353 poolLock.notify(); 1354 } 1355 1356 1357 if (log.isDebugEnabled()) { 1358 log.debug("Connection " + connectionToRelease.getId() + " '" + 1359 connectionToRelease.getDescription() + 1360 "' released back to pool. Now " + inUse.size() + 1361 " connected"); 1362 } 1363 } 1364 1365 1370 public int getMaxConnections() { 1371 return maxPoolSize; 1372 } 1373 1374 1379 public synchronized void setMaxConnections(int newMax) 1380 throws DBException { 1381 maxPoolSize = newMax; 1382 } 1383 1384 1385 1390 protected synchronized void setDBName(String newDBName) { 1391 if (StringUtil.notNull(newDBName).equals("")) { 1392 newDBName = DBConnection.DEFAULT_DB_CONTEXT_NAME; 1393 } 1394 1395 dbName = newDBName; 1396 } 1397 1398 1403 protected synchronized void setDataContext(String newDBName) { 1404 if (StringUtil.notNull(newDBName).equals("")) { 1405 newDBName = DBConnection.DEFAULT_DB_CONTEXT_NAME; 1406 } 1407 1408 dbName = newDBName; 1409 } 1410 1411 1421 private synchronized void setParams(JDBCConfig theParams) throws DBException { 1422 String myName = (THIS_CLASS + 1423 "setParams(String, String, String, String, String)"); 1424 dbDriverType = theParams.getDriverType(); 1425 dbDriver = theParams.getDriver(); 1426 dbURL = theParams.getUrl(); 1427 dbConnectFormat = theParams.getConnectFormat(); 1428 dbLogin = theParams.getLogin(); 1429 dbPassword = theParams.getPassword(); 1430 1431 1432 if (dbDriverType == null) { 1433 dbDriverType = ("manager"); 1434 } 1435 1436 if (dbDriver == null) { 1437 throw new ConnectionPoolException(myName + ":Database driver name cannot be " + 1438 "null"); 1439 } 1440 if (dbURL == null) { 1441 throw new ConnectionPoolException(myName + ":Database URL cannot be null"); 1442 } 1443 if (dbConnectFormat == null) { 1444 throw new ConnectionPoolException(myName + ":Database connection format " + 1445 "cannot be null"); 1446 } 1447 if (dbLogin == null) { 1448 throw new ConnectionPoolException(myName + ":Database login cannot be null"); 1449 } 1450 if (dbPassword == null) { 1451 throw new ConnectionPoolException(myName + 1452 ":Database password cannot be null"); 1453 } 1454 1455 try { 1456 escapeHandler = (EscapeHandler) ClassLocator.loadClass(theParams 1457 .getEscapeHandler()).newInstance(); 1458 } catch (Exception ex) { 1459 log.warn("Error instantiating escape handler " + theParams.getEscapeHandler()); 1460 escapeHandler = new DefaultEscapeHandler(); 1463 } 1464 1465 if (dbDriverType.equalsIgnoreCase("datasource")) { 1471 if (this.getJNDIConfig(theParams) == null) { 1472 throw new ConnectionPoolException(myName + "JNDI info configure for datasource"); 1473 } 1474 1475 try { 1476 jndiDS = new JndiDataSource(this.getJNDIConfig(theParams), theParams.getUrl()); 1477 jndiDS.setupContext(); 1478 } catch (DSException dse) { 1479 throw new ConnectionPoolException(myName + ":Cannot initialize jndi Context Factory"); 1480 } 1481 } 1482 1483 initialized = true; 1484 } 1485 1486 1487 1492 public synchronized void setTestQuery(String newTestQuery) { 1493 testQuery = newTestQuery; 1494 } 1495 1496 1497 1506 public synchronized void setTimeOutInterval(int newInterval) 1507 throws DBException { 1508 1509 if (newInterval < 1) { 1510 String myName = (THIS_CLASS + "setTimeOutInterval(int)"); 1511 throw new ConnectionPoolException(myName + ":Interval must be greater than 0"); 1512 } 1513 1514 interval = (long) newInterval * 1000; 1515 maxttl = interval * 10; 1516 } 1517 1518 1519 1522 private synchronized void setWildCards() throws DBException { 1523 boolean propsFound = false; 1524 1525 JDBCConfig myConfig = getJDBCConfig(this.getDataContext()); 1526 1527 for (Enumeration e = myConfig.getWildcards().elements(); 1528 e.hasMoreElements();) { 1529 propsFound = true; 1530 wildCards.add(e.nextElement()); 1531 } 1532 1540 if (!propsFound) { 1541 1542 for (Iterator it = getDefaultWildCards().iterator(); 1545 it.hasNext();) { 1546 wildCards.add(it.next()); 1547 } 1548 } 1549 } 1550 1551 1552 1555 public synchronized static void reInitialize() 1556 throws DBException { 1557 synchronized (otherDBPools) { 1558 1559 for (Iterator it = otherDBPools.values().iterator(); it.hasNext();) { 1560 DBConnectionPool onePool = (DBConnectionPool) it.next(); 1561 onePool.disconnectAll(); 1562 } 1563 1564 otherDBPools = new HashMap (); 1565 System.gc(); 1566 } 1567 } 1568 1569 1570 1578 public synchronized int getLimitationPosition() { 1579 return limitationPosition; 1580 } 1581 1582 1589 public synchronized void setLimitationPosition(int pos) 1590 throws DBException { 1591 if (pos != LIMITATION_DISABLED && pos != LIMITATION_AFTER_TABLE && 1592 pos != LIMITATION_AFTER_WHERE && 1593 pos != LIMITATION_AFTER_ORDER_BY && 1594 pos != LIMITATION_AFTER_SELECT) { 1595 throw new ConnectionPoolException("illegal argument for limitation optimisation position"); 1596 } 1597 1598 this.limitationPosition = pos; 1599 } 1600 1601 1602 1610 public synchronized void setLimitationPosition(String pos) { 1611 if (pos.equalsIgnoreCase("LIMITATION_DISABLED")) { 1612 this.limitationPosition = LIMITATION_DISABLED; 1613 } else if (pos.equalsIgnoreCase("LIMITATION_AFTER_TABLE")) { 1614 this.limitationPosition = LIMITATION_AFTER_TABLE; 1615 } else if (pos.equalsIgnoreCase("LIMITATION_AFTER_WHERE")) { 1616 this.limitationPosition = LIMITATION_AFTER_WHERE; 1617 } else if (pos.equalsIgnoreCase("LIMITATION_AFTER_ORDER_BY")) { 1618 this.limitationPosition = LIMITATION_AFTER_ORDER_BY; 1619 } else if (pos.equalsIgnoreCase("LIMITATION_AFTER_SELECT")) { 1620 this.limitationPosition = LIMITATION_AFTER_SELECT; 1621 } else { 1622 log.warn("DB Object '" + getClass().getName() + 1623 "' illegal string argument for limitation optimisation position."); 1624 } 1625 } 1626 1627 1635 public synchronized String getLimitationSyntax() { 1636 return limitationSyntax; 1637 } 1638 1639 1646 public synchronized EscapeHandler getEscapeHandler() { 1647 return this.escapeHandler; 1648 } 1649 1650 1658 public synchronized void setLimitationSyntax(String syntax) { 1659 this.limitationSyntax = syntax; 1660 } 1661 1662 1679 public void setDistinctRowsetKeyword(String keyword) { 1680 uniqueRowKeyword = keyword; 1681 } 1682 1683 1695 public String getDistinctRowsetKeyword() { 1696 return uniqueRowKeyword; 1697 } 1698 1699 1705 public void setCheckZeroUpdate(boolean newValue) { 1706 String myName = (THIS_CLASS + "setCheckZeroUpdate() "); 1707 System.out.println(myName + " newValue:" + newValue); 1708 this.checkZeroUpdate = newValue; 1709 } 1710 1711 1718 public boolean getCheckZeroUpdate() { 1719 return this.checkZeroUpdate; 1720 } 1721 1722 1723 1733 protected JNDIConfig getJNDIConfig(JDBCConfig curConfig) throws ConnectionPoolException { 1734 if (curConfig instanceof com.jcorporate.expresso.core.misc.ConfigJdbc) { 1735 return ((com.jcorporate.expresso.core.misc.ConfigJdbc) curConfig).getMyJndi(); 1736 } else { 1737 RootContainerInterface runtime = ExpressoRuntimeMap.getDefaultRuntime(); 1738 LocatorUtils lc = new LocatorUtils(runtime); 1739 JNDIConfig manager = (JNDIConfig) lc 1740 .locateComponent(this.getDataContext() + ".PersistenceManager.JNDIConfig"); 1741 if (manager == null) { 1742 throw new ConnectionPoolException( 1743 "Unable to locate PersistenceManager for data context: " + this.getDataContext()); 1744 } 1745 return null; 1746 } 1747 } 1748 1749 1757 static protected JDBCConfig getJDBCConfig(String dataContext) throws ConnectionPoolException { 1758 RootContainerInterface runtime = ExpressoRuntimeMap.getDefaultRuntime(); 1759 1760 if (runtime == null) { 1762 try { 1763 return ConfigManager.getJdbcRequired(dataContext); 1764 } catch (ConfigurationException ex) { 1765 throw new ConnectionPoolException("Unable to get Database Configuration Information for context " 1766 + dataContext, ex); 1767 } 1768 } else { 1769 LocatorUtils lc = new LocatorUtils(runtime); 1770 PersistenceManager manager = (PersistenceManager) lc.locateComponent(dataContext + ".PersistenceManager"); 1771 if (manager == null) { 1772 throw new ConnectionPoolException( 1773 "Unable to locate PersistenceManager component for data context " + dataContext); 1774 } 1775 1776 return manager.getDBConfig().getCurrentConfig(); 1777 } 1778 } 1779 1780 1787 public ArrayList getDefaultWildCards() { 1788 ArrayList newChars = new ArrayList (4); 1789 newChars.add(("%")); 1790 newChars.add(("_")); 1791 newChars.add(("[")); 1792 newChars.add(("]")); 1793 1794 return newChars; 1795 } 1796} 1797 | Popular Tags |