Source Code Cross Referenced for DbConnectionDefaultPool.java in  » Forum » yazd » com » Yasna » forum » database » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Forum » yazd » com.Yasna.forum.database 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /**
0002:         * Copyright (C) 2001 Yasna.com. All rights reserved.
0003:         *
0004:         * ===================================================================
0005:         * The Apache Software License, Version 1.1
0006:         *
0007:         * Redistribution and use in source and binary forms, with or without
0008:         * modification, are permitted provided that the following conditions
0009:         * are met:
0010:         *
0011:         * 1. Redistributions of source code must retain the above copyright
0012:         *    notice, this list of conditions and the following disclaimer.
0013:         *
0014:         * 2. Redistributions in binary form must reproduce the above copyright
0015:         *    notice, this list of conditions and the following disclaimer in
0016:         *    the documentation and/or other materials provided with the
0017:         *    distribution.
0018:         *
0019:         * 3. The end-user documentation included with the redistribution,
0020:         *    if any, must include the following acknowledgment:
0021:         *       "This product includes software developed by
0022:         *        Yasna.com (http://www.yasna.com)."
0023:         *    Alternately, this acknowledgment may appear in the software itself,
0024:         *    if and wherever such third-party acknowledgments normally appear.
0025:         *
0026:         * 4. The names "Yazd" and "Yasna.com" must not be used to
0027:         *    endorse or promote products derived from this software without
0028:         *    prior written permission. For written permission, please
0029:         *    contact yazd@yasna.com.
0030:         *
0031:         * 5. Products derived from this software may not be called "Yazd",
0032:         *    nor may "Yazd" appear in their name, without prior written
0033:         *    permission of Yasna.com.
0034:         *
0035:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0036:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0037:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0038:         * DISCLAIMED.  IN NO EVENT SHALL YASNA.COM OR
0039:         * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0040:         * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0041:         * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0042:         * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0043:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0044:         * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0045:         * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0046:         * SUCH DAMAGE.
0047:         * ====================================================================
0048:         *
0049:         * This software consists of voluntary contributions made by many
0050:         * individuals on behalf of Yasna.com. For more information
0051:         * on Yasna.com, please see <http://www.yasna.com>.
0052:         */
0053:
0054:        /**
0055:         * Copyright (C) 2000 CoolServlets.com. All rights reserved.
0056:         *
0057:         * ===================================================================
0058:         * The Apache Software License, Version 1.1
0059:         *
0060:         * Redistribution and use in source and binary forms, with or without
0061:         * modification, are permitted provided that the following conditions
0062:         * are met:
0063:         *
0064:         * 1. Redistributions of source code must retain the above copyright
0065:         *    notice, this list of conditions and the following disclaimer.
0066:         *
0067:         * 2. Redistributions in binary form must reproduce the above copyright
0068:         *    notice, this list of conditions and the following disclaimer in
0069:         *    the documentation and/or other materials provided with the
0070:         *    distribution.
0071:         *
0072:         * 3. The end-user documentation included with the redistribution,
0073:         *    if any, must include the following acknowledgment:
0074:         *       "This product includes software developed by
0075:         *        CoolServlets.com (http://www.coolservlets.com)."
0076:         *    Alternately, this acknowledgment may appear in the software itself,
0077:         *    if and wherever such third-party acknowledgments normally appear.
0078:         *
0079:         * 4. The names "Jive" and "CoolServlets.com" must not be used to
0080:         *    endorse or promote products derived from this software without
0081:         *    prior written permission. For written permission, please
0082:         *    contact webmaster@coolservlets.com.
0083:         *
0084:         * 5. Products derived from this software may not be called "Jive",
0085:         *    nor may "Jive" appear in their name, without prior written
0086:         *    permission of CoolServlets.com.
0087:         *
0088:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0089:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0090:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0091:         * DISCLAIMED.  IN NO EVENT SHALL COOLSERVLETS.COM OR
0092:         * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0093:         * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0094:         * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0095:         * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0096:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0097:         * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0098:         * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0099:         * SUCH DAMAGE.
0100:         * ====================================================================
0101:         *
0102:         * This software consists of voluntary contributions made by many
0103:         * individuals on behalf of CoolServlets.com. For more information
0104:         * on CoolServlets.com, please see <http://www.coolservlets.com>.
0105:         */package com.Yasna.forum.database;
0106:
0107:        import java.sql.*;
0108:        import java.util.*;
0109:        import java.io.*;
0110:        import java.text.*;
0111:        import java.util.Date;
0112:        import com.Yasna.forum.*;
0113:
0114:        /**
0115:         * Default Yazd connection provider. It uses the excellent connection pool
0116:         * available from http://www.javaexchange.com. This connection provider is a
0117:         * a good choice unless you can use a container-managed one.
0118:         */
0119:        public class DbConnectionDefaultPool extends DbConnectionProvider {
0120:
0121:            private static final String NAME = "Default Connection Pool";
0122:            private static final String DESCRIPTION = "The default connection provider "
0123:                    + "that uses the connection pool from javaexchange.com. It works with "
0124:                    + "almost any database setup, is customizable, and offers good performance. "
0125:                    + "Use this connection provider unless you have your own or can use a "
0126:                    + "container managed connection pool.";
0127:            private static final String AUTHOR = "Yazd.Yasna.com";
0128:            private static final int MAJOR_VERSION = 1;
0129:            private static final int MINOR_VERSION = 0;
0130:            private static final boolean POOLED = true;
0131:
0132:            private ConnectionPool connectionPool = null;
0133:            private Properties props;
0134:            private Properties propDescriptions;
0135:
0136:            private Object initLock = new Object();
0137:
0138:            public DbConnectionDefaultPool() {
0139:                //this.manager = manager;
0140:                props = new Properties();
0141:                propDescriptions = new Properties();
0142:                //Initialize all property values
0143:                initializeProperties();
0144:                //Load any existing property values
0145:                loadProperties();
0146:            }
0147:
0148:            /**
0149:             * Returns a database connection.
0150:             */
0151:            public Connection getConnection() {
0152:                if (connectionPool == null) {
0153:                    //block until the init has been done
0154:                    synchronized (initLock) {
0155:                        //if still null, something has gone wrong
0156:                        if (connectionPool == null) {
0157:                            System.err
0158:                                    .println("Warning: DbConnectionDefaultPool.getConnection() was "
0159:                                            + "called when the internal pool has not been initialized.");
0160:                            return null;
0161:                        }
0162:                    }
0163:                }
0164:                return new ConnectionWrapper(connectionPool.getConnection(),
0165:                        connectionPool);
0166:            }
0167:
0168:            /**
0169:             * Starts the pool.
0170:             */
0171:            protected void start() {
0172:                //acquire lock so that no connections can be returned.
0173:                synchronized (initLock) {
0174:                    //Get properties
0175:                    String driver = props.getProperty("driver");
0176:                    String server = props.getProperty("server");
0177:                    String username = props.getProperty("username");
0178:                    String password = props.getProperty("password");
0179:                    int minConnections = 0, maxConnections = 0;
0180:                    double connectionTimeout = 0.0;
0181:                    try {
0182:                        minConnections = Integer.parseInt(props
0183:                                .getProperty("minConnections"));
0184:                        maxConnections = Integer.parseInt(props
0185:                                .getProperty("maxConnections"));
0186:                        connectionTimeout = Double.parseDouble(props
0187:                                .getProperty("connectionTimeout"));
0188:                    } catch (Exception e) {
0189:                        System.err
0190:                                .println("Error: could not parse default pool properties. "
0191:                                        + "Make sure the values exist and are correct.");
0192:                        e.printStackTrace();
0193:                        return;
0194:                    }
0195:                    String logPath = props.getProperty("logPath");
0196:
0197:                    try {
0198:                        connectionPool = new ConnectionPool(driver, server,
0199:                                username, password, minConnections,
0200:                                maxConnections, logPath, connectionTimeout);
0201:                    } catch (IOException ioe) {
0202:                        System.err
0203:                                .println("Error starting DbConnectionDefaultPool: "
0204:                                        + ioe);
0205:                        ioe.printStackTrace();
0206:                    }
0207:                }
0208:            }
0209:
0210:            /**
0211:             * Restarts the pool to take into account any property changes.
0212:             */
0213:            protected void restart() {
0214:                //Kill off pool.
0215:                destroy();
0216:                //Reload properties.
0217:                loadProperties();
0218:                //Start a new pool.
0219:                start();
0220:            }
0221:
0222:            /**
0223:             * Destroys the connection pool.
0224:             */
0225:            protected void destroy() {
0226:                if (connectionPool != null) {
0227:                    try {
0228:                        connectionPool.destroy(1);
0229:                    } catch (Exception e) {
0230:                        e.printStackTrace();
0231:                    }
0232:                }
0233:                //Release reference to connectionPool
0234:                connectionPool = null;
0235:            }
0236:
0237:            /**
0238:             * Returns the value of a property of the connection provider.
0239:             *
0240:             * @param name the name of the property.
0241:             * @returns the value of the property.
0242:             */
0243:            public String getProperty(String name) {
0244:                return (String) props.get(name);
0245:            }
0246:
0247:            /**
0248:             * Returns the description of a property of the connection provider.
0249:             *
0250:             * @param name the name of the property.
0251:             * @return the description of the property.
0252:             */
0253:            public String getPropertyDescription(String name) {
0254:                return (String) propDescriptions.get(name);
0255:            }
0256:
0257:            /**
0258:             * Returns an enumeration of the property names for the connection provider.
0259:             */
0260:            public Enumeration propertyNames() {
0261:                return props.propertyNames();
0262:            }
0263:
0264:            /**
0265:             * Sets a property of the connection provider. Each provider has a set number
0266:             * of properties that are determined by the author. Trying to set a non-
0267:             * existant property will result in an IllegalArgumentException.
0268:             *
0269:             * @param name the name of the property to set.
0270:             * @param value the new value for the property.
0271:             *
0272:             */
0273:            public void setProperty(String name, String value) {
0274:                props.put(name, value);
0275:                saveProperties();
0276:            }
0277:
0278:            /**
0279:             * Give default values to all the properties and descriptions.
0280:             */
0281:            private void initializeProperties() {
0282:                props.put("driver", "");
0283:                props.put("server", "");
0284:                props.put("username", "");
0285:                props.put("password", "");
0286:                props.put("minConnections", "");
0287:                props.put("maxConnections", "");
0288:                props.put("logPath", "");
0289:                props.put("connectionTimeout", "");
0290:
0291:                propDescriptions.put("driver",
0292:                        "JDBC driver. e.g. 'oracle.jdbc.driver.OracleDriver'");
0293:                propDescriptions
0294:                        .put("server",
0295:                                "JDBC connect string. e.g. 'jdbc:oracle:thin:@203.92.21.109:1526:orcl'");
0296:                propDescriptions.put("username",
0297:                        "Database username. e.g. 'Scott'");
0298:                propDescriptions.put("password",
0299:                        "Database password. e.g. 'Tiger'");
0300:                propDescriptions
0301:                        .put(
0302:                                "minConnections",
0303:                                "Minimum # of connections to start with in pool. Three is the recommended minimum");
0304:                propDescriptions
0305:                        .put(
0306:                                "maxConnections",
0307:                                "Maximum # of connections in dynamic pool. Fifteen should give good performance for an average load.");
0308:                propDescriptions
0309:                        .put("logPath",
0310:                                "Absolute path name for log file. e.g. 'c:\\logs\\yazdDbLog.log'");
0311:                propDescriptions.put("connectionTimeout",
0312:                        "Time in days between connection resets. e.g. '.5'");
0313:            }
0314:
0315:            /**
0316:             * Load whatever properties that already exist.
0317:             */
0318:            private void loadProperties() {
0319:                String driver = PropertyManager
0320:                        .getProperty("DbConnectionDefaultPool.driver");
0321:                String server = PropertyManager
0322:                        .getProperty("DbConnectionDefaultPool.server");
0323:                String username = PropertyManager
0324:                        .getProperty("DbConnectionDefaultPool.username");
0325:                String password = PropertyManager
0326:                        .getProperty("DbConnectionDefaultPool.password");
0327:                String minConnections = PropertyManager
0328:                        .getProperty("DbConnectionDefaultPool.minConnections");
0329:                String maxConnections = PropertyManager
0330:                        .getProperty("DbConnectionDefaultPool.maxConnections");
0331:                String logPath = PropertyManager
0332:                        .getProperty("DbConnectionDefaultPool.logPath");
0333:                String connectionTimeout = PropertyManager
0334:                        .getProperty("DbConnectionDefaultPool.connectionTimeout");
0335:
0336:                if (driver != null) {
0337:                    props.setProperty("driver", driver);
0338:                }
0339:                if (server != null) {
0340:                    props.setProperty("server", server);
0341:                }
0342:                if (username != null) {
0343:                    props.setProperty("username", username);
0344:                }
0345:                if (password != null) {
0346:                    props.setProperty("password", password);
0347:                }
0348:                if (minConnections != null) {
0349:                    props.setProperty("minConnections", minConnections);
0350:                }
0351:                if (maxConnections != null) {
0352:                    props.setProperty("maxConnections", maxConnections);
0353:                }
0354:                if (logPath != null) {
0355:                    props.setProperty("logPath", logPath);
0356:                }
0357:                if (connectionTimeout != null) {
0358:                    props.setProperty("connectionTimeout", connectionTimeout);
0359:                }
0360:            }
0361:
0362:            private void saveProperties() {
0363:                PropertyManager.setProperty("DbConnectionDefaultPool.driver",
0364:                        props.getProperty("driver"));
0365:                PropertyManager.setProperty("DbConnectionDefaultPool.server",
0366:                        props.getProperty("server"));
0367:                PropertyManager.setProperty("DbConnectionDefaultPool.username",
0368:                        props.getProperty("username"));
0369:                PropertyManager.setProperty("DbConnectionDefaultPool.password",
0370:                        props.getProperty("password"));
0371:                PropertyManager.setProperty(
0372:                        "DbConnectionDefaultPool.minConnections", props
0373:                                .getProperty("minConnections"));
0374:                PropertyManager.setProperty(
0375:                        "DbConnectionDefaultPool.maxConnections", props
0376:                                .getProperty("maxConnections"));
0377:                PropertyManager.setProperty("DbConnectionDefaultPool.logPath",
0378:                        props.getProperty("logPath"));
0379:                PropertyManager.setProperty(
0380:                        "DbConnectionDefaultPool.connectionTimeout", props
0381:                                .getProperty("connectionTimeout"));
0382:            }
0383:
0384:            /**
0385:             * DbConnectionBroker
0386:             * @version 1.0.11 12/7/99
0387:             * @author Marc A. Mnich
0388:             *
0389:             * ----------------------------------------
0390:             * Modified June 18, 2000 by Matt Tucker
0391:             *   Changes:
0392:             *     - New package name, class name to make it nice to embed as
0393:             *        an internal class.
0394:             *     - Source code reformatting.
0395:             *     - Added more error handling code in constructor, createConn method
0396:             *       so that more information is given to Yazd users.
0397:             * DbConnectionBroker rules! Download it from javaexchange.com
0398:             * ----------------------------------------
0399:             *
0400:             * DbConnectionBroker
0401:             * A servlet-based broker for database connections.
0402:             * Creates and manages a pool of database connections.
0403:             * @version 1.0.11 12/7/99
0404:             * @author Marc A. Mnich
0405:             */
0406:            private class ConnectionPool implements  Runnable {
0407:                private Thread runner;
0408:
0409:                private Connection[] connPool;
0410:                private int[] connStatus;
0411:
0412:                private long[] connLockTime, connCreateDate;
0413:                private String[] connID;
0414:                private String dbDriver, dbServer, dbLogin, dbPassword,
0415:                        logFileString;
0416:                private int currConnections, connLast, minConns, maxConns,
0417:                        maxConnMSec;
0418:
0419:                //available: set to false on destroy, checked by getConnection()
0420:                private boolean available = true;
0421:
0422:                private PrintWriter log;
0423:                private SQLWarning currSQLWarning;
0424:                private String pid;
0425:
0426:                /**
0427:                 * Creates a new Connection Broker<br>
0428:                 * dbDriver:        JDBC driver. e.g. 'oracle.jdbc.driver.OracleDriver'<br>
0429:                 * dbServer:        JDBC connect string. e.g. 'jdbc:oracle:thin:@203.92.21.109:1526:orcl'<br>
0430:                 * dbLogin:         Database login name.  e.g. 'Scott'<br>
0431:                 * dbPassword:      Database password.    e.g. 'Tiger'<br>
0432:                 * minConns:        Minimum number of connections to start with.<br>
0433:                 * maxConns:        Maximum number of connections in dynamic pool.<br>
0434:                 * logFileString:   Absolute path name for log file. e.g. 'c:\temp\mylog.log' <br>
0435:                 * maxConnTime:     Time in days between connection resets. (Reset does a basic cleanup)<br>
0436:                 */
0437:                public ConnectionPool(String dbDriver, String dbServer,
0438:                        String dbLogin, String dbPassword, int minConns,
0439:                        int maxConns, String logFileString, double maxConnTime)
0440:                        throws IOException {
0441:                    connPool = new Connection[maxConns];
0442:                    connStatus = new int[maxConns];
0443:                    connLockTime = new long[maxConns];
0444:                    connCreateDate = new long[maxConns];
0445:                    connID = new String[maxConns];
0446:                    currConnections = minConns;
0447:                    this .maxConns = maxConns;
0448:                    this .dbDriver = dbDriver;
0449:                    this .dbServer = dbServer;
0450:                    this .dbLogin = dbLogin;
0451:                    this .dbPassword = dbPassword;
0452:                    this .logFileString = logFileString;
0453:                    maxConnMSec = (int) (maxConnTime * 86400000.0); //86400 sec/day
0454:                    if (maxConnMSec < 30000) { // Recycle no less than 30 seconds.
0455:                        maxConnMSec = 30000;
0456:                    }
0457:
0458:                    try {
0459:                        log = new PrintWriter(new FileOutputStream(
0460:                                logFileString), true);
0461:                        // Can't open the requested file. Open the default file.
0462:                    } catch (IOException e1) {
0463:                        System.err
0464:                                .println("Warning: DbConnectionDefaultPool could not open \""
0465:                                        + logFileString
0466:                                        + "\" to write log to. Make sure that your Java "
0467:                                        + "process has permission to write to the file and that the directory exists.");
0468:                        try {
0469:                            log = new PrintWriter(new FileOutputStream("DCB_"
0470:                                    + System.currentTimeMillis() + ".log"),
0471:                                    true);
0472:                        } catch (IOException e2) {
0473:                            throw new IOException("Can't open any log file");
0474:                        }
0475:                    }
0476:
0477:                    // Write the pid file (used to clean up dead/broken connection)
0478:                    SimpleDateFormat formatter = new SimpleDateFormat(
0479:                            "yyyy.MM.dd G 'at' hh:mm:ss a zzz");
0480:                    java.util.Date nowc = new java.util.Date();
0481:                    pid = formatter.format(nowc);
0482:
0483:                    BufferedWriter pidout = new BufferedWriter(new FileWriter(
0484:                            logFileString + "pid"));
0485:                    pidout.write(pid);
0486:                    pidout.close();
0487:
0488:                    log.println("Starting ConnectionPool:");
0489:                    log.println("dbDriver = " + dbDriver);
0490:                    log.println("dbServer = " + dbServer);
0491:                    log.println("dbLogin = " + dbLogin);
0492:                    log.println("log file = " + logFileString);
0493:                    log.println("minconnections = " + minConns);
0494:                    log.println("maxconnections = " + maxConns);
0495:                    log.println("Total refresh interval = " + maxConnTime
0496:                            + " days");
0497:                    log.println("-----------------------------------------");
0498:
0499:                    // Initialize the pool of connections with the mininum connections:
0500:                    // Problems creating connections may be caused during reboot when the
0501:                    //    servlet is started before the database is ready.  Handle this
0502:                    //    by waiting and trying again.  The loop allows 5 minutes for
0503:                    //    db reboot.
0504:                    boolean connectionsSucceeded = false;
0505:                    int dbLoop = 20;
0506:
0507:                    try {
0508:                        for (int i = 1; i < dbLoop; i++) {
0509:                            try {
0510:                                for (int j = 0; j < currConnections; j++) {
0511:                                    createConn(j);
0512:                                }
0513:                                connectionsSucceeded = true;
0514:                                break;
0515:                            } catch (SQLException e) {
0516:                                log
0517:                                        .println("--->Attempt ("
0518:                                                + String.valueOf(i)
0519:                                                + " of "
0520:                                                + String.valueOf(dbLoop)
0521:                                                + ") failed to create new connections set at startup: ");
0522:                                log.println("    " + e);
0523:                                log
0524:                                        .println("    Will try again in 15 seconds...");
0525:                                try {
0526:                                    Thread.sleep(15000);
0527:                                } catch (InterruptedException e1) {
0528:                                }
0529:                            }
0530:                        }
0531:                        if (!connectionsSucceeded) { // All attempts at connecting to db exhausted
0532:                            log
0533:                                    .println("\r\nAll attempts at connecting to Database exhausted");
0534:                            throw new IOException();
0535:                        }
0536:                    } catch (Exception e) {
0537:                        e.printStackTrace();
0538:                        throw new IOException();
0539:                    }
0540:
0541:                    // Fire up the background housekeeping thread
0542:
0543:                    runner = new Thread(this );
0544:                    runner.start();
0545:
0546:                } //End ConnectionPool()
0547:
0548:                /**
0549:                 * Housekeeping thread.  Runs in the background with low CPU overhead.
0550:                 * Connections are checked for warnings and closure and are periodically
0551:                 * restarted.
0552:                 * This thread is a catchall for corrupted
0553:                 * connections and prevents the buildup of open cursors. (Open cursors
0554:                 * result when the application fails to close a Statement).
0555:                 * This method acts as fault tolerance for bad connection/statement programming.
0556:                 */
0557:                public void run() {
0558:                    boolean forever = true;
0559:                    Statement stmt = null;
0560:                    String currCatalog = null;
0561:
0562:                    while (forever) {
0563:                        // Make sure the log file is the one this instance opened
0564:                        // If not, clean it up!
0565:                        try {
0566:                            BufferedReader in = new BufferedReader(
0567:                                    new FileReader(logFileString + "pid"));
0568:                            String curr_pid = in.readLine();
0569:                            if (curr_pid.equals(pid)) {
0570:                                //log.println("They match = " + curr_pid);
0571:                            } else {
0572:                                //log.println("No match = " + curr_pid);
0573:                                log.close();
0574:
0575:                                // Close all connections silently - they are definitely dead.
0576:                                for (int i = 0; i < currConnections; i++) {
0577:                                    try {
0578:                                        connPool[i].close();
0579:                                    } catch (SQLException e1) {
0580:                                    } // ignore
0581:                                }
0582:                                // Returning from the run() method kills the thread
0583:                                return;
0584:                            }
0585:                            in.close();
0586:                        } catch (IOException e1) {
0587:                            log.println("Can't read the file for pid info: "
0588:                                    + logFileString + "pid");
0589:                        }
0590:
0591:                        // Get any Warnings on connections and print to event file
0592:                        for (int i = 0; i < currConnections; i++) {
0593:                            try {
0594:                                currSQLWarning = connPool[i].getWarnings();
0595:                                if (currSQLWarning != null) {
0596:                                    log.println("Warnings on connection "
0597:                                            + String.valueOf(i) + " "
0598:                                            + currSQLWarning);
0599:                                    connPool[i].clearWarnings();
0600:                                }
0601:                            } catch (SQLException e) {
0602:                                log.println("Cannot access Warnings: " + e);
0603:                            }
0604:                        }
0605:
0606:                        for (int i = 0; i < currConnections; i++) { // Do for each connection
0607:                            long age = System.currentTimeMillis()
0608:                                    - connCreateDate[i];
0609:
0610:                            synchronized (connStatus) {
0611:                                if (connStatus[i] > 0) { // In use, catch it next time!
0612:                                    continue;
0613:                                }
0614:                                connStatus[i] = 2; // Take offline (2 indicates housekeeping lock)
0615:                            }
0616:
0617:                            try { // Test the connection with createStatement call
0618:                                if (age > maxConnMSec) { // Force a reset at the max conn time
0619:                                    throw new SQLException();
0620:                                }
0621:
0622:                                stmt = connPool[i].createStatement();
0623:                                connStatus[i] = 0; // Connection is O.K.
0624:                                //log.println("Connection confirmed for conn = " +
0625:                                //             String.valueOf(i));
0626:
0627:                                // Some DBs return an object even if DB is shut down
0628:                                if (connPool[i].isClosed()) {
0629:                                    throw new SQLException();
0630:                                }
0631:                                // Connection has a problem, restart it
0632:                            } catch (SQLException e) {
0633:                                try {
0634:                                    log.println(new Date().toString()
0635:                                            + " ***** Recycling connection "
0636:                                            + String.valueOf(i) + ":");
0637:
0638:                                    connPool[i].close();
0639:                                    createConn(i);
0640:                                } catch (SQLException e1) {
0641:                                    log.println("Failed: " + e1);
0642:                                    connStatus[i] = 0; // Can't open, try again next time
0643:                                }
0644:                            } finally {
0645:                                try {
0646:                                    if (stmt != null) {
0647:                                        stmt.close();
0648:                                    }
0649:                                } catch (SQLException e1) {
0650:                                }
0651:                                ;
0652:                            }
0653:                        }
0654:
0655:                        try {
0656:                            Thread.sleep(20000);
0657:                        } // Wait 20 seconds for next cycle
0658:                        catch (InterruptedException e) {
0659:                            // Returning from the run method sets the internal
0660:                            // flag referenced by Thread.isAlive() to false.
0661:                            // This is required because we don't use stop() to
0662:                            // shutdown this thread.
0663:                            return;
0664:                        }
0665:                    }
0666:                } // End run
0667:
0668:                /**
0669:                 * This method hands out the connections in round-robin order.
0670:                 * This prevents a faulty connection from locking
0671:                 * up an application entirely.  A browser 'refresh' will
0672:                 * get the next connection while the faulty
0673:                 * connection is cleaned up by the housekeeping thread.
0674:                 *
0675:                 * If the min number of threads are ever exhausted, new
0676:                 * threads are added up the the max thread count.
0677:                 * Finally, if all threads are in use, this method waits
0678:                 * 2 seconds and tries again, up to ten times.  After that, it
0679:                 * returns a null.
0680:                 */
0681:                public Connection getConnection() {
0682:
0683:                    Connection conn = null;
0684:
0685:                    if (available) {
0686:                        boolean gotOne = false;
0687:
0688:                        for (int outerloop = 1; outerloop <= 10; outerloop++) {
0689:
0690:                            try {
0691:                                int loop = 0;
0692:                                int roundRobin = connLast + 1;
0693:                                if (roundRobin >= currConnections)
0694:                                    roundRobin = 0;
0695:
0696:                                do {
0697:                                    synchronized (connStatus) {
0698:                                        if ((connStatus[roundRobin] < 1)
0699:                                                && (!connPool[roundRobin]
0700:                                                        .isClosed())) {
0701:                                            conn = connPool[roundRobin];
0702:                                            connStatus[roundRobin] = 1;
0703:                                            connLockTime[roundRobin] = System
0704:                                                    .currentTimeMillis();
0705:                                            connLast = roundRobin;
0706:                                            gotOne = true;
0707:                                            break;
0708:                                        } else {
0709:                                            loop++;
0710:                                            roundRobin++;
0711:                                            if (roundRobin >= currConnections)
0712:                                                roundRobin = 0;
0713:                                        }
0714:                                    }
0715:                                } while ((gotOne == false)
0716:                                        && (loop < currConnections));
0717:                            } catch (SQLException e1) {
0718:                            }
0719:
0720:                            if (gotOne) {
0721:                                break;
0722:                            } else {
0723:                                synchronized (this ) { // Add new connections to the pool
0724:                                    if (currConnections < maxConns) {
0725:                                        try {
0726:                                            createConn(currConnections);
0727:                                            currConnections++;
0728:                                        } catch (SQLException e) {
0729:                                            log
0730:                                                    .println("Unable to create new connection: "
0731:                                                            + e);
0732:                                        }
0733:                                    }
0734:                                }
0735:
0736:                                try {
0737:                                    Thread.sleep(2000);
0738:                                } catch (InterruptedException e) {
0739:                                }
0740:                                log
0741:                                        .println("-----> Connections Exhausted!  Will wait and try "
0742:                                                + "again in loop "
0743:                                                + String.valueOf(outerloop));
0744:                            }
0745:                        } // End of try 10 times loop
0746:
0747:                    } else {
0748:                        log
0749:                                .println("Unsuccessful getConnection() request during destroy()");
0750:                    } // End if(available)
0751:
0752:                    return conn;
0753:                }
0754:
0755:                /**
0756:                 * Returns the local JDBC ID for a connection.
0757:                 */
0758:                public int idOfConnection(Connection conn) {
0759:                    int match;
0760:                    String tag;
0761:
0762:                    try {
0763:                        tag = conn.toString();
0764:                    } catch (NullPointerException e1) {
0765:                        tag = "none";
0766:                    }
0767:
0768:                    match = -1;
0769:
0770:                    for (int i = 0; i < currConnections; i++) {
0771:                        if (connID[i].equals(tag)) {
0772:                            match = i;
0773:                            break;
0774:                        }
0775:                    }
0776:                    return match;
0777:                }
0778:
0779:                /**
0780:                 * Frees a connection.  Replaces connection back into the main pool for
0781:                 * reuse.
0782:                 */
0783:                public String freeConnection(Connection conn) {
0784:                    String res = "";
0785:
0786:                    int this conn = idOfConnection(conn);
0787:                    if (this conn >= 0) {
0788:                        connStatus[this conn] = 0;
0789:                        res = "freed " + conn.toString();
0790:                        //log.println("Freed connection " + String.valueOf(thisconn) +
0791:                        //            " normal exit: ");
0792:                    } else {
0793:                        log.println("----> Could not free connection!!!");
0794:                    }
0795:
0796:                    return res;
0797:                }
0798:
0799:                /**
0800:                 * Returns the age of a connection -- the time since it was handed out to
0801:                 * an application.
0802:                 */
0803:                public long getAge(Connection conn) { // Returns the age of the connection in millisec.
0804:                    int this conn = idOfConnection(conn);
0805:                    return System.currentTimeMillis() - connLockTime[this conn];
0806:                }
0807:
0808:                private void createConn(int i) throws SQLException {
0809:                    Date now = new Date();
0810:                    try {
0811:                        Class.forName(dbDriver);
0812:                        connPool[i] = DriverManager.getConnection(dbServer,
0813:                                dbLogin, dbPassword);
0814:                        connStatus[i] = 0;
0815:                        connID[i] = connPool[i].toString();
0816:                        connLockTime[i] = 0;
0817:                        connCreateDate[i] = now.getTime();
0818:
0819:                        log.println(now.toString() + "  Opening connection "
0820:                                + String.valueOf(i) + " "
0821:                                + connPool[i].toString() + ":");
0822:                    } catch (ClassNotFoundException e2) {
0823:                        e2.printStackTrace();
0824:                        throw new SQLException(e2.getMessage());
0825:                    }
0826:                }
0827:
0828:                /**
0829:                 * Shuts down the housekeeping thread and closes all connections
0830:                 * in the pool. Call this method from the destroy() method of the servlet.
0831:                 */
0832:
0833:                /**
0834:                 * Multi-phase shutdown.  having following sequence:
0835:                 * <OL>
0836:                 * <LI><code>getConnection()</code> will refuse to return connections.
0837:                 * <LI>The housekeeping thread is shut down.<br>
0838:                 *    Up to the time of <code>millis</code> milliseconds after shutdown of
0839:                 *    the housekeeping thread, <code>freeConnection()</code> can still be
0840:                 *    called to return used connections.
0841:                 * <LI>After <code>millis</code> milliseconds after the shutdown of the
0842:                 *    housekeeping thread, all connections in the pool are closed.
0843:                 * <LI>If any connections were in use while being closed then a
0844:                 *    <code>SQLException</code> is thrown.
0845:                 * <LI>The log is closed.
0846:                 * </OL><br>
0847:                 * Call this method from a servlet destroy() method.
0848:                 *
0849:                 * @param      millis   the time to wait in milliseconds.
0850:                 * @exception  SQLException if connections were in use after
0851:                 * <code>millis</code>.
0852:                 */
0853:                public void destroy(int millis) throws SQLException {
0854:
0855:                    // Checking for invalid negative arguments is not necessary,
0856:                    // Thread.join() does this already in runner.join().
0857:
0858:                    // Stop issuing connections
0859:                    available = false;
0860:
0861:                    // Shut down the background housekeeping thread
0862:                    runner.interrupt();
0863:
0864:                    // Wait until the housekeeping thread has died.
0865:                    try {
0866:                        runner.join(millis);
0867:                    } catch (InterruptedException e) {
0868:                    } // ignore
0869:
0870:                    // The housekeeping thread could still be running
0871:                    // (e.g. if millis is too small). This case is ignored.
0872:                    // At worst, this method will throw an exception with the
0873:                    // clear indication that the timeout was too short.
0874:
0875:                    long startTime = System.currentTimeMillis();
0876:
0877:                    // Wait for freeConnection() to return any connections
0878:                    // that are still used at this time.
0879:                    int useCount;
0880:                    while ((useCount = getUseCount()) > 0
0881:                            && System.currentTimeMillis() - startTime <= millis) {
0882:                        try {
0883:                            Thread.sleep(500);
0884:                        } catch (InterruptedException e) {
0885:                        } // ignore
0886:                    }
0887:
0888:                    // Close all connections, whether safe or not
0889:                    for (int i = 0; i < currConnections; i++) {
0890:                        try {
0891:                            connPool[i].close();
0892:                        } catch (SQLException e1) {
0893:                            log.println("Cannot close connections on Destroy");
0894:                        }
0895:                    }
0896:
0897:                    if (useCount > 0) {
0898:                        //bt-test successful
0899:                        String msg = "Unsafe shutdown: Had to close "
0900:                                + useCount + " active DB connections after "
0901:                                + millis + "ms";
0902:                        log.println(msg);
0903:                        // Close all open files
0904:                        log.close();
0905:                        // Throwing following Exception is essential because servlet authors
0906:                        // are likely to have their own error logging requirements.
0907:                        throw new SQLException(msg);
0908:                    }
0909:
0910:                    // Close all open files
0911:                    log.close();
0912:
0913:                }//End destroy()
0914:
0915:                /**
0916:                 * Less safe shutdown.  Uses default timeout value.
0917:                 * This method simply calls the <code>destroy()</code> method
0918:                 * with a <code>millis</code>
0919:                 * value of 10000 (10 seconds) and ignores <code>SQLException</code>
0920:                 * thrown by that method.
0921:                 * @see     #destroy(int)
0922:                 */
0923:                public void destroy() {
0924:                    try {
0925:                        destroy(10000);
0926:                    } catch (SQLException e) {
0927:                    }
0928:                }
0929:
0930:                /**
0931:                 * Returns the number of connections in use.
0932:                 */
0933:                // This method could be reduced to return a counter that is
0934:                // maintained by all methods that update connStatus.
0935:                // However, it is more efficient to do it this way because:
0936:                // Updating the counter would put an additional burden on the most
0937:                // frequently used methods; in comparison, this method is
0938:                // rarely used (although essential).
0939:                public int getUseCount() {
0940:                    int useCount = 0;
0941:                    synchronized (connStatus) {
0942:                        for (int i = 0; i < currConnections; i++) {
0943:                            if (connStatus[i] > 0) { // In use
0944:                                useCount++;
0945:                            }
0946:                        }
0947:                    }
0948:                    return useCount;
0949:                }//End getUseCount()
0950:
0951:                /**
0952:                 * Returns the number of connections in the dynamic pool.
0953:                 */
0954:                public int getSize() {
0955:                    return currConnections;
0956:                }//End getSize()
0957:
0958:            } // End class
0959:
0960:            /**
0961:             * An implementation of the Connection interface that wraps an underlying
0962:             * Connection object. It releases the connection back to a connection pool
0963:             * when Connection.close() is called.
0964:             */
0965:            public class ConnectionWrapper implements  Connection {
0966:
0967:                private Connection connection;
0968:                private ConnectionPool connectionPool;
0969:
0970:                public ConnectionWrapper(Connection connection,
0971:                        ConnectionPool connectionPool) {
0972:                    this .connection = connection;
0973:                    this .connectionPool = connectionPool;
0974:                }
0975:
0976:                /**
0977:                 * Instead of closing the underlying connection, we simply release
0978:                 * it back into the pool.
0979:                 */
0980:                public void close() throws SQLException {
0981:                    connectionPool.freeConnection(this .connection);
0982:                    //Release object references. Any further method calls on the
0983:                    //connection will fail.
0984:                    connection = null;
0985:                    connectionPool = null;
0986:                }
0987:
0988:                public String toString() {
0989:                    if (connection != null) {
0990:                        return connection.toString();
0991:                    } else {
0992:                        return "CoolServlets connection wrapper";
0993:                    }
0994:                }
0995:
0996:                public Statement createStatement() throws SQLException {
0997:                    return connection.createStatement();
0998:                }
0999:
1000:                public void setHoldability(int holdability) throws SQLException {
1001:                    connection.setHoldability(holdability);
1002:                }
1003:
1004:                public int getHoldability() throws SQLException {
1005:                    return connection.getHoldability();
1006:                }
1007:
1008:                public Savepoint setSavepoint() throws SQLException {
1009:                    return connection.setSavepoint();
1010:                }
1011:
1012:                public Savepoint setSavepoint(String name) throws SQLException {
1013:                    return connection.setSavepoint(name);
1014:                }
1015:
1016:                public void rollback(Savepoint savepoint) throws SQLException {
1017:                    connection.rollback(savepoint);
1018:                }
1019:
1020:                public PreparedStatement prepareStatement(String sql)
1021:                        throws SQLException {
1022:                    return connection.prepareStatement(sql);
1023:                }
1024:
1025:                public CallableStatement prepareCall(String sql)
1026:                        throws SQLException {
1027:                    return connection.prepareCall(sql);
1028:                }
1029:
1030:                public String nativeSQL(String sql) throws SQLException {
1031:                    return connection.nativeSQL(sql);
1032:                }
1033:
1034:                public void setAutoCommit(boolean autoCommit)
1035:                        throws SQLException {
1036:                    connection.setAutoCommit(autoCommit);
1037:                }
1038:
1039:                public boolean getAutoCommit() throws SQLException {
1040:                    return connection.getAutoCommit();
1041:                }
1042:
1043:                public void commit() throws SQLException {
1044:                    connection.commit();
1045:                }
1046:
1047:                public void rollback() throws SQLException {
1048:                    connection.rollback();
1049:                }
1050:
1051:                public boolean isClosed() throws SQLException {
1052:                    return connection.isClosed();
1053:                }
1054:
1055:                public DatabaseMetaData getMetaData() throws SQLException {
1056:                    return connection.getMetaData();
1057:                }
1058:
1059:                public void setReadOnly(boolean readOnly) throws SQLException {
1060:                    connection.setReadOnly(readOnly);
1061:                }
1062:
1063:                public boolean isReadOnly() throws SQLException {
1064:                    return connection.isReadOnly();
1065:                }
1066:
1067:                public void setCatalog(String catalog) throws SQLException {
1068:                    connection.setCatalog(catalog);
1069:                }
1070:
1071:                public String getCatalog() throws SQLException {
1072:                    return connection.getCatalog();
1073:                }
1074:
1075:                public void setTransactionIsolation(int level)
1076:                        throws SQLException {
1077:                    connection.setTransactionIsolation(level);
1078:                }
1079:
1080:                public int getTransactionIsolation() throws SQLException {
1081:                    return connection.getTransactionIsolation();
1082:                }
1083:
1084:                public SQLWarning getWarnings() throws SQLException {
1085:                    return connection.getWarnings();
1086:                }
1087:
1088:                public void clearWarnings() throws SQLException {
1089:                    connection.clearWarnings();
1090:                }
1091:
1092:                public void releaseSavepoint(Savepoint savepoint)
1093:                        throws SQLException {
1094:                    connection.releaseSavepoint(savepoint);
1095:                }
1096:
1097:                public Statement createStatement(int resultSetType,
1098:                        int resultSetConcurrency) throws SQLException {
1099:                    return connection.createStatement(resultSetType,
1100:                            resultSetConcurrency);
1101:                }
1102:
1103:                public Statement createStatement(int resultSetType,
1104:                        int resultSetConcurrency, int resultSetHoldability)
1105:                        throws SQLException {
1106:                    return connection.createStatement(resultSetType,
1107:                            resultSetConcurrency, resultSetHoldability);
1108:                }
1109:
1110:                public PreparedStatement prepareStatement(String sql,
1111:                        int resultSetType, int resultSetConcurrency)
1112:                        throws SQLException {
1113:                    return connection.prepareStatement(sql, resultSetType,
1114:                            resultSetConcurrency);
1115:                }
1116:
1117:                public CallableStatement prepareCall(String sql,
1118:                        int resultSetType, int resultSetConcurrency)
1119:                        throws SQLException {
1120:                    return connection.prepareCall(sql, resultSetType,
1121:                            resultSetConcurrency);
1122:                }
1123:
1124:                public Map getTypeMap() throws SQLException {
1125:                    return connection.getTypeMap();
1126:                }
1127:
1128:                public PreparedStatement prepareStatement(String sql,
1129:                        String[] columnNames) throws SQLException {
1130:                    return connection.prepareStatement(sql, columnNames);
1131:                }
1132:
1133:                public PreparedStatement prepareStatement(String sql,
1134:                        int[] columnIndexes) throws SQLException {
1135:                    return connection.prepareStatement(sql, columnIndexes);
1136:                }
1137:
1138:                public PreparedStatement prepareStatement(String sql,
1139:                        int autoGeneratedKeys) throws SQLException {
1140:                    return connection.prepareStatement(sql, autoGeneratedKeys);
1141:                }
1142:
1143:                public PreparedStatement prepareStatement(String sql,
1144:                        int resultSetType, int resultSetConcurrency,
1145:                        int resultSetHoldability) throws SQLException {
1146:                    return connection.prepareStatement(sql, resultSetType,
1147:                            resultSetConcurrency, resultSetHoldability);
1148:                }
1149:
1150:                public CallableStatement prepareCall(String sql,
1151:                        int resultSetType, int resultSetConcurrency,
1152:                        int resultSetHoldability) throws SQLException {
1153:                    return connection.prepareCall(sql, resultSetType,
1154:                            resultSetConcurrency, resultSetHoldability);
1155:                }
1156:
1157:                public void setTypeMap(Map map) throws SQLException {
1158:                    connection.setTypeMap(map);
1159:                }
1160:
1161:            }
1162:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.