[ARTEMIS-294] Use doPriviledged block for ServiceLoader

In ServiceUtils, loads services from an AccessController.doPriviledged
block and use the ServiceUtils's own classloader instead of the TCCL
(that may be different depending on who's requesting a managed
connection factory first)

JIRA: https://issues.apache.org/jira/browse/ARTEMIS-294
This commit is contained in:
Jeff Mesnil 2015-11-04 11:38:43 +01:00
parent 8f1848108a
commit 7d6a6de8dd
3 changed files with 47 additions and 45 deletions

View File

@ -16,12 +16,15 @@
*/ */
package org.apache.activemq.artemis.service.extensions; package org.apache.activemq.artemis.service.extensions;
import javax.transaction.TransactionManager; import java.security.AccessController;
import javax.transaction.xa.XAResource; import java.security.PrivilegedAction;
import java.util.Iterator; import java.util.Iterator;
import java.util.Map; import java.util.Map;
import java.util.ServiceLoader; import java.util.ServiceLoader;
import javax.transaction.TransactionManager;
import javax.transaction.xa.XAResource;
import org.apache.activemq.artemis.service.extensions.transactions.TransactionManagerLocator; import org.apache.activemq.artemis.service.extensions.transactions.TransactionManagerLocator;
import org.apache.activemq.artemis.service.extensions.xa.ActiveMQXAResourceWrapper; import org.apache.activemq.artemis.service.extensions.xa.ActiveMQXAResourceWrapper;
import org.apache.activemq.artemis.service.extensions.xa.ActiveMQXAResourceWrapperFactory; import org.apache.activemq.artemis.service.extensions.xa.ActiveMQXAResourceWrapperFactory;
@ -37,7 +40,7 @@ public class ServiceUtils {
private static ActiveMQXAResourceWrapperFactory getActiveMQXAResourceWrapperFactory() { private static ActiveMQXAResourceWrapperFactory getActiveMQXAResourceWrapperFactory() {
if (activeMQXAResourceWrapperFactory == null) { if (activeMQXAResourceWrapperFactory == null) {
setActiveMQXAResourceWrapperFactory(ServiceLoader.load(ActiveMQXAResourceWrapperFactory.class)); activeMQXAResourceWrapperFactory = findActiveMQXAResourceWrapperFactory();
} }
return activeMQXAResourceWrapperFactory; return activeMQXAResourceWrapperFactory;
} }
@ -48,11 +51,7 @@ public class ServiceUtils {
public static synchronized TransactionManager getTransactionManager() { public static synchronized TransactionManager getTransactionManager() {
if (!transactionManagerLoaded) { if (!transactionManagerLoaded) {
Iterator<TransactionManagerLocator> it = ServiceLoader.load(TransactionManagerLocator.class).iterator(); transactionManager = findTransactionManager();
while (it.hasNext() && transactionManager == null) {
transactionManager = it.next().getTransactionManager();
}
if (transactionManager != null) { if (transactionManager != null) {
transactionManagerLoaded = true; transactionManagerLoaded = true;
} }
@ -68,13 +67,39 @@ public class ServiceUtils {
transactionManagerLoaded = (transactionManager != null); transactionManagerLoaded = (transactionManager != null);
} }
private static void setActiveMQXAResourceWrapperFactory(Iterable<ActiveMQXAResourceWrapperFactory> iterable) {
if (iterable.iterator().hasNext()) { /**
activeMQXAResourceWrapperFactory = iterable.iterator().next(); * Find the <em>first</em> transaction manager loaded from the {@code TransactionManagerLocator} service or {@code null} if none is loaded.
} */
else { private static TransactionManager findTransactionManager() {
activeMQXAResourceWrapperFactory = new ActiveMQXAResourceWrapperFactoryImpl(); return AccessController.doPrivileged(new PrivilegedAction<TransactionManager>() {
} @Override
public TransactionManager run() {
Iterator<TransactionManagerLocator> it = ServiceLoader.load(TransactionManagerLocator.class, ServiceUtils.class.getClassLoader()).iterator();
while (it.hasNext() && transactionManager == null) {
transactionManager = it.next().getTransactionManager();
}
return transactionManager;
}
});
} }
/**
* Find the <em>first</em> wrapper factory loaded from the {@code ActiveMQXAResourceWrapperFactory} service or
* use the default {@code ActiveMQXAResourceWrapperFactoryImpl} if none is loaded.
*/
private static ActiveMQXAResourceWrapperFactory findActiveMQXAResourceWrapperFactory() {
return AccessController.doPrivileged(new PrivilegedAction<ActiveMQXAResourceWrapperFactory>() {
@Override
public ActiveMQXAResourceWrapperFactory run() {
Iterator<ActiveMQXAResourceWrapperFactory> iterator = ServiceLoader.load(ActiveMQXAResourceWrapperFactory.class, ServiceUtils.class.getClassLoader()).iterator();
if (iterator.hasNext()) {
return iterator.next();
}
else {
return new ActiveMQXAResourceWrapperFactoryImpl();
}
}
});
}
} }

View File

@ -16,44 +16,20 @@
*/ */
package org.apache.activemq.artemis.service.extensions.tests.xa; package org.apache.activemq.artemis.service.extensions.tests.xa;
import java.lang.reflect.Field; import static org.jgroups.util.Util.assertTrue;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.apache.activemq.artemis.service.extensions.ServiceUtils; import org.apache.activemq.artemis.service.extensions.ServiceUtils;
import org.apache.activemq.artemis.service.extensions.xa.ActiveMQXAResourceWrapperFactory;
import org.apache.activemq.artemis.service.extensions.xa.ActiveMQXAResourceWrapperFactoryImpl;
import org.junit.Test; import org.junit.Test;
import static org.jgroups.util.Util.assertTrue;
public class ServiceUtilsTest { public class ServiceUtilsTest {
@Test @Test
public void testSetActiveMQXAResourceWrapperFactorySetsDefaultImplWhenNoOther() throws Exception { public void testGetActiveMQXAResourceWrapperFactoryLoadsService() throws Exception {
List<ActiveMQXAResourceWrapperFactory> factories = new ArrayList<ActiveMQXAResourceWrapperFactory>(); Method method = ServiceUtils.class.getDeclaredMethod("getActiveMQXAResourceWrapperFactory");
Method method = ServiceUtils.class.getDeclaredMethod("setActiveMQXAResourceWrapperFactory", Iterable.class);
method.setAccessible(true); method.setAccessible(true);
method.invoke(null, factories); Object o = method.invoke(null);
assertTrue(o instanceof MockActiveMQResourceWrapperFactory);
Field field = ServiceUtils.class.getDeclaredField("activeMQXAResourceWrapperFactory");
field.setAccessible(true);
assertTrue(field.get(null) instanceof ActiveMQXAResourceWrapperFactoryImpl);
}
@Test
public void testSetActiveMQXAResourceWrapperFactorySetsExtensionImplWhenSupplied() throws Exception {
List<ActiveMQXAResourceWrapperFactory> factories = new ArrayList<ActiveMQXAResourceWrapperFactory>();
factories.add(new MockActiveMQResourceWrapperFactory());
Method method = ServiceUtils.class.getDeclaredMethod("setActiveMQXAResourceWrapperFactory", Iterable.class);
method.setAccessible(true);
method.invoke(null, factories);
Field field = ServiceUtils.class.getDeclaredField("activeMQXAResourceWrapperFactory");
field.setAccessible(true);
assertTrue(field.get(null) instanceof MockActiveMQResourceWrapperFactory);
} }
} }

View File

@ -0,0 +1 @@
org.apache.activemq.artemis.service.extensions.tests.xa.MockActiveMQResourceWrapperFactory