001: /*
002: * ConnectionDataSource.java
003: *
004: * Copyright (C) 2002, 2003, 2004, 2005, 2006 Takis Diakoumis
005: *
006: * This program is free software; you can redistribute it and/or
007: * modify it under the terms of the GNU General Public License
008: * as published by the Free Software Foundation; either version 2
009: * of the License, or any later version.
010: *
011: * This program is distributed in the hope that it will be useful,
012: * but WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
014: * GNU General Public License for more details.
015: *
016: * You should have received a copy of the GNU General Public License
017: * along with this program; if not, write to the Free Software
018: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
019: *
020: */
021:
022: package org.executequery.datasource;
023:
024: import java.io.PrintWriter;
025: import java.net.MalformedURLException;
026: import java.net.URL;
027: import java.sql.Connection;
028: import java.sql.Driver;
029: import java.sql.DriverManager;
030: import java.sql.SQLException;
031: import java.util.HashMap;
032: import java.util.Map;
033: import java.util.Properties;
034:
035: import javax.sql.DataSource;
036: import org.underworldlabs.util.DynamicLibraryLoader;
037: import org.underworldlabs.util.MiscUtils;
038: import org.executequery.databasemediators.*;
039: import org.executequery.util.Log;
040:
041: /* ----------------------------------------------------------
042: * CVS NOTE: Changes to the CVS repository prior to the
043: * release of version 3.0.0beta1 has meant a
044: * resetting of CVS revision numbers.
045: * ----------------------------------------------------------
046: */
047:
048: /**
049: * Acts as a wrapper to the actual data source and JDBC driver.
050: *
051: * @author Takis Diakoumis
052: * @version $Revision: 1.7 $
053: * @date $Date: 2006/09/30 03:39:21 $
054: */
055: public class ConnectionDataSource implements DataSource {
056:
057: public static final int ORACLE = 1;
058: public static final int SYBASE = 2;
059: public static final int DB2 = 3;
060: public static final int SQLSERVER = 4;
061: public static final int MYSQL = 5;
062: public static final int POSTGRESQL = 6;
063: public static final int INFORMIX = 7;
064: public static final int HSQL = 8;
065: public static final int POINTBASE = 9;
066: public static final int ODBC = 10;
067: public static final int ACCESS = 11;
068: public static final int OTHER = 99;
069:
070: public static final String PORT = "[port]";
071: public static final String SOURCE = "[source]";
072: public static final String HOST = "[host]";
073:
074: private static final String PORT_REGEX = "\\[port\\]";
075: private static final String SOURCE_REGEX = "\\[source\\]";
076: private static final String HOST_REGEX = "\\[host\\]";
077:
078: private static Map<DatabaseDriver, Driver> loadedDrivers;
079:
080: protected boolean usingOracleThinDriver;
081: protected boolean usingODBC;
082:
083: /** the generated JDBC URL */
084: private String jdbcUrl;
085:
086: /** driver properties object for this source */
087: protected DatabaseDriver databaseDriver;
088:
089: /** the loaded java.sql.Driver */
090: protected Driver _driver;
091:
092: /** the genrated driver connection properties */
093: protected Properties driverProps;
094:
095: /** Whether the driver has been loaded */
096: protected boolean driverLoaded;
097:
098: /** The database connection object of this data source */
099: protected DatabaseConnection databaseConnection;
100:
101: public ConnectionDataSource(DatabaseConnection databaseConnection) {
102: this .databaseConnection = databaseConnection;
103: if (databaseConnection.hasAdvancedProperties()) {
104: driverProps = new Properties(databaseConnection
105: .getJdbcProperties());
106: } else {
107: driverProps = new Properties();
108: }
109:
110: Log.info("Initialising data source for "
111: + databaseConnection.getName());
112:
113: driverProps.put("user", databaseConnection.getUserName());
114: driverProps.put("password", databaseConnection
115: .getUnencryptedPassword());
116:
117: databaseDriver = databaseConnection.getJDBCDriver();
118: }
119:
120: static {
121: loadedDrivers = new HashMap<DatabaseDriver, Driver>();
122: }
123:
124: protected void destroy() {
125: _driver = null;
126: databaseDriver = null;
127: driverProps = null;
128: }
129:
130: public boolean isUsingOracleThinDriver() {
131: return usingOracleThinDriver;
132: }
133:
134: public void setUsingOracleThinDriver(boolean thin) {
135: usingOracleThinDriver = thin;
136: }
137:
138: public String getJdbcUrl() {
139: return jdbcUrl;
140: }
141:
142: private void loadDriver() throws SQLException {
143:
144: if (databaseDriver == null) {
145: throw new SQLException("No JDBC driver specified");
146: }
147:
148: try {
149: driverLoaded = false;
150: int driverType = databaseDriver.getType();
151:
152: if (driverType == ORACLE) {
153: usingOracleThinDriver = true;
154: } else if (driverType == ODBC) {
155: usingODBC = true;
156: }
157:
158: jdbcUrl = databaseConnection.getURL();
159:
160: // if the url is null - generate it
161: if (MiscUtils.isNull(jdbcUrl)) {
162:
163: /* Generate the JDBC URL as specfied in jdbcdrivers.xml
164: * using the server, port and source values for the connection. */
165: String value = null;
166: jdbcUrl = databaseDriver.getURL();
167:
168: Log.info("JDBC URL pattern: " + jdbcUrl);
169:
170: // check if this url needs the server/host name
171: if (jdbcUrl.indexOf(HOST) != -1) {
172: value = databaseConnection.getHost();
173: if (MiscUtils.isNull(value)) {
174: handleInformationException();
175: }
176: jdbcUrl = jdbcUrl.replaceAll(HOST_REGEX, value);
177: }
178:
179: // check if this url needs the port number
180: if (jdbcUrl.indexOf(PORT) != -1) {
181: value = databaseConnection.getPort();
182: if (MiscUtils.isNull(value)) {
183: handleInformationException();
184: }
185: jdbcUrl = jdbcUrl.replaceAll(PORT_REGEX, value);
186: }
187:
188: // check if this url needs the source name
189: if (jdbcUrl.indexOf(SOURCE) != -1) {
190: value = databaseConnection.getSourceName();
191: if (MiscUtils.isNull(value)) {
192: handleInformationException();
193: }
194: jdbcUrl = jdbcUrl.replaceAll(SOURCE_REGEX, value);
195: }
196:
197: Log.info("JDBC URL generated: " + jdbcUrl);
198: } else {
199: Log.info("Using user specified JDBC URL: " + jdbcUrl);
200: }
201:
202: // check if this driver has already been loaded
203: if (loadedDrivers.containsKey(databaseDriver)) {
204: _driver = loadedDrivers.get(databaseDriver);
205: driverLoaded = true;
206: return;
207: }
208:
209: Class clazz = null;
210: String driverName = databaseDriver.getClassName();
211:
212: if (!usingODBC) {
213: String path = databaseDriver.getPath();
214: if (!MiscUtils.isNull(path)) {
215: URL[] urls = MiscUtils.loadURLs(path);
216:
217: /* Load the JDBC libraries and initialise the driver. */
218: DynamicLibraryLoader loader = new DynamicLibraryLoader(
219: urls);
220: clazz = loader.loadLibrary(driverName);
221: } else {
222: clazz = Class.forName(driverName, true, ClassLoader
223: .getSystemClassLoader());
224: }
225: } else {
226: clazz = Class.forName(driverName, true, ClassLoader
227: .getSystemClassLoader());
228: }
229:
230: Object object = clazz.newInstance();
231: _driver = (Driver) object;
232: loadedDrivers.put(databaseDriver, _driver);
233: driverLoaded = true;
234: //DriverManager.setLogStream(System.out);
235:
236: } catch (ClassNotFoundException cExc) {
237: driverLoaded = false;
238: throw new SQLException(
239: "The specified JDBC driver class was not found");
240: } catch (IllegalAccessException e) {
241: driverLoaded = false;
242: throw new SQLException(
243: "The specified JDBC driver class was not accessible");
244: } catch (MalformedURLException e) {
245: driverLoaded = false;
246: throw new SQLException(e.getMessage());
247: } catch (InstantiationException e) {
248: driverLoaded = false;
249: throw new SQLException(e.getMessage());
250: }
251:
252: }
253:
254: private void handleInformationException() throws SQLException {
255: driverLoaded = false;
256: throw new SQLException(
257: "Insufficient information was provided to establish the connection.\n"
258: + "Please ensure all required details have been entered.");
259: }
260:
261: public Connection getConnection() throws SQLException {
262: return getConnection(databaseConnection.getUserName(),
263: databaseConnection.getUnencryptedPassword());
264: }
265:
266: public Connection getConnection(String user, String password)
267: throws SQLException {
268:
269: if (!driverLoaded) {
270: loadDriver();
271: }
272:
273: if (driverProps == null) {
274: driverProps = new Properties();
275: if (!MiscUtils.isNull(user)) {
276: driverProps.put("user", user);
277: }
278: if (!MiscUtils.isNull(password)) {
279: driverProps.put("password", password);
280: }
281: }
282:
283: //Log.info("Retrieving connection from URL: " + jdbcUrl);
284: if (_driver != null) {
285: return _driver.connect(jdbcUrl, driverProps);
286: }
287:
288: return null;
289: }
290:
291: public void setDriverObject(DatabaseDriver d) {
292: databaseDriver = d;
293: }
294:
295: public String getDriverClassName() {
296: return databaseDriver.getClassName();
297: }
298:
299: public int getLoginTimeout() throws SQLException {
300: return DriverManager.getLoginTimeout();
301: }
302:
303: public PrintWriter getLogWriter() throws SQLException {
304: return DriverManager.getLogWriter();
305: }
306:
307: public void setLoginTimeout(int timeout) throws SQLException {
308: DriverManager.setLoginTimeout(timeout);
309: }
310:
311: public void setLogWriter(PrintWriter writer) throws SQLException {
312: DriverManager.setLogWriter(writer);
313: }
314:
315: public boolean isDriverLoaded() {
316: return driverLoaded;
317: }
318:
319: }
|