001: package net.sourceforge.squirrel_sql.fw.sql;
002:
003: /*
004: * Copyright (C) 2001-2003 Colin Bell
005: * colbell@users.sourceforge.net
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 (at your option) 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 USA
020: */
021: import java.beans.PropertyChangeEvent;
022: import java.beans.PropertyChangeListener;
023: import java.net.MalformedURLException;
024: import java.sql.Connection;
025: import java.sql.Driver;
026: import java.sql.SQLException;
027: import java.util.HashMap;
028: import java.util.Map;
029: import java.util.Properties;
030:
031: import net.sourceforge.squirrel_sql.fw.id.IIdentifier;
032: import net.sourceforge.squirrel_sql.fw.util.StringManager;
033: import net.sourceforge.squirrel_sql.fw.util.StringManagerFactory;
034: import net.sourceforge.squirrel_sql.fw.util.StringUtilities;
035: import net.sourceforge.squirrel_sql.fw.util.log.ILogger;
036: import net.sourceforge.squirrel_sql.fw.util.log.LoggerController;
037:
038: /**
039: * This class replaces the standard Java class <TT>java.ql.DriverManager</TT>.
040: * The main reason for replacing it is that <TT>java.ql.DriverManager</TT>
041: * won't handle JDBC driver classes that were loaded by a custom classloader.
042: *
043: * @author <A HREF="mailto:colbell@users.sourceforge.net">Colin Bell</A>
044: */
045: public class SQLDriverManager {
046: /** Internationalized strings for this class. */
047: private static final StringManager s_stringMgr = StringManagerFactory
048: .getStringManager(SQLDriverManager.class);
049:
050: private static final ILogger s_log = LoggerController
051: .createLogger(SQLDriverManager.class);
052:
053: /**
054: * Collection of instances of <TT>java.sql.Driver</TT> objects keyed
055: * by the <TT>SQLDriver.getIdentifier()</TT>.
056: */
057: private Map<IIdentifier, Driver> _driverInfo = new HashMap<IIdentifier, Driver>();
058:
059: /**
060: * Collection of the <TT>SQLDriverClassLoader</TT> class loaders used for
061: * each driver. keyed by <TT>SQLDriver.getIdentifier()</TT>.
062: */
063: private Map<IIdentifier, SQLDriverClassLoader> _classLoaders = new HashMap<IIdentifier, SQLDriverClassLoader>();
064:
065: private MyDriverListener _myDriverListener = new MyDriverListener();
066:
067: public synchronized void registerSQLDriver(ISQLDriver sqlDriver)
068: throws IllegalAccessException, InstantiationException,
069: ClassNotFoundException, MalformedURLException {
070: unregisterSQLDriver(sqlDriver);
071: sqlDriver.addPropertyChangeListener(_myDriverListener);
072: SQLDriverClassLoader loader = new SQLDriverClassLoader(
073: sqlDriver);
074: Driver driver = (Driver) (Class.forName(sqlDriver
075: .getDriverClassName(), false, loader).newInstance());
076: _driverInfo.put(sqlDriver.getIdentifier(), driver);
077: _classLoaders.put(sqlDriver.getIdentifier(), loader);
078: sqlDriver.setJDBCDriverClassLoaded(true);
079: }
080:
081: public synchronized void unregisterSQLDriver(ISQLDriver sqlDriver) {
082: sqlDriver.setJDBCDriverClassLoaded(false);
083: sqlDriver.removePropertyChangeListener(_myDriverListener);
084: _driverInfo.remove(sqlDriver.getIdentifier());
085: _classLoaders.remove(sqlDriver.getIdentifier());
086: }
087:
088: public ISQLConnection getConnection(ISQLDriver sqlDriver,
089: ISQLAlias alias, String user, String pw)
090: throws ClassNotFoundException, IllegalAccessException,
091: InstantiationException, MalformedURLException, SQLException {
092: return getConnection(sqlDriver, alias, user, pw, null);
093: }
094:
095: public synchronized SQLConnection getConnection(
096: ISQLDriver sqlDriver, ISQLAlias alias, String user,
097: String pw, SQLDriverPropertyCollection props)
098: throws ClassNotFoundException, IllegalAccessException,
099: InstantiationException, MalformedURLException, SQLException {
100: Properties myProps = new Properties();
101: if (props != null) {
102: props.applyTo(myProps);
103: }
104: if (user != null) {
105: myProps.put("user", user);
106: }
107: if (pw != null) {
108: myProps.put("password", pw);
109: }
110:
111: Driver driver = _driverInfo.get(sqlDriver.getIdentifier());
112: if (driver == null) {
113: // TODO: Why shouldn't we call registerSQLDriver here? RMM 20070401
114: s_log.debug("Loading driver that wasn't registered: "
115: + sqlDriver.getDriverClassName());
116: ClassLoader loader = new SQLDriverClassLoader(sqlDriver);
117: driver = (Driver) (Class.forName(sqlDriver
118: .getDriverClassName(), false, loader).newInstance());
119:
120: }
121: Connection jdbcConn = driver.connect(alias.getUrl(), myProps);
122: if (jdbcConn == null) {
123: throw new SQLException(s_stringMgr
124: .getString("SQLDriverManager.error.noconnection"));
125: }
126: return new SQLConnection(jdbcConn, props, sqlDriver);
127: }
128:
129: /**
130: * Return the <TT>java.sql.Driver</TT> being used for the passed
131: * <TT>ISQLDriver.getIdentifier()</TT> or <TT>null</TT> if none found.
132: *
133: * @return the <TT>java.sql.Driver</TT> being used for the passed
134: * <TT>ISQLDriver.getIdentifier()</TT> or <TT>null if none found.
135: *
136: * @throws IllegalArgumentException
137: * Thrown if <TT>null</TT> IIdentifier</TT> passed.
138: */
139: public Driver getJDBCDriver(IIdentifier id) {
140: if (id == null) {
141: throw new IllegalArgumentException("IIdentifier == null");
142: }
143:
144: return _driverInfo.get(id);
145: }
146:
147: /**
148: * Return the <TT>SQLDriverClassLoader</TT> used for the passed driver.
149: *
150: * @param sqlDriver Driver to find class loader for.
151: *
152: * @throws IllegalArgumentException
153: * Thrown if <TT>null</TT> <TT>SQLDriverClassLoader</TT> passed.
154: *
155: * @return ClassLoader or null.
156: */
157: public SQLDriverClassLoader getSQLDriverClassLoader(
158: ISQLDriver driver) {
159: if (driver == null) {
160: throw new IllegalArgumentException(
161: "SQLDriverClassLoader == null");
162: }
163:
164: return _classLoaders.get(driver.getIdentifier());
165: }
166:
167: private final class MyDriverListener implements
168: PropertyChangeListener {
169: public void propertyChange(PropertyChangeEvent evt) {
170: final String propName = evt.getPropertyName();
171: if (propName == null
172: || propName
173: .equals(ISQLDriver.IPropertyNames.DRIVER_CLASS)
174: || propName
175: .equals(ISQLDriver.IPropertyNames.JARFILE_NAMES)) {
176: Object obj = evt.getSource();
177: if (obj instanceof ISQLDriver) {
178: ISQLDriver driver = (ISQLDriver) obj;
179: SQLDriverManager.this .unregisterSQLDriver(driver);
180: try {
181: SQLDriverManager.this .registerSQLDriver(driver);
182: } catch (IllegalAccessException ex) {
183: s_log.error(
184: "Unable to create instance of Class "
185: + driver.getDriverClassName()
186: + " for JDBC driver "
187: + driver.getName(), ex);
188: } catch (InstantiationException ex) {
189: s_log.error(
190: "Unable to create instance of Class "
191: + driver.getDriverClassName()
192: + " for JDBC driver "
193: + driver.getName(), ex);
194: } catch (MalformedURLException ex) {
195: s_log.error(
196: "Unable to create instance of Class "
197: + driver.getDriverClassName()
198: + " for JDBC driver "
199: + driver.getName(), ex);
200: } catch (ClassNotFoundException ex) {
201: String[] jars = driver.getJarFileNames();
202: String jarFileList = "<empty list>";
203: if (jars != null) {
204: jarFileList = "[ "
205: + StringUtilities.join(jars, ", ")
206: + " ]";
207: }
208:
209: s_log.error("Unable to find Driver Class "
210: + driver.getDriverClassName()
211: + " for JDBC driver "
212: + driver.getName()
213: + "; jar filenames = " + jarFileList);
214: }
215: } else {
216: s_log
217: .error("SqlDriverManager.MyDriverListener is listening to a non-ISQLDriver");
218: }
219: }
220: }
221: }
222: }
|