[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:
parent
8f1848108a
commit
7d6a6de8dd
|
@ -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.
|
||||||
|
*/
|
||||||
|
private static TransactionManager findTransactionManager() {
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
else {
|
return transactionManager;
|
||||||
activeMQXAResourceWrapperFactory = new ActiveMQXAResourceWrapperFactoryImpl();
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
org.apache.activemq.artemis.service.extensions.tests.xa.MockActiveMQResourceWrapperFactory
|
Loading…
Reference in New Issue