activemq-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From clebertsuco...@apache.org
Subject [2/2] activemq-artemis git commit: ARTEMIS-276 JMSBridge should be TCCL aware
Date Fri, 23 Oct 2015 14:25:40 GMT
ARTEMIS-276 JMSBridge should be TCCL aware


Project: http://git-wip-us.apache.org/repos/asf/activemq-artemis/repo
Commit: http://git-wip-us.apache.org/repos/asf/activemq-artemis/commit/02cedbf8
Tree: http://git-wip-us.apache.org/repos/asf/activemq-artemis/tree/02cedbf8
Diff: http://git-wip-us.apache.org/repos/asf/activemq-artemis/diff/02cedbf8

Branch: refs/heads/master
Commit: 02cedbf8da89e3cf0f5b1e7834dc5abc94827336
Parents: 270ad3e
Author: Howard Gao <howard.gao@gmail.com>
Authored: Fri Oct 23 21:46:50 2015 +0800
Committer: Clebert Suconic <clebertsuconic@apache.org>
Committed: Fri Oct 23 10:25:28 2015 -0400

----------------------------------------------------------------------
 .../artemis/jms/bridge/impl/JMSBridgeImpl.java  |  28 ++++-
 .../jms/bridge/impl/JMSBridgeImplTest.java      | 114 +++++++++++++++++++
 2 files changed, 141 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/02cedbf8/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/bridge/impl/JMSBridgeImpl.java
