/**
* Alipay.com Inc.
* Copyright (c) 2004-2012 All Rights Reserved.
*/
package com.alipay.zdal.datasource.resource.adapter.jdbc.local;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
import javax.security.auth.Subject;
import com.alipay.zdal.datasource.resource.JBossResourceException;
import com.alipay.zdal.datasource.resource.ResourceException;
import com.alipay.zdal.datasource.resource.adapter.jdbc.BaseWrapperManagedConnectionFactory;
import com.alipay.zdal.datasource.resource.spi.ConnectionManager;
import com.alipay.zdal.datasource.resource.spi.ConnectionRequestInfo;
import com.alipay.zdal.datasource.resource.spi.ManagedConnection;
import com.alipay.zdal.datasource.resource.util.NestedRuntimeException;
/**
* LocalManagedConnectionFactory
*
*
* @author ����
* @version $Id: LocalManagedConnectionFactory.java, v 0.1 2014-1-6 ����05:32:13 Exp $
*/
public class LocalManagedConnectionFactory extends BaseWrapperManagedConnectionFactory {
static final long serialVersionUID = 4698955390505160469L;
private String driverClass;
private transient Driver driver;
private String connectionURL;
protected String connectionProperties;
/**
* Get the value of ConnectionURL.
*
* @return value of ConnectionURL.
*/
public String getConnectionURL() {
return connectionURL;
}
/**
* Set the value of ConnectionURL.
*
* @param connectionURL Value to assign to ConnectionURL.
*/
public void setConnectionURL(final String connectionURL) {
this.connectionURL = connectionURL;
}
/**
* Get the DriverClass value.
*
* @return the DriverClass value.
*/
public String getDriverClass() {
return driverClass;
}
/**
* Set the DriverClass value.
*
* @param driverClass The new DriverClass value.
*/
public synchronized void setDriverClass(final String driverClass) {
this.driverClass = driverClass;
driver = null;
}
/**
* Get the value of connectionProperties.
*
* @return value of connectionProperties.
*/
public String getConnectionProperties() {
return connectionProperties;
}
/**
* Set the value of connectionProperties.
*
* @param connectionProperties Value to assign to connectionProperties.
*/
public void setConnectionProperties(String connectionProperties) {
this.connectionProperties = connectionProperties;
connectionProps.clear();
if (connectionProperties != null) {
// Map any \ to \\
connectionProperties = connectionProperties.replaceAll("\\\\", "\\\\\\\\");
InputStream is = new ByteArrayInputStream(connectionProperties.getBytes());
try {
connectionProps.load(is);
} catch (IOException ioe) {
throw new NestedRuntimeException("Could not load connection properties", ioe);
}
}
}
public void setConnectionProperties(Map<String, String> connectionProperties) {
connectionProps.clear();
connectionProps.putAll(connectionProperties);
StringBuilder sb = new StringBuilder();
for (Map.Entry<String, String> property : connectionProperties.entrySet()) {
if (sb.length() > 0) {
sb.append('\n');
}
sb.append(property.getKey()).append('=').append(property.getValue());
}
}
/**
* @see com.alipay.zdal.datasource.resource.spi.ManagedConnectionFactory#createManagedConnection(javax.security.auth.Subject, com.alipay.zdal.datasource.resource.spi.ConnectionRequestInfo)
*/
public ManagedConnection createManagedConnection(Subject subject, ConnectionRequestInfo cri)
throws com.alipay.zdal.datasource.resource.ResourceException {
Properties props = getConnectionProperties(subject, cri);
// Some friendly drivers (Oracle, you guessed right) modify the props you supply.
// Since we use our copy to identify compatibility in matchManagedConnection, we need
// a pristine copy for our own use. So give the friendly driver a copy.
Properties copy = (Properties) props.clone();
if (log.isDebugEnabled()) {
// Make yet another copy to mask the password
Properties logCopy = copy;
if (copy.getProperty("password") != null) {
logCopy = (Properties) props.clone();
logCopy.setProperty("password", "--hidden--");
}
log.debug("Using properties: " + logCopy);
}
try {
String url = getConnectionURL();
Driver d = getDriver(url);
Connection con = d.connect(url, copy);
if (con == null) {
throw new JBossResourceException("Wrong driver class for this connection URL");
}
String stz = copy.getProperty("sessionTimeZone");//֧��oracle-driver������timestamp�ֶε�����.
if (stz != null && stz.trim().length() > 0
&& (con instanceof oracle.jdbc.OracleConnection)) {
((oracle.jdbc.OracleConnection) con).setSessionTimeZone(stz);
}
return new LocalManagedConnection(this, con, props, transactionIsolation,
preparedStatementCacheSize);
} catch (Exception e) {
throw new JBossResourceException("Could not create connection,the url = "
+ getConnectionURL(), e);
}
}
/**
* @see com.alipay.zdal.datasource.resource.spi.ManagedConnectionFactory#matchManagedConnections(java.util.Set, javax.security.auth.Subject, com.alipay.zdal.datasource.resource.spi.ConnectionRequestInfo)
*/
public ManagedConnection matchManagedConnections(final Set mcs, final Subject subject,
final ConnectionRequestInfo cri)
throws ResourceException {
Properties newProps = getConnectionProperties(subject, cri);
for (Iterator i = mcs.iterator(); i.hasNext();) {
Object o = i.next();
if (o instanceof LocalManagedConnection) {
LocalManagedConnection mc = (LocalManagedConnection) o;
//First check the properties
if (mc.getProps().equals(newProps)) {
//Next check to see if we are validating on matchManagedConnections
if ((getValidateOnMatch() && mc.checkValid()) || !getValidateOnMatch()) {
return mc;
}
}
}
}
return null;
}
/**
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
int result = 17;
result = result * 37 + ((connectionURL == null) ? 0 : connectionURL.hashCode());
result = result * 37 + ((driverClass == null) ? 0 : driverClass.hashCode());
result = result * 37 + ((userName == null) ? 0 : userName.hashCode());
result = result * 37 + ((password == null) ? 0 : password.hashCode());
result = result * 37 + transactionIsolation;
return result;
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (getClass() != other.getClass()) {
return false;
}
LocalManagedConnectionFactory otherMcf = (LocalManagedConnectionFactory) other;
return this.connectionURL.equals(otherMcf.connectionURL)
&& this.driverClass.equals(otherMcf.driverClass)
&& ((this.userName == null) ? otherMcf.userName == null : this.userName
.equals(otherMcf.userName))
&& ((this.password == null) ? otherMcf.password == null : this.password
.equals(otherMcf.password))
&& this.transactionIsolation == otherMcf.transactionIsolation;
}
/**
* Check the driver for the given URL. If it is not registered already
* then register it.
*
* @param url The JDBC URL which we need a driver for.
*/
protected synchronized Driver getDriver(final String url) throws ResourceException {
// don't bother if it is loaded already
if (driver != null) {
return driver;
}
if (log.isDebugEnabled()) {
log.debug("Checking driver for URL: " + url);
}
if (driverClass == null) {
throw new JBossResourceException("No Driver class specified!");
}
// Check if the driver is already loaded, if not then try to load it
if (isDriverLoadedForURL(url)) {
return driver;
} // end of if ()
try {
if (isDriverLoadedForURL(url)) {
//return immediately, some drivers (Cloudscape) do not let you create an instance.
return driver;
}
// //We loaded the class, but either it didn't register
// //and is not spec compliant, or is the wrong class.
// if (url.startsWith("jdbc:oracle:oci") && driverClass.equals("oracle.jdbc.OracleDriver")) {//ֻ����oracle-oci��ʱ�����Ҫ��cloundengine�л�ȡdriver.
// driver = ZDataSourceOciDriver.getDriver(driverClass, url);
// } else {
Class<?> clazz = Class.forName(driverClass, true, Thread.currentThread()
.getContextClassLoader());
driver = (Driver) clazz.newInstance();
// }
DriverManager.registerDriver(driver);
if (isDriverLoadedForURL(url)) {
return driver;
}
//We can even instantiate one, it must be the wrong class for the URL.
} catch (Exception e) {
throw new JBossResourceException("ERROR ## Failed to register driver for: "
+ driverClass, e);
}
throw new JBossResourceException(
"ERROR ## Apparently wrong driver class specified for URL: class: " + driverClass
+ ", url: " + url);
}
private boolean isDriverLoadedForURL(String url) {
try {
driver = DriverManager.getDriver(url);
if (log.isDebugEnabled()) {
log.debug("Driver already registered for url: " + url);
}
return true;
} catch (Exception e) {
if (log.isDebugEnabled()) {
log.debug("Driver not yet registered for url: " + url);
}
return false;
}
}
protected String internalGetConnectionURL() {
return connectionURL;
}
public Object createConnectionFactory(ConnectionManager cxManager) throws ResourceException {
throw new JBossResourceException("NYI");
}
@Override
public Object createConnectionFactory(ConnectionManager cxManager, String dataSourceName)
throws ResourceException {
return null;
}
}