001: /*
002: * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved
003: *
004: * This file is part of Resin(R) Open Source
005: *
006: * Each copy or derived work must preserve the copyright notice and this
007: * notice unmodified.
008: *
009: * Resin Open Source is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU General Public License as published by
011: * the Free Software Foundation; either version 2 of the License, or
012: * (at your option) any later version.
013: *
014: * Resin Open Source is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
017: * of NON-INFRINGEMENT. See the GNU General Public License for more
018: * details.
019: *
020: * You should have received a copy of the GNU General Public License
021: * along with Resin Open Source; if not, write to the
022: *
023: * Free Software Foundation, Inc.
024: * 59 Temple Place, Suite 330
025: * Boston, MA 02111-1307 USA
026: *
027: * @author Scott Ferguson
028: */
029:
030: package com.caucho.sql;
031:
032: import com.caucho.loader.EnvironmentLocal;
033: import com.caucho.util.L10N;
034: import com.caucho.config.ConfigException;
035: import com.caucho.vfs.*;
036:
037: import java.net.*;
038: import java.sql.*;
039: import javax.sql.*;
040: import java.util.*;
041: import java.util.logging.*;
042:
043: /**
044: * Manages databases in a local environment, e.g. for PHP dynamic
045: * database lookup.
046: */
047: public class DatabaseManager {
048: protected static final Logger log = Logger
049: .getLogger(DatabaseManager.class.getName());
050: private static final L10N L = new L10N(DatabaseManager.class);
051:
052: private static final EnvironmentLocal<DatabaseManager> _localManager = new EnvironmentLocal<DatabaseManager>();
053:
054: private final HashMap<String, DBPool> _databaseMap = new HashMap<String, DBPool>();
055:
056: private final ArrayList<Driver> _driverList = new ArrayList<Driver>();
057:
058: private static int _gId;
059:
060: /**
061: * The manager is never instantiated.
062: */
063: private DatabaseManager() {
064: initDriverList();
065: }
066:
067: /**
068: * Returns the database manager for the local environment.
069: */
070: private static DatabaseManager getLocalManager() {
071: synchronized (_localManager) {
072: DatabaseManager manager = _localManager.getLevel();
073:
074: if (manager == null) {
075: manager = new DatabaseManager();
076:
077: _localManager.set(manager);
078: }
079:
080: return manager;
081: }
082: }
083:
084: /**
085: * Returns a matching dbpool.
086: */
087: public static DataSource findDatabase(String url)
088: throws SQLException {
089: String driver = findDriverByUrl(url);
090:
091: return getLocalManager().findDatabaseImpl(url, driver);
092: }
093:
094: /**
095: * Returns a matching dbpool.
096: */
097: public static DataSource findDatabase(String url, String driver)
098: throws SQLException {
099: return getLocalManager().findDatabaseImpl(url, driver);
100: }
101:
102: /**
103: * Looks up the local database, creating if necessary.
104: */
105: private DataSource findDatabaseImpl(String url, String driverName)
106: throws SQLException {
107: try {
108: synchronized (_databaseMap) {
109: DBPool db = _databaseMap.get(url);
110:
111: if (db == null) {
112: db = new DBPool();
113:
114: db.setVar(url + "-" + _gId++);
115:
116: DriverConfig driver = db.createDriver();
117:
118: ClassLoader loader = Thread.currentThread()
119: .getContextClassLoader();
120:
121: Class driverClass = Class.forName(driverName,
122: false, loader);
123:
124: driver.setType(driverClass);
125: driver.setURL(url);
126:
127: db.init();
128:
129: _databaseMap.put(url, db);
130: }
131:
132: return db;
133: }
134: } catch (RuntimeException e) {
135: throw e;
136: } catch (SQLException e) {
137: throw e;
138: } catch (Exception e) {
139: throw ConfigException.create(e);
140: }
141: }
142:
143: public static String findDriverByUrl(String url) {
144: return getLocalManager().findDriverByUrlImpl(url);
145: }
146:
147: private String findDriverByUrlImpl(String url) {
148: for (int i = 0; i < _driverList.size(); i++) {
149: try {
150: Driver driver = (Driver) _driverList.get(i);
151:
152: if (driver.acceptsURL(url))
153: return driver.getClass().getName();
154: } catch (Exception e) {
155: log.log(Level.FINE, e.toString(), e);
156: }
157: }
158:
159: return null;
160: }
161:
162: private void initDriverList() {
163: try {
164: Thread thread = Thread.currentThread();
165: ClassLoader loader = thread.getContextClassLoader();
166:
167: Enumeration iter = loader
168: .getResources("META-INF/services/java.sql.Driver");
169: while (iter.hasMoreElements()) {
170: URL url = (URL) iter.nextElement();
171:
172: ReadStream is = null;
173: try {
174: is = Vfs.lookup(url.toString()).openRead();
175:
176: String filename;
177:
178: while ((filename = is.readLine()) != null) {
179: int p = filename.indexOf('#');
180:
181: if (p >= 0)
182: filename = filename.substring(0, p);
183:
184: filename = filename.trim();
185: if (filename.length() == 0)
186: continue;
187:
188: try {
189: Class cl = Class.forName(filename, false,
190: loader);
191: Driver driver = null;
192:
193: if (Driver.class.isAssignableFrom(cl))
194: driver = (Driver) cl.newInstance();
195:
196: if (driver != null) {
197: log
198: .fine(L
199: .l(
200: "DatabaseManager adding driver '{0}'",
201: driver
202: .getClass()
203: .getName()));
204:
205: _driverList.add(driver);
206: }
207: } catch (Exception e) {
208: log.log(Level.FINE, e.toString(), e);
209: }
210: }
211: } catch (Exception e) {
212: log.log(Level.FINE, e.toString(), e);
213: } finally {
214: if (is != null)
215: is.close();
216: }
217: }
218: } catch (Exception e) {
219: log.log(Level.FINE, e.toString(), e);
220: }
221: }
222:
223: static class DatabaseKey {
224: private String _url;
225: private String _catalog;
226:
227: DatabaseKey(String url, String catalog) {
228: _url = url;
229: _catalog = catalog;
230: }
231:
232: public int hashCode() {
233: int hash = 37;
234:
235: hash = 65521 * hash + _url.hashCode();
236:
237: if (_catalog != null)
238: hash = 65521 * hash + _catalog.hashCode();
239:
240: return hash;
241: }
242:
243: public boolean equals(Object o) {
244: if (!(o instanceof DatabaseKey))
245: return false;
246:
247: DatabaseKey key = (DatabaseKey) o;
248:
249: if (!_url.equals(key._url))
250: return false;
251:
252: return (_catalog == key._catalog || _catalog != null
253: && _catalog.equals(key._catalog));
254: }
255: }
256: }
|