001/* 002 * HA-JDBC: High-Availability JDBC 003 * Copyright (C) 2012 Paul Ferraro 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Lesser General Public License as published by 007 * the Free Software Foundation, either version 3 of the License, or 008 * (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018package net.sf.hajdbc.sql; 019 020import java.io.PrintWriter; 021import java.sql.SQLException; 022import java.sql.SQLFeatureNotSupportedException; 023import java.util.concurrent.TimeUnit; 024import java.util.logging.Logger; 025 026import javax.naming.BinaryRefAddr; 027import javax.naming.Reference; 028import javax.naming.Referenceable; 029import javax.naming.StringRefAddr; 030 031import net.sf.hajdbc.Database; 032import net.sf.hajdbc.DatabaseCluster; 033import net.sf.hajdbc.DatabaseClusterConfiguration; 034import net.sf.hajdbc.DatabaseClusterConfigurationFactory; 035import net.sf.hajdbc.DatabaseClusterFactory; 036import net.sf.hajdbc.ExceptionType; 037import net.sf.hajdbc.util.Objects; 038import net.sf.hajdbc.util.TimePeriod; 039import net.sf.hajdbc.util.concurrent.ReferenceRegistryStoreFactory; 040import net.sf.hajdbc.util.concurrent.LifecycleRegistry; 041import net.sf.hajdbc.util.concurrent.Registry; 042import net.sf.hajdbc.xml.XMLDatabaseClusterConfigurationFactory; 043 044/** 045 * @author Paul Ferraro 046 * @param <Z> data source class 047 */ 048public abstract class CommonDataSource<Z extends javax.sql.CommonDataSource, D extends Database<Z>, F extends CommonDataSourceProxyFactory<Z, D>> implements Referenceable, javax.sql.CommonDataSource, CommonDataSourceProxyFactoryFactory<Z, D, F>, Registry.Factory<Void, DatabaseCluster<Z, D>, Void, SQLException> 049{ 050 private final Class<? extends DatabaseClusterConfiguration<Z, D>> configurationClass; 051 052 private final Registry<Void, DatabaseCluster<Z, D>, Void, SQLException> registry = new LifecycleRegistry<Void, DatabaseCluster<Z, D>, Void, SQLException>(this, new ReferenceRegistryStoreFactory(), ExceptionType.SQL.<SQLException>getExceptionFactory()); 053 054 private volatile TimePeriod timeout = new TimePeriod(10, TimeUnit.SECONDS); 055 private volatile String cluster; 056 private volatile String config; 057 private volatile String user; 058 private volatile String password; 059 private volatile DatabaseClusterFactory<Z, D> factory = new DatabaseClusterFactoryImpl<Z, D>(); 060 private volatile DatabaseClusterConfigurationFactory<Z, D> configurationFactory; 061 062 protected CommonDataSource(Class<? extends DatabaseClusterConfiguration<Z, D>> configurationClass) 063 { 064 this.configurationClass = configurationClass; 065 } 066 067 public void stop() throws SQLException 068 { 069 this.registry.remove(null); 070 } 071 072 /** 073 * {@inheritDoc} 074 */ 075 @Override 076 public DatabaseCluster<Z, D> create(Void key, Void context) throws SQLException 077 { 078 DatabaseClusterConfigurationFactory<Z, D> factory = (this.configurationFactory != null) ? this.configurationFactory : new XMLDatabaseClusterConfigurationFactory<Z, D>(this.configurationClass, this.cluster, this.config); 079 080 return this.factory.createDatabaseCluster(this.cluster, factory); 081 } 082 083 public Z getProxy() throws SQLException 084 { 085 return this.createProxyFactory(this.registry.get(null, null)).createProxy(); 086 } 087 088 /** 089 * @return the cluster 090 */ 091 public String getCluster() 092 { 093 return this.cluster; 094 } 095 096 /** 097 * @param cluster the cluster to set 098 */ 099 public void setCluster(String cluster) 100 { 101 this.cluster = cluster; 102 } 103 104 /** 105 * @return the config 106 */ 107 public String getConfig() 108 { 109 return this.config; 110 } 111 112 /** 113 * @param config the config to set 114 */ 115 public void setConfig(String config) 116 { 117 this.config = config; 118 } 119 120 public String getUser() 121 { 122 return this.user; 123 } 124 125 public void setUser(String user) 126 { 127 this.user = user; 128 } 129 130 public String getPassword() 131 { 132 return this.password; 133 } 134 135 public void setPassword(String password) 136 { 137 this.password = password; 138 } 139 140 public DatabaseClusterConfigurationFactory<Z, D> getConfigurationFactory() 141 { 142 return this.configurationFactory; 143 } 144 145 public void setConfigurationFactory(DatabaseClusterConfigurationFactory<Z, D> configurationFactory) 146 { 147 this.configurationFactory = configurationFactory; 148 } 149 150 public DatabaseClusterFactory<Z, D> getFactory() 151 { 152 return this.factory; 153 } 154 155 public void setFactory(DatabaseClusterFactory<Z, D> clusterFactory) 156 { 157 this.factory = clusterFactory; 158 } 159 160 /** 161 * @return the timeout 162 */ 163 @Override 164 public TimePeriod getTimeout() 165 { 166 return this.timeout; 167 } 168 169 /** 170 * @param value the timeout to set, expressed in the specified units 171 * @param unit the time unit with which to qualify the specified timeout value 172 */ 173 public void setTimeout(long value, TimeUnit unit) 174 { 175 this.timeout = new TimePeriod(value, unit); 176 } 177 178 /** 179 * @throws SQLFeatureNotSupportedException 180 * @see javax.sql.CommonDataSource#getParentLogger() 181 */ 182 @Override 183 public Logger getParentLogger() throws SQLFeatureNotSupportedException 184 { 185 try 186 { 187 return this.getProxy().getParentLogger(); 188 } 189 catch (SQLFeatureNotSupportedException e) 190 { 191 throw e; 192 } 193 catch (SQLException e) 194 { 195 throw new SQLFeatureNotSupportedException(e.getMessage(), e.getSQLState(), e.getErrorCode(), e.getCause()); 196 } 197 } 198 199 /** 200 * @see javax.sql.CommonDataSource#getLoginTimeout() 201 */ 202 @Override 203 public int getLoginTimeout() throws SQLException 204 { 205 return this.getProxy().getLoginTimeout(); 206 } 207 208 /** 209 * @see javax.sql.CommonDataSource#getLogWriter() 210 */ 211 @Override 212 public PrintWriter getLogWriter() throws SQLException 213 { 214 return this.getProxy().getLogWriter(); 215 } 216 217 /** 218 * @see javax.sql.CommonDataSource#setLoginTimeout(int) 219 */ 220 @Override 221 public void setLoginTimeout(int timeout) throws SQLException 222 { 223 this.getProxy().setLoginTimeout(timeout); 224 } 225 226 /** 227 * @see javax.sql.CommonDataSource#setLogWriter(java.io.PrintWriter) 228 */ 229 @Override 230 public void setLogWriter(PrintWriter writer) throws SQLException 231 { 232 this.getProxy().setLogWriter(writer); 233 } 234 235 @Override 236 public Reference getReference() 237 { 238 Reference reference = new Reference(this.getClass().getName(), CommonDataSourceFactory.class.getName(), null); 239 reference.add(new StringRefAddr(CommonDataSourceFactory.CLUSTER, this.cluster)); 240 DatabaseClusterConfigurationFactory<Z, D> factory = this.getConfigurationFactory(); 241 if (factory != null) 242 { 243 reference.add(new BinaryRefAddr(CommonDataSourceFactory.CONFIG, Objects.serialize(factory))); 244 } 245 else 246 { 247 reference.add(new StringRefAddr(CommonDataSourceFactory.CONFIG, this.config)); 248 } 249 if (this.user != null) 250 { 251 reference.add(new StringRefAddr(CommonDataSourceFactory.USER, this.user)); 252 } 253 if (this.password != null) 254 { 255 reference.add(new StringRefAddr(CommonDataSourceFactory.PASSWORD, this.password)); 256 } 257 return reference; 258 } 259}