/*
* JBoss, Home of Professional Open Source
* Copyright 2009 Red Hat Inc. and/or its affiliates and other
* contributors as indicated by the @author tags. All rights reserved.
* See the copyright.txt 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 org.infinispan.transaction.lookup;
import org.infinispan.config.Configuration;
import org.infinispan.factories.annotations.Inject;
import org.infinispan.transaction.tm.DummyTransactionManager;
import org.infinispan.util.Util;
import org.infinispan.util.logging.Log;
import org.infinispan.util.logging.LogFactory;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.transaction.TransactionManager;
import java.lang.reflect.Method;
/**
* A transaction manager lookup class that attempts to locate a TransactionManager. A variety of different classes and
* JNDI locations are tried, for servers such as: <ul> <li> JBoss <li> JRun4 <li> Resin <li> Orion <li> JOnAS <li> BEA
* Weblogic <li> Websphere 4.0, 5.0, 5.1, 6.0 <li> Sun, Glassfish </ul> If a transaction manager is not found, returns a
* {@link org.infinispan.transaction.tm.DummyTransactionManager}.
*
* @author Markus Plesser
* @since 4.0
*/
public class GenericTransactionManagerLookup implements TransactionManagerLookup {
private static final Log log = LogFactory.getLog(GenericTransactionManagerLookup.class);
/**
* JNDI lookups performed?
*/
private boolean lookupDone = false;
/**
* No JNDI available?
*/
private boolean lookupFailed = false;
/**
* No JBoss TM embedded jars found?
*/
private boolean noJBossTM = false;
/**
* The JTA TransactionManager found.
*/
private TransactionManager tm = null;
/**
* JNDI locations for TransactionManagers we know of
*/
private static String[][] knownJNDIManagers =
{
{"java:jboss/TransactionManager", "JBoss AS 7"},
{"java:/TransactionManager", "JBoss AS 4 ~ 6, JRun4"},
{"java:comp/TransactionManager", "Resin 3.x"},
{"java:appserver/TransactionManager", "Sun Glassfish"},
{"java:pm/TransactionManager", "Borland, Sun"},
{"javax.transaction.TransactionManager", "BEA WebLogic"},
{"java:comp/UserTransaction", "Resin, Orion, JOnAS (JOTM)"},
};
/**
* WebSphere 5.1 and 6.0 TransactionManagerFactory
*/
private static final String WS_FACTORY_CLASS_5_1 = "com.ibm.ws.Transaction.TransactionManagerFactory";
/**
* WebSphere 5.0 TransactionManagerFactory
*/
private static final String WS_FACTORY_CLASS_5_0 = "com.ibm.ejs.jts.jta.TransactionManagerFactory";
/**
* WebSphere 4.0 TransactionManagerFactory
*/
private static final String WS_FACTORY_CLASS_4 = "com.ibm.ejs.jts.jta.JTSXA";
private Configuration configuration;
@Inject
public void setConfiguration(Configuration configuration) {
this.configuration = configuration;
}
/**
* Get the systemwide used TransactionManager
*
* @return TransactionManager
*/
@Override
public TransactionManager getTransactionManager() {
if (!lookupDone)
doLookups(configuration.getClassLoader());
if (tm != null)
return tm;
if (lookupFailed) {
if (!noJBossTM) {
// First try an embedded JBossTM instance
tryEmbeddedJBossTM();
}
if (noJBossTM) {
//fall back to a dummy from Infinispan
useDummyTM();
}
}
return tm;
}
private void useDummyTM() {
tm = DummyTransactionManager.getInstance();
log.fallingBackToDummyTm();
}
private void tryEmbeddedJBossTM() {
try {
JBossStandaloneJTAManagerLookup jBossStandaloneJTAManagerLookup = new JBossStandaloneJTAManagerLookup();
jBossStandaloneJTAManagerLookup.init(configuration);
tm = jBossStandaloneJTAManagerLookup.getTransactionManager();
} catch (Exception e) {
noJBossTM = true;
}
}
/**
* Try to figure out which TransactionManager to use
*/
private void doLookups(ClassLoader cl) {
if (lookupFailed)
return;
InitialContext ctx = null;
try {
ctx = new InitialContext();
}
catch (NamingException e) {
log.failedToCreateInitialCtx(e);
lookupFailed = true;
Util.close(ctx);
return;
}
try {
//probe jndi lookups first
for (String[] knownJNDIManager : knownJNDIManagers) {
Object jndiObject;
try {
log.debugf("Trying to lookup TransactionManager for %s", knownJNDIManager[1]);
jndiObject = ctx.lookup(knownJNDIManager[0]);
}
catch (NamingException e) {
log.debugf("Failed to perform a lookup for [%s (%s)]",
knownJNDIManager[0], knownJNDIManager[1]);
continue;
}
if (jndiObject instanceof TransactionManager) {
tm = (TransactionManager) jndiObject;
log.debugf("Found TransactionManager for %s", knownJNDIManager[1]);
return;
}
}
lookupDone = true;
} finally {
Util.close(ctx);
}
//try to find websphere lookups since we came here
// The TM may be deployed embedded alongside the app, so this needs to be looked up on the same CL as the Cache
Class<?> clazz;
try {
log.debugf("Trying WebSphere 5.1: %s", WS_FACTORY_CLASS_5_1);
clazz = Util.loadClassStrict(WS_FACTORY_CLASS_5_1, cl);
log.debugf("Found WebSphere 5.1: %s", WS_FACTORY_CLASS_5_1);
}
catch (ClassNotFoundException ex) {
try {
log.debugf("Trying WebSphere 5.0: %s", WS_FACTORY_CLASS_5_0);
clazz = Util.loadClassStrict(WS_FACTORY_CLASS_5_0, cl);
log.debugf("Found WebSphere 5.0: %s", WS_FACTORY_CLASS_5_0);
}
catch (ClassNotFoundException ex2) {
try {
log.debugf("Trying WebSphere 4: %s", WS_FACTORY_CLASS_4);
clazz = Util.loadClassStrict(WS_FACTORY_CLASS_4, cl);
log.debugf("Found WebSphere 4: %s", WS_FACTORY_CLASS_4);
}
catch (ClassNotFoundException ex3) {
log.debug("Couldn't find any WebSphere TransactionManager factory class, neither for WebSphere version 5.1 nor 5.0 nor 4");
lookupFailed = true;
return;
}
}
}
try {
Class<?>[] signature = null;
Object[] args = null;
Method method = clazz.getMethod("getTransactionManager", signature);
tm = (TransactionManager) method.invoke(null, args);
}
catch (Exception ex) {
log.unableToInvokeWebsphereStaticGetTmMethod(ex, clazz.getName());
}
}
}