View Javadoc

1   /*
2    * $Header: /cvsroot/jdbforms/dbforms/src/org/dbforms/conprovider/ProtomatterConnectionProvider.java,v 1.14 2005/11/30 20:31:17 hkollmann Exp $
3    * $Revision: 1.14 $
4    * $Date: 2005/11/30 20:31:17 $
5    *
6    * DbForms - a Rapid Application Development Framework
7    * Copyright (C) 2001 Joachim Peer <joepeer@excite.com>
8    *
9    * This library is free software; you can redistribute it and/or
10   * modify it under the terms of the GNU Lesser General Public
11   * License as published by the Free Software Foundation; either
12   * version 2.1 of the License, or (at your option) any later version.
13   *
14   * This library is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17   * Lesser General Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser General Public
20   * License along with this library; if not, write to the Free Software
21   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
22   */
23  
24  package org.dbforms.conprovider;
25  
26  
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  
30  import org.dbforms.util.Util;
31  
32  import java.sql.Connection;
33  import java.sql.DriverManager;
34  import java.sql.SQLException;
35  
36  import java.util.Enumeration;
37  import java.util.Hashtable;
38  import java.util.Properties;
39  
40  
41  
42  /***
43   * Connection provider for Protomatter Connection pool. <br>
44   * See <code>http://protomatter.sourceforge.net/</code> for further
45   * informations.
46   *
47   * @author Luca Fossato
48   */
49  public class ProtomatterConnectionProvider extends AbstractConnectionProvider {
50     /*** the initial pool size (default is 0) */
51     protected static final String CP_PROPS_INITIALSIZE = "pool.initialSize";
52  
53     /***
54      * the max pool size (default is -1). If the max pool size is -1, the pool
55      * grows infinitely.
56      */
57     protected static final String CP_PROPS_MAXSIZE = "pool.maxSize";
58  
59     /***
60      * the grow size (default is 1). When a new object is needed, this many are
61      * created.
62      */
63     protected static final String CP_PROPS_GROWBLOCK = "pool.growBlock";
64  
65     /***
66      * the time (in ms) to sleep between pool object creates (default is 0).
67      * This is useful for database connection pools where it's possible to
68      * overload the database by trying to make too many connections too
69      * quickly.
70      */
71     protected static final String CP_PROPS_CREATEWAITTIME = "pool.createWaitTime";
72  
73     /***
74      * A SQL statement that is guaranteed to return at least 1 row. For Oracle,
75      * this is "select 1 from dual" and for Sybase it is "select 1". This
76      * statement is used as a means of checking that a connection is indeed
77      * working.
78      */
79     protected static final String CP_PROPS_VALIDITYCHECKSTATEMENT = "jdbc.validityCheckStatement";
80  
81     /***
82      * If this property is present, and the
83      * <code>pool.maidThreadCheckInterval</code> property is also present, then
84      * a thread will be created that looks for connections that have been idle
85      * for more than <code>pool.maxConnectionIdleTime</code> seconds. When this
86      * thread finds them, it closed the connection and logs a warning with a
87      * stack trace of when the connection was checked out of the pool. This is
88      * primarily here as a debugging aid for finding places where connections
89      * are not getting close, and should not be used in a production
90      * environment
91      */
92     protected static final String CP_PROPS_MAXCONNECTIONIDLETIME = "pool.maxConnectionIdleTime";
93  
94     /***
95      * this is the number of seconds between attempts by the maid thread (if
96      * present) to find idle connections.
97      */
98     protected static final String CP_PROPS_MAIDTHREADCHECKINTERVAL = "pool.maidThreadCheckInterval";
99  
100    /*** connection pool driver class */
101    private static final String CP_DRIVER = "com.protomatter.jdbc.pool.JdbcConnectionPoolDriver";
102 
103    /*** Protomatter connectionPool */
104    private static Log                logCat = LogFactory.getLog(ProtomatterConnectionProvider.class);
105 
106    /***
107     * Default constructor.
108     *
109     * @exception Exception Description of the Exception
110     * @throws Exception because of the <code>throws Exception</code> clause of
111     *         the  <code>init</code> method.
112     */
113    public ProtomatterConnectionProvider() throws Exception {
114       super();
115    }
116 
117    /***
118     * Get a JDBC Connection
119     *
120     * @return a JDBC Connection
121     *
122     * @exception SQLException Description of the Exception
123     */
124    protected Connection getConnection() throws SQLException {
125       return DriverManager.getConnection(getPrefs().getConnectionPoolURL(),
126                                          getPrefs().getUser(),
127                                          getPrefs().getPassword());
128    }
129 
130 
131    /***
132     * Initialize the Protomatter connection pool.
133     *
134     * @throws Exception if any error occurs
135     */
136    protected void init() throws Exception {
137       Properties props = null;
138 
139       // initialization params are kept in a Hashtable
140       Hashtable args = new Hashtable();
141 
142       // the underlying driver
143       args.put("jdbc.driver", getPrefs().getJdbcDriver());
144 
145       // the URL to connect the underlyng driver with the server
146       args.put("jdbc.URL", getPrefs().getJdbcURL());
147 
148       // these are properties that get passed to DriverManager.getConnection(...)
149       Properties jdbcProperties = new Properties();
150       jdbcProperties.put("user", getPrefs().getUser());
151       jdbcProperties.put("password", getPrefs().getPassword());
152 
153       // set the jdbc connection properties;
154       if ((props = getPrefs()
155                             .getProperties()) != null) {
156          for (Enumeration e = props.propertyNames(); e.hasMoreElements();) {
157             String key = (String) e.nextElement();
158             jdbcProperties.put(key, props.getProperty(key));
159             logCat.info("::init - JDBC property [" + key + "] = ["
160                         + props.getProperty(key) + "]");
161          }
162       }
163 
164       args.put("jdbc.properties", jdbcProperties);
165 
166       // now set the connection pool custom properties;
167       // if the connectionPool properties object is null,
168       // instance a new properties object anyway, to use default values;
169       if ((props = getPrefs()
170                             .getPoolProperties()) == null) {
171          props = new Properties();
172       }
173 
174       // use defaults values as specified into the documentation;
175       setIntegerArg(args, props, CP_PROPS_INITIALSIZE, "0");
176       setIntegerArg(args, props, CP_PROPS_MAXSIZE, "-1");
177       setIntegerArg(args, props, CP_PROPS_GROWBLOCK, "1");
178       setIntegerArg(args, props, CP_PROPS_CREATEWAITTIME, "0");
179       setArg(args, props, CP_PROPS_VALIDITYCHECKSTATEMENT, null);
180       setIntegerArg(args, props, CP_PROPS_MAXCONNECTIONIDLETIME, null);
181       setIntegerArg(args, props, CP_PROPS_MAIDTHREADCHECKINTERVAL, null);
182 
183       // finally create the pool and we're ready to go!
184       Class.forName(CP_DRIVER).newInstance();
185    }
186 
187 
188    /***
189     * Set a new String value into the input hashTable.
190     *
191     * @param args the hashTable where to put the value
192     * @param props the properties object where to retrieve the value;
193     * @param key the key value used to retrieve the value from the props
194     *        object. The same key is used to store the retrieved value into
195     *        the args hashMap
196     * @param defValue the default value to use if the input key does not
197     *        retrieve a valid value from the props object
198     */
199    private final void setArg(Hashtable  args,
200                              Properties props,
201                              String     key,
202                              String     defValue) {
203       String value = props.getProperty(key, defValue);
204 
205       if (!Util.isNull(value)) {
206          args.put(key, value);
207          logCat.info("::setArg - [" + key + "] = [" + value + "]");
208       }
209    }
210 
211 
212    /***
213     * Set a new Integer value into the input hashTable.
214     *
215     * @param args the hashTable where to put the value
216     * @param props the properties object where to retrieve the value;
217     * @param key the key value used to retrieve the value from the props
218     *        object. The same key is used to store the retrieved value into
219     *        the args hashMap
220     * @param defValue the default value to use if the input key does not
221     *        retrieve a valid value from the props object
222     */
223    private final void setIntegerArg(Hashtable  args,
224                                     Properties props,
225                                     String     key,
226                                     String     defValue) {
227       String value = props.getProperty(key, defValue);
228 
229       if (!Util.isNull(value)) {
230          args.put(key, new Integer(value));
231          logCat.info("::setIntegerArg - [" + key + "] = [" + value + "]");
232       }
233    }
234 }