001: /*
002: * XAPool: Open Source XA JDBC Pool
003: * Copyright (C) 2003 Objectweb.org
004: * Initial Developer: Lutris Technologies Inc.
005: * Contact: xapool-public@lists.debian-sf.objectweb.org
006: *
007: * This library is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU Lesser General Public
009: * License as published by the Free Software Foundation; either
010: * version 2.1 of the License, or any later version.
011: *
012: * This library is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this library; if not, write to the Free Software
019: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
020: * USA
021: */
022: package org.enhydra.jdbc.standard;
023:
024: import java.sql.Connection;
025: import java.sql.DriverManager;
026: import java.sql.SQLException;
027: import java.util.Hashtable;
028: import javax.naming.Context;
029: import javax.naming.Name;
030: import javax.naming.NamingException;
031: import javax.naming.Reference;
032: import javax.naming.StringRefAddr;
033: import javax.sql.DataSource;
034: import org.enhydra.jdbc.core.CoreDataSource;
035: import java.sql.Driver;
036: import java.util.Properties;
037: import org.enhydra.jdbc.util.Logger;
038: import org.apache.commons.logging.LogFactory;
039:
040: /**
041: * Provides a Data Source which can be used to generate JDBC connections.
042: * <P>
043: * This class is generic in the sense that it does not rely upon anything other
044: * than standard Java APIs. It uses java.sql.DriverManager and preconfigured
045: * properties to construct a JDBC connection.
046: * Important : networkProtocol, portNumber, serverName are not used. Please use
047: * instead the url property.
048: */
049: public class StandardDataSource extends CoreDataSource implements
050: DataSource {
051:
052: // Standard Data Source properties
053: transient Driver driver;
054: String driverName; // name of the Standard JDBC driver
055: String url; // an explicit JDBC URL used to access this data source
056: private int transIsolation; // transaction isolation level
057: private boolean loadedFromCCL = false;
058:
059: /**
060: * Constructors
061: */
062: public StandardDataSource() {
063: // This constructor is needed by the object factory
064: super ();
065: driver = null;
066: driverName = "";
067: url = "";
068: transIsolation = -1; //use default
069: setLogger(new Logger(LogFactory
070: .getLog("org.enhydra.jdbc.xapool")));
071: }
072:
073: protected StandardDataSource(Driver drv) throws SQLException {
074: this ();
075: driver = drv;
076: driverName = drv.getClass().getName();
077: setLogger(new Logger(LogFactory
078: .getLog("org.enhydra.jdbc.xapool")));
079: }
080:
081: /**
082: * return the name of the driver
083: * @return the string representation of the driver name
084: */
085: public String getDriverName() {
086: return driverName;
087: }
088:
089: /**
090: * return the url of the database
091: * @return the string representation of the database url
092: */
093: public String getUrl() {
094: return url;
095: }
096:
097: /**
098: * set the name of the jdbc driver
099: * @param driverName the string representation of the jdbc driver name
100: * @throws SQLException
101: */
102: public void setDriverName(String driverName) throws SQLException {
103: if (!this .driverName.equals(driverName)) {
104: this .driverName = driverName;
105: driver = null;
106: }
107: /*
108: try {
109: driver= (Driver)Class.forName (driverName).newInstance();
110: log("StandardDataSource:setDriverName a new driver instance is created");
111: } catch (Exception e) {
112: throw new SQLException ("Error trying to load driver: "+driverName+"\n"+e.getMessage());
113: } // try-catch
114: */
115: }
116:
117: /**
118: * set the database url
119: * @param url the string representation of the database url
120: */
121: public void setUrl(String url) {
122: this .url = url;
123: }
124:
125: /**
126: * set the level of the transaction isolation for the current database
127: * @param level the integer level
128: */
129: public void setTransactionIsolation(int level) {
130: transIsolation = level;
131: }
132:
133: /**
134: * return the transaction isolation level defined for the current database
135: * @return the transaction isolation level
136: */
137: public int getTransactionIsolation() {
138: return transIsolation;
139: }
140:
141: /**
142: *
143: * @return
144: * @throws SQLException
145: */
146: synchronized public Connection getConnection() throws SQLException {
147: return getConnection(user, password);
148: }
149:
150: /**
151: *
152: * @param u
153: * @param p
154: * @return
155: * @throws SQLException
156: */
157: synchronized public Connection getConnection(String u, String p)
158: throws SQLException {
159: Connection ret = null; // the connection that gets returned
160: Properties prop = new Properties();
161: if (u != null)
162: prop.put("user", u);
163: if (p != null)
164: prop.put("password", p);
165: if (url == null) { // if no explicit url provided
166: // Build URL from serverName, NetworkProtocol etc.
167: } else { // explicit URL provided
168: if (driver == null) {
169: try {
170: driver = (Driver) Class.forName(driverName)
171: .newInstance();
172: loadedFromCCL = false;
173: log
174: .debug("StandardDataSource:getConnection a new driver instance is created");
175: } catch (Exception e) {
176: try {
177: driver = (Driver) Class.forName(
178: driverName,
179: true,
180: Thread.currentThread()
181: .getContextClassLoader())
182: .newInstance();
183: loadedFromCCL = true;
184: } catch (Exception e2) {
185: throw new SQLException(
186: "Error trying to load driver: "
187: + driverName + " : "
188: + e2.getMessage());
189: }
190: }
191: }
192: // commenting out since at least one driver will complain if you
193: // instantiate the driver outside the Driver Manager
194: // (ie. Cloudscape RMI)
195: /*
196: if (!driver.acceptsURL(url)) {
197: log("Driver does not accept url "+url);
198: throw new SQLException("Driver does not accept url "+url);
199: }
200: */
201: try {
202: if (loadedFromCCL) {
203: ret = driver.connect(url, prop);
204: // Driver creates the connection
205: } else {
206: ret = DriverManager.getConnection(url, prop);
207: // DriverManager creates the connection
208: }
209: int transIsolation = getTransactionIsolation();
210: if (transIsolation >= 0) {
211: ret.setTransactionIsolation(transIsolation);
212: }
213: log
214: .debug("StandardDataSource:getConnection Connection from DriverManager is returned");
215: } catch (SQLException e) {
216: throw new SQLException("Cannot get connection for URL "
217: + url + " : " + e.getMessage());
218: }
219: }
220: return ret;
221: }
222:
223: /**
224: * Methods inherited from referenceable
225: */
226: public Reference getReference() throws NamingException {
227: // Note that we use getClass().getName() to provide the factory
228: // class name. It is assumed that this class, and all of its
229: // descendants are their own factories.
230:
231: Reference ref = new Reference(getClass().getName(), getClass()
232: .getName(), null);
233: ref.add(new StringRefAddr("driverName", getDriverName()));
234: ref.add(new StringRefAddr("url", getUrl()));
235: ref.add(new StringRefAddr("user", getUser()));
236: ref.add(new StringRefAddr("password", getPassword()));
237: ref.add(new StringRefAddr("description", getDescription()));
238: ref.add(new StringRefAddr("loginTimeout", Integer
239: .toString(getLoginTimeout())));
240: ref.add(new StringRefAddr("transIsolation", Integer
241: .toString(getTransactionIsolation())));
242: log.debug("StandardDataSource:getReference object returned");
243: return ref;
244: }
245:
246: /**
247: * Methods inherited from ObjectFactory
248: */
249: public Object getObjectInstance(Object refObj, Name name,
250: Context nameCtx, Hashtable env) throws Exception {
251: Reference ref = (Reference) refObj;
252: this .setDriverName((String) ref.get("driverName").getContent());
253: this .setUrl((String) ref.get("url").getContent());
254: this .setUser((String) ref.get("user").getContent());
255: this .setPassword((String) ref.get("password").getContent());
256: this .setDescription((String) ref.get("description")
257: .getContent());
258: this .setLoginTimeout(Integer.parseInt((String) ref.get(
259: "loginTimeout").getContent()));
260: this .setTransactionIsolation(Integer.parseInt((String) ref.get(
261: "transIsolation").getContent()));
262: return this ;
263: }
264:
265: public boolean equals(Object obj) {
266: if (this == obj) {
267: return true;
268: }
269: if (obj == null) {
270: return false;
271: }
272: return false;
273: /*
274: if (obj instanceof StandardDataSource) {
275: StandardDataSource other = (StandardDataSource)obj;
276: if (!(this.url == null || this.user == null)) {
277: return (this.url.equals(other.url) && this.user.equals(other.user));
278: } else if (this.url != null) {
279: return (this.url.equals(other.url) && this.user == other.user);
280: } else if (this.user != null) {
281: return (this.url == other.url && this.user.equals(other.user));
282: } else {
283: return (this.url == other.url && this.user == other.user);
284: }
285: } else {
286: return false;
287: }
288: */
289: }
290:
291: /* (non-Javadoc)
292: * @see java.lang.Object#toString()
293: */
294:
295: public String toString() {
296: StringBuffer sb = new StringBuffer();
297: sb.append("StandardDataSource:\n");
298: sb.append(" driver=<" + driver + ">\n");
299: sb.append(" url=<" + url + ">\n");
300: sb.append(" user=<" + user + ">\n");
301: sb.append(super .toString());
302:
303: return sb.toString();
304: }
305:
306: public int hashCode() {
307: return toString().hashCode();
308: }
309: }
|