----------------------------------------------------------------------
diff --git a/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/bridge/impl/JMSBridgeImpl.java
b/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/bridge/impl/JMSBridgeImpl.java
index 8a22bb1..f3bd337 100644
--- a/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/bridge/impl/JMSBridgeImpl.java
+++ b/artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/bridge/impl/JMSBridgeImpl.java
@@ -58,6 +58,8 @@ import javax.transaction.Transaction;
 import javax.transaction.TransactionManager;
 import javax.transaction.TransactionRolledbackException;
 import javax.transaction.xa.XAResource;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
 import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -67,6 +69,7 @@ import java.util.Map.Entry;
 import java.util.ServiceLoader;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
 import java.util.concurrent.TimeUnit;
 
 public final class JMSBridgeImpl implements JMSBridge {
@@ -176,6 +179,8 @@ public final class JMSBridgeImpl implements JMSBridge {
 
    private ActiveMQRegistry registry;
 
+   private ClassLoader moduleTccl;
+
    /*
     * Constructor for MBean
     */
@@ -319,6 +324,12 @@ public final class JMSBridgeImpl implements JMSBridge {
          stopping = false;
       }
 
+      moduleTccl = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>()
{
+         public ClassLoader run() {
+            return Thread.currentThread().getContextClassLoader();
+         }
+      });
+
       locateRecoveryRegistry();
 
       if (started) {
@@ -1545,7 +1556,22 @@ public final class JMSBridgeImpl implements JMSBridge {
     * and 1 for the eventual failureHandler)
     */
    private ExecutorService createExecutor() {
-      return Executors.newFixedThreadPool(3);
+      ExecutorService service = Executors.newFixedThreadPool(3, new ThreadFactory() {
+         @Override
+         public Thread newThread(Runnable r) {
+            final Thread thr = new Thread(r);
+            if (moduleTccl != null) {
+               AccessController.doPrivileged(new PrivilegedAction() {
+                  public Object run() {
+                     thr.setContextClassLoader(moduleTccl);
+                     return null;
+                  }
+               });
+            }
+            return thr;
+         }
+      });
+      return service;
    }
 
    // Inner classes ---------------------------------------------------------------

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/02cedbf8/tests/timing-tests/src/test/java/org/apache/activemq/artemis/tests/timing/jms/bridge/impl/JMSBridgeImplTest.java
----------------------------------------------------------------------
diff --git a/tests/timing-tests/src/test/java/org/apache/activemq/artemis/tests/timing/jms/bridge/impl/JMSBridgeImplTest.java
b/tests/timing-tests/src/test/java/org/apache/activemq/artemis/tests/timing/jms/bridge/impl/JMSBridgeImplTest.java
index 9e9fd09..2ff8886 100644
--- a/tests/timing-tests/src/test/java/org/apache/activemq/artemis/tests/timing/jms/bridge/impl/JMSBridgeImplTest.java
+++ b/tests/timing-tests/src/test/java/org/apache/activemq/artemis/tests/timing/jms/bridge/impl/JMSBridgeImplTest.java
@@ -68,6 +68,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
 
 public class JMSBridgeImplTest extends ActiveMQTestBase {
@@ -83,6 +84,8 @@ public class JMSBridgeImplTest extends ActiveMQTestBase {
 
    private JMSServerManager jmsServer;
 
+   private static final AtomicBoolean tcclClassFound = new AtomicBoolean(false);
+
    @Rule
    public ExpectedException thrown = ExpectedException.none();
 
@@ -148,6 +151,26 @@ public class JMSBridgeImplTest extends ActiveMQTestBase {
       return cf;
    }
 
+   private static ConnectionFactoryFactory newTCCLAwareConnectionFactoryFactory(final ConnectionFactory
cf) {
+      return new ConnectionFactoryFactory() {
+         public ConnectionFactory createConnectionFactory() throws Exception {
+            loadATCCLClass();
+            return cf;
+         }
+
+         private void loadATCCLClass() {
+            ClassLoader tcclClassLoader = Thread.currentThread().getContextClassLoader();
+            try {
+               tcclClassLoader.loadClass("com.class.only.visible.to.tccl.SomeClass");
+               tcclClassFound.set(true);
+            }
+            catch (ClassNotFoundException e) {
+               e.printStackTrace();
+            }
+         }
+      };
+   }
+
    // Constructors --------------------------------------------------
 
    // Public --------------------------------------------------------
@@ -546,9 +569,80 @@ public class JMSBridgeImplTest extends ActiveMQTestBase {
 
    }
 
+   @Test
+   public void testStartWithSpecificTCCL() throws Exception {
+      MockContextClassLoader mockTccl = setMockTCCL();
+      try {
+         final AtomicReference<Connection> sourceConn = new AtomicReference<Connection>();
+         ActiveMQJMSConnectionFactory failingSourceCF = new ActiveMQJMSConnectionFactory(false,
new TransportConfiguration(InVMConnectorFactory.class.getName())) {
+            private static final long serialVersionUID = -8866390811966688830L;
+
+            @Override
+            public Connection createConnection() throws JMSException {
+               sourceConn.set(super.createConnection());
+               return sourceConn.get();
+            }
+         };
+         // Note! We disable automatic reconnection on the session factory. The bridge needs
to do the reconnection
+         failingSourceCF.setReconnectAttempts(0);
+         failingSourceCF.setBlockOnNonDurableSend(true);
+         failingSourceCF.setBlockOnDurableSend(true);
+
+         ConnectionFactoryFactory sourceCFF = JMSBridgeImplTest.newTCCLAwareConnectionFactoryFactory(failingSourceCF);
+         ConnectionFactoryFactory targetCFF = JMSBridgeImplTest.newConnectionFactoryFactory(JMSBridgeImplTest.createConnectionFactory());
+         DestinationFactory sourceDF = JMSBridgeImplTest.newDestinationFactory(ActiveMQJMSClient.createQueue(JMSBridgeImplTest.SOURCE));
+         DestinationFactory targetDF = JMSBridgeImplTest.newDestinationFactory(ActiveMQJMSClient.createQueue(JMSBridgeImplTest.TARGET));
+         TransactionManager tm = JMSBridgeImplTest.newTransactionManager();
+
+         JMSBridgeImpl bridge = new JMSBridgeImpl();
+         Assert.assertNotNull(bridge);
+
+         bridge.setSourceConnectionFactoryFactory(sourceCFF);
+         bridge.setSourceDestinationFactory(sourceDF);
+         bridge.setTargetConnectionFactoryFactory(targetCFF);
+         bridge.setTargetDestinationFactory(targetDF);
+         bridge.setFailureRetryInterval(10);
+         bridge.setMaxRetries(2);
+         bridge.setMaxBatchSize(1);
+         bridge.setMaxBatchTime(-1);
+         bridge.setTransactionManager(tm);
+         bridge.setQualityOfServiceMode(QualityOfServiceMode.AT_MOST_ONCE);
+
+         Assert.assertFalse(bridge.isStarted());
+         bridge.start();
+         Assert.assertTrue(bridge.isStarted());
+
+         unsetMockTCCL(mockTccl);
+         tcclClassFound.set(false);
+
+         sourceConn.get().getExceptionListener().onException(new JMSException("exception
on the source"));
+         Thread.sleep(4 * bridge.getFailureRetryInterval());
+         // reconnection must have succeeded
+         Assert.assertTrue(bridge.isStarted());
+
+         bridge.stop();
+         Assert.assertFalse(bridge.isStarted());
+         assertTrue(tcclClassFound.get());
+      }
+      finally {
+         if (mockTccl != null) unsetMockTCCL(mockTccl);
+      }
+   }
+
+
    // Package protected ---------------------------------------------
 
    // Protected -----------------------------------------------------
+   private static MockContextClassLoader setMockTCCL() {
+      ClassLoader parent = JMSBridgeImpl.class.getClassLoader();
+      MockContextClassLoader tccl = new MockContextClassLoader(parent);
+      Thread.currentThread().setContextClassLoader(tccl);
+      return tccl;
+   }
+
+   private static void unsetMockTCCL(MockContextClassLoader mockTccl) {
+      Thread.currentThread().setContextClassLoader(mockTccl.getOriginal());
+   }
 
    @Override
    @Before
@@ -633,5 +727,25 @@ public class JMSBridgeImplTest extends ActiveMQTestBase {
    // Private -------------------------------------------------------
 
    // Inner classes -------------------------------------------------
+   private static class MockContextClassLoader extends ClassLoader {
+      private final ClassLoader original;
+      private final String knownClass = "com.class.only.visible.to.tccl.SomeClass";
 
+      public MockContextClassLoader(ClassLoader parent) {
+         super(parent);
+         original = Thread.currentThread().getContextClassLoader();
+      }
+
+      public ClassLoader getOriginal() {
+         return original;
+      }
+
+      @Override
+      protected Class<?> findClass(String name) throws ClassNotFoundException {
+         if (knownClass.equals(name)) {
+            return null;
+         }
+         return super.findClass(name);
+      }
+   }
 }


Mime
View raw message