001: /*
002: * HA-JDBC: High-Availability JDBC
003: * Copyright (c) 2004-2007 Paul Ferraro
004: *
005: * This library is free software; you can redistribute it and/or modify it
006: * under the terms of the GNU Lesser General Public License as published by the
007: * Free Software Foundation; either version 2.1 of the License, or (at your
008: * option) any later version.
009: *
010: * This library is distributed in the hope that it will be useful, but WITHOUT
011: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
012: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
013: * for more details.
014: *
015: * You should have received a copy of the GNU Lesser General Public License
016: * along with this library; if not, write to the Free Software Foundation,
017: * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
018: *
019: * Contact: ferraro@users.sourceforge.net
020: */
021: package net.sf.hajdbc.sql;
022:
023: import java.sql.Connection;
024: import java.sql.DriverManager;
025: import java.sql.DriverPropertyInfo;
026: import java.sql.SQLException;
027: import java.util.Properties;
028: import java.util.regex.Matcher;
029: import java.util.regex.Pattern;
030:
031: import net.sf.hajdbc.Database;
032: import net.sf.hajdbc.DatabaseCluster;
033: import net.sf.hajdbc.DatabaseClusterFactory;
034: import net.sf.hajdbc.Messages;
035: import net.sf.hajdbc.util.SQLExceptionFactory;
036: import net.sf.hajdbc.util.Strings;
037: import net.sf.hajdbc.util.reflect.ProxyFactory;
038:
039: import org.slf4j.Logger;
040: import org.slf4j.LoggerFactory;
041:
042: /**
043: * @author Paul Ferraro
044: * @version $Revision: 2015 $
045: */
046: public final class Driver implements java.sql.Driver {
047: private static final Pattern URL_PATTERN = Pattern
048: .compile("jdbc:ha-jdbc:(.+)"); //$NON-NLS-1$
049: private static final String CONFIG = "config"; //$NON-NLS-1$
050:
051: private static Logger logger = LoggerFactory
052: .getLogger(Driver.class);
053:
054: static {
055: try {
056: DriverManager.registerDriver(new Driver());
057: } catch (SQLException e) {
058: logger.error(Messages.getMessage(
059: Messages.DRIVER_REGISTER_FAILED, Driver.class
060: .getName()), e);
061: }
062: }
063:
064: /**
065: * @see java.sql.Driver#acceptsURL(java.lang.String)
066: */
067: @Override
068: public boolean acceptsURL(String url) {
069: return (this .parse(url) != null);
070: }
071:
072: /**
073: * @see java.sql.Driver#connect(java.lang.String, java.util.Properties)
074: */
075: @Override
076: public Connection connect(String url, final Properties properties)
077: throws SQLException {
078: String id = this .parse(url);
079:
080: if (id == null)
081: return null;
082:
083: DatabaseCluster<java.sql.Driver> cluster = this
084: .getDatabaseCluster(id, properties);
085:
086: DriverInvocationHandler handler = new DriverInvocationHandler(
087: cluster);
088:
089: java.sql.Driver driver = ProxyFactory.createProxy(
090: java.sql.Driver.class, handler);
091:
092: Invoker<java.sql.Driver, java.sql.Driver, Connection> invoker = new Invoker<java.sql.Driver, java.sql.Driver, Connection>() {
093: public Connection invoke(
094: Database<java.sql.Driver> database,
095: java.sql.Driver driver) throws SQLException {
096: String url = ((DriverDatabase) database).getUrl();
097:
098: return driver.connect(url, properties);
099: }
100: };
101:
102: TransactionContext<java.sql.Driver> context = new LocalTransactionContext<java.sql.Driver>(
103: cluster);
104:
105: try {
106: return new ConnectionInvocationStrategy<java.sql.Driver, java.sql.Driver>(
107: cluster, driver, context).invoke(handler, invoker);
108: } catch (Exception e) {
109: throw SQLExceptionFactory.createSQLException(e);
110: }
111: }
112:
113: /**
114: * @see java.sql.Driver#getMajorVersion()
115: */
116: @Override
117: public int getMajorVersion() {
118: return Integer.parseInt(version()[0]);
119: }
120:
121: /**
122: * @see java.sql.Driver#getMinorVersion()
123: */
124: @Override
125: public int getMinorVersion() {
126: return Integer.parseInt(version()[1]);
127: }
128:
129: private String[] version() {
130: return DatabaseClusterFactory.getVersion().split(Strings.DASH)[0]
131: .split(Pattern.quote(Strings.DOT));
132: }
133:
134: /**
135: * @see java.sql.Driver#getPropertyInfo(java.lang.String, java.util.Properties)
136: */
137: @Override
138: public DriverPropertyInfo[] getPropertyInfo(String url,
139: final Properties properties) throws SQLException {
140: String id = this .parse(url);
141:
142: if (id == null)
143: return null;
144:
145: DatabaseCluster<java.sql.Driver> cluster = this
146: .getDatabaseCluster(id, properties);
147:
148: DriverInvocationHandler handler = new DriverInvocationHandler(
149: cluster);
150:
151: Invoker<java.sql.Driver, java.sql.Driver, DriverPropertyInfo[]> invoker = new Invoker<java.sql.Driver, java.sql.Driver, DriverPropertyInfo[]>() {
152: public DriverPropertyInfo[] invoke(
153: Database<java.sql.Driver> database,
154: java.sql.Driver driver) throws SQLException {
155: String url = ((DriverDatabase) database).getUrl();
156:
157: return driver.getPropertyInfo(url, properties);
158: }
159: };
160:
161: try {
162: return new DriverReadInvocationStrategy<java.sql.Driver, java.sql.Driver, DriverPropertyInfo[]>()
163: .invoke(handler, invoker);
164: } catch (Exception e) {
165: throw SQLExceptionFactory.createSQLException(e);
166: }
167: }
168:
169: /**
170: * @see java.sql.Driver#jdbcCompliant()
171: */
172: @Override
173: public boolean jdbcCompliant() {
174: return true;
175: }
176:
177: private DatabaseCluster<java.sql.Driver> getDatabaseCluster(
178: String id, Properties properties) throws SQLException {
179: DatabaseCluster<java.sql.Driver> cluster = DatabaseClusterFactory
180: .getDatabaseCluster(id, DriverDatabaseCluster.class,
181: DriverDatabaseClusterMBean.class, properties
182: .getProperty(CONFIG));
183:
184: if (cluster == null) {
185: throw new SQLException(Messages.getMessage(
186: Messages.INVALID_DATABASE_CLUSTER, id));
187: }
188:
189: return cluster;
190: }
191:
192: private String parse(String url) {
193: Matcher matcher = URL_PATTERN.matcher(url);
194:
195: if (!matcher.matches()) {
196: return null;
197: }
198:
199: return matcher.group(1);
200: }
201: }
|