/*
* JBoss, Home of Professional Open Source.
* Copyright 2013, Red Hat, Inc., and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package io.narayana.spi.util;
import javax.naming.*;
import javax.naming.spi.ObjectFactory;
import javax.sql.XADataSource;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
public class XADSWrapperObjectFactory implements ObjectFactory {
private static Map<String, String> jdbcDrivers = new HashMap<String, String>() {{
put("org.postgresql.Driver", "org.postgresql.xa.PGXADataSource");
put("org.h2.Driver", "org.h2.jdbcx.JdbcDataSource");
put("oracle.jdbc.driver.OracleDriver", "oracle.jdbc.xa.client.OracleXADataSource");
put("com.microsoft.sqlserver.jdbc.SQLServerDriver", "com.microsoft.sqlserver.jdbc.SQLServerXADataSource"); // no setPassword
put("com.mysql.jdbc.Driver", "com.mysql.jdbc.jdbc2.optional.MysqlXADataSource");
put("com.ibm.db2.jcc.DB2Driver", "com.ibm.db2.jcc.DB2XADataSource"); // for DB2 version 8.2 // no setPassword
put("com.sybase.jdbc3.jdbc.SybDriver", "com.sybase.jdbc3.jdbc.SybXADataSource"); // no setPassword
}};
@Override
public Object getObjectInstance(Object obj, Name name, Context nameCtx, Hashtable<?, ?> environment) throws Exception {
Reference ref = (Reference)obj;
XADataSource xads = getXADataSource(
getStringProperty(ref, "binding"),
getStringProperty(ref, "driver"),
getStringProperty(ref, "databaseName"),
getStringProperty(ref, "host"),
getIntegerProperty(ref, "port", 0),
getStringProperty(ref, "username"),
getStringProperty(ref, "password")
);
return xads;
}
public static Reference getReference(String className, String binding,
String driver, String databaseName,
String host, Integer port,
String userName, String password) throws NamingException {
Reference ref = new Reference(className, XADSWrapperObjectFactory.class.getName(), null);
ref.add(new StringRefAddr("binding", binding));
ref.add(new StringRefAddr("driver", driver));
ref.add(new StringRefAddr("databaseName", databaseName));
ref.add(new StringRefAddr("host", host));
ref.add(new StringRefAddr("port", port.toString()));
ref.add(new StringRefAddr("username", userName));
ref.add(new StringRefAddr("password", password));
return ref;
}
public static XADSWrapper getXADataSource(String binding, String driver, String databaseName, String host, Integer port, String userName, String password)
throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
XADSWrapper wrapper;
String xaDSClassName = jdbcDrivers.get(driver);
if (xaDSClassName == null)
throw new RuntimeException("JDBC2 driver " + driver + " not recognised");
wrapper = new XADSWrapper(binding, driver, databaseName, host, port, xaDSClassName, userName, password);
if( driver.equals("org.h2.Driver")) {
wrapper.setProperty("URL", databaseName);
} else {
wrapper.setProperty("databaseName", databaseName);
wrapper.setProperty("serverName", host);
wrapper.setProperty("portNumber", port);
}
if (driver.equals("oracle.jdbc.driver.OracleDriver")) {
wrapper.setProperty("driverType", "thin");
} else if( driver.equals("com.microsoft.sqlserver.jdbc.SQLServerDriver")) {
wrapper.setProperty("sendStringParametersAsUnicode", false);
} else if( driver.equals("com.mysql.jdbc.Driver")) {
// Note: MySQL XA only works on InnoDB tables.
// set 'default-storage-engine=innodb' in e.g. /etc/my.cnf
// so that the 'CREATE TABLE ...' statments behave correctly.
// doing this config on a per connection basis instead is
// possible but would require lots of code changes :-(
wrapper.setProperty("pinGlobalTxToPhysicalConnection", true); // Bad Things happen if you forget this bit.
} else if( driver.equals("com.ibm.db2.jcc.DB2Driver")) {
wrapper.setProperty("driverType", 4);
} else if( driver.equals("org.h2.Driver")) {
wrapper.setProperty("URL", databaseName);
}
return wrapper;
}
private String getStringProperty(Reference ref, String propName) {
RefAddr addr = ref.get(propName);
return (addr == null ? null : (String)addr.getContent());
}
private Integer getIntegerProperty(Reference ref, String propName, int defValue) {
RefAddr addr = ref.get(propName);
if (addr == null)
return defValue;
Object content = addr.getContent();
return (content == null ? defValue : Integer.parseInt(content.toString()));
}
}