<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cluster/failover/PageCleanupWhileReplicaCatchupTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.cluster.failover;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import java.util.HashMap;
import java.util.Map;

import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.paging.impl.PagingStoreImpl;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.NodeManager;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.apache.activemq.artemis.core.settings.impl.AddressFullMessagePolicy;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.tests.util.CFUtil;
import org.apache.activemq.artemis.utils.Wait;
import org.jboss.logging.Logger;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class PageCleanupWhileReplicaCatchupTest extends FailoverTestBase {

   private static final Logger logger = Logger.getLogger(PageCleanupWhileReplicaCatchupTest.class);
   volatile boolean running = true;

   @Override
   @Before
   public void setUp() throws Exception {
      startBackupServer = false;
      super.setUp();
   }

   @Override
   protected void createConfigs() throws Exception {
      createReplicatedConfigs();
   }

   @Override
   protected TransportConfiguration getAcceptorTransportConfiguration(final boolean live) {
      return getNettyAcceptorTransportConfiguration(live);
   }

   @Override
   protected TransportConfiguration getConnectorTransportConfiguration(final boolean live) {
      return getNettyConnectorTransportConfiguration(live);
   }

   @Override
   protected ActiveMQServer createInVMFailoverServer(final boolean realFiles,
                                                     final Configuration configuration,
                                                     final NodeManager nodeManager,
                                                     int id) {
      Map<String, AddressSettings> conf = new HashMap<>();
      AddressSettings as = new AddressSettings().setMaxSizeBytes(PAGE_MAX).setPageSizeBytes(PAGE_SIZE).setAddressFullMessagePolicy(AddressFullMessagePolicy.PAGE);
      conf.put(ADDRESS.toString(), as);
      return createInVMFailoverServer(realFiles, configuration, PAGE_SIZE, PAGE_MAX, conf, nodeManager, id);
   }

   @Test(timeout = 120_000)
   public void testPageCleanup() throws Throwable {
      int numberOfWorkers = 20;

      Worker[] workers = new Worker[numberOfWorkers];

      for (int i = 0; i < 20; i++) {
         liveServer.getServer().addAddressInfo(new AddressInfo("WORKER_" + i).setAutoCreated(false).addRoutingType(RoutingType.ANYCAST));
         liveServer.getServer().createQueue(new QueueConfiguration("WORKER_" + i).setRoutingType(RoutingType.ANYCAST).setDurable(true));
         workers[i] = new Worker("WORKER_" + i);
         workers[i].start();
      }

      for (int i = 0; i < 25; i++) {
         logger.debug("Starting replica " + i);
         backupServer.start();
         Wait.assertTrue(backupServer.getServer()::isReplicaSync);
         backupServer.stop();
      }

      running = false;

      for (Worker worker : workers) {
         worker.join();
      }

      Throwable toThrow = null;
      for (Worker worker : workers) {
         if (worker.throwable != null) {
            worker.queue.getPagingStore().getCursorProvider().scheduleCleanup();
            Thread.sleep(2000);
            worker.queue.getPagingStore().getCursorProvider().cleanup();

            // This is more a debug statement in case there is an issue with the test
            System.out.println("PagingStore(" + worker.queueName + ")::isPaging() = " + worker.queue.getPagingStore().isPaging() + " after test failure " + worker.throwable.getMessage());
            toThrow = worker.throwable;
         }
      }

      if (toThrow != null) {
         throw toThrow;
      }

      for (Worker worker : workers) {
         PagingStoreImpl storeImpl = (PagingStoreImpl)worker.queue.getPagingStore();
         Assert.assertTrue("Store impl " + worker.queueName + " had more files than expected on " + storeImpl.getFolder(), storeImpl.getNumberOfFiles() <= 1);
      }
   }

   class Worker extends Thread {

      final String queueName;
      final Queue queue;
      volatile Throwable throwable;

      Worker(String queue) {
         super("Worker on queue " + queue + " for test on PageCleanupWhileReplicaCatchupTest");
         this.queueName = queue;
         this.queue = liveServer.getServer().locateQueue(queueName);
      }

      @Override
      public void run() {
         try {
            ConnectionFactory factory = CFUtil.createConnectionFactory("CORE", "tcp://localhost:61616");
            try (Connection connection = factory.createConnection()) {
               Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
               connection.start();
               javax.jms.Queue jmsQueue = session.createQueue(queueName);
               MessageConsumer consumer = session.createConsumer(jmsQueue);
               MessageProducer producer = session.createProducer(jmsQueue);
               while (running) {
                  queue.getPagingStore().startPaging();
                  for (int i = 0; i < 10; i++) {
                     producer.send(session.createTextMessage("hello " + i));
                  }
                  Wait.assertTrue(queue.getPagingStore()::isPaging);
                  for (int i = 0; i < 10; i++) {
                     Assert.assertNotNull(consumer.receive(5000));
                  }
                  Wait.assertFalse("Waiting for !Paging on " + queueName + " with folder " + queue.getPagingStore().getFolder(), queue.getPagingStore()::isPaging);
               }
            }
         } catch (Throwable e) {
            e.printStackTrace(System.out);
            this.throwable = e;
         }

      }
   }

}


<|start_filename|>artemis-core-client/src/main/java/org/apache/activemq/artemis/spi/core/remoting/ssl/OpenSSLContextFactory.java<|end_filename|>
/*
 * Copyright 2021 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.spi.core.remoting.ssl;

import java.util.Map;

import io.netty.handler.ssl.SslContext;
import org.jboss.logging.Logger;

/**
 * Service interface to create an {@link SslContext} for a configuration.
 * This is ONLY used with OpenSSL.
 * To create and use your own implementation you need to create a file
 * <code>META-INF/services/org.apache.activemq.artemis.spi.core.remoting.ssl.OpenSSLContextFactory</code>
 * in your jar and fill it with the full qualified name of your implementation.
 */
public interface OpenSSLContextFactory extends Comparable<OpenSSLContextFactory> {

   Logger log = Logger.getLogger(OpenSSLContextFactory.class);

   /**
    * Release any cached {@link SslContext} instances.
    */
   default void clearSslContexts() {
   }

   @Override
   default int compareTo(final OpenSSLContextFactory other) {
      return this.getPriority() - other.getPriority();
   }

   /**
    * @param additionalOpts implementation specific additional options.
    *
    * @return an {@link SslContext} instance for the given configuration.
    */
   SslContext getClientSslContext(SSLContextConfig config, Map<String, Object> additionalOpts) throws Exception;

   /**
    * @param additionalOpts implementation specific additional options.
    *
    * @return an {@link SslContext} instance for the given configuration.
    */
   SslContext getServerSslContext(SSLContextConfig config, Map<String, Object> additionalOpts) throws Exception;

   /**
    * The priority for the {@link OpenSSLContextFactory} when resolving the service to get the implementation.
    * This is used when selecting the implementation when several implementations are loaded.
    * The highest priority implementation will be used.
    */
   int getPriority();
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/largemessages/AmqpReplicatedLargeMessageTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.tests.integration.amqp.largemessages;

import java.net.URI;
import java.util.concurrent.TimeUnit;

import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.apache.activemq.artemis.tests.util.TransportConfigurationUtils;
import org.apache.activemq.artemis.tests.util.Wait;
import org.apache.activemq.transport.amqp.client.AmqpClient;
import org.apache.activemq.transport.amqp.client.AmqpConnection;
import org.apache.activemq.transport.amqp.client.AmqpMessage;
import org.apache.activemq.transport.amqp.client.AmqpReceiver;
import org.apache.activemq.transport.amqp.client.AmqpSender;
import org.apache.activemq.transport.amqp.client.AmqpSession;
import org.apache.qpid.proton.amqp.messaging.Data;
import org.junit.Assert;
import org.junit.Test;

public class AmqpReplicatedLargeMessageTest extends AmqpReplicatedTestSupport {

   private String smallFrameLive = new String("tcp://localhost:" + (AMQP_PORT + 10));
   private String smallFrameBackup = new String("tcp://localhost:" + (AMQP_PORT + 10));

   @Override
   protected TransportConfiguration getAcceptorTransportConfiguration(final boolean live) {
      return TransportConfigurationUtils.getInVMAcceptor(live);
   }

   @Override
   protected TransportConfiguration getConnectorTransportConfiguration(final boolean live) {
      return TransportConfigurationUtils.getInVMConnector(live);
   }

   @Override
   public void setUp() throws Exception {
      super.setUp();

      createReplicatedConfigs();
      liveConfig.addAcceptorConfiguration("amqp", smallFrameLive + "?protocols=AMQP;useEpoll=false;maxFrameSize=512");
      backupConfig.addAcceptorConfiguration("amqp", smallFrameBackup + "?protocols=AMQP;useEpoll=false;maxFrameSize=512");
      liveServer.start();
      backupServer.start();

      liveServer.getServer().addAddressInfo(new AddressInfo(getQueueName(), RoutingType.ANYCAST));
      liveServer.getServer().createQueue(new QueueConfiguration(getQueueName()).setRoutingType(RoutingType.ANYCAST));


      waitForRemoteBackupSynchronization(backupServer.getServer());
   }

   public SimpleString getQueueName() {
      return SimpleString.toSimpleString("replicatedTest");
   }


   @Test(timeout = 60_000)
   public void testSimpleSend() throws Exception {
      try {

         ActiveMQServer server = liveServer.getServer();

         boolean crashServer = true;
         int size = 100 * 1024;
         AmqpClient client = createAmqpClient(new URI(smallFrameLive));
         AmqpConnection connection = client.createConnection();
         addConnection(connection);
         connection.setMaxFrameSize(2 * 1024);
         connection.connect();

         AmqpSession session = connection.createSession();

         AmqpSender sender = session.createSender(getQueueName().toString());

         Queue queueView = server.locateQueue(getQueueName());
         assertNotNull(queueView);
         assertEquals(0, queueView.getMessageCount());

         session.begin();
         for (int m = 0; m < 100; m++) {
            AmqpMessage message = new AmqpMessage();
            message.setDurable(true);
            message.setApplicationProperty("i", "m " + m);
            byte[] bytes = new byte[size];
            for (int i = 0; i < bytes.length; i++) {
               bytes[i] = (byte) 'z';
            }

            message.setBytes(bytes);
            sender.send(message);
         }
         session.commit();

         AMQPLargeMessagesTestUtil.validateAllTemporaryBuffers(server);

         if (crashServer) {
            connection.close();
            liveServer.crash();

            Wait.assertTrue(backupServer::isActive);

            server = backupServer.getServer();

            client = createAmqpClient(new URI(smallFrameBackup));
            connection = client.createConnection();
            addConnection(connection);
            connection.setMaxFrameSize(2 * 1024);
            connection.connect();
            session = connection.createSession();
         }

         queueView = server.locateQueue(getQueueName());
         Wait.assertEquals(100, queueView::getMessageCount);

         AmqpReceiver receiver = session.createReceiver(getQueueName().toString());
         receiver.flow(100);
         for (int i = 0; i < 100; i++) {
            AmqpMessage msgReceived = receiver.receive(10, TimeUnit.SECONDS);
            Assert.assertNotNull(msgReceived);
            Data body = (Data)msgReceived.getWrappedMessage().getBody();
            byte[] bodyArray = body.getValue().getArray();
            for (int bI = 0; bI < size; bI++) {
               Assert.assertEquals((byte)'z', bodyArray[bI]);
            }
            msgReceived.accept(true);
         }

         receiver.flow(1);
         Assert.assertNull(receiver.receiveNoWait());


         receiver.close();

         connection.close();

         Wait.assertEquals(0, queueView::getMessageCount);
         validateNoFilesOnLargeDir(getLargeMessagesDir(0, true), 0);
      } catch (Exception e) {
         e.printStackTrace();
         throw e;
      }
   }

}


<|start_filename|>artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/activemq/artemis/protocol/amqp/converter/message/DirectConvertTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.protocol.amqp.converter.message;

import org.apache.activemq.artemis.api.core.ICoreMessage;
import org.apache.activemq.artemis.core.message.impl.CoreMessage;
import org.apache.activemq.artemis.core.persistence.impl.nullpm.NullStorageManager;
import org.apache.activemq.artemis.protocol.amqp.broker.AMQPMessage;
import org.apache.activemq.artemis.protocol.amqp.broker.AMQPStandardMessage;
import org.apache.activemq.artemis.protocol.amqp.converter.CoreAmqpConverter;
import org.junit.Assert;
import org.junit.Test;

public class DirectConvertTest {

   @Test
   public void testConvertScheduledAMQPCore() {
      long deliveryTime = System.currentTimeMillis() + 10_000;
      AMQPStandardMessage standardMessage = AMQPStandardMessage.createMessage(1, 0,
                                                                              null, null, null,
                                                                              null, null, null, null, null);
      standardMessage.setScheduledDeliveryTime(deliveryTime);

      ICoreMessage coreMessage = standardMessage.toCore();

      Assert.assertEquals((Long)deliveryTime, coreMessage.getScheduledDeliveryTime());
   }


   @Test
   public void testConvertTTLdAMQPCore() {
      long time = System.currentTimeMillis() + 10_000;
      AMQPStandardMessage standardMessage = AMQPStandardMessage.createMessage(1, 0,
                                                                              null, null, null,
                                                                              null, null, null, null, null);
      standardMessage.setExpiration(time);

      ICoreMessage coreMessage = standardMessage.toCore();

      Assert.assertEquals(time, coreMessage.getExpiration());
   }

   @Test
   public void testConvertScheduledCoreAMQP() throws Exception {
      long deliveryTime = System.currentTimeMillis() + 10_000;
      CoreMessage coreMessage = new CoreMessage();
      coreMessage.setScheduledDeliveryTime(deliveryTime);
      coreMessage.initBuffer(1024);

      AMQPMessage amqpMessage = CoreAmqpConverter.fromCore(coreMessage, new NullStorageManager());
      Assert.assertEquals((Long)deliveryTime, amqpMessage.getScheduledDeliveryTime());
   }

   @Test
   public void testConvertTTLCoreAMQP() throws Exception {
      long time = System.currentTimeMillis() + 10_000;
      CoreMessage coreMessage = new CoreMessage();
      coreMessage.setExpiration(time);
      coreMessage.initBuffer(1024);

      AMQPMessage amqpMessage = CoreAmqpConverter.fromCore(coreMessage, new NullStorageManager());
      Assert.assertEquals(time, amqpMessage.getExpiration());
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/CreateQueueTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.client;

import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Set;

import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.ActiveMQExceptionType;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class CreateQueueTest extends ActiveMQTestBase {

   private boolean legacyCreateQueue;

   public final SimpleString addressA = new SimpleString("addressA");
   public final SimpleString addressB = new SimpleString("addressB");
   public final SimpleString queueA = new SimpleString("queueA");
   public final SimpleString queueB = new SimpleString("queueB");
   public final SimpleString queueC = new SimpleString("queueC");
   public final SimpleString queueD = new SimpleString("queueD");

   private ServerLocator locator;
   private ActiveMQServer server;
   private ClientSessionFactory cf;

   @Parameterized.Parameters(name = "legacyCreateQueue={0}")
   public static Collection<Object[]> getParams() {
      return Arrays.asList(new Object[][]{{true}, {false}});
   }

   public CreateQueueTest(boolean legacyCreateQueue) {
      this.legacyCreateQueue = legacyCreateQueue;
   }

   @Override
   @Before
   public void setUp() throws Exception {
      super.setUp();
      locator = createInVMNonHALocator();
      server = createServer(false);

      server.start();
      cf = createSessionFactory(locator);
   }

   @Test
   public void testUnsupportedRoutingType() throws Exception {
      ClientSession sendSession = cf.createSession(false, true, true);
      server.getAddressSettingsRepository().addMatch(addressA.toString(), new AddressSettings().setAutoCreateAddresses(false));
      server.getAddressSettingsRepository().addMatch(addressB.toString(), new AddressSettings().setAutoCreateAddresses(false));

      EnumSet<RoutingType> routingTypes = EnumSet.of(RoutingType.ANYCAST);
      sendSession.createAddress(addressA, routingTypes, false);
      try {
         if (legacyCreateQueue) {
            sendSession.createQueue(addressA, RoutingType.MULTICAST, queueA);
         } else {
            sendSession.createQueue(new QueueConfiguration(queueA).setAddress(addressA));
         }
         fail("Creating a queue here should fail since the queue routing type differs from what is supported on the address.");
      } catch (Exception e) {
         assertTrue(e instanceof ActiveMQException);
         ActiveMQException ae = (ActiveMQException) e;
         assertEquals(ActiveMQExceptionType.INTERNAL_ERROR, ae.getType());
      }

      routingTypes = EnumSet.of(RoutingType.MULTICAST);
      sendSession.createAddress(addressB, routingTypes, false);
      try {
         if (legacyCreateQueue) {
            sendSession.createQueue(addressB, RoutingType.ANYCAST, queueB);
         } else {
            sendSession.createQueue(new QueueConfiguration(queueB).setAddress(addressB).setRoutingType(RoutingType.ANYCAST));
         }
         fail("Creating a queue here should fail since the queue routing type differs from what is supported on the address.");
      } catch (Exception e) {
         assertTrue(e instanceof ActiveMQException);
         ActiveMQException ae = (ActiveMQException) e;
         assertEquals(ActiveMQExceptionType.INTERNAL_ERROR, ae.getType());
      }
      sendSession.close();
   }

   @Test
   public void testAddressDoesNotExist() throws Exception {
      ClientSession sendSession = cf.createSession(false, true, true);
      server.getAddressSettingsRepository().addMatch(addressA.toString(), new AddressSettings().setAutoCreateAddresses(false));
      Set<RoutingType> routingTypes = new HashSet<>();
      routingTypes.add(RoutingType.ANYCAST);
      try {
         if (legacyCreateQueue) {
            sendSession.createQueue(addressA, RoutingType.MULTICAST, queueA);
         } else {
            sendSession.createQueue(new QueueConfiguration(queueA).setAddress(addressA));
         }
         fail("Creating a queue here should fail since the queue's address doesn't exist and auto-create-addresses = false.");
      } catch (Exception e) {
         assertTrue(e instanceof ActiveMQException);
         ActiveMQException ae = (ActiveMQException) e;
         assertEquals(ActiveMQExceptionType.ADDRESS_DOES_NOT_EXIST, ae.getType());
      }
      sendSession.close();
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/openwire/OpenWireFlowControlFailTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.openwire;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import java.util.Map;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.apache.activemq.artemis.core.settings.impl.AddressFullMessagePolicy;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.junit.Assert;
import org.junit.Test;

public class OpenWireFlowControlFailTest extends OpenWireTestBase {

   public static final String OWHOST = "localhost";
   public static final int OWPORT = 61616;

   protected static final String urlString = "tcp://" + OWHOST + ":" + OWPORT + "?wireFormat.cacheEnabled=true";

   @Override
   protected void configureAddressSettings(Map<String, AddressSettings> addressSettingsMap) {
      addressSettingsMap.put("#", new AddressSettings().setAutoCreateQueues(false).setAutoCreateAddresses(false).
         setDeadLetterAddress(new SimpleString("ActiveMQ.DLQ")).setAddressFullMessagePolicy(AddressFullMessagePolicy.FAIL).setMaxSizeBytes(10000));
   }

   @Test(timeout = 60000)
   public void testMesagesNotSent() throws Exception {

      AddressInfo addressInfo = new AddressInfo(SimpleString.toSimpleString("Test"), RoutingType.ANYCAST);
      server.addAddressInfo(addressInfo);
      server.createQueue(new QueueConfiguration(addressInfo.getName()).setRoutingType(RoutingType.ANYCAST));

      StringBuffer textBody = new StringBuffer();
      for (int i = 0; i < 10; i++) {
         textBody.append(" ");
      }
      ConnectionFactory factory = new ActiveMQConnectionFactory(urlString);
      int numberOfMessage = 0;
      try (Connection connection = factory.createConnection()) {
         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
         javax.jms.Queue queue = session.createQueue(addressInfo.getName().toString());
         MessageProducer producer = session.createProducer(queue);
         boolean failed = false;
         try {
            for (int i = 0; i < 1000; i++) {
               TextMessage message = session.createTextMessage(textBody.toString());
               message.setIntProperty("i", i);

               producer.send(message);
               numberOfMessage++;
            }
         } catch (Exception e) {
            e.printStackTrace(System.out);
            failed = true;
            try {
               producer.send(session.createTextMessage(textBody.toString()));
               Assert.fail("Exception expected");
            } catch (JMSException expected) {
               expected.printStackTrace();

            }
         }
         Assert.assertTrue(failed);
      }

      factory = new ActiveMQConnectionFactory(urlString);
      try (Connection connection2 = factory.createConnection()) {
         Session session2 = connection2.createSession(false, Session.AUTO_ACKNOWLEDGE);
         javax.jms.Queue queue = session2.createQueue(addressInfo.getName().toString());

         MessageConsumer consumer = session2.createConsumer(queue);
         connection2.start();
         for (int i = 0; i < numberOfMessage; i++) {
            TextMessage message = (TextMessage) consumer.receive(5000);
            Assert.assertNotNull(message);
            Assert.assertEquals(textBody.toString(), message.getText());
         }

         TextMessage msg = (TextMessage)consumer.receive(500);
         Assert.assertNull(msg);
      }
   }
}


<|start_filename|>artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/services/pagination.js<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
var Artemis;
(function (Artemis) {

    Artemis._module.factory('pagination',
        function () {
            return {
                pageSizeOptions: [10,20,50,100],
                pageSize: 10,
                pageNumber: 1,
                totalItems: 1,
                firstItem: 1,
                lastItem: 1,
                pages: 1,
                page: function (resultsSize) {
                   this.totalItems = resultsSize;
                   this.firstItem = this.pageNumber * this.pageSize - this.pageSize + 1;
                   this.lastItem = this.firstItem + this.pageSize - 1;
                   if (this.lastItem > this.totalItems) {
                       this.lastItem = this.totalItems;
                   }
                   this.pages = Math.ceil(this.totalItems/this.pageSize);
                },
                nextPage: function () {
                   this.pageNumber++;
                   this.load();
                },
                previousPage: function () {
                   this.pageNumber--;
                   this.load();
                },
                lastPage: function () {
                   this.pageNumber = this.pages;
                   this.load();
                },
                firstPage: function () {
                   this.pageNumber = 1;
                   this.load();
                },
                reset: function () {
                   this.pageNumber = 1;
                },
                load: function () {},
                setOperation: function (operation) {
                   this.load = operation;
                }
            }
           
       }).run(configurePagination);

       function configurePagination($templateCache) {
           $templateCache.put('plugin/artemispagination.html',
                `
                <div ng_show="$ctrl.pagination.totalItems > 0">
                    <form class="content-view-pf-pagination table-view-pf-pagination clearfix" id="pagination1">
                       <div class="form-group">
                           <select ng-model="$ctrl.pagination.pageSize" ng-options="qn for qn in $ctrl.pagination.pageSizeOptions" id="pagination.values.pageSize">
                           </select>
                           <span>per page</span>
                       </div>
                       <div class="form-group">
                           <span><span class="pagination-pf-items-current">{{$ctrl.pagination.firstItem}}-{{$ctrl.pagination.lastItem}}</span> of <span class="pagination-pf-items-total">{{$ctrl.pagination.totalItems}}</span></span>
                           <ul class="pagination pagination-pf-back">
                               <li class="{{$ctrl.pagination.pageNumber == 1 ? 'disabled' : ''}}"><a href="#" title="First Page" ng-click="$ctrl.pagination.pageNumber != 1  && $ctrl.pagination.firstPage()"><span class="i fa fa-angle-double-left"></span></a></li>
                               <li class="{{$ctrl.pagination.pageNumber == 1 ? 'disabled' : ''}}"><a href="#" title="Previous Page" ng-click="$ctrl.pagination.pageNumber != 1 && $ctrl.pagination.previousPage()"><span class="i fa fa-angle-left"></span></a></li>
                           </ul>
                           <label for="pagination1-page" class="sr-only">Current Page</label>
                           <input class="pagination-pf-page" type="text" value="{{$ctrl.pagination.pageNumber}}" id="pagination1-page" on-change="$ctrl.firstPage()"/>
                           <span>of <span class="pagination-pf-pages">{{$ctrl.pagination.pages}}</span></span>
                           <ul class="pagination pagination-pf-forward">
                               <li class="{{$ctrl.pagination.pageNumber == $ctrl.pagination.pages ? 'disabled' : ''}}"><a href="#" title="Next Page" ng-click="$ctrl.pagination.pageNumber != $ctrl.pagination.pages && $ctrl.pagination.nextPage()"><span class="i fa fa-angle-right"></span></a></li>
                               <li class="{{$ctrl.pagination.pageNumber == $ctrl.pagination.pages ? 'disabled' : ''}}"><a href="#" title="Last Page" ng-click="$ctrl.pagination.pageNumber != $ctrl.pagination.pages && $ctrl.pagination.lastPage()"><span class="i fa fa-angle-double-right"></span></a></li>
                           </ul>
                       </div>
                    </form>
                </div>
               `
           )
       }
       configurePagination.$inject = ['$templateCache'];

})(Artemis || (Artemis = {}));

<|start_filename|>artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/artemisHelpers.js<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
var Artemis;
(function (Artemis) {
    function artemisJmxDomain() {
        return localStorage['artemisJmxDomain'] || "org.apache.activemq.artemis";
    }
    Artemis.artemisJmxDomain = artemisJmxDomain;;

    function ownUnescape(name) {
        //simple return unescape(name); does not work for this :(
        return name.replace(/\\\\/g, "\\").replace(/\\\*/g, "*").replace(/\\\?/g, "?");
    };
    Artemis.ownUnescape = ownUnescape;

    function getBrokerMBean(workspace, jolokia) {
        var mbean = null;
        var selection = workspace.selection;
        var folderNames = selection.folderNames;
        mbean = "" + folderNames[0] + ":broker=\"" + folderNames[1] + "\"";
        return mbean;
    }
    Artemis.getBrokerMBean = getBrokerMBean;

})(Artemis || (Artemis = {}));

<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/AmqpFlowControlTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.amqp;

import java.io.IOException;
import java.net.URI;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.ResourceAllocationException;
import javax.jms.Session;

import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.settings.impl.AddressFullMessagePolicy;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.transport.amqp.client.AmqpClient;
import org.apache.activemq.transport.amqp.client.AmqpConnection;
import org.apache.activemq.transport.amqp.client.AmqpMessage;
import org.apache.activemq.transport.amqp.client.AmqpReceiver;
import org.apache.activemq.transport.amqp.client.AmqpSender;
import org.apache.activemq.transport.amqp.client.AmqpSession;
import org.junit.Assert;
import org.junit.Test;

public class AmqpFlowControlTest extends JMSClientTestSupport {

   private static final long MAX_SIZE_BYTES = 1 * 1024 * 1024;
   private static final long MAX_SIZE_BYTES_REJECT_THRESHOLD = 2 * 1024 * 1024;

   private String singleCreditAcceptorURI = new String("tcp://localhost:" + (AMQP_PORT + 8));
   private int messagesSent;

   @Override
   public void setUp() throws Exception {
      super.setUp();

      messagesSent = 0;
   }

   @Override
   protected void addAdditionalAcceptors(ActiveMQServer server) throws Exception {
      server.getConfiguration().addAcceptorConfiguration("flow", singleCreditAcceptorURI + "?protocols=AMQP;useEpoll=false;amqpCredits=1;amqpLowCredits=1");
   }

   @Override
   protected void configureAddressPolicy(ActiveMQServer server) {
      // For BLOCK tests
      AddressSettings addressSettings = server.getAddressSettingsRepository().getMatch("#");
      addressSettings.setAddressFullMessagePolicy(AddressFullMessagePolicy.BLOCK);
      addressSettings.setMaxSizeBytes(MAX_SIZE_BYTES);
      addressSettings.setMaxSizeBytesRejectThreshold(MAX_SIZE_BYTES_REJECT_THRESHOLD);
      server.getAddressSettingsRepository().addMatch("#", addressSettings);
   }

   @Test(timeout = 60000)
   public void testCreditsAreAllocatedOnceOnLinkCreated() throws Exception {
      AmqpClient client = createAmqpClient(new URI(singleCreditAcceptorURI));
      AmqpConnection connection = addConnection(client.connect());

      try {
         AmqpSession session = connection.createSession();
         AmqpSender sender = session.createSender(getQueueName());
         assertEquals("Should only be issued one credit", 1, sender.getSender().getCredit());
      } finally {
         connection.close();
      }
   }

   @Test(timeout = 60000)
   public void testCreditsAreNotAllocatedWhenAddressIsFull() throws Exception {
      AmqpClient client = createAmqpClient(new URI(singleCreditAcceptorURI));
      AmqpConnection connection = addConnection(client.connect());

      try {
         AmqpSession session = connection.createSession();
         AmqpSender sender = session.createSender(getQueueName());

         // Use blocking send to ensure buffered messages do not interfere with credit.
         sender.setSendTimeout(-1);
         sendUntilFull(sender);

         // This should be -1. A single message is buffered in the client, and 0 credit has been allocated.
         assertTrue(sender.getSender().getCredit() == -1);

         long addressSize = server.getPagingManager().getPageStore(new SimpleString(getQueueName())).getAddressSize();
         assertTrue(addressSize >= MAX_SIZE_BYTES && addressSize <= MAX_SIZE_BYTES_REJECT_THRESHOLD);
      } finally {
         connection.close();
      }
   }

   @Test(timeout = 60000)
   public void testAddressIsBlockedForOtherProdudersWhenFull() throws Exception {
      Connection connection = createConnection();
      Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
      Destination d = session.createQueue(getQueueName());
      MessageProducer p = session.createProducer(d);

      fillAddress(getQueueName());

      Exception e = null;
      try {
         p.send(session.createBytesMessage());
      } catch (ResourceAllocationException rae) {
         e = rae;
      }
      assertTrue(e instanceof ResourceAllocationException);
      assertTrue(e.getMessage().contains("resource-limit-exceeded"));

      long addressSize = server.getPagingManager().getPageStore(new SimpleString(getQueueName())).getAddressSize();
      assertTrue(addressSize >= MAX_SIZE_BYTES_REJECT_THRESHOLD);
   }

   @Test(timeout = 60000)
   public void testCreditsAreRefreshedWhenAddressIsUnblocked() throws Exception {
      fillAddress(getQueueName());

      AmqpClient client = createAmqpClient();
      AmqpConnection connection = addConnection(client.connect());

      try {
         AmqpSession session = connection.createSession();
         AmqpSender sender = session.createSender(getQueueName());

         // Wait for a potential flow frame.
         Thread.sleep(500);
         assertEquals(0, sender.getSender().getCredit());

         // Empty Address except for 1 message used later.
         AmqpReceiver receiver = session.createReceiver(getQueueName());
         receiver.flow(100);

         AmqpMessage m;
         for (int i = 0; i < messagesSent - 1; i++) {
            m = receiver.receive(5000, TimeUnit.MILLISECONDS);
            m.accept();
         }

         // Wait for address to unblock and flow frame to arrive
         Thread.sleep(500);

         assertTrue(sender.getSender().getCredit() >= 0);
      } finally {
         connection.close();
      }
   }

   @Test(timeout = 60000)
   public void testNewLinkAttachAreNotAllocatedCreditsWhenAddressIsBlocked() throws Exception {
      fillAddress(getQueueName());

      AmqpClient client = createAmqpClient();
      AmqpConnection connection = addConnection(client.connect());

      try {
         AmqpSession session = connection.createSession();
         AmqpSender sender = session.createSender(getQueueName());

         // Wait for a potential flow frame.
         Thread.sleep(1000);
         assertEquals(0, sender.getSender().getCredit());
      } finally {
         connection.close();
      }
   }

   @Test(timeout = 60000)
   public void testTxIsRolledBackOnRejectedPreSettledMessage() throws Throwable {

      // Create the link attach before filling the address to ensure the link is allocated credit.
      AmqpClient client = createAmqpClient();
      AmqpConnection connection = addConnection(client.connect());

      AmqpSession session = connection.createSession();
      AmqpSender sender = session.createSender(getQueueName());
      sender.setPresettle(true);

      fillAddress(getQueueName());

      final AmqpMessage message = new AmqpMessage();
      byte[] payload = new byte[50 * 1024];
      message.setBytes(payload);

      Exception expectedException = null;
      try {
         session.begin();
         sender.send(message);
         session.commit();
      } catch (Exception e) {
         expectedException = e;
      } finally {
         connection.close();
      }

      assertNotNull(expectedException);
      assertTrue(expectedException.getMessage().contains("resource-limit-exceeded"));
      assertTrue(expectedException.getMessage().contains("Address is full: " + getQueueName()));
   }

   /*
    * Fills an address.  Careful when using this method.  Only use when rejected messages are switched on.
    */
   private void fillAddress(String address) throws Exception {
      AmqpClient client = createAmqpClient();
      AmqpConnection connection = addConnection(client.connect());
      Exception exception = null;
      try {
         AmqpSession session = connection.createSession();
         AmqpSender sender = session.createSender(address);
         sendUntilFull(sender);
      } catch (Exception e) {
         exception = e;
      } finally {
         connection.close();
      }

      // Should receive a rejected error
      assertNotNull(exception);
      assertTrue(exception.getMessage().contains("amqp:resource-limit-exceeded"));
   }

   private void sendUntilFull(final AmqpSender sender) throws Exception {
      final AmqpMessage message = new AmqpMessage();
      byte[] payload = new byte[50 * 1024];
      message.setBytes(payload);

      final int maxMessages = 50;
      final AtomicInteger sentMessages = new AtomicInteger(0);
      final Exception[] errors = new Exception[1];
      final CountDownLatch timeout = new CountDownLatch(1);

      Runnable sendMessages = new Runnable() {
         @Override
         public void run() {
            try {
               for (int i = 0; i < maxMessages; i++) {
                  sender.send(message);
                  sentMessages.getAndIncrement();
               }
               timeout.countDown();
            } catch (IOException e) {
               errors[0] = e;
            }
         }
      };

      Thread t = new Thread(sendMessages);

      try {
         t.start();

         timeout.await(1, TimeUnit.SECONDS);

         messagesSent = sentMessages.get();
         if (errors[0] != null) {
            throw errors[0];
         }
      } finally {
         t.interrupt();
         t.join(1000);
         Assert.assertFalse(t.isAlive());
      }
   }
}


<|start_filename|>tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/remoting/impl/netty/NettyAcceptorTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.unit.core.remoting.impl.netty;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.core.remoting.impl.netty.NettyAcceptor;
import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants;
import org.apache.activemq.artemis.core.server.ActiveMQComponent;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.spi.core.protocol.ProtocolManager;
import org.apache.activemq.artemis.spi.core.remoting.BufferHandler;
import org.apache.activemq.artemis.spi.core.remoting.Connection;
import org.apache.activemq.artemis.spi.core.remoting.ServerConnectionLifeCycleListener;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.utils.ActiveMQThreadFactory;
import org.apache.activemq.artemis.utils.PortCheckRule;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class NettyAcceptorTest extends ActiveMQTestBase {

   private ScheduledExecutorService pool2;
   private ExecutorService pool3;

   @Override
   @Before
   public void setUp() throws Exception {
      super.setUp();
   }

   @Override
   @After
   public void tearDown() throws Exception {
      if (pool3 != null)
         pool3.shutdown();

      if (pool2 != null)
         pool2.shutdownNow();

      super.tearDown();
   }

   @Test
   public void testStartStop() throws Exception {
      BufferHandler handler = new BufferHandler() {

         @Override
         public void bufferReceived(final Object connectionID, final ActiveMQBuffer buffer) {
         }
      };

      Map<String, Object> params = new HashMap<>();
      ServerConnectionLifeCycleListener listener = new ServerConnectionLifeCycleListener() {

         @Override
         public void connectionException(final Object connectionID, final ActiveMQException me) {
         }

         @Override
         public void connectionDestroyed(final Object connectionID) {
         }

         @Override
         public void connectionCreated(final ActiveMQComponent component,
                                       final Connection connection,
                                       final ProtocolManager protocol) {
         }

         @Override
         public void connectionReadyForWrites(Object connectionID, boolean ready) {
         }
      };
      pool2 = Executors.newScheduledThreadPool(ActiveMQDefaultConfiguration.getDefaultScheduledThreadPoolMaxSize(), ActiveMQThreadFactory.defaultThreadFactory());
      pool3 = Executors.newSingleThreadExecutor(ActiveMQThreadFactory.defaultThreadFactory());
      NettyAcceptor acceptor = new NettyAcceptor("netty", null, params, handler, listener, pool2, pool3, new HashMap<String, ProtocolManager>());

      addActiveMQComponent(acceptor);
      acceptor.start();
      Assert.assertTrue(acceptor.isStarted());
      acceptor.stop();
      Assert.assertFalse(acceptor.isStarted());
      Assert.assertTrue(PortCheckRule.checkAvailable(TransportConstants.DEFAULT_PORT));

      acceptor.start();
      Assert.assertTrue(acceptor.isStarted());
      acceptor.stop();
      Assert.assertFalse(acceptor.isStarted());
      Assert.assertTrue(PortCheckRule.checkAvailable(TransportConstants.DEFAULT_PORT));
   }

   @Test
   public void testAutoStart() throws Exception {
      ActiveMQServer server = createServer(false, createDefaultInVMConfig());
      server.getConfiguration().addAcceptorConfiguration("default", "tcp://127.0.0.1:61617");
      server.getConfiguration().addAcceptorConfiguration("start", "tcp://127.0.0.1:61618?autoStart=true");
      server.getConfiguration().addAcceptorConfiguration("noStart", "tcp://127.0.0.1:61619?autoStart=false");
      server.start();
      assertTrue(server.getRemotingService().getAcceptor("default").isStarted());
      assertTrue(server.getRemotingService().getAcceptor("start").isStarted());
      assertFalse(server.getRemotingService().getAcceptor("noStart").isStarted());
   }
}


<|start_filename|>artemis-core-client/src/test/java/org/apache/activemq/artemis/api/core/management/ResourceNamesTest.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.api.core.management;

import java.util.Arrays;
import java.util.Collection;
import java.util.UUID;

import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(value = Parameterized.class)
public class ResourceNamesTest extends Assert {

   char delimiterChar;
   final String delimiter;
   final SimpleString testAddress;
   final String prefix;
   final String baseName;
   final String testResourceAddressName;
   final String testResourceMulticastQueueName;
   final String testResourceAnycastQueueName;
   final String testResourceDivertName;


   @Parameterized.Parameters(name = "delimiterChar={0}")
   public static Collection<Object[]> getParams() {
      return Arrays.asList(new Object[][] {{'/'}, {'.'}});
   }

   public ResourceNamesTest(char delimiterChar) {
      super();
      this.delimiterChar = delimiterChar;
      delimiter = "" + delimiterChar;
      testAddress = SimpleString.toSimpleString(UUID.randomUUID().toString());
      prefix = ActiveMQDefaultConfiguration.getInternalNamingPrefix().replace('.', delimiterChar);
      baseName = prefix + testAddress + delimiter;
      testResourceAddressName = baseName + ResourceNames.ADDRESS.replace('.', delimiterChar) + ResourceNames.RETROACTIVE_SUFFIX;
      testResourceMulticastQueueName = baseName + ResourceNames.QUEUE.replace('.', delimiterChar) + RoutingType.MULTICAST.toString().toLowerCase() + delimiter + ResourceNames.RETROACTIVE_SUFFIX;
      testResourceAnycastQueueName = baseName + ResourceNames.QUEUE.replace('.', delimiterChar) + RoutingType.ANYCAST.toString().toLowerCase() + delimiter + ResourceNames.RETROACTIVE_SUFFIX;
      testResourceDivertName = baseName + ResourceNames.DIVERT.replace('.', delimiterChar) + ResourceNames.RETROACTIVE_SUFFIX;
   }

   @Test
   public void testGetRetroactiveResourceAddressName() {
      assertEquals(testResourceAddressName, ResourceNames.getRetroactiveResourceAddressName(prefix, delimiter, testAddress).toString());
   }

   @Test
   public void testGetRetroactiveResourceQueueName() {
      assertEquals(testResourceMulticastQueueName, ResourceNames.getRetroactiveResourceQueueName(prefix, delimiter, testAddress, RoutingType.MULTICAST).toString());
      assertEquals(testResourceAnycastQueueName, ResourceNames.getRetroactiveResourceQueueName(prefix, delimiter, testAddress, RoutingType.ANYCAST).toString());
   }

   @Test
   public void testGetRetroactiveResourceDivertName() {
      assertEquals(testResourceDivertName, ResourceNames.getRetroactiveResourceDivertName(prefix, delimiter, testAddress).toString());
   }

   @Test
   public void testDecomposeRetroactiveResourceAddressName() {
      assertEquals(testAddress.toString(), ResourceNames.decomposeRetroactiveResourceAddressName(prefix, delimiter, testResourceAddressName));
   }

   @Test
   public void testIsRetroactiveResource() {
      assertTrue(ResourceNames.isRetroactiveResource(prefix, SimpleString.toSimpleString(testResourceAddressName)));
      assertTrue(ResourceNames.isRetroactiveResource(prefix, SimpleString.toSimpleString(testResourceMulticastQueueName)));
      assertTrue(ResourceNames.isRetroactiveResource(prefix, SimpleString.toSimpleString(testResourceDivertName)));
   }
}


<|start_filename|>artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/components/deleteAddress.js<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 /// <reference path="tree.component.ts"/>
var Artemis;
(function (Artemis) {
    Artemis._module.component('artemisDeleteAddress', {
        template:
            `
             <h1>Delete Address
                 <button type="button" class="btn btn-link jvm-title-popover"
                           uib-popover-template="'delete-address-instructions.html'" popover-placement="bottom-left"
                           popover-title="Instructions" popover-trigger="'outsideClick'">
                     <span class="pficon pficon-help"></span>
                 </button>
             </h1>
             <p>
               <div class="alert alert-warning">
                 <span class="pficon pficon-warning-triangle-o"></span>
                 This operation cannot be undone. Please be careful!
               </div>
             </p>

             <h2>Delete address</h2>
             <p>Remove the address completely.</p>
             <button type="submit" class="btn btn-danger" ng-click="$ctrl.deleteDialog = true">
               Delete address
             </button>

             <div hawtio-confirm-dialog="$ctrl.deleteDialog"
                  title="Confirm delete address"
                  ok-button-text="Delete"
                  cancel-button-text="Cancel"
                  on-ok="$ctrl.deleteAddress()">
               <div class="dialog-body">
                 <p>You are about to delete address <b>{{ $ctrl.selectedName() }}</b>.</p>
                 <p>This operation cannot be undone so please be careful.</p>
               </div>
             </div>
             <script type="text/ng-template" id="delete-address-instructions.html">
             <div>
                <p>
                    This page allows you to delete the chosen address on the broker.
                </p>
                <p>
                    Note that this will only succeed if the address has no queues bound to it.
                </p>
                </div>
             </script>
        `,
        controller: DeleteAddressController
    })
    .name;
    Artemis.log.debug("loaded address " + Artemis.addressModule);

    function DeleteAddressController($scope, workspace, jolokia, localStorage) {
        var ctrl = this;
        ctrl.workspace = workspace;
        ctrl.deleteDialog = false;

        $onInit = function () {
            Artemis.log.debug("loaded address controller");
        }

        $scope.$watch('workspace.selection', function () {
            workspace.moveIfViewInvalid();
        });

        function operationSuccess() {
            // lets set the selection to the parent
            workspace.removeAndSelectParentNode();
            ctrl.workspace.operationCounter += 1;
            Core.$apply($scope);
            Core.notification("success", $scope.message);
            ctrl.workspace.loadTree();
        }

        function onError(response) {
            Core.notification("error", "Could not delete address: " + response.error);
        }

        ctrl.deleteAddress = function () {
            var selection = workspace.selection;
            var entries = selection.entries;
            var mbean = Artemis.getBrokerMBean(workspace, jolokia);
            Artemis.log.debug(mbean);
            if (mbean) {
                if (selection && jolokia && entries) {
                    var domain = selection.domain;
                    var name = entries["address"];
                    Artemis.log.debug("name = " + name)
                    name = Core.unescapeHTML(name);
                    if (name.charAt(0) === '"' && name.charAt(name.length -1) === '"')
                    {
                        name = name.substr(1,name.length -2);
                    }
                    name = Artemis.ownUnescape(name);
                    Artemis.log.debug(name);
                    var operation;
                    $scope.message = "Deleted address " + name;
                    jolokia.execute(mbean, "deleteAddress(java.lang.String)", name,  Core.onSuccess(operationSuccess, { error: onError }));
                }
            }
        };

        ctrl.selectedName = function () {
            var selection = ctrl.workspace.selection;
            return selection ? _.unescape(selection.text) : null;
        };
    }
    DeleteAddressController.$inject = ['$scope', 'workspace', 'jolokia', 'localStorage'];

})(Artemis || (Artemis = {}));


<|start_filename|>examples/features/standard/security-keycloak/src/main/resources/activemq/server0/keycloak-js-client.json<|end_filename|>
{
  "realm"    : "artemis-keycloak-demo",
  "clientId" : "artemis-console",
  "url"      : "http://localhost:8080/auth"
}

<|start_filename|>artemis-commons/src/test/java/org/apache/activemq/artemis/utils/collections/SparseArrayLinkedListTest.java<|end_filename|>
/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */
package org.apache.activemq.artemis.utils.collections;

import java.util.ArrayList;
import java.util.List;

import org.junit.Assert;
import org.junit.Test;

import static org.hamcrest.core.Is.is;

public class SparseArrayLinkedListTest {

   private static final int SPARSE_ARRAY_CAPACITY = 4;
   private static final int ELEMENTS = SPARSE_ARRAY_CAPACITY * 4;

   private final SparseArrayLinkedList<Integer> list;

   public SparseArrayLinkedListTest() {
      list = new SparseArrayLinkedList<>(SPARSE_ARRAY_CAPACITY);
   }

   @Test(expected = IllegalArgumentException.class)
   public void shouldFailToCreateZeroArrayCapacityCollection() {
      new SparseArrayLinkedList<>(0);
   }

   @Test(expected = IllegalArgumentException.class)
   public void shouldFailToCreateNegativeArrayCapacityCollection() {
      new SparseArrayLinkedList<>(-1);
   }

   @Test(expected = NullPointerException.class)
   public void shouldFailToAddNull() {
      list.add(null);
   }

   @Test
   public void shouldNumberOfElementsBeTheSameOfTheAddedElements() {
      final int elements = ELEMENTS;
      for (int i = 0; i < elements; i++) {
         Assert.assertEquals(i, list.size());
         list.add(i);
      }
      Assert.assertEquals(elements, list.size());
   }

   @Test
   public void shouldClearConsumeElementsInOrder() {
      final int elements = ELEMENTS;
      Assert.assertEquals(0, list.clear(null));
      final ArrayList<Integer> expected = new ArrayList<>(elements);
      for (int i = 0; i < elements; i++) {
         final Integer added = i;
         list.add(added);
         expected.add(added);
      }
      final List<Integer> removed = new ArrayList<>(elements);
      Assert.assertEquals(elements, list.clear(removed::add));
      Assert.assertEquals(1, list.sparseArraysCount());
      Assert.assertEquals(0, list.size());
      Assert.assertThat(removed, is(expected));
   }

   @Test
   public void shouldRemoveMatchingElements() {
      final int elements = ELEMENTS;
      for (int i = 0; i < elements; i++) {
         list.add(i);
      }
      Assert.assertEquals(1, list.remove(e -> e.intValue() == 0));
      Assert.assertEquals(elements - 1, list.size());
      Assert.assertEquals(0, list.remove(e -> e.intValue() == 0));
      Assert.assertEquals(elements - 1, list.size());
      Assert.assertEquals(elements - 1, list.remove(e -> true));
      Assert.assertEquals(0, list.size());
      Assert.assertEquals(1, list.sparseArraysCount());
      Assert.assertEquals(0, list.remove(e -> true));
      Assert.assertEquals(1, list.sparseArraysCount());
   }

   @Test
   public void shouldRemoveDetachSparseArrays() {
      final int elements = list.sparseArrayCapacity() * 3;
      for (int i = 0; i < elements; i++) {
         list.add(i);
      }
      // remove elements in the middle
      final int startInclusiveMiddle = list.sparseArrayCapacity();
      final int endNotInclusiveMiddle = startInclusiveMiddle + list.sparseArrayCapacity();
      Assert.assertEquals(list.sparseArrayCapacity(),
                          list.remove(e -> e.intValue() >= startInclusiveMiddle && e.intValue() < endNotInclusiveMiddle));
      Assert.assertEquals(2, list.sparseArraysCount());
      // remove elements at the beginning
      final int startInclusiveFirst = 0;
      final int endNotInclusiveFirst = startInclusiveMiddle;
      Assert.assertEquals(list.sparseArrayCapacity(),
                          list.remove(e -> e.intValue() >= startInclusiveFirst && e.intValue() < endNotInclusiveFirst));
      Assert.assertEquals(1, list.sparseArraysCount());
      // remove all elements at the end
      final int startInclusiveLast = endNotInclusiveMiddle;
      final int endNotInclusiveLast = elements;
      Assert.assertEquals(list.sparseArrayCapacity(),
                          list.remove(e -> e.intValue() >= startInclusiveLast && e.intValue() < endNotInclusiveLast));
      Assert.assertEquals(1, list.sparseArraysCount());
   }

   @Test
   public void shouldAddAfterRemoveAtTheEndReusingTheAvailableSpace() {
      final int elements = list.sparseArrayCapacity();
      for (int i = 0; i < elements; i++) {
         list.add(i);
      }
      Assert.assertEquals(1, list.sparseArraysCount());
      // removing last element
      Assert.assertEquals(1, list.remove(e -> e.intValue() == elements - 1));
      list.add(elements - 1);
      Assert.assertEquals(1, list.sparseArraysCount());
      Assert.assertEquals(1, list.remove(e -> e.intValue() == 0));
      list.add(elements);
      Assert.assertEquals(2, list.sparseArraysCount());
   }

   @Test
   public void shouldReuseAllTheAvailableSpaceInTheSameArray() {
      final int elements = list.sparseArrayCapacity();
      for (int i = 0; i < elements; i++) {
         list.add(i);
      }
      Assert.assertEquals(1, list.sparseArraysCount());
      // removing all elements
      Assert.assertEquals(elements, list.remove(e -> true));
      Assert.assertEquals(1, list.sparseArraysCount());
      for (int i = 0; i < elements; i++) {
         list.add(i);
      }
      Assert.assertEquals(1, list.sparseArraysCount());
   }

   @Test
   public void shouldClearConsumeRemainingElementsInOrder() {
      final int elements = ELEMENTS;
      final Integer zero = 0;
      list.add(zero);
      for (int i = 1; i < elements; i++) {
         list.add(i);
      }
      Assert.assertEquals(elements - 1, list.remove(e -> e != zero));
      final ArrayList<Integer> remaining = new ArrayList<>();
      Assert.assertEquals(1, list.clear(remaining::add));
      Assert.assertEquals(0, list.size());
      Assert.assertEquals(1, remaining.size());
      Assert.assertEquals(zero, remaining.get(0));
   }

}


<|start_filename|>artemis-commons/src/test/java/org/apache/activemq/artemis/utils/critical/CriticalAnalyzerTest.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.utils.critical;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.activemq.artemis.utils.ArtemisCloseable;
import org.apache.activemq.artemis.utils.ReusableLatch;
import org.apache.activemq.artemis.utils.ThreadLeakCheckRule;
import org.junit.After;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;

public class CriticalAnalyzerTest {

   @Rule
   public ThreadLeakCheckRule rule = new ThreadLeakCheckRule();

   private CriticalAnalyzer analyzer;

   @After
   public void tearDown() throws Exception {
      if (analyzer != null) {
         analyzer.stop();
      }
   }

   @Test
   public void testDummy() {

      analyzer = new CriticalAnalyzerImpl().setTimeout(100, TimeUnit.MILLISECONDS).setCheckTime(50, TimeUnit.MILLISECONDS);
      CriticalComponent component = new CriticalComponentImpl(analyzer, 2);
      analyzer.add(component);

      CriticalCloseable closeable1 = component.measureCritical(0);

      Assert.assertFalse(CriticalMeasure.isDummy(closeable1));

      ArtemisCloseable closeable2 = component.measureCritical(0);

      Assert.assertTrue(CriticalMeasure.isDummy(closeable2));

      closeable1.close();

      closeable2 = component.measureCritical(0);

      Assert.assertFalse(CriticalMeasure.isDummy(closeable2));
   }

   @Test
   public void testCall() {

      analyzer = new CriticalAnalyzerImpl().setTimeout(100, TimeUnit.MILLISECONDS).setCheckTime(50, TimeUnit.MILLISECONDS);
      CriticalComponent component = new CriticalComponentImpl(analyzer, 2);
      analyzer.add(component);

      CriticalCloseable closeable = component.measureCritical(0);
      Assert.assertFalse(CriticalMeasure.isDummy(closeable));

      CriticalCloseable dummy = component.measureCritical(0);

      boolean exception = false;
      try {
         dummy.beforeClose(() -> System.out.println("never hapening"));
      } catch (Throwable e) {
         exception = true;
      }

      Assert.assertTrue(exception);

      AtomicInteger value = new AtomicInteger(0);

      closeable.beforeClose(() -> value.set(1000));

      Assert.assertEquals(0, value.get());

      closeable.close();

      Assert.assertEquals(1000, value.get());
   }


   @Test
   public void testAction() throws Exception {
      analyzer = new CriticalAnalyzerImpl().setTimeout(100, TimeUnit.MILLISECONDS).setCheckTime(50, TimeUnit.MILLISECONDS);
      analyzer.add(new CriticalComponent() {
         @Override
         public CriticalAnalyzer getCriticalAnalyzer() {
            return null;
         }

         @Override
         public CriticalCloseable measureCritical(int path) {
            return null;
         }

         @Override
         public boolean checkExpiration(long timeout, boolean reset) {
            return true;
         }
      });

      CountDownLatch latch = new CountDownLatch(1);

      analyzer.start();

      analyzer.addAction((CriticalComponent comp) -> {
         latch.countDown();
      });

      Assert.assertTrue(latch.await(10, TimeUnit.SECONDS));

      analyzer.stop();
   }

   @Test
   public void testActionOnImpl() throws Exception {
      CountDownLatch latch = new CountDownLatch(1);

      analyzer = new CriticalAnalyzerImpl().setTimeout(10, TimeUnit.MILLISECONDS).setCheckTime(5, TimeUnit.MILLISECONDS);

      analyzer.addAction((CriticalComponent comp) -> {
         latch.countDown();
      });

      CriticalComponent component = new CriticalComponentImpl(analyzer, 2);
      analyzer.add(component);

      component.measureCritical(0).close();
      component.measureCritical(1);


      analyzer.start();

      Assert.assertTrue(latch.await(10, TimeUnit.SECONDS));

      analyzer.stop();
   }

   @Test
   public void testEnterNoLeaveNoExpire() throws Exception {
      analyzer = new CriticalAnalyzerImpl().setTimeout(10, TimeUnit.MILLISECONDS).setCheckTime(5, TimeUnit.MILLISECONDS);
      CriticalComponent component = new CriticalComponentImpl(analyzer, 2);
      component.measureCritical(0);
      Assert.assertFalse(component.checkExpiration(TimeUnit.MINUTES.toNanos(1), false));
      analyzer.stop();

   }

   @Test
   public void testEnterNoLeaveExpire() throws Exception {
      analyzer = new CriticalAnalyzerImpl().setTimeout(10, TimeUnit.MILLISECONDS).setCheckTime(5, TimeUnit.MILLISECONDS);
      CriticalComponent component = new CriticalComponentImpl(analyzer, 2);
      component.measureCritical(0);
      Thread.sleep(50);
      Assert.assertTrue(component.checkExpiration(0, false));
      analyzer.stop();

   }

   @Test
   public void testNegative() throws Exception {
      CountDownLatch latch = new CountDownLatch(1);

      analyzer = new CriticalAnalyzerImpl().setTimeout(10, TimeUnit.MILLISECONDS).setCheckTime(5, TimeUnit.MILLISECONDS);

      analyzer.addAction((CriticalComponent comp) -> {
         latch.countDown();
      });

      CriticalComponent component = new CriticalComponentImpl(analyzer, 1);
      analyzer.add(component);

      component.measureCritical(0).close();

      analyzer.start();

      Assert.assertFalse(latch.await(100, TimeUnit.MILLISECONDS));

      analyzer.stop();
   }

   @Test
   public void testPositive() throws Exception {
      ReusableLatch latch = new ReusableLatch(1);

      analyzer = new CriticalAnalyzerImpl().setTimeout(10, TimeUnit.MILLISECONDS).setCheckTime(5, TimeUnit.MILLISECONDS);

      analyzer.addAction((CriticalComponent comp) -> {
         latch.countDown();
      });

      CriticalComponent component = new CriticalComponentImpl(analyzer, 1);
      analyzer.add(component);

      AutoCloseable measure = component.measureCritical(0);
      Thread.sleep(50);

      analyzer.start();

      Assert.assertTrue(latch.await(100, TimeUnit.MILLISECONDS));

      measure.close();

      latch.setCount(1);

      Assert.assertFalse(latch.await(100, TimeUnit.MILLISECONDS));

      analyzer.stop();
   }
}

<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/settings/impl/SlowConsumerThresholdMeasurementUnit.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.settings.impl;

import java.util.concurrent.TimeUnit;

public enum SlowConsumerThresholdMeasurementUnit {
   MESSAGES_PER_SECOND(1), MESSAGES_PER_MINUTE(60), MESSAGES_PER_HOUR(3600), MESSAGES_PER_DAY(3600 * 24);

   private final int measurementUnitInSeconds;

   SlowConsumerThresholdMeasurementUnit(int measurementUnitInSeconds) {
      this.measurementUnitInSeconds = measurementUnitInSeconds;
   }

   public static SlowConsumerThresholdMeasurementUnit valueOf(int measurementUnitInSeconds) {
      switch (measurementUnitInSeconds) {
         case 1:
            return MESSAGES_PER_SECOND;
         case 60:
            return MESSAGES_PER_MINUTE;
         case 3600:
            return MESSAGES_PER_HOUR;
         case 3600 * 24:
            return MESSAGES_PER_DAY;
         default:
            return null;
      }
   }

   public static TimeUnit unitOf(int measurementUnitInSeconds) {
      switch (measurementUnitInSeconds) {
         case 1:
            return TimeUnit.SECONDS;
         case 60:
            return TimeUnit.MINUTES;
         case 3600:
            return TimeUnit.HOURS;
         case 3600 * 24:
            return TimeUnit.DAYS;
         default:
            return null;
      }
   }

   public int getValue() {
      return measurementUnitInSeconds;
   }
}


<|start_filename|>tests/stress-tests/src/test/java/org/apache/activemq/artemis/tests/stress/client/SendStressTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.stress.client;

import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.junit.Assert;
import org.junit.Test;

public class SendStressTest extends ActiveMQTestBase {

   // Constants -----------------------------------------------------

   // Attributes ----------------------------------------------------

   // Static --------------------------------------------------------

   // Constructors --------------------------------------------------

   // Public --------------------------------------------------------

   // Remove this method to re-enable those tests
   @Test
   public void testStressSendNetty() throws Exception {
      doTestStressSend(true);
   }

   @Test
   public void testStressSendInVM() throws Exception {
      doTestStressSend(false);
   }

   public void doTestStressSend(final boolean netty) throws Exception {
      ActiveMQServer server = createServer(false, netty);
      server.start();
      ServerLocator locator = createNonHALocator(netty);
      ClientSessionFactory sf = createSessionFactory(locator);

      ClientSession session = null;

      final int batchSize = 2000;

      final int numberOfMessages = 100000;

      try {
         server.start();

         session = sf.createSession(false, false);

         session.createQueue(new QueueConfiguration("queue").setAddress("address"));

         ClientProducer producer = session.createProducer("address");

         ClientMessage message = session.createMessage(false);

         message.getBodyBuffer().writeBytes(new byte[1024]);

         for (int i = 0; i < numberOfMessages; i++) {
            producer.send(message);
            if (i % batchSize == 0) {
               System.out.println("Sent " + i);
               session.commit();
            }
         }

         session.commit();

         session.close();

         session = sf.createSession(false, false);

         ClientConsumer consumer = session.createConsumer("queue");

         session.start();

         for (int i = 0; i < numberOfMessages; i++) {
            ClientMessage msg = consumer.receive(5000);
            Assert.assertNotNull(msg);
            msg.acknowledge();

            if (i % batchSize == 0) {
               System.out.println("Consumed " + i);
               session.commit();
            }
         }

         session.commit();
      } finally {
         if (session != null) {
            try {
               sf.close();
               session.close();
            } catch (Exception e) {
               e.printStackTrace();
            }
         }
         locator.close();
         server.stop();
      }

   }

   // Package protected ---------------------------------------------

   // Protected -----------------------------------------------------

   // Private -------------------------------------------------------

   // Inner classes -------------------------------------------------

}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/ForceDeleteQueue.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.tests.integration.client;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;

import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.MessageReference;
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.logs.AssertionLoggerHandler;
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.tests.util.CFUtil;
import org.apache.activemq.artemis.tests.util.Wait;
import org.apache.activemq.artemis.utils.collections.LinkedListIterator;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class ForceDeleteQueue extends ActiveMQTestBase {

   ActiveMQServer server;
   String protocol = "openwire";
   String uri = "tcp://localhost:61616";

   public ForceDeleteQueue(String protocol) {
      this.protocol = protocol;
   }

   @Parameterized.Parameters(name = "protocol={0}")
   public static Collection<Object[]> data() {
      Object[][] params = new Object[][]{{"openwire"}, {"core"}, {"amqp"}};
      return Arrays.asList(params);
   }

   @Override
   @Before
   public void setUp() throws Exception {
      super.setUp();

      if (protocol.equals("openwire")) {
         uri = "tcp://localhost:61616?jms.prefetchPolicy.all=5000";
      }

      server = createServer(true, true);
      server.getAddressSettingsRepository().addMatch("#",
                                                     new AddressSettings().setMaxDeliveryAttempts(2));

      server.start();
   }

   @Test
   public void testForceDelete() throws Exception {
      SimpleString queueName = SimpleString.toSimpleString("testForceDelete");
      server.addAddressInfo(new AddressInfo(queueName, RoutingType.ANYCAST));
      server.createQueue(queueName, RoutingType.ANYCAST, queueName, null, true, false);

      ConnectionFactory factory = CFUtil.createConnectionFactory(protocol, uri);
      Connection conn = factory.createConnection();

      AssertionLoggerHandler.startCapture();
      try {
         Session session = conn.createSession(true, Session.SESSION_TRANSACTED);
         Queue queue = session.createQueue(queueName.toString());
         MessageProducer producer = session.createProducer(queue);
         for (int i = 0; i < 1000; i++) {
            TextMessage message = session.createTextMessage("Text " + i);
            producer.send(message);
         }
         session.commit();

         org.apache.activemq.artemis.core.server.Queue serverQueue = server.locateQueue(queueName);

         Wait.assertEquals(1000, serverQueue::getMessageCount);

         conn.close();

         conn = factory.createConnection();
         session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);

         conn.start();

         LinkedListIterator<MessageReference> queueiterator =  serverQueue.browserIterator();
         ArrayList<Long> listQueue = new ArrayList<>(1000);

         while (queueiterator.hasNext()) {
            MessageReference ref = queueiterator.next();

            listQueue.add(ref.getMessageID());
         }

         queueiterator.close();

         MessageConsumer consumer = session.createConsumer(queue);

         Wait.assertTrue(() -> serverQueue.getDeliveringCount() > 100);

         for (Long l : listQueue) {
            // this is forcing an artificial situation where the message was removed during a failure condition
            server.getStorageManager().deleteMessage(l);
         }

         server.destroyQueue(queueName, null, false);

         for (RemotingConnection connection : server.getRemotingService().getConnections()) {
            connection.fail(new ActiveMQException("failure"));
         }


         Assert.assertFalse(AssertionLoggerHandler.findText("Cannot find add info"));


      } finally {
         AssertionLoggerHandler.stopCapture();
         try {
            conn.close();
         } catch (Throwable ignored) {
         }
      }

   }

}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/JournalLoader.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.server.impl;

import javax.transaction.xa.Xid;
import java.util.List;
import java.util.Map;

import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.api.core.Pair;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.journal.Journal;
import org.apache.activemq.artemis.core.persistence.AddressBindingInfo;
import org.apache.activemq.artemis.core.persistence.GroupingInfo;
import org.apache.activemq.artemis.core.persistence.QueueBindingInfo;
import org.apache.activemq.artemis.core.persistence.impl.PageCountPending;
import org.apache.activemq.artemis.core.persistence.impl.journal.AddMessageRecord;
import org.apache.activemq.artemis.core.server.MessageReference;
import org.apache.activemq.artemis.core.transaction.ResourceManager;
import org.apache.activemq.artemis.core.transaction.Transaction;

public interface JournalLoader {

   void initQueues(Map<Long, QueueBindingInfo> queueBindingInfosMap,
                   List<QueueBindingInfo> queueBindingInfos) throws Exception;

   void initAddresses(List<AddressBindingInfo> addressBindingInfo) throws Exception;

   void handleAddMessage(Map<Long, Map<Long, AddMessageRecord>> queueMap) throws Exception;

   void handleNoMessageReferences(Map<Long, Message> messages);

   void handleGroupingBindings(List<GroupingInfo> groupingInfos);

   void handleDuplicateIds(Map<SimpleString, List<Pair<byte[], Long>>> duplicateIDMap) throws Exception;

   void postLoad(Journal messageJournal,
                 ResourceManager resourceManager,
                 Map<SimpleString, List<Pair<byte[], Long>>> duplicateIDMap) throws Exception;

   void handlePreparedSendMessage(Message message, Transaction tx, long queueID) throws Exception;

   void handlePreparedAcknowledge(long messageID,
                                  List<MessageReference> referencesToAck,
                                  long queueID) throws Exception;

   void handlePreparedTransaction(Transaction tx,
                                  List<MessageReference> referencesToAck,
                                  Xid xid,
                                  ResourceManager resourceManager) throws Exception;

   void recoverPendingPageCounters(List<PageCountPending> pendingNonTXPageCounter) throws Exception;

   void cleanUp();
}


<|start_filename|>artemis-cli/src/test/java/org/apache/activemq/cli/test/CheckTest.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.cli.test;

import java.io.File;

import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.api.core.Pair;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.management.QueueControl;
import org.apache.activemq.artemis.api.core.management.ResourceNames;
import org.apache.activemq.artemis.cli.Artemis;
import org.apache.activemq.artemis.cli.CLIException;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.commands.Run;
import org.apache.activemq.artemis.cli.commands.check.NodeCheck;
import org.apache.activemq.artemis.cli.commands.check.QueueCheck;
import org.apache.activemq.artemis.cli.commands.tools.LockAbstract;
import org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl;
import org.apache.activemq.artemis.utils.Base64;
import org.apache.activemq.artemis.utils.Wait;
import org.junit.Assert;
import org.junit.Test;

public class CheckTest extends CliTestBase {
   final String queueName = "TEST";

   @Test
   public void testNodeCheckUp() throws Exception {
      NodeCheck nodeCheck;
      TestActionContext context;

      startServer();

      try {
         context = new TestActionContext();
         nodeCheck = new NodeCheck();
         nodeCheck.setUser("admin");
         nodeCheck.setPassword("<PASSWORD>");
         Assert.assertEquals(1, nodeCheck.execute(context));

         context = new TestActionContext();
         nodeCheck = new NodeCheck();
         nodeCheck.setUser("admin");
         nodeCheck.setPassword("<PASSWORD>");
         nodeCheck.setUp(true);
         Assert.assertEquals(1, nodeCheck.execute(context));
      } finally {
         stopServer();
      }
   }

   @Test
   public void testNodeCheckDiskUsage() throws Exception {
      NodeCheck nodeCheck;
      TestActionContext context;

      startServer();

      try {
         context = new TestActionContext();
         nodeCheck = new NodeCheck();
         nodeCheck.setUser("admin");
         nodeCheck.setPassword("<PASSWORD>");
         nodeCheck.setDiskUsage(-1);
         Assert.assertEquals(1, nodeCheck.execute(context));

         context = new TestActionContext();
         nodeCheck = new NodeCheck();
         nodeCheck.setUser("admin");
         nodeCheck.setPassword("<PASSWORD>");
         nodeCheck.setDiskUsage(90);
         Assert.assertEquals(1, nodeCheck.execute(context));

         try {
            context = new TestActionContext();
            nodeCheck = new NodeCheck();
            nodeCheck.setUser("admin");
            nodeCheck.setPassword("<PASSWORD>");
            nodeCheck.setDiskUsage(0);
            nodeCheck.execute(context);

            Assert.fail("CLIException expected.");
         } catch (Exception e) {
            Assert.assertTrue("CLIException expected.", e instanceof CLIException);
         }
      } finally {
         stopServer();
      }
   }

   @Test
   public void testNodeCheckMemoryUsage() throws Exception {
      NodeCheck nodeCheck;
      TestActionContext context;

      startServer();

      try {
         context = new TestActionContext();
         nodeCheck = new NodeCheck();
         nodeCheck.setUser("admin");
         nodeCheck.setPassword("<PASSWORD>");
         nodeCheck.setMemoryUsage(90);
         Assert.assertEquals(1, nodeCheck.execute(context));

         try {
            context = new TestActionContext();
            nodeCheck = new NodeCheck();
            nodeCheck.setUser("admin");
            nodeCheck.setPassword("<PASSWORD>");
            nodeCheck.setMemoryUsage(-1);
            nodeCheck.execute(context);

            Assert.fail("CLIException expected.");
         } catch (Exception e) {
            Assert.assertTrue("CLIException expected.", e instanceof CLIException);
         }
      } finally {
         stopServer();
      }
   }

   @Test
   public void testNodeCheckTopology() throws Exception {
      NodeCheck nodeCheck;
      TestActionContext context;

      File masterInstance = new File(temporaryFolder.getRoot(), "masterInstance");
      File slaveInstance = new File(temporaryFolder.getRoot(), "slaveInstance");

      Run.setEmbedded(true);
      setupAuth(masterInstance);

      Artemis.main("create", masterInstance.getAbsolutePath(), "--cluster-password", "<PASSWORD>", "--cluster-user", "artemis", "--clustered",
                   "--replicated", "--host", "127.0.0.1", "--default-port", "61616", "--silent", "--no-autotune", "--no-web", "--require-login");
      Artemis.main("create", slaveInstance.getAbsolutePath(), "--cluster-password", "<PASSWORD>", "--cluster-user", "artemis", "--clustered",
                   "--replicated", "--host", "127.0.0.1", "--default-port", "61626", "--silent", "--no-autotune", "--no-web", "--require-login", "--slave");

      System.setProperty("artemis.instance", masterInstance.getAbsolutePath());
      Object master = Artemis.execute(false, null, masterInstance, "run");
      ActiveMQServerImpl masterServer = (ActiveMQServerImpl)((Pair)master).getB();

      try {
         Wait.assertTrue("Master isn't active", () -> masterServer.isActive(), 10000);

         context = new TestActionContext();
         nodeCheck = new NodeCheck();
         nodeCheck.setUser("admin");
         nodeCheck.setPassword("<PASSWORD>");
         nodeCheck.setLive(true);
         Assert.assertEquals(1, nodeCheck.execute(context));

         try {
            context = new TestActionContext();
            nodeCheck = new NodeCheck();
            nodeCheck.setUser("admin");
            nodeCheck.setPassword("<PASSWORD>");
            nodeCheck.setBackup(true);
            nodeCheck.execute(context);

            Assert.fail("CLIException expected.");
         } catch (Exception e) {
            Assert.assertTrue("CLIException expected.", e instanceof CLIException);
         }

         LockAbstract.unlock();
         Object slave = Artemis.execute(false, null, slaveInstance, "run");
         ActiveMQServerImpl slaveServer = (ActiveMQServerImpl)((Pair)slave).getB();

         Wait.assertTrue("Backup isn't announced", () -> slaveServer.getBackupManager() != null &&
            slaveServer.getBackupManager().isStarted() && slaveServer.getBackupManager().isBackupAnnounced(), 30000);

         try {
            context = new TestActionContext();
            nodeCheck = new NodeCheck();
            nodeCheck.setUser("admin");
            nodeCheck.setPassword("<PASSWORD>");
            nodeCheck.setLive(true);
            nodeCheck.setBackup(true);
            nodeCheck.setPeers(2);
            Assert.assertEquals(3, nodeCheck.execute(context));
         } finally {
            Artemis.internalExecute(null, slaveInstance, new String[] {"stop"}, ActionContext.system());
         }
      } finally {
         stopServer();
      }
   }

   @Test
   public void testQueueCheckUp() throws Exception {
      QueueCheck queueCheck;
      TestActionContext context;

      Object serverInstance = startServer();

      try {
         ActiveMQServerImpl server = (ActiveMQServerImpl)((Pair)serverInstance).getB();

         try {
            context = new TestActionContext();
            queueCheck = new QueueCheck();
            queueCheck.setUser("admin");
            queueCheck.setPassword("<PASSWORD>");
            queueCheck.setName(queueName);
            queueCheck.execute(context);

            Assert.fail("CLIException expected.");
         } catch (Exception e) {
            Assert.assertTrue("CLIException expected.", e instanceof CLIException);
         }

         server.createQueue(new QueueConfiguration(queueName));

         context = new TestActionContext();
         queueCheck = new QueueCheck();
         queueCheck.setUser("admin");
         queueCheck.setPassword("<PASSWORD>");
         queueCheck.setName(queueName);
         Assert.assertEquals(1, queueCheck.execute(context));

         context = new TestActionContext();
         queueCheck = new QueueCheck();
         queueCheck.setUser("admin");
         queueCheck.setPassword("<PASSWORD>");
         queueCheck.setUp(true);
         queueCheck.setName(queueName);
         Assert.assertEquals(1, queueCheck.execute(context));
      } finally {
         stopServer();
      }
   }

   @Test
   public void testQueueCheckBrowse() throws Exception {
      final int messages = 3;

      QueueCheck queueCheck;
      TestActionContext context;

      Object serverInstance = startServer();

      try {
         ActiveMQServerImpl server = (ActiveMQServerImpl)((Pair)serverInstance).getB();

         server.createQueue(new QueueConfiguration(queueName));

         context = new TestActionContext();
         queueCheck = new QueueCheck();
         queueCheck.setUser("admin");
         queueCheck.setPassword("<PASSWORD>");
         queueCheck.setName(queueName);
         queueCheck.setBrowse(null);
         Assert.assertEquals(1, queueCheck.execute(context));

         QueueControl queueControl = (QueueControl)server.getManagementService().
            getResource(ResourceNames.QUEUE + queueName);

         for (int i = 0; i < messages; i++) {
            queueControl.sendMessage(null, Message.BYTES_TYPE, Base64.encodeBytes(
               queueName.getBytes()), true, "admin", "admin");
         }

         context = new TestActionContext();
         queueCheck = new QueueCheck();
         queueCheck.setUser("admin");
         queueCheck.setPassword("<PASSWORD>");
         queueCheck.setName(queueName);
         queueCheck.setBrowse(messages);
         Assert.assertEquals(1, queueCheck.execute(context));
      } finally {
         stopServer();
      }
   }

   @Test
   public void testQueueCheckConsume() throws Exception {
      final int messages = 3;

      QueueCheck queueCheck;
      TestActionContext context;

      Object serverInstance = startServer();

      try {
         ActiveMQServerImpl server = (ActiveMQServerImpl)((Pair)serverInstance).getB();

         server.createQueue(new QueueConfiguration(queueName).setRoutingType(RoutingType.ANYCAST));

         context = new TestActionContext();
         queueCheck = new QueueCheck();
         queueCheck.setUser("admin");
         queueCheck.setPassword("<PASSWORD>");
         queueCheck.setName(queueName);
         queueCheck.setConsume(null);
         Assert.assertEquals(1, queueCheck.execute(context));

         QueueControl queueControl = (QueueControl)server.getManagementService().
            getResource(ResourceNames.QUEUE + queueName);

         for (int i = 0; i < messages; i++) {
            queueControl.sendMessage(null, Message.BYTES_TYPE, Base64.encodeBytes(
               queueName.getBytes()), true, "admin", "admin");
         }

         context = new TestActionContext();
         queueCheck = new QueueCheck();
         queueCheck.setUser("admin");
         queueCheck.setPassword("<PASSWORD>");
         queueCheck.setName(queueName);
         queueCheck.setConsume(messages);
         Assert.assertEquals(1, queueCheck.execute(context));
      } finally {
         stopServer();
      }
   }

   @Test
   public void testQueueCheckConsumeTimeout() throws Exception {
      QueueCheck queueCheck;
      TestActionContext context;

      startServer();

      try {
         try {
            context = new TestActionContext();
            queueCheck = new QueueCheck();
            queueCheck.setUser("admin");
            queueCheck.setPassword("<PASSWORD>");
            queueCheck.setName(queueName);
            queueCheck.setConsume(1);
            queueCheck.setTimeout(100);
            queueCheck.execute(context);

            Assert.fail("CLIException expected.");
         } catch (Exception e) {
            Assert.assertTrue("CLIException expected.", e instanceof CLIException);
         }
      } finally {
         stopServer();
      }
   }

   @Test
   public void testQueueCheckProduce() throws Exception {
      final int messages = 3;

      QueueCheck queueCheck;
      TestActionContext context;
      QueueControl queueControl;

      Object serverInstance = startServer();
      ActiveMQServerImpl server = (ActiveMQServerImpl)((Pair)serverInstance).getB();

      try {
         context = new TestActionContext();
         queueCheck = new QueueCheck();
         queueCheck.setUser("admin");
         queueCheck.setPassword("<PASSWORD>");
         queueCheck.setName(queueName);
         queueCheck.setProduce(messages);
         Assert.assertEquals(1, queueCheck.execute(context));

         queueControl = (QueueControl)server.getManagementService().
            getResource(ResourceNames.QUEUE + queueName);
         Wait.assertEquals(messages, queueControl::getMessageCount);
      } finally {
         stopServer();
      }
   }

   @Test
   public void testQueueCheckProduceAndConsume() throws Exception {
      final int messages = 3;

      QueueCheck queueCheck;
      TestActionContext context;

      Object serverInstance = startServer();
      ActiveMQServerImpl server = (ActiveMQServerImpl)((Pair)serverInstance).getB();

      server.createQueue(new QueueConfiguration(queueName).setRoutingType(RoutingType.ANYCAST));

      try {
         context = new TestActionContext();
         queueCheck = new QueueCheck();
         queueCheck.setUser("admin");
         queueCheck.setPassword("<PASSWORD>");
         queueCheck.setName(queueName);
         queueCheck.setProduce(messages);
         queueCheck.setBrowse(messages);
         queueCheck.setConsume(messages);
         Assert.assertEquals(3, queueCheck.execute(context));

         QueueControl queueControl = (QueueControl)server.getManagementService().
            getResource(ResourceNames.QUEUE + queueName);
         Assert.assertEquals(0, queueControl.getMessageCount());
      } finally {
         stopServer();
      }
   }
}


<|start_filename|>tests/stress-tests/src/test/java/org/apache/activemq/artemis/tests/stress/journal/MultiThreadConsumerStressTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.stress.journal;

import java.util.ArrayList;
import java.util.concurrent.CountDownLatch;

import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.JournalType;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

/**
 * A MultiThreadConsumerStressTest
 * <br>
 * This test validates consuming / sending messages while compacting is working
 */
public class MultiThreadConsumerStressTest extends ActiveMQTestBase {

   // Constants -----------------------------------------------------

   // Attributes ----------------------------------------------------

   final SimpleString ADDRESS = new SimpleString("SomeAddress");

   final SimpleString QUEUE = new SimpleString("SomeQueue");

   private ActiveMQServer server;

   private ClientSessionFactory sf;

   @Override
   @Before
   public void setUp() throws Exception {
      super.setUp();
      setupServer(JournalType.NIO);
   }

   @Test
   public void testProduceAndConsume() throws Throwable {
      int numberOfConsumers = 5;
      // this test assumes numberOfConsumers == numberOfProducers
      int numberOfProducers = numberOfConsumers;
      int produceMessage = 10000;
      int commitIntervalProduce = 100;
      int consumeMessage = (int) (produceMessage * 0.9);
      int commitIntervalConsume = 100;

      ClientSession session = sf.createSession(false, false);
      session.createQueue(new QueueConfiguration("compact-queue").setAddress("compact"));

      ClientProducer producer = session.createProducer("compact");

      for (int i = 0; i < 100; i++) {
         producer.send(session.createMessage(true));
      }

      session.commit();

      // Number of messages expected to be received after restart
      int numberOfMessagesExpected = (produceMessage - consumeMessage) * numberOfConsumers;

      CountDownLatch latchReady = new CountDownLatch(numberOfConsumers + numberOfProducers);

      CountDownLatch latchStart = new CountDownLatch(1);

      ArrayList<BaseThread> threads = new ArrayList<>();

      ProducerThread[] prod = new ProducerThread[numberOfProducers];
      for (int i = 0; i < numberOfProducers; i++) {
         prod[i] = new ProducerThread(i, latchReady, latchStart, produceMessage, commitIntervalProduce);
         prod[i].start();
         threads.add(prod[i]);
      }

      ConsumerThread[] cons = new ConsumerThread[numberOfConsumers];

      for (int i = 0; i < numberOfConsumers; i++) {
         cons[i] = new ConsumerThread(i, latchReady, latchStart, consumeMessage, commitIntervalConsume);
         cons[i].start();
         threads.add(cons[i]);
      }

      ActiveMQTestBase.waitForLatch(latchReady);
      latchStart.countDown();

      for (BaseThread t : threads) {
         t.join();
         if (t.e != null) {
            throw t.e;
         }
      }

      server.stop();

      setupServer(JournalType.NIO);

      ClientSession sess = sf.createSession(true, true);

      ClientConsumer consumer = sess.createConsumer(QUEUE);

      sess.start();

      for (int i = 0; i < numberOfMessagesExpected; i++) {
         ClientMessage msg = consumer.receive(5000);
         Assert.assertNotNull(msg);

         if (i % 1000 == 0) {
            System.out.println("Received #" + i + "  on thread before end");
         }
         msg.acknowledge();
      }

      Assert.assertNull(consumer.receiveImmediate());

      sess.close();

   }

   private void setupServer(final JournalType journalType) throws Exception {
      Configuration config = createDefaultNettyConfig().setJournalType(journalType).setJournalFileSize(ActiveMQDefaultConfiguration.getDefaultJournalFileSize()).setJournalMinFiles(ActiveMQDefaultConfiguration.getDefaultJournalMinFiles()).setJournalCompactMinFiles(2).setJournalCompactPercentage(50);

      server = createServer(true, config);

      server.start();

      ServerLocator locator = createNettyNonHALocator().setBlockOnDurableSend(false).setBlockOnNonDurableSend(false).setBlockOnAcknowledge(false);

      sf = createSessionFactory(locator);

      ClientSession sess = sf.createSession();

      try {
         sess.createQueue(new QueueConfiguration(QUEUE).setAddress(ADDRESS));
      } catch (Exception ignored) {
      }

      sess.close();
      locator.close();
      locator = createInVMNonHALocator();
      sf = createSessionFactory(locator);
   }

   // Static --------------------------------------------------------

   // Constructors --------------------------------------------------

   // Public --------------------------------------------------------

   class BaseThread extends Thread {

      Throwable e;

      final CountDownLatch latchReady;

      final CountDownLatch latchStart;

      final int numberOfMessages;

      final int commitInterval;

      BaseThread(final String name,
                 final CountDownLatch latchReady,
                 final CountDownLatch latchStart,
                 final int numberOfMessages,
                 final int commitInterval) {
         super(name);
         this.latchReady = latchReady;
         this.latchStart = latchStart;
         this.commitInterval = commitInterval;
         this.numberOfMessages = numberOfMessages;
      }

   }

   class ProducerThread extends BaseThread {

      ProducerThread(final int id,
                     final CountDownLatch latchReady,
                     final CountDownLatch latchStart,
                     final int numberOfMessages,
                     final int commitInterval) {
         super("ClientProducer:" + id, latchReady, latchStart, numberOfMessages, commitInterval);
      }

      @Override
      public void run() {
         ClientSession session = null;
         latchReady.countDown();
         try {
            ActiveMQTestBase.waitForLatch(latchStart);
            session = sf.createSession(false, false);
            ClientProducer prod = session.createProducer(ADDRESS);
            for (int i = 0; i < numberOfMessages; i++) {
               if (i % commitInterval == 0) {
                  session.commit();
               }
               if (i % 1000 == 0) {
                  // System.out.println(Thread.currentThread().getName() + "::received #" + i);
               }
               ClientMessage msg = session.createMessage(true);
               prod.send(msg);
            }

            session.commit();

            System.out.println("Thread " + Thread.currentThread().getName() +
                                  " sent " +
                                  numberOfMessages +
                                  "  messages");
         } catch (Throwable e) {
            e.printStackTrace();
            this.e = e;
         } finally {
            try {
               session.close();
            } catch (Throwable e) {
               e.printStackTrace();
            }
         }
      }
   }

   class ConsumerThread extends BaseThread {

      ConsumerThread(final int id,
                     final CountDownLatch latchReady,
                     final CountDownLatch latchStart,
                     final int numberOfMessages,
                     final int commitInterval) {
         super("ClientConsumer:" + id, latchReady, latchStart, numberOfMessages, commitInterval);
      }

      @Override
      public void run() {
         ClientSession session = null;
         latchReady.countDown();
         try {
            ActiveMQTestBase.waitForLatch(latchStart);
            session = sf.createSession(false, false);
            session.start();
            ClientConsumer cons = session.createConsumer(QUEUE);
            for (int i = 0; i < numberOfMessages; i++) {
               ClientMessage msg = cons.receive(60 * 1000);
               msg.acknowledge();
               if (i % commitInterval == 0) {
                  session.commit();
               }
               if (i % 1000 == 0) {
                  // System.out.println(Thread.currentThread().getName() + "::sent #" + i);
               }
            }

            System.out.println("Thread " + Thread.currentThread().getName() +
                                  " received " +
                                  numberOfMessages +
                                  " messages");

            session.commit();
         } catch (Throwable e) {
            this.e = e;
         } finally {
            try {
               session.close();
            } catch (Throwable e) {
               this.e = e;
            }
         }
      }
   }

   // Package protected ---------------------------------------------

   // Protected -----------------------------------------------------

   // Private -------------------------------------------------------

   // Inner classes -------------------------------------------------

}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/impl/PagedMessageImpl.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.paging.impl;

import java.util.Arrays;

import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.ActiveMQBuffers;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.ICoreMessage;
import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.core.paging.PagedMessage;
import org.apache.activemq.artemis.core.persistence.StorageManager;
import org.apache.activemq.artemis.core.persistence.impl.journal.codec.LargeMessagePersister;
import org.apache.activemq.artemis.core.server.LargeServerMessage;
import org.apache.activemq.artemis.spi.core.protocol.MessagePersister;
import org.apache.activemq.artemis.utils.DataConstants;

/**
 * This class represents a paged message
 */
public class PagedMessageImpl implements PagedMessage {

   // It encapsulates the logic to detect large message types
   private static final class LargeMessageType {

      private static final byte NONE = 0;
      private static final byte CORE = 1;
      private static final byte OLD_CORE = -1;
      private static final byte NOT_CORE = 2;

      public static boolean isLargeMessage(byte encodedValue) {
         switch (encodedValue) {
            case LargeMessageType.NONE:
               return false;
            case LargeMessageType.CORE:
            case LargeMessageType.OLD_CORE:
            case LargeMessageType.NOT_CORE:
               return true;
            default:
               throw new IllegalStateException("This largeMessageType isn't supported: " + encodedValue);
         }
      }

      public static boolean isCoreLargeMessage(Message message) {
         return message.isLargeMessage() && message instanceof ICoreMessage;
      }

      public static boolean isCoreLargeMessageType(byte encodedValue) {
         return encodedValue == LargeMessageType.CORE ||
            encodedValue == LargeMessageType.OLD_CORE;
      }

      public static byte valueOf(Message message) {
         if (!message.isLargeMessage()) {
            return NONE;
         }
         if (message instanceof ICoreMessage) {
            return CORE;
         }
         return NOT_CORE;
      }
   }
   /**
    * Large messages will need to be instantiated lazily during getMessage when the StorageManager
    * is available
    */
   private byte[] largeMessageLazyData;

   private Message message;

   private long[] queueIDs;

   private long transactionID = 0;

   private final int storedSize;

   private final StorageManager storageManager;

   public PagedMessageImpl(final Message message, final long[] queueIDs, final long transactionID) {
      this(message, queueIDs);
      this.transactionID = transactionID;
   }

   public PagedMessageImpl(final Message message, final long[] queueIDs) {
      this.storageManager = null;
      this.queueIDs = queueIDs;
      this.message = message;
      this.storedSize = 0;
   }

   public PagedMessageImpl(int storedSize, StorageManager storageManager) {
      this.storageManager = storageManager;
      this.storedSize = storedSize;
   }


   @Override
   public int getStoredSize() {
      if (storedSize <= 0) {
         return getEncodeSize();
      } else {
         return storedSize;
      }
   }

   @Override
   public Message getMessage() {
      return message;
   }

   @Override
   public void initMessage(StorageManager storage) {
      if (largeMessageLazyData != null) {
         LargeServerMessage lgMessage = storage.createLargeMessage();

         ActiveMQBuffer buffer = ActiveMQBuffers.wrappedBuffer(largeMessageLazyData);
         lgMessage = LargeMessagePersister.getInstance().decode(buffer, lgMessage, null);
         if (lgMessage.toMessage() instanceof LargeServerMessage) {
            ((LargeServerMessage)lgMessage.toMessage()).setStorageManager(storage);
         }
         lgMessage.toMessage().usageUp();
         lgMessage.setPaged();
         this.message = lgMessage.toMessage();
         largeMessageLazyData = null;
      } else {
         if (message != null && message instanceof LargeServerMessage) {
            ((LargeServerMessage)message).setStorageManager(storageManager);
         }
      }
   }

   @Override
   public long getTransactionID() {
      return transactionID;
   }

   @Override
   public long[] getQueueIDs() {
      return queueIDs;
   }

   // EncodingSupport implementation --------------------------------

   /**
    * This method won't move the {@link ActiveMQBuffer#readerIndex()} of {@code buffer}.
    */
   public static boolean isLargeMessage(ActiveMQBuffer buffer) {
      // skip transactionID
      return LargeMessageType.isLargeMessage(buffer.getByte(buffer.readerIndex() + Long.BYTES));
   }

   @Override
   public void decode(final ActiveMQBuffer buffer) {
      transactionID = buffer.readLong();

      boolean isCoreLargeMessage = LargeMessageType.isCoreLargeMessageType(buffer.readByte());

      if (isCoreLargeMessage) {
         int largeMessageHeaderSize = buffer.readInt();

         if (storageManager == null) {
            largeMessageLazyData = new byte[largeMessageHeaderSize];
            buffer.readBytes(largeMessageLazyData);
         } else {
            this.message = storageManager.createLargeMessage().toMessage();
            LargeMessagePersister.getInstance().decode(buffer, (LargeServerMessage) message, null);
            ((LargeServerMessage) message).setStorageManager(storageManager);
            ((LargeServerMessage) message).toMessage().usageUp();
         }
      } else {
         this.message = MessagePersister.getInstance().decode(buffer, null, null, storageManager);
         if (message.isLargeMessage()) {
            message.usageUp();
         }
      }


      int queueIDsSize = buffer.readInt();

      queueIDs = new long[queueIDsSize];

      for (int i = 0; i < queueIDsSize; i++) {
         queueIDs[i] = buffer.readLong();
      }
   }

   @Override
   public void encode(final ActiveMQBuffer buffer) {
      buffer.writeLong(transactionID);

      byte largeMessageType = LargeMessageType.valueOf(message);

      buffer.writeByte(largeMessageType);

      if (LargeMessageType.isCoreLargeMessageType(largeMessageType)) {
         buffer.writeInt(LargeMessagePersister.getInstance().getEncodeSize((LargeServerMessage) message));
         LargeMessagePersister.getInstance().encode(buffer, (LargeServerMessage) message);
      } else {
         message.getPersister().encode(buffer, message);
      }

      buffer.writeInt(queueIDs.length);

      for (long queueID : queueIDs) {
         buffer.writeLong(queueID);
      }
   }

   @Override
   public int getEncodeSize() {
      if (LargeMessageType.isCoreLargeMessage(message)) {
         return DataConstants.SIZE_LONG + DataConstants.SIZE_BYTE + DataConstants.SIZE_INT + LargeMessagePersister.getInstance().getEncodeSize((LargeServerMessage)message) +
            DataConstants.SIZE_INT + queueIDs.length * DataConstants.SIZE_LONG;
      } else {
         return DataConstants.SIZE_LONG + DataConstants.SIZE_BYTE + message.getPersister().getEncodeSize(message) +
            DataConstants.SIZE_INT + queueIDs.length * DataConstants.SIZE_LONG;
      }
   }

   @Override
   public String toString() {
      return "PagedMessageImpl [queueIDs=" + Arrays.toString(queueIDs) +
         ", transactionID=" +
         transactionID +
         ", message=" +
         message +
         "]";
   }

   @Override
   public long getPersistentSize() throws ActiveMQException {
      return message.getPersistentSize();
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cluster/bridge/BridgeFailoverTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.cluster.bridge;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.config.BridgeConfiguration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.cluster.impl.BridgeImpl;
import org.apache.activemq.artemis.tests.integration.cluster.util.MultiServerTestBase;
import org.junit.Test;

public class BridgeFailoverTest extends MultiServerTestBase {

   @Test
   public void testSimpleConnectOnMultipleNodes() throws Exception {
      BridgeConfiguration bridgeConfiguration = new BridgeConfiguration();

      String ORIGINAL_QUEUE = "noCluster.originalQueue";
      String TARGET_QUEUE = "noCluster.targetQueue";

      bridgeConfiguration.setHA(true);
      List<String> connectors = new ArrayList<>();
      connectors.add("target-4");
      connectors.add("backup-4");
      bridgeConfiguration.setName("Bridge-for-test");
      bridgeConfiguration.setStaticConnectors(connectors);
      bridgeConfiguration.setQueueName(ORIGINAL_QUEUE);
      bridgeConfiguration.setForwardingAddress(TARGET_QUEUE);
      bridgeConfiguration.setRetryInterval(100);
      bridgeConfiguration.setConfirmationWindowSize(1);
      bridgeConfiguration.setReconnectAttempts(-1);
      servers[2].getConfiguration().getBridgeConfigurations().add(bridgeConfiguration);

      for (ActiveMQServer server : servers) {
         server.getConfiguration().addQueueConfiguration(new QueueConfiguration(ORIGINAL_QUEUE));
         server.getConfiguration().addQueueConfiguration(new QueueConfiguration(TARGET_QUEUE));
      }

      startServers();

      // The server where the bridge source is configured at
      ServerLocator locator = createLocator(false, 2);

      ClientSessionFactory factory = addSessionFactory(locator.createSessionFactory());
      ClientSession session = addClientSession(factory.createSession(false, false));
      ClientProducer producer = addClientProducer(session.createProducer(ORIGINAL_QUEUE));

      for (int i = 0; i < 100; i++) {
         ClientMessage msg = session.createMessage(true);
         msg.putIntProperty("i", i);
         producer.send(msg);
      }
      session.commit();

      ServerLocator locatorConsumer = createLocator(false, 4);
      ClientSessionFactory factoryConsumer = addSessionFactory(locatorConsumer.createSessionFactory());
      ClientSession sessionConsumer = addClientSession(factoryConsumer.createSession(false, false));
      ClientConsumer consumer = sessionConsumer.createConsumer(TARGET_QUEUE);

      sessionConsumer.start();

      for (int i = 0; i < 100; i++) {
         ClientMessage message = consumer.receive(10000);
         assertNotNull(message);
         message.acknowledge();
      }

      sessionConsumer.commit();
   }

   @Test
   public void testFailoverOnBridgeNoRetryOnSameNode() throws Exception {
      internalTestFailoverOnBridge(0);
   }

   @Test
   public void testFailoverOnBridgeForeverRetryOnSameNode() throws Exception {
      internalTestFailoverOnBridge(-1);
   }

   public void internalTestFailoverOnBridge(int retriesSameNode) throws Exception {
      BridgeConfiguration bridgeConfiguration = new BridgeConfiguration();

      String ORIGINAL_QUEUE = "noCluster.originalQueue";
      String TARGET_QUEUE = "noCluster.targetQueue";

      bridgeConfiguration.setHA(true);
      List<String> connectors = new ArrayList<>();
      connectors.add("target-4");
      connectors.add("backup-4");
      bridgeConfiguration.setName("Bridge-for-test");
      bridgeConfiguration.setStaticConnectors(connectors);
      bridgeConfiguration.setQueueName(ORIGINAL_QUEUE);
      bridgeConfiguration.setForwardingAddress(TARGET_QUEUE);
      bridgeConfiguration.setRetryInterval(100);
      bridgeConfiguration.setConfirmationWindowSize(1);
      bridgeConfiguration.setReconnectAttempts(-1);
      bridgeConfiguration.setReconnectAttemptsOnSameNode(retriesSameNode);
      bridgeConfiguration.setHA(true);
      servers[2].getConfiguration().getBridgeConfigurations().add(bridgeConfiguration);

      for (ActiveMQServer server : servers) {
         server.getConfiguration().addQueueConfiguration(new QueueConfiguration(ORIGINAL_QUEUE));
         server.getConfiguration().addQueueConfiguration(new QueueConfiguration(TARGET_QUEUE));
      }

      startServers();

      BridgeImpl bridge = (BridgeImpl) servers[2].getClusterManager().getBridges().get("Bridge-for-test");
      assertNotNull(bridge);

      long timeout = System.currentTimeMillis() + 5000;

      while (bridge.getTargetNodeFromTopology() == null && timeout > System.currentTimeMillis()) {
         Thread.sleep(100);
      }

      assertNotNull(bridge.getTargetNodeFromTopology());

      // The server where the bridge source is configured at
      ServerLocator locatorProducer = createLocator(false, 2);

      ClientSessionFactory factory = addSessionFactory(locatorProducer.createSessionFactory());
      ClientSession session = addClientSession(factory.createSession(false, false));
      ClientProducer producer = addClientProducer(session.createProducer(ORIGINAL_QUEUE));

      for (int i = 0; i < 100; i++) {
         ClientMessage msg = session.createMessage(true);
         msg.putIntProperty("i", i);
         producer.send(msg);
      }
      session.commit();

      ServerLocator locatorConsumer = createLocator(false, 4);
      ClientSessionFactory factoryConsumer = addSessionFactory(locatorConsumer.createSessionFactory());
      ClientSession sessionConsumer = addClientSession(factoryConsumer.createSession(false, false));
      ClientConsumer consumer = sessionConsumer.createConsumer(TARGET_QUEUE);

      sessionConsumer.start();

      for (int i = 0; i < 100; i++) {
         ClientMessage message = consumer.receive(10000);
         assertNotNull(message);
         message.acknowledge();
      }

      // We rollback as we will receive them again
      sessionConsumer.rollback();

      factoryConsumer.close();
      sessionConsumer.close();

      crashAndWaitForFailure(servers[4], locatorConsumer);

      locatorConsumer.close();

      assertTrue("Backup server didn't activate.", backupServers[4].waitForActivation(5, TimeUnit.SECONDS));

      for (int i = 100; i < 200; i++) {
         ClientMessage msg = session.createMessage(true);
         msg.putIntProperty("i", i);
         producer.send(msg);
      }

      session.commit();

      locatorConsumer = createLocator(false, 9);
      factoryConsumer = addSessionFactory(locatorConsumer.createSessionFactory());
      sessionConsumer = addClientSession(factoryConsumer.createSession());

      consumer = sessionConsumer.createConsumer(TARGET_QUEUE);

      sessionConsumer.start();

      for (int i = 0; i < 200; i++) {
         ClientMessage message = consumer.receive(10000);
         assertNotNull(message);
         message.acknowledge();
      }

      sessionConsumer.commit();

   }

   @Test
   public void testInitialConnectionNodeAlreadyDown() throws Exception {
      BridgeConfiguration bridgeConfiguration = new BridgeConfiguration();

      String ORIGINAL_QUEUE = "noCluster.originalQueue";
      String TARGET_QUEUE = "noCluster.targetQueue";

      bridgeConfiguration.setHA(true);
      List<String> connectors = new ArrayList<>();
      connectors.add("target-4");
      connectors.add("backup-4");
      bridgeConfiguration.setName("Bridge-for-test");
      bridgeConfiguration.setStaticConnectors(connectors);
      bridgeConfiguration.setQueueName(ORIGINAL_QUEUE);
      bridgeConfiguration.setForwardingAddress(TARGET_QUEUE);
      bridgeConfiguration.setRetryInterval(100);
      bridgeConfiguration.setConfirmationWindowSize(1);
      bridgeConfiguration.setReconnectAttempts(-1);
      servers[2].getConfiguration().getBridgeConfigurations().add(bridgeConfiguration);

      for (ActiveMQServer server : servers) {
         server.getConfiguration().addQueueConfiguration(new QueueConfiguration(ORIGINAL_QUEUE));
         server.getConfiguration().addQueueConfiguration(new QueueConfiguration(TARGET_QUEUE));
      }

      startBackups(0, 1, 3, 4);
      startServers(0, 1, 3, 4);

      waitForTopology(servers[4], getNumberOfServers() - 1, getNumberOfServers() - 1);

      crashAndWaitForFailure(servers[4], createLocator(false, 4));
      waitForServerToStart(backupServers[4]);

      startBackups(2);
      startServers(2);

      // The server where the bridge source is configured at
      ServerLocator locator = createLocator(false, 2); // connecting to the backup

      ClientSessionFactory factory = addSessionFactory(locator.createSessionFactory());
      ClientSession session = addClientSession(factory.createSession(false, false));
      ClientProducer producer = addClientProducer(session.createProducer(ORIGINAL_QUEUE));

      for (int i = 0; i < 100; i++) {
         ClientMessage msg = session.createMessage(true);
         msg.putIntProperty("i", i);
         producer.send(msg);
      }
      session.commit();

      ServerLocator locatorConsumer = createLocator(false, 9);
      ClientSessionFactory factoryConsumer = addSessionFactory(locatorConsumer.createSessionFactory());
      ClientSession sessionConsumer = addClientSession(factoryConsumer.createSession(false, false));
      ClientConsumer consumer = sessionConsumer.createConsumer(TARGET_QUEUE);

      sessionConsumer.start();

      for (int i = 0; i < 100; i++) {
         ClientMessage message = consumer.receive(10000);
         assertNotNull(message);
         message.acknowledge();
      }

      sessionConsumer.commit();
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/largemessages/AmqpReplicatedTestSupport.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.tests.integration.amqp.largemessages;

import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.config.ha.ReplicaPolicyConfiguration;
import org.apache.activemq.artemis.core.config.ha.SharedStoreSlavePolicyConfiguration;
import org.apache.activemq.artemis.core.server.NodeManager;
import org.apache.activemq.artemis.core.server.impl.InVMNodeManager;
import org.apache.activemq.artemis.tests.integration.amqp.AmqpTestSupport;
import org.apache.activemq.artemis.tests.integration.cluster.util.SameProcessActiveMQServer;
import org.apache.activemq.artemis.tests.integration.cluster.util.TestableServer;
import org.apache.activemq.artemis.tests.util.ReplicatedBackupUtils;

public abstract class AmqpReplicatedTestSupport extends AmqpTestSupport {

   protected TestableServer liveServer;

   protected TestableServer backupServer;

   protected Configuration backupConfig;

   protected Configuration liveConfig;

   protected abstract TransportConfiguration getAcceptorTransportConfiguration(boolean live);

   protected abstract TransportConfiguration getConnectorTransportConfiguration(boolean live);

   protected NodeManager nodeManager;

   @Override
   public void setUp() throws Exception {
      super.setUp();

      createReplicatedConfigs();
   }

   protected void createReplicatedConfigs() throws Exception {
      final TransportConfiguration liveConnector = getConnectorTransportConfiguration(true);
      final TransportConfiguration backupConnector = getConnectorTransportConfiguration(false);
      final TransportConfiguration backupAcceptor = getAcceptorTransportConfiguration(false);

      backupConfig = createDefaultInVMConfig();
      liveConfig = createDefaultInVMConfig();

      ReplicatedBackupUtils.configureReplicationPair(backupConfig, backupConnector, backupAcceptor, liveConfig, liveConnector, null);

      backupConfig.setBindingsDirectory(getBindingsDir(0, true)).setJournalDirectory(getJournalDir(0, true)).setPagingDirectory(getPageDir(0, true)).setLargeMessagesDirectory(getLargeMessagesDir(0, true)).setSecurityEnabled(false);

      setupHAPolicyConfiguration();
      nodeManager = createReplicatedBackupNodeManager(backupConfig);

      backupServer = createTestableServer(backupConfig);

      liveConfig.clearAcceptorConfigurations().addAcceptorConfiguration(getAcceptorTransportConfiguration(true));

      liveServer = createTestableServer(liveConfig);
   }

   /**
    * Override this if is needed a different implementation of {@link NodeManager} to be used into {@link #createReplicatedConfigs()}.
    */
   protected NodeManager createReplicatedBackupNodeManager(Configuration backupConfig) {
      return new InVMNodeManager(true, backupConfig.getJournalLocation());
   }

   protected void setupHAPolicyConfiguration() {
      ((ReplicaPolicyConfiguration) backupConfig.getHAPolicyConfiguration()).setMaxSavedReplicatedJournalsSize(-1).setAllowFailBack(true);
      ((ReplicaPolicyConfiguration) backupConfig.getHAPolicyConfiguration()).setRestartBackup(false);
   }

   protected TestableServer createTestableServer(Configuration config) throws Exception {
      return createTestableServer(config, nodeManager);
   }

   protected TestableServer createTestableServer(Configuration config, NodeManager nodeManager) throws Exception {
      boolean isBackup = config.getHAPolicyConfiguration() instanceof ReplicaPolicyConfiguration || config.getHAPolicyConfiguration() instanceof SharedStoreSlavePolicyConfiguration;
      return new SameProcessActiveMQServer(createInVMFailoverServer(true, config, nodeManager, isBackup ? 2 : 1));
   }

}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/stomp/StompPropertiesInterceptorTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.stomp;

import org.apache.activemq.artemis.core.protocol.stomp.StompFrame;
import org.apache.activemq.artemis.core.protocol.stomp.StompFrameInterceptor;
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.tests.integration.stomp.util.ClientStompFrame;
import org.apache.activemq.artemis.tests.integration.stomp.util.StompClientConnection;
import org.apache.activemq.artemis.tests.integration.stomp.util.StompClientConnectionFactory;
import org.apache.felix.resolver.util.ArrayMap;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.Map;

@RunWith(value = Parameterized.class)
public class StompPropertiesInterceptorTest extends StompTestBase {

   @Parameterized.Parameters(name = "{0}")
   public static Collection<Object[]> data() {
      return Arrays.asList(new Object[][]{{"ws+v12.stomp"}, {"tcp+v12.stomp"}});
   }

   @Override
   public List<String> getIncomingInterceptors() {
      List<String> stompIncomingInterceptor = new ArrayList<>();
      stompIncomingInterceptor.add("org.apache.activemq.artemis.tests.integration.stomp.StompPropertiesInterceptorTest$StompFramePropertiesInterceptor");
      return stompIncomingInterceptor;
   }

   @Override
   public List<String> getOutgoingInterceptors() {
      List<String> stompOutgoingInterceptor = new ArrayList<>();
      stompOutgoingInterceptor.add("org.apache.activemq.artemis.tests.integration.stomp.StompPropertiesInterceptorTest$StompFramePropertiesInterceptor");

      return stompOutgoingInterceptor;
   }

   public static class StompFramePropertiesInterceptor implements StompFrameInterceptor {

      @Override
      public boolean intercept(StompFrame stompFrame, RemotingConnection connection) {
         if (stompFrame.getCommand().equals("CONNECT") || stompFrame.getCommand().equals("CONNECTED")) {
            return true;
         }
         assertNotNull(stompFrame);
         assertEquals(stompFrame.getHeader(MY_HEADER), expectedProperties.get(MY_HEADER));
         assertEquals(stompFrame.getBody(), expectedProperties.get(MESSAGE_TEXT));
         return true;
      }
   }


   private static final String MESSAGE_TEXT = "messageText";
   private static final String MY_HEADER = "my-header";
   private static Map<String, Object> expectedProperties = new ArrayMap<>();

   @Test(timeout = 60000)
   public void testCheckInterceptedStompMessageProperties() throws Exception {
      final String msgText = "Test intercepted message";
      final String myHeader = "TestInterceptedHeader";
      expectedProperties.put(MESSAGE_TEXT, msgText);
      expectedProperties.put(MY_HEADER, myHeader);

      StompClientConnection conn = StompClientConnectionFactory.createClientConnection(uri);
      conn.connect(defUser, defPass);

      ClientStompFrame subFrame = conn.createFrame("SUBSCRIBE");

      subFrame.addHeader("subscription-type", "ANYCAST");
      subFrame.addHeader("destination", name.getMethodName());
      subFrame.addHeader("ack", "auto");
      subFrame.addHeader(MY_HEADER, myHeader);
      subFrame.setBody(msgText);

      conn.sendFrame(subFrame);

      ClientStompFrame frame = conn.createFrame("SEND");
      frame.addHeader("destination", name.getMethodName());
      frame.addHeader("ack", "auto");
      frame.addHeader(MY_HEADER, myHeader);
      conn.sendFrame(frame);

      conn.disconnect();

   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/paging/PagingOrderTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.paging;

import javax.jms.BytesMessage;
import javax.jms.Connection;
import javax.jms.DeliveryMode;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import java.nio.ByteBuffer;
import java.util.HashMap;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
import org.apache.activemq.artemis.api.jms.JMSFactoryType;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.paging.PagingStore;
import org.apache.activemq.artemis.core.postoffice.Binding;
import org.apache.activemq.artemis.core.postoffice.Bindings;
import org.apache.activemq.artemis.core.postoffice.impl.LocalQueueBinding;
import org.apache.activemq.artemis.core.registry.JndiBindingRegistry;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.apache.activemq.artemis.core.server.impl.QueueImpl;
import org.apache.activemq.artemis.core.settings.impl.AddressFullMessagePolicy;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.jms.client.ActiveMQJMSConnectionFactory;
import org.apache.activemq.artemis.jms.server.impl.JMSServerManagerImpl;
import org.apache.activemq.artemis.tests.unit.util.InVMNamingContext;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.junit.Test;

/**
 * A PagingOrderTest. PagingTest has a lot of tests already. I decided to create a newer one more
 * specialized on Ordering and counters
 */
public class PagingOrderTest extends ActiveMQTestBase {

   private static final int PAGE_MAX = 100 * 1024;

   private static final int PAGE_SIZE = 10 * 1024;

   // Attributes ----------------------------------------------------

   // Static --------------------------------------------------------

   static final SimpleString ADDRESS = new SimpleString("SimpleAddress");

   private Connection conn;

   @Test
   public void testOrder1() throws Throwable {
      boolean persistentMessages = true;

      Configuration config = createDefaultInVMConfig().setJournalSyncNonTransactional(false);

      ActiveMQServer server = createServer(true, config, PAGE_SIZE, PAGE_MAX, new HashMap<String, AddressSettings>());

      server.start();

      final int messageSize = 1024;

      final int numberOfMessages = 500;

      ServerLocator locator = createInVMNonHALocator().setClientFailureCheckPeriod(1000).setConnectionTTL(2000).setReconnectAttempts(0).setBlockOnNonDurableSend(true).setBlockOnDurableSend(true).setBlockOnAcknowledge(true).setConsumerWindowSize(1024 * 1024);

      ClientSessionFactory sf = createSessionFactory(locator);

      ClientSession session = sf.createSession(false, false, false);

      server.addAddressInfo(new AddressInfo(ADDRESS, RoutingType.ANYCAST));
      server.createQueue(new QueueConfiguration(ADDRESS).setRoutingType(RoutingType.ANYCAST));

      ClientProducer producer = session.createProducer(PagingTest.ADDRESS);

      byte[] body = new byte[messageSize];

      ByteBuffer bb = ByteBuffer.wrap(body);

      for (int j = 1; j <= messageSize; j++) {
         bb.put(getSamplebyte(j));
      }

      for (int i = 0; i < numberOfMessages; i++) {
         ClientMessage message = session.createMessage(persistentMessages);

         ActiveMQBuffer bodyLocal = message.getBodyBuffer();

         bodyLocal.writeBytes(body);

         message.putIntProperty(new SimpleString("id"), i);

         producer.send(message);
         if (i % 1000 == 0) {
            session.commit();
         }
      }

      session.commit();

      session.close();

      session = sf.createSession(true, true, 0);

      session.start();

      ClientConsumer consumer = session.createConsumer(ADDRESS);

      for (int i = 0; i < numberOfMessages / 2; i++) {
         ClientMessage message = consumer.receive(5000);
         assertNotNull(message);
         assertEquals(i, message.getIntProperty("id").intValue());

         if (i < 100) {
            // Do not consume the last one so we could restart
            message.acknowledge();
         }
      }

      session.close();

      sf.close();
      sf = createSessionFactory(locator);

      session = sf.createSession(true, true, 0);

      session.start();

      consumer = session.createConsumer(ADDRESS);

      for (int i = 100; i < numberOfMessages; i++) {
         ClientMessage message = consumer.receive(5000);
         assertNotNull(message);
         assertEquals(i, message.getIntProperty("id").intValue());
         message.acknowledge();
      }

      session.close();
   }

   @Test
   public void testPageCounter() throws Throwable {
      boolean persistentMessages = true;

      Configuration config = createDefaultInVMConfig().setJournalSyncNonTransactional(false);

      ActiveMQServer server = createServer(true, config, PAGE_SIZE, PAGE_MAX, new HashMap<String, AddressSettings>());

      server.start();

      final int messageSize = 1024;

      final int numberOfMessages = 500;

      ServerLocator locator = createInVMNonHALocator().setClientFailureCheckPeriod(1000).setConnectionTTL(2000).setReconnectAttempts(0).setBlockOnNonDurableSend(true).setBlockOnDurableSend(true).setBlockOnAcknowledge(true).setConsumerWindowSize(1024 * 1024);

      ClientSessionFactory sf = createSessionFactory(locator);

      ClientSession session = sf.createSession(false, false, false);

      server.addAddressInfo(new AddressInfo(ADDRESS, RoutingType.ANYCAST));
      Queue q1 = server.createQueue(new QueueConfiguration(ADDRESS));

      Queue q2 = server.createQueue(new QueueConfiguration(new SimpleString("inactive")).setAddress(ADDRESS).setRoutingType(RoutingType.MULTICAST));

      ClientProducer producer = session.createProducer(PagingTest.ADDRESS);

      byte[] body = new byte[messageSize];

      ByteBuffer bb = ByteBuffer.wrap(body);

      for (int j = 1; j <= messageSize; j++) {
         bb.put(getSamplebyte(j));
      }

      final AtomicInteger errors = new AtomicInteger(0);

      Thread t1 = new Thread() {
         @Override
         public void run() {
            try {
               ServerLocator sl = createInVMNonHALocator();
               ClientSessionFactory sf = sl.createSessionFactory();
               ClientSession sess = sf.createSession(true, true, 0);
               sess.start();
               ClientConsumer cons = sess.createConsumer(ADDRESS);
               for (int i = 0; i < numberOfMessages; i++) {
                  ClientMessage msg = cons.receive(5000);
                  assertNotNull(msg);
                  assertEquals(i, msg.getIntProperty("id").intValue());
                  msg.acknowledge();
               }

               assertNull(cons.receiveImmediate());
               sess.close();
               sl.close();
            } catch (Throwable e) {
               e.printStackTrace();
               errors.incrementAndGet();
            }

         }
      };

      t1.start();

      for (int i = 0; i < numberOfMessages; i++) {
         ClientMessage message = session.createMessage(persistentMessages);

         ActiveMQBuffer bodyLocal = message.getBodyBuffer();

         bodyLocal.writeBytes(body);

         message.putIntProperty(new SimpleString("id"), i);

         producer.send(message);
         if (i % 20 == 0) {
            session.commit();
         }
      }

      session.commit();

      t1.join();

      assertEquals(0, errors.get());

      assertEquals(numberOfMessages, getMessageCount(q2));
      assertEquals(numberOfMessages, getMessagesAdded(q2));
      assertEquals(0, getMessageCount(q1));
      assertEquals(numberOfMessages, getMessagesAdded(q1));

      session.close();
      sf.close();
      locator.close();

      server.stop();

      server.start();

      Bindings bindings = server.getPostOffice().getBindingsForAddress(ADDRESS);

      q1 = null;
      q2 = null;

      for (Binding bind : bindings.getBindings()) {
         if (bind instanceof LocalQueueBinding) {
            LocalQueueBinding qb = (LocalQueueBinding) bind;
            if (qb.getQueue().getName().equals(ADDRESS)) {
               q1 = qb.getQueue();
            }

            if (qb.getQueue().getName().equals(new SimpleString("inactive"))) {
               q2 = qb.getQueue();
            }
         }
      }

      assertNotNull(q1);

      assertNotNull(q2);

      assertEquals("q2 msg count", numberOfMessages, getMessageCount(q2));
      assertEquals("q2 msgs added", numberOfMessages, getMessagesAdded(q2));
      assertEquals("q1 msg count", 0, getMessageCount(q1));
      // 0, since nothing was sent to the queue after the server was restarted
      assertEquals("q1 msgs added", 0, getMessagesAdded(q1));

   }

   @Test
   public void testPageCounter2() throws Throwable {
      boolean persistentMessages = true;

      Configuration config = createDefaultInVMConfig().setJournalSyncNonTransactional(false);

      ActiveMQServer server = createServer(true, config, PAGE_SIZE, PAGE_MAX, new HashMap<String, AddressSettings>());

      server.start();

      final int messageSize = 1024;

      final int numberOfMessages = 500;

      ServerLocator locator = createInVMNonHALocator().setClientFailureCheckPeriod(1000).setConnectionTTL(2000).setReconnectAttempts(0).setBlockOnNonDurableSend(true).setBlockOnDurableSend(true).setBlockOnAcknowledge(true).setConsumerWindowSize(1024 * 1024);

      ClientSessionFactory sf = createSessionFactory(locator);

      ClientSession session = sf.createSession(false, false, false);

      server.addAddressInfo(new AddressInfo(ADDRESS, RoutingType.ANYCAST));
      Queue q1 = server.createQueue(new QueueConfiguration(ADDRESS));

      Queue q2 = server.createQueue(new QueueConfiguration(new SimpleString("inactive")).setAddress(ADDRESS).setRoutingType(RoutingType.MULTICAST));

      ClientProducer producer = session.createProducer(PagingTest.ADDRESS);

      byte[] body = new byte[messageSize];

      ByteBuffer bb = ByteBuffer.wrap(body);

      for (int j = 1; j <= messageSize; j++) {
         bb.put(getSamplebyte(j));
      }

      final AtomicInteger errors = new AtomicInteger(0);

      Thread t1 = new Thread() {
         @Override
         public void run() {
            try {
               ServerLocator sl = createInVMNonHALocator();
               ClientSessionFactory sf = sl.createSessionFactory();
               ClientSession sess = sf.createSession(true, true, 0);
               sess.start();
               ClientConsumer cons = sess.createConsumer(ADDRESS);
               for (int i = 0; i < 100; i++) {
                  ClientMessage msg = cons.receive(5000);
                  assertNotNull(msg);
                  assertEquals(i, msg.getIntProperty("id").intValue());
                  msg.acknowledge();
               }
               sess.close();
               sl.close();
            } catch (Throwable e) {
               e.printStackTrace();
               errors.incrementAndGet();
            }

         }
      };

      for (int i = 0; i < numberOfMessages; i++) {
         ClientMessage message = session.createMessage(persistentMessages);

         ActiveMQBuffer bodyLocal = message.getBodyBuffer();

         bodyLocal.writeBytes(body);

         message.putIntProperty(new SimpleString("id"), i);

         producer.send(message);
         if (i % 20 == 0) {
            session.commit();
         }
      }

      session.commit();

      t1.start();
      t1.join();

      assertEquals(0, errors.get());
      long timeout = System.currentTimeMillis() + 10000;
      while (numberOfMessages - 100 != getMessageCount(q1) && System.currentTimeMillis() < timeout) {
         Thread.sleep(500);

      }

      assertEquals(numberOfMessages, getMessageCount(q2));
      assertEquals(numberOfMessages, getMessagesAdded(q2));
      assertEquals(numberOfMessages - 100, getMessageCount(q1));
   }

   @Test
   public void testOrderOverRollback() throws Throwable {
      boolean persistentMessages = true;

      Configuration config = createDefaultInVMConfig().setJournalSyncNonTransactional(false);

      ActiveMQServer server = createServer(true, config, PAGE_SIZE, PAGE_MAX, new HashMap<String, AddressSettings>());

      server.start();

      final int messageSize = 1024;

      final int numberOfMessages = 3000;

      ServerLocator locator = createInVMNonHALocator().setClientFailureCheckPeriod(1000).setConnectionTTL(2000).setReconnectAttempts(0).setBlockOnNonDurableSend(true).setBlockOnDurableSend(true).setBlockOnAcknowledge(true).setConsumerWindowSize(1024 * 1024);

      ClientSessionFactory sf = createSessionFactory(locator);

      ClientSession session = sf.createSession(false, false, false);

      server.addAddressInfo(new AddressInfo(ADDRESS, RoutingType.ANYCAST));
      server.createQueue(new QueueConfiguration(ADDRESS).setRoutingType(RoutingType.ANYCAST));

      ClientProducer producer = session.createProducer(PagingTest.ADDRESS);

      byte[] body = new byte[messageSize];

      ByteBuffer bb = ByteBuffer.wrap(body);

      for (int j = 1; j <= messageSize; j++) {
         bb.put(getSamplebyte(j));
      }

      for (int i = 0; i < numberOfMessages; i++) {
         ClientMessage message = session.createMessage(persistentMessages);

         ActiveMQBuffer bodyLocal = message.getBodyBuffer();

         bodyLocal.writeBytes(body);

         message.putIntProperty(new SimpleString("id"), i);

         producer.send(message);
         if (i % 1000 == 0) {
            session.commit();
         }
      }

      session.commit();

      session.close();

      session = sf.createSession(false, false, 0);

      session.start();

      ClientConsumer consumer = session.createConsumer(ADDRESS);

      for (int i = 0; i < numberOfMessages / 2; i++) {
         ClientMessage message = consumer.receive(5000);
         assertNotNull(message);
         assertEquals(i, message.getIntProperty("id").intValue());
         message.acknowledge();
      }

      session.rollback();

      session.close();

      session = sf.createSession(false, false, 0);

      session.start();

      consumer = session.createConsumer(ADDRESS);

      for (int i = 0; i < numberOfMessages; i++) {
         ClientMessage message = consumer.receive(5000);
         assertNotNull(message);
         assertEquals(i, message.getIntProperty("id").intValue());
         message.acknowledge();
      }

      session.commit();
   }

   @Test
   public void testOrderOverRollback2() throws Throwable {
      boolean persistentMessages = true;

      Configuration config = createDefaultInVMConfig().setJournalSyncNonTransactional(false);

      ActiveMQServer server = createServer(true, config, PAGE_SIZE, PAGE_MAX, new HashMap<String, AddressSettings>());

      server.start();

      final int messageSize = 1024;

      final int numberOfMessages = 200;

      ServerLocator locator = createInVMNonHALocator().setClientFailureCheckPeriod(1000).setConnectionTTL(2000).setReconnectAttempts(0).setBlockOnNonDurableSend(true).setBlockOnDurableSend(true).setBlockOnAcknowledge(true).setConsumerWindowSize(0);

      ClientSessionFactory sf = createSessionFactory(locator);

      ClientSession session = sf.createSession(false, false, false);

      server.addAddressInfo(new AddressInfo(ADDRESS, RoutingType.ANYCAST));
      QueueImpl queue = (QueueImpl) server.createQueue(new QueueConfiguration(ADDRESS).setRoutingType(RoutingType.ANYCAST));

      ClientProducer producer = session.createProducer(PagingTest.ADDRESS);

      byte[] body = new byte[messageSize];

      ByteBuffer bb = ByteBuffer.wrap(body);

      for (int j = 1; j <= messageSize; j++) {
         bb.put(getSamplebyte(j));
      }

      for (int i = 0; i < numberOfMessages; i++) {
         ClientMessage message = session.createMessage(persistentMessages);

         ActiveMQBuffer bodyLocal = message.getBodyBuffer();

         bodyLocal.writeBytes(body);

         message.putIntProperty(new SimpleString("id"), i);

         producer.send(message);
         if (i % 1000 == 0) {
            session.commit();
         }
      }

      session.commit();

      session.close();

      session = sf.createSession(false, false, 0);

      session.start();

      ClientConsumer consumer = session.createConsumer(ADDRESS);

      // number of references without paging
      int numberOfRefs = queue.getNumberOfReferences();

      // consume all non-paged references
      for (int ref = 0; ref < numberOfRefs; ref++) {
         ClientMessage msg = consumer.receive(5000);
         assertNotNull(msg);
         msg.acknowledge();
      }

      session.commit();

      session.close();

      session = sf.createSession(false, false, 0);

      session.start();

      consumer = session.createConsumer(ADDRESS);

      ClientMessage msg = consumer.receive(5000);
      assertNotNull(msg);
      int msgIDRolledBack = msg.getIntProperty("id").intValue();
      msg.acknowledge();

      session.rollback();

      msg = consumer.receive(5000);

      assertNotNull(msg);

      assertEquals(msgIDRolledBack, msg.getIntProperty("id").intValue());

      session.rollback();

      session.close();

      sf.close();
      locator.close();

      server.stop();

      server.start();

      locator = createInVMNonHALocator().setClientFailureCheckPeriod(1000).setConnectionTTL(2000).setReconnectAttempts(0).setBlockOnNonDurableSend(true).setBlockOnDurableSend(true).setBlockOnAcknowledge(true).setConsumerWindowSize(0);

      sf = createSessionFactory(locator);

      session = sf.createSession(false, false, 0);

      session.start();

      consumer = session.createConsumer(ADDRESS);

      for (int i = msgIDRolledBack; i < numberOfMessages; i++) {
         ClientMessage message = consumer.receive(5000);
         assertNotNull(message);
         assertEquals(i, message.getIntProperty("id").intValue());
         message.acknowledge();
      }

      session.commit();

      session.close();
   }

   @Test
   public void testPagingOverCreatedDestinationTopics() throws Exception {

      Configuration config = createDefaultInVMConfig().setJournalSyncNonTransactional(false);

      ActiveMQServer server = createServer(true, config, PAGE_SIZE, -1, new HashMap<String, AddressSettings>());

      JMSServerManagerImpl jmsServer = new JMSServerManagerImpl(server);
      InVMNamingContext context = new InVMNamingContext();
      jmsServer.setRegistry(new JndiBindingRegistry(context));
      jmsServer.start();

      jmsServer.createTopic(true, "tt", "/topic/TT");

      server.getActiveMQServerControl().addAddressSettings("TT", "DLQ", "DLQ", -1, false, 5, 1024 * 1024, 1024 * 10, 5, 5, 1, 1000, 0, false, "PAGE", -1, 10, "KILL", true, true, true, true);

      ActiveMQJMSConnectionFactory cf = (ActiveMQJMSConnectionFactory) ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY));

      Connection conn = cf.createConnection();
      conn.setClientID("tst");
      Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
      Topic topic = (Topic) context.lookup("/topic/TT");
      sess.createDurableSubscriber(topic, "t1");

      MessageProducer prod = sess.createProducer(topic);
      prod.setDeliveryMode(DeliveryMode.PERSISTENT);
      TextMessage txt = sess.createTextMessage("TST");
      prod.send(txt);

      PagingStore store = server.getPagingManager().getPageStore(new SimpleString("TT"));

      assertEquals(1024 * 1024, store.getMaxSize());
      assertEquals(10 * 1024, store.getPageSizeBytes());

      jmsServer.stop();

      server = createServer(true, config, PAGE_SIZE, -1, new HashMap<String, AddressSettings>());

      jmsServer = new JMSServerManagerImpl(server);
      context = new InVMNamingContext();
      jmsServer.setRegistry(new JndiBindingRegistry(context));
      jmsServer.start();

      AddressSettings settings = server.getAddressSettingsRepository().getMatch("TT");

      assertEquals(1024 * 1024, settings.getMaxSizeBytes());
      assertEquals(10 * 1024, settings.getPageSizeBytes());
      assertEquals(AddressFullMessagePolicy.PAGE, settings.getAddressFullMessagePolicy());

      store = server.getPagingManager().getPageStore(new SimpleString("TT"));

      conn.close();

      server.stop();

   }

   @Test
   public void testPagingOverCreatedDestinationQueues() throws Exception {

      Configuration config = createDefaultInVMConfig().setJournalSyncNonTransactional(false);

      ActiveMQServer server = createServer(true, config, -1, -1, new HashMap<String, AddressSettings>());
      server.getAddressSettingsRepository().getMatch("#").setAddressFullMessagePolicy(AddressFullMessagePolicy.BLOCK);

      JMSServerManagerImpl jmsServer = new JMSServerManagerImpl(server);
      InVMNamingContext context = new InVMNamingContext();
      jmsServer.setRegistry(new JndiBindingRegistry(context));
      jmsServer.start();

      server.getActiveMQServerControl().addAddressSettings("Q1", "DLQ", "DLQ", -1, false, 5, 100 * 1024, 10 * 1024, 5, 5, 1, 1000, 0, false, "PAGE", -1, 10, "KILL", true, true, true, true);

      jmsServer.createQueue(true, "Q1", null, true, "/queue/Q1");

      ActiveMQJMSConnectionFactory cf = (ActiveMQJMSConnectionFactory) ActiveMQJMSClient.createConnectionFactoryWithoutHA(JMSFactoryType.CF, new TransportConfiguration(INVM_CONNECTOR_FACTORY));

      conn = cf.createConnection();
      conn.setClientID("tst");
      Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
      javax.jms.Queue queue = (javax.jms.Queue) context.lookup("/queue/Q1");

      MessageProducer prod = sess.createProducer(queue);
      prod.setDeliveryMode(DeliveryMode.PERSISTENT);
      BytesMessage bmt = sess.createBytesMessage();

      bmt.writeBytes(new byte[1024]);

      for (int i = 0; i < 500; i++) {
         prod.send(bmt);
      }

      PagingStore store = server.getPagingManager().getPageStore(new SimpleString("Q1"));

      assertEquals(100 * 1024, store.getMaxSize());
      assertEquals(10 * 1024, store.getPageSizeBytes());
      assertEquals(AddressFullMessagePolicy.PAGE, store.getAddressFullMessagePolicy());

      jmsServer.stop();

      server = createServer(true, config, -1, -1, new HashMap<String, AddressSettings>());
      server.getAddressSettingsRepository().getMatch("#").setAddressFullMessagePolicy(AddressFullMessagePolicy.BLOCK);

      jmsServer = new JMSServerManagerImpl(server);
      context = new InVMNamingContext();
      jmsServer.setRegistry(new JndiBindingRegistry(context));
      jmsServer.start();

      AddressSettings settings = server.getAddressSettingsRepository().getMatch("Q1");

      assertEquals(100 * 1024, settings.getMaxSizeBytes());
      assertEquals(10 * 1024, settings.getPageSizeBytes());
      assertEquals(AddressFullMessagePolicy.PAGE, settings.getAddressFullMessagePolicy());

      store = server.getPagingManager().getPageStore(new SimpleString("Q1"));
      assertEquals(100 * 1024, store.getMaxSize());
      assertEquals(10 * 1024, store.getPageSizeBytes());
      assertEquals(AddressFullMessagePolicy.PAGE, store.getAddressFullMessagePolicy());
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cluster/distribution/SymmetricClusterTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.cluster.distribution;

import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.server.cluster.impl.MessageLoadBalancingType;
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.jboss.logging.Logger;
import org.junit.Before;
import org.junit.Test;

/**
 * A SymmetricClusterTest
 *
 * Most of the cases are covered in OneWayTwoNodeClusterTest - we don't duplicate them all here
 */
public class SymmetricClusterTest extends ClusterTestBase {

   private static final Logger log = Logger.getLogger(SymmetricClusterTest.class);

   @Override
   @Before
   public void setUp() throws Exception {
      super.setUp();

      setupServers();
   }

   protected boolean isNetty() {
      return false;
   }

   @Test
   public void testStopAllStartAll() throws Throwable {
      try {
         setupCluster();

         startServers();

         setupSessionFactory(0, isNetty());
         setupSessionFactory(1, isNetty());
         setupSessionFactory(2, isNetty());
         setupSessionFactory(3, isNetty());
         setupSessionFactory(4, isNetty());

         createQueue(0, "queues.testaddress", "queue0", null, false);
         createQueue(1, "queues.testaddress", "queue0", null, false);
         createQueue(2, "queues.testaddress", "queue0", null, false);
         createQueue(3, "queues.testaddress", "queue0", null, false);
         createQueue(4, "queues.testaddress", "queue0", null, false);

         addConsumer(0, 0, "queue0", null);
         addConsumer(1, 1, "queue0", null);
         addConsumer(2, 2, "queue0", null);
         addConsumer(3, 3, "queue0", null);
         addConsumer(4, 4, "queue0", null);

         waitForBindings(0, "queues.testaddress", 1, 1, true);
         waitForBindings(1, "queues.testaddress", 1, 1, true);
         waitForBindings(2, "queues.testaddress", 1, 1, true);
         waitForBindings(3, "queues.testaddress", 1, 1, true);
         waitForBindings(4, "queues.testaddress", 1, 1, true);

         waitForBindings(0, "queues.testaddress", 4, 4, false);
         waitForBindings(1, "queues.testaddress", 4, 4, false);
         waitForBindings(2, "queues.testaddress", 4, 4, false);
         waitForBindings(3, "queues.testaddress", 4, 4, false);
         waitForBindings(4, "queues.testaddress", 4, 4, false);

         send(0, "queues.testaddress", 10, false, null);

         verifyReceiveRoundRobinInSomeOrder(10, 0, 1, 2, 3, 4);

         verifyNotReceive(0, 1, 2, 3, 4);

         removeConsumer(0);
         removeConsumer(1);
         removeConsumer(2);
         removeConsumer(3);
         removeConsumer(4);

         closeAllSessionFactories();

         closeAllServerLocatorsFactories();

         stopServers(0, 1, 2, 3, 4);

         startServers();

         setupSessionFactory(0, isNetty());
         setupSessionFactory(1, isNetty());
         setupSessionFactory(2, isNetty());
         setupSessionFactory(3, isNetty());
         setupSessionFactory(4, isNetty());

         createQueue(0, "queues.testaddress", "queue0", null, false);
         createQueue(1, "queues.testaddress", "queue0", null, false);
         createQueue(2, "queues.testaddress", "queue0", null, false);
         createQueue(3, "queues.testaddress", "queue0", null, false);
         createQueue(4, "queues.testaddress", "queue0", null, false);

         addConsumer(0, 0, "queue0", null);
         addConsumer(1, 1, "queue0", null);
         addConsumer(2, 2, "queue0", null);
         addConsumer(3, 3, "queue0", null);
         addConsumer(4, 4, "queue0", null);

         waitForBindings(0, "queues.testaddress", 1, 1, true);
         waitForBindings(1, "queues.testaddress", 1, 1, true);
         waitForBindings(2, "queues.testaddress", 1, 1, true);
         waitForBindings(3, "queues.testaddress", 1, 1, true);
         waitForBindings(4, "queues.testaddress", 1, 1, true);

         waitForBindings(0, "queues.testaddress", 4, 4, false);
         waitForBindings(1, "queues.testaddress", 4, 4, false);
         waitForBindings(2, "queues.testaddress", 4, 4, false);
         waitForBindings(3, "queues.testaddress", 4, 4, false);
         waitForBindings(4, "queues.testaddress", 4, 4, false);

         send(0, "queues.testaddress", 10, false, null);

         verifyReceiveRoundRobinInSomeOrder(10, 0, 1, 2, 3, 4);

         verifyNotReceive(0, 1, 2, 3, 4);

      } catch (Throwable e) {
         System.out.println(ActiveMQTestBase.threadDump("SymmetricClusterTest::testStopAllStartAll"));
         throw e;
      }

   }

   @Test
   public void testBasicRoundRobin() throws Exception {
      setupCluster();

      startServers();

      setupSessionFactory(0, isNetty());
      setupSessionFactory(1, isNetty());
      setupSessionFactory(2, isNetty());
      setupSessionFactory(3, isNetty());
      setupSessionFactory(4, isNetty());

      createQueue(0, "queues.testaddress", "queue0", null, false);
      createQueue(1, "queues.testaddress", "queue0", null, false);
      createQueue(2, "queues.testaddress", "queue0", null, false);
      createQueue(3, "queues.testaddress", "queue0", null, false);
      createQueue(4, "queues.testaddress", "queue0", null, false);

      addConsumer(0, 0, "queue0", null);
      addConsumer(1, 1, "queue0", null);
      addConsumer(2, 2, "queue0", null);
      addConsumer(3, 3, "queue0", null);
      addConsumer(4, 4, "queue0", null);

      waitForBindings(0, "queues.testaddress", 1, 1, true);
      waitForBindings(1, "queues.testaddress", 1, 1, true);
      waitForBindings(2, "queues.testaddress", 1, 1, true);
      waitForBindings(3, "queues.testaddress", 1, 1, true);
      waitForBindings(4, "queues.testaddress", 1, 1, true);

      waitForBindings(0, "queues.testaddress", 4, 4, false);
      waitForBindings(1, "queues.testaddress", 4, 4, false);
      waitForBindings(2, "queues.testaddress", 4, 4, false);
      waitForBindings(3, "queues.testaddress", 4, 4, false);
      waitForBindings(4, "queues.testaddress", 4, 4, false);

      send(0, "queues.testaddress", 10, false, null);

      verifyReceiveRoundRobinInSomeOrder(10, 0, 1, 2, 3, 4);

      verifyNotReceive(0, 1, 2, 3, 4);
   }

   @Test
   public void testBasicRoundRobinManyMessages() throws Exception {
      setupCluster();

      startServers();

      setupSessionFactory(0, isNetty());
      setupSessionFactory(1, isNetty());
      setupSessionFactory(2, isNetty());
      setupSessionFactory(3, isNetty());
      setupSessionFactory(4, isNetty());

      createQueue(0, "queues.testaddress", "queue0", null, false);
      createQueue(1, "queues.testaddress", "queue0", null, false);
      createQueue(2, "queues.testaddress", "queue0", null, false);
      createQueue(3, "queues.testaddress", "queue0", null, false);
      createQueue(4, "queues.testaddress", "queue0", null, false);

      addConsumer(0, 0, "queue0", null);
      addConsumer(1, 1, "queue0", null);
      addConsumer(2, 2, "queue0", null);
      addConsumer(3, 3, "queue0", null);
      addConsumer(4, 4, "queue0", null);

      waitForBindings(0, "queues.testaddress", 1, 1, true);
      waitForBindings(1, "queues.testaddress", 1, 1, true);
      waitForBindings(2, "queues.testaddress", 1, 1, true);
      waitForBindings(3, "queues.testaddress", 1, 1, true);
      waitForBindings(4, "queues.testaddress", 1, 1, true);

      waitForBindings(0, "queues.testaddress", 4, 4, false);
      waitForBindings(1, "queues.testaddress", 4, 4, false);
      waitForBindings(2, "queues.testaddress", 4, 4, false);
      waitForBindings(3, "queues.testaddress", 4, 4, false);
      waitForBindings(4, "queues.testaddress", 4, 4, false);

      send(0, "queues.testaddress", 1000, true, null);

      verifyReceiveRoundRobinInSomeOrder(1000, 0, 1, 2, 3, 4);

      verifyNotReceive(0, 1, 2, 3, 4);
   }

   @Test
   public void testBasicRoundRobinManyMessagesNoAddressAutoCreate() throws Exception {
      setupCluster();

      startServers();

      for (int i = 0; i < 5; i++) {
         servers[i].getAddressSettingsRepository().addMatch("#", new AddressSettings().setAutoCreateAddresses(false).setAutoCreateQueues(false));
      }

      for (int i = 0; i < 5; i++) {
         setupSessionFactory(i, isNetty());
      }

      for (int i = 0; i < 5; i++) {
         servers[i].addAddressInfo(new AddressInfo(SimpleString.toSimpleString("queues.testaddress"), RoutingType.MULTICAST));
         createQueue(i, "queues.testaddress", "queue0", null, false);
      }

      for (int i = 0; i < 5; i++) {
         addConsumer(i, i, "queue0", null);
      }

      for (int i = 0; i < 5; i++) {
         waitForBindings(i, "queues.testaddress", 1, 1, true);
      }

      for (int i = 0; i < 5; i++) {
         waitForBindings(i, "queues.testaddress", 4, 4, false);
      }

      send(0, "queues.testaddress", 1000, true, null);

      verifyReceiveRoundRobinInSomeOrder(1000, 0, 1, 2, 3, 4);

      verifyNotReceive(0, 1, 2, 3, 4);
   }

   @Test
   public void testRoundRobinMultipleQueues() throws Exception {
      log.debug("starting");
      setupCluster();

      log.debug("setup cluster");

      startServers();

      log.debug("started servers");

      setupSessionFactory(0, isNetty());
      setupSessionFactory(1, isNetty());
      setupSessionFactory(2, isNetty());
      setupSessionFactory(3, isNetty());
      setupSessionFactory(4, isNetty());

      log.debug("Set up session factories");

      createQueue(0, "queues.testaddress", "queue0", null, false);
      createQueue(1, "queues.testaddress", "queue0", null, false);
      createQueue(2, "queues.testaddress", "queue0", null, false);
      createQueue(3, "queues.testaddress", "queue0", null, false);
      createQueue(4, "queues.testaddress", "queue0", null, false);

      createQueue(0, "queues.testaddress", "queue1", null, false);
      createQueue(1, "queues.testaddress", "queue1", null, false);
      createQueue(2, "queues.testaddress", "queue1", null, false);
      createQueue(3, "queues.testaddress", "queue1", null, false);
      createQueue(4, "queues.testaddress", "queue1", null, false);

      createQueue(0, "queues.testaddress", "queue2", null, false);
      createQueue(1, "queues.testaddress", "queue2", null, false);
      createQueue(2, "queues.testaddress", "queue2", null, false);
      createQueue(3, "queues.testaddress", "queue2", null, false);
      createQueue(4, "queues.testaddress", "queue2", null, false);

      log.debug("created queues");

      addConsumer(0, 0, "queue0", null);
      addConsumer(1, 1, "queue0", null);
      addConsumer(2, 2, "queue0", null);
      addConsumer(3, 3, "queue0", null);
      addConsumer(4, 4, "queue0", null);

      addConsumer(5, 0, "queue1", null);
      addConsumer(6, 1, "queue1", null);
      addConsumer(7, 2, "queue1", null);
      addConsumer(8, 3, "queue1", null);
      addConsumer(9, 4, "queue1", null);

      addConsumer(10, 0, "queue2", null);
      addConsumer(11, 1, "queue2", null);
      addConsumer(12, 2, "queue2", null);
      addConsumer(13, 3, "queue2", null);
      addConsumer(14, 4, "queue2", null);

      log.debug("added consumers");

      waitForBindings(0, "queues.testaddress", 3, 3, true);
      waitForBindings(1, "queues.testaddress", 3, 3, true);
      waitForBindings(2, "queues.testaddress", 3, 3, true);
      waitForBindings(3, "queues.testaddress", 3, 3, true);
      waitForBindings(4, "queues.testaddress", 3, 3, true);

      waitForBindings(0, "queues.testaddress", 12, 12, false);
      waitForBindings(1, "queues.testaddress", 12, 12, false);
      waitForBindings(2, "queues.testaddress", 12, 12, false);
      waitForBindings(3, "queues.testaddress", 12, 12, false);
      waitForBindings(4, "queues.testaddress", 12, 12, false);

      log.debug("waited for bindings");

      send(0, "queues.testaddress", 10, false, null);

      log.debug("sent messages");

      verifyReceiveRoundRobinInSomeOrder(10, 0, 1, 2, 3, 4);

      log.debug("verified 1");

      verifyReceiveRoundRobinInSomeOrder(10, 5, 6, 7, 8, 9);

      log.debug("verified 2");

      verifyReceiveRoundRobinInSomeOrder(10, 10, 11, 12, 13, 14);

      log.debug("verified 3");
   }

   @Test
   public void testMultipleNonLoadBalancedQueues() throws Exception {
      setupCluster();

      startServers();

      setupSessionFactory(0, isNetty());
      setupSessionFactory(1, isNetty());
      setupSessionFactory(2, isNetty());
      setupSessionFactory(3, isNetty());
      setupSessionFactory(4, isNetty());

      createQueue(0, "queues.testaddress", "queue0", null, false);
      createQueue(1, "queues.testaddress", "queue1", null, false);
      createQueue(2, "queues.testaddress", "queue2", null, false);
      createQueue(3, "queues.testaddress", "queue3", null, false);
      createQueue(4, "queues.testaddress", "queue4", null, false);

      createQueue(0, "queues.testaddress", "queue5", null, false);
      createQueue(1, "queues.testaddress", "queue6", null, false);
      createQueue(2, "queues.testaddress", "queue7", null, false);
      createQueue(3, "queues.testaddress", "queue8", null, false);
      createQueue(4, "queues.testaddress", "queue9", null, false);

      createQueue(0, "queues.testaddress", "queue10", null, false);
      createQueue(1, "queues.testaddress", "queue11", null, false);
      createQueue(2, "queues.testaddress", "queue12", null, false);
      createQueue(3, "queues.testaddress", "queue13", null, false);
      createQueue(4, "queues.testaddress", "queue14", null, false);

      addConsumer(0, 0, "queue0", null);
      addConsumer(1, 1, "queue1", null);
      addConsumer(2, 2, "queue2", null);
      addConsumer(3, 3, "queue3", null);
      addConsumer(4, 4, "queue4", null);

      addConsumer(5, 0, "queue5", null);
      addConsumer(6, 1, "queue6", null);
      addConsumer(7, 2, "queue7", null);
      addConsumer(8, 3, "queue8", null);
      addConsumer(9, 4, "queue9", null);

      addConsumer(10, 0, "queue10", null);
      addConsumer(11, 1, "queue11", null);
      addConsumer(12, 2, "queue12", null);
      addConsumer(13, 3, "queue13", null);
      addConsumer(14, 4, "queue14", null);

      waitForBindings(0, "queues.testaddress", 3, 3, true);
      waitForBindings(1, "queues.testaddress", 3, 3, true);
      waitForBindings(2, "queues.testaddress", 3, 3, true);
      waitForBindings(3, "queues.testaddress", 3, 3, true);
      waitForBindings(4, "queues.testaddress", 3, 3, true);

      waitForBindings(0, "queues.testaddress", 12, 12, false);
      waitForBindings(1, "queues.testaddress", 12, 12, false);
      waitForBindings(2, "queues.testaddress", 12, 12, false);
      waitForBindings(3, "queues.testaddress", 12, 12, false);
      waitForBindings(4, "queues.testaddress", 12, 12, false);

      send(0, "queues.testaddress", 10, false, null);

      verifyReceiveAll(10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);
   }

   @Test
   public void testMixtureLoadBalancedAndNonLoadBalancedQueues() throws Exception {
      setupCluster();

      startServers();

      setupSessionFactory(0, isNetty());
      setupSessionFactory(1, isNetty());
      setupSessionFactory(2, isNetty());
      setupSessionFactory(3, isNetty());
      setupSessionFactory(4, isNetty());

      createQueue(0, "queues.testaddress", "queue0", null, false);
      createQueue(1, "queues.testaddress", "queue1", null, false);
      createQueue(2, "queues.testaddress", "queue2", null, false);
      createQueue(3, "queues.testaddress", "queue3", null, false);
      createQueue(4, "queues.testaddress", "queue4", null, false);

      createQueue(0, "queues.testaddress", "queue5", null, false);
      createQueue(1, "queues.testaddress", "queue6", null, false);
      createQueue(2, "queues.testaddress", "queue7", null, false);
      createQueue(3, "queues.testaddress", "queue8", null, false);
      createQueue(4, "queues.testaddress", "queue9", null, false);

      createQueue(0, "queues.testaddress", "queue10", null, false);
      createQueue(1, "queues.testaddress", "queue11", null, false);
      createQueue(2, "queues.testaddress", "queue12", null, false);
      createQueue(3, "queues.testaddress", "queue13", null, false);
      createQueue(4, "queues.testaddress", "queue14", null, false);

      createQueue(0, "queues.testaddress", "queue15", null, false);
      createQueue(1, "queues.testaddress", "queue15", null, false);
      createQueue(2, "queues.testaddress", "queue15", null, false);
      createQueue(3, "queues.testaddress", "queue15", null, false);
      createQueue(4, "queues.testaddress", "queue15", null, false);

      createQueue(2, "queues.testaddress", "queue16", null, false);
      createQueue(3, "queues.testaddress", "queue16", null, false);
      createQueue(4, "queues.testaddress", "queue16", null, false);

      createQueue(0, "queues.testaddress", "queue17", null, false);
      createQueue(1, "queues.testaddress", "queue17", null, false);
      createQueue(4, "queues.testaddress", "queue17", null, false);

      createQueue(3, "queues.testaddress", "queue18", null, false);
      createQueue(4, "queues.testaddress", "queue18", null, false);

      addConsumer(0, 0, "queue0", null);
      addConsumer(1, 1, "queue1", null);
      addConsumer(2, 2, "queue2", null);
      addConsumer(3, 3, "queue3", null);
      addConsumer(4, 4, "queue4", null);

      addConsumer(5, 0, "queue5", null);
      addConsumer(6, 1, "queue6", null);
      addConsumer(7, 2, "queue7", null);
      addConsumer(8, 3, "queue8", null);
      addConsumer(9, 4, "queue9", null);

      addConsumer(10, 0, "queue10", null);
      addConsumer(11, 1, "queue11", null);
      addConsumer(12, 2, "queue12", null);
      addConsumer(13, 3, "queue13", null);
      addConsumer(14, 4, "queue14", null);

      addConsumer(15, 0, "queue15", null);
      addConsumer(16, 1, "queue15", null);
      addConsumer(17, 2, "queue15", null);
      addConsumer(18, 3, "queue15", null);
      addConsumer(19, 4, "queue15", null);

      addConsumer(20, 2, "queue16", null);
      addConsumer(21, 3, "queue16", null);
      addConsumer(22, 4, "queue16", null);

      addConsumer(23, 0, "queue17", null);
      addConsumer(24, 1, "queue17", null);
      addConsumer(25, 4, "queue17", null);

      addConsumer(26, 3, "queue18", null);
      addConsumer(27, 4, "queue18", null);

      waitForBindings(0, "queues.testaddress", 5, 5, true);
      waitForBindings(1, "queues.testaddress", 5, 5, true);
      waitForBindings(2, "queues.testaddress", 5, 5, true);
      waitForBindings(3, "queues.testaddress", 6, 6, true);
      waitForBindings(4, "queues.testaddress", 7, 7, true);

      waitForBindings(0, "queues.testaddress", 23, 23, false);
      waitForBindings(1, "queues.testaddress", 23, 23, false);
      waitForBindings(2, "queues.testaddress", 23, 23, false);
      waitForBindings(3, "queues.testaddress", 22, 22, false);
      waitForBindings(4, "queues.testaddress", 21, 21, false);

      send(0, "queues.testaddress", 10, false, null);

      verifyReceiveAll(10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);

      verifyReceiveRoundRobinInSomeOrder(10, 15, 16, 17, 18, 19);

      verifyReceiveRoundRobinInSomeOrder(10, 20, 21, 22);

      verifyReceiveRoundRobinInSomeOrder(10, 23, 24, 25);

      verifyReceiveRoundRobinInSomeOrder(10, 26, 27);
   }

   @Test
   public void testMixtureLoadBalancedAndNonLoadBalancedQueuesRemoveSomeQueuesAndConsumers() throws Exception {
      setupCluster();

      startServers();

      setupSessionFactory(0, isNetty());
      setupSessionFactory(1, isNetty());
      setupSessionFactory(2, isNetty());
      setupSessionFactory(3, isNetty());
      setupSessionFactory(4, isNetty());

      createQueue(0, "queues.testaddress", "queue0", null, false);
      createQueue(1, "queues.testaddress", "queue1", null, false);
      createQueue(2, "queues.testaddress", "queue2", null, false);
      createQueue(3, "queues.testaddress", "queue3", null, false);
      createQueue(4, "queues.testaddress", "queue4", null, false);

      createQueue(0, "queues.testaddress", "queue5", null, false);
      createQueue(1, "queues.testaddress", "queue6", null, false);
      createQueue(2, "queues.testaddress", "queue7", null, false);
      createQueue(3, "queues.testaddress", "queue8", null, false);
      createQueue(4, "queues.testaddress", "queue9", null, false);

      createQueue(0, "queues.testaddress", "queue10", null, false);
      createQueue(1, "queues.testaddress", "queue11", null, false);
      createQueue(2, "queues.testaddress", "queue12", null, false);
      createQueue(3, "queues.testaddress", "queue13", null, false);
      createQueue(4, "queues.testaddress", "queue14", null, false);

      createQueue(0, "queues.testaddress", "queue15", null, false);
      createQueue(1, "queues.testaddress", "queue15", null, false);
      createQueue(2, "queues.testaddress", "queue15", null, false);
      createQueue(3, "queues.testaddress", "queue15", null, false);
      createQueue(4, "queues.testaddress", "queue15", null, false);

      createQueue(2, "queues.testaddress", "queue16", null, false);
      createQueue(3, "queues.testaddress", "queue16", null, false);
      createQueue(4, "queues.testaddress", "queue16", null, false);

      createQueue(0, "queues.testaddress", "queue17", null, false);
      createQueue(1, "queues.testaddress", "queue17", null, false);
      createQueue(4, "queues.testaddress", "queue17", null, false);

      createQueue(3, "queues.testaddress", "queue18", null, false);
      createQueue(4, "queues.testaddress", "queue18", null, false);

      addConsumer(0, 0, "queue0", null);
      addConsumer(1, 1, "queue1", null);
      addConsumer(2, 2, "queue2", null);
      addConsumer(3, 3, "queue3", null);
      addConsumer(4, 4, "queue4", null);

      addConsumer(5, 0, "queue5", null);
      addConsumer(6, 1, "queue6", null);
      addConsumer(7, 2, "queue7", null);
      addConsumer(8, 3, "queue8", null);
      addConsumer(9, 4, "queue9", null);

      addConsumer(10, 0, "queue10", null);
      addConsumer(11, 1, "queue11", null);
      addConsumer(12, 2, "queue12", null);
      addConsumer(13, 3, "queue13", null);
      addConsumer(14, 4, "queue14", null);

      addConsumer(15, 0, "queue15", null);
      addConsumer(16, 1, "queue15", null);
      addConsumer(17, 2, "queue15", null);
      addConsumer(18, 3, "queue15", null);
      addConsumer(19, 4, "queue15", null);

      addConsumer(20, 2, "queue16", null);
      addConsumer(21, 3, "queue16", null);
      addConsumer(22, 4, "queue16", null);

      addConsumer(23, 0, "queue17", null);
      addConsumer(24, 1, "queue17", null);
      addConsumer(25, 4, "queue17", null);

      addConsumer(26, 3, "queue18", null);
      addConsumer(27, 4, "queue18", null);

      waitForBindings(0, "queues.testaddress", 5, 5, true);
      waitForBindings(1, "queues.testaddress", 5, 5, true);
      waitForBindings(2, "queues.testaddress", 5, 5, true);
      waitForBindings(3, "queues.testaddress", 6, 6, true);
      waitForBindings(4, "queues.testaddress", 7, 7, true);

      waitForBindings(0, "queues.testaddress", 23, 23, false);
      waitForBindings(1, "queues.testaddress", 23, 23, false);
      waitForBindings(2, "queues.testaddress", 23, 23, false);
      waitForBindings(3, "queues.testaddress", 22, 22, false);
      waitForBindings(4, "queues.testaddress", 21, 21, false);

      send(0, "queues.testaddress", 10, false, null);

      verifyReceiveAll(10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);

      verifyReceiveRoundRobinInSomeOrder(10, 15, 16, 17, 18, 19);

      verifyReceiveRoundRobinInSomeOrder(10, 20, 21, 22);

      verifyReceiveRoundRobinInSomeOrder(10, 23, 24, 25);

      verifyReceiveRoundRobinInSomeOrder(10, 26, 27);

      removeConsumer(16);
      removeConsumer(18);
      removeConsumer(21);
      removeConsumer(22);
      removeConsumer(26);

      deleteQueue(1, "queue15");
      deleteQueue(3, "queue15");

      deleteQueue(3, "queue16");
      deleteQueue(4, "queue16");

      deleteQueue(3, "queue18");

      waitForBindings(0, "queues.testaddress", 5, 5, true);
      waitForBindings(1, "queues.testaddress", 4, 4, true);
      waitForBindings(2, "queues.testaddress", 5, 5, true);
      waitForBindings(3, "queues.testaddress", 3, 3, true);
      waitForBindings(4, "queues.testaddress", 6, 6, true);

      waitForBindings(0, "queues.testaddress", 18, 18, false);
      waitForBindings(1, "queues.testaddress", 19, 19, false);
      waitForBindings(2, "queues.testaddress", 18, 18, false);
      waitForBindings(3, "queues.testaddress", 20, 20, false);
      waitForBindings(4, "queues.testaddress", 17, 17, false);

      send(0, "queues.testaddress", 10, false, null);

      verifyReceiveAll(10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 20, 27);

      verifyReceiveRoundRobinInSomeOrder(10, 15, 17, 19);

      verifyReceiveRoundRobinInSomeOrder(10, 23, 24, 25);
   }

   @Test
   public void testMixtureLoadBalancedAndNonLoadBalancedQueuesAddQueuesAndConsumersBeforeAllServersAreStarted() throws Exception {
      setupCluster();

      startServers(0);

      setupSessionFactory(0, isNetty());

      createQueue(0, "queues.testaddress", "queue0", null, false);
      createQueue(0, "queues.testaddress", "queue5", null, false);
      createQueue(0, "queues.testaddress", "queue10", null, false);
      createQueue(0, "queues.testaddress", "queue15", null, false);
      createQueue(0, "queues.testaddress", "queue17", null, false);

      addConsumer(0, 0, "queue0", null);
      addConsumer(5, 0, "queue5", null);

      startServers(1);
      setupSessionFactory(1, isNetty());

      createQueue(1, "queues.testaddress", "queue1", null, false);
      createQueue(1, "queues.testaddress", "queue6", null, false);
      createQueue(1, "queues.testaddress", "queue11", null, false);
      createQueue(1, "queues.testaddress", "queue15", null, false);
      createQueue(1, "queues.testaddress", "queue17", null, false);

      addConsumer(1, 1, "queue1", null);
      addConsumer(6, 1, "queue6", null);
      addConsumer(11, 1, "queue11", null);
      addConsumer(16, 1, "queue15", null);

      startServers(2);
      setupSessionFactory(2, isNetty());

      createQueue(2, "queues.testaddress", "queue2", null, false);
      createQueue(2, "queues.testaddress", "queue7", null, false);
      createQueue(2, "queues.testaddress", "queue12", null, false);
      createQueue(2, "queues.testaddress", "queue15", null, false);
      createQueue(2, "queues.testaddress", "queue16", null, false);

      addConsumer(2, 2, "queue2", null);
      addConsumer(7, 2, "queue7", null);
      addConsumer(12, 2, "queue12", null);
      addConsumer(17, 2, "queue15", null);

      startServers(3);
      setupSessionFactory(3, isNetty());

      createQueue(3, "queues.testaddress", "queue3", null, false);
      createQueue(3, "queues.testaddress", "queue8", null, false);
      createQueue(3, "queues.testaddress", "queue13", null, false);
      createQueue(3, "queues.testaddress", "queue15", null, false);
      createQueue(3, "queues.testaddress", "queue16", null, false);
      createQueue(3, "queues.testaddress", "queue18", null, false);

      addConsumer(3, 3, "queue3", null);
      addConsumer(8, 3, "queue8", null);
      addConsumer(13, 3, "queue13", null);
      addConsumer(18, 3, "queue15", null);

      startServers(4);
      setupSessionFactory(4, isNetty());

      createQueue(4, "queues.testaddress", "queue4", null, false);
      createQueue(4, "queues.testaddress", "queue9", null, false);
      createQueue(4, "queues.testaddress", "queue14", null, false);
      createQueue(4, "queues.testaddress", "queue15", null, false);
      createQueue(4, "queues.testaddress", "queue16", null, false);
      createQueue(4, "queues.testaddress", "queue17", null, false);
      createQueue(4, "queues.testaddress", "queue18", null, false);

      addConsumer(4, 4, "queue4", null);
      addConsumer(9, 4, "queue9", null);
      addConsumer(10, 0, "queue10", null);
      addConsumer(14, 4, "queue14", null);

      addConsumer(15, 0, "queue15", null);
      addConsumer(19, 4, "queue15", null);

      addConsumer(20, 2, "queue16", null);
      addConsumer(21, 3, "queue16", null);
      addConsumer(22, 4, "queue16", null);

      addConsumer(23, 0, "queue17", null);
      addConsumer(24, 1, "queue17", null);
      addConsumer(25, 4, "queue17", null);

      addConsumer(26, 3, "queue18", null);
      addConsumer(27, 4, "queue18", null);

      waitForBindings(0, "queues.testaddress", 5, 5, true);
      waitForBindings(1, "queues.testaddress", 5, 5, true);
      waitForBindings(2, "queues.testaddress", 5, 5, true);
      waitForBindings(3, "queues.testaddress", 6, 6, true);
      waitForBindings(4, "queues.testaddress", 7, 7, true);

      waitForBindings(0, "queues.testaddress", 23, 23, false);
      waitForBindings(1, "queues.testaddress", 23, 23, false);
      waitForBindings(2, "queues.testaddress", 23, 23, false);
      waitForBindings(3, "queues.testaddress", 22, 22, false);
      waitForBindings(4, "queues.testaddress", 21, 21, false);

      send(0, "queues.testaddress", 10, false, null);

      verifyReceiveAll(10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);

      verifyReceiveRoundRobinInSomeOrder(10, 15, 16, 17, 18, 19);

      verifyReceiveRoundRobinInSomeOrder(10, 20, 21, 22);

      verifyReceiveRoundRobinInSomeOrder(10, 23, 24, 25);

      verifyReceiveRoundRobinInSomeOrder(10, 26, 27);
   }

   @Test
   public void testMixtureLoadBalancedAndNonLoadBalancedQueuesWithFilters() throws Exception {
      setupCluster();

      startServers();

      setupSessionFactory(0, isNetty());
      setupSessionFactory(1, isNetty());
      setupSessionFactory(2, isNetty());
      setupSessionFactory(3, isNetty());
      setupSessionFactory(4, isNetty());

      String filter1 = "haggis";
      String filter2 = "scotch-egg";

      createQueue(0, "queues.testaddress", "queue0", null, false);
      createQueue(1, "queues.testaddress", "queue1", filter1, false);
      createQueue(2, "queues.testaddress", "queue2", null, false);
      createQueue(3, "queues.testaddress", "queue3", filter2, false);
      createQueue(4, "queues.testaddress", "queue4", null, false);

      createQueue(0, "queues.testaddress", "queue5", filter1, false);
      createQueue(1, "queues.testaddress", "queue6", null, false);
      createQueue(2, "queues.testaddress", "queue7", filter2, false);
      createQueue(3, "queues.testaddress", "queue8", null, false);
      createQueue(4, "queues.testaddress", "queue9", filter1, false);

      createQueue(0, "queues.testaddress", "queue10", null, false);
      createQueue(1, "queues.testaddress", "queue11", filter2, false);
      createQueue(2, "queues.testaddress", "queue12", null, false);
      createQueue(3, "queues.testaddress", "queue13", null, false);
      createQueue(4, "queues.testaddress", "queue14", filter1, false);

      createQueue(0, "queues.testaddress", "queue15", filter1, false);
      createQueue(1, "queues.testaddress", "queue15", filter1, false);
      createQueue(2, "queues.testaddress", "queue15", null, false);
      createQueue(3, "queues.testaddress", "queue15", filter2, false);
      createQueue(4, "queues.testaddress", "queue15", filter2, false);

      createQueue(2, "queues.testaddress", "queue16", filter1, false);
      createQueue(3, "queues.testaddress", "queue16", null, false);
      createQueue(4, "queues.testaddress", "queue16", null, false);

      createQueue(0, "queues.testaddress", "queue17", null, false);
      createQueue(1, "queues.testaddress", "queue17", null, false);
      createQueue(4, "queues.testaddress", "queue17", null, false);

      createQueue(3, "queues.testaddress", "queue18", filter2, false);
      createQueue(4, "queues.testaddress", "queue18", null, false);

      addConsumer(0, 0, "queue0", null);
      addConsumer(1, 1, "queue1", null);
      addConsumer(2, 2, "queue2", null);
      addConsumer(3, 3, "queue3", null);
      addConsumer(4, 4, "queue4", null);

      addConsumer(5, 0, "queue5", null);
      addConsumer(6, 1, "queue6", null);
      addConsumer(7, 2, "queue7", null);
      addConsumer(8, 3, "queue8", null);
      addConsumer(9, 4, "queue9", null);

      addConsumer(10, 0, "queue10", null);
      addConsumer(11, 1, "queue11", null);
      addConsumer(12, 2, "queue12", null);
      addConsumer(13, 3, "queue13", null);
      addConsumer(14, 4, "queue14", null);

      addConsumer(15, 0, "queue15", null);
      addConsumer(16, 1, "queue15", null);
      addConsumer(17, 2, "queue15", null);
      addConsumer(18, 3, "queue15", null);
      addConsumer(19, 4, "queue15", null);

      addConsumer(20, 2, "queue16", null);
      addConsumer(21, 3, "queue16", null);
      addConsumer(22, 4, "queue16", null);

      addConsumer(23, 0, "queue17", null);
      addConsumer(24, 1, "queue17", null);
      addConsumer(25, 4, "queue17", null);

      addConsumer(26, 3, "queue18", null);
      addConsumer(27, 4, "queue18", null);

      waitForBindings(0, "queues.testaddress", 5, 5, true);
      waitForBindings(1, "queues.testaddress", 5, 5, true);
      waitForBindings(2, "queues.testaddress", 5, 5, true);
      waitForBindings(3, "queues.testaddress", 6, 6, true);
      waitForBindings(4, "queues.testaddress", 7, 7, true);

      waitForBindings(0, "queues.testaddress", 23, 23, false);
      waitForBindings(1, "queues.testaddress", 23, 23, false);
      waitForBindings(2, "queues.testaddress", 23, 23, false);
      waitForBindings(3, "queues.testaddress", 22, 22, false);
      waitForBindings(4, "queues.testaddress", 21, 21, false);

      send(0, "queues.testaddress", 10, false, filter1);

      verifyReceiveAll(10, 0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 27);

      verifyReceiveRoundRobinInSomeOrder(10, 15, 16, 17);

      verifyReceiveRoundRobinInSomeOrder(10, 20, 21, 22);

      verifyReceiveRoundRobinInSomeOrder(10, 23, 24, 25);

      send(0, "queues.testaddress", 10, false, filter2);

      verifyReceiveAll(10, 0, 2, 3, 4, 6, 7, 8, 10, 11, 12, 13);

      verifyReceiveRoundRobinInSomeOrder(10, 17, 18, 19);

      verifyReceiveRoundRobinInSomeOrder(10, 21, 22);

      verifyReceiveRoundRobinInSomeOrder(10, 23, 24, 25);

      verifyReceiveRoundRobinInSomeOrder(10, 26, 27);

      send(0, "queues.testaddress", 10, false, null);

      verifyReceiveAll(10, 0, 2, 4, 6, 8, 10, 12, 13, 17, 27);

      verifyReceiveRoundRobinInSomeOrder(10, 21, 22);

      verifyReceiveRoundRobinInSomeOrder(10, 23, 24, 25);
   }

   @Test
   public void testMixtureLoadBalancedAndNonLoadBalancedQueuesWithConsumersWithFilters() throws Exception {
      setupCluster();

      startServers();

      setupSessionFactory(0, isNetty());
      setupSessionFactory(1, isNetty());
      setupSessionFactory(2, isNetty());
      setupSessionFactory(3, isNetty());
      setupSessionFactory(4, isNetty());

      String filter1 = "haggis";
      String filter2 = "scotch-egg";

      createQueue(0, "queues.testaddress", "queue0", null, false);
      createQueue(1, "queues.testaddress", "queue1", null, false);
      createQueue(2, "queues.testaddress", "queue2", null, false);
      createQueue(3, "queues.testaddress", "queue3", null, false);
      createQueue(4, "queues.testaddress", "queue4", null, false);

      createQueue(0, "queues.testaddress", "queue5", null, false);
      createQueue(1, "queues.testaddress", "queue6", null, false);
      createQueue(2, "queues.testaddress", "queue7", null, false);
      createQueue(3, "queues.testaddress", "queue8", null, false);
      createQueue(4, "queues.testaddress", "queue9", null, false);

      createQueue(0, "queues.testaddress", "queue10", null, false);
      createQueue(1, "queues.testaddress", "queue11", null, false);
      createQueue(2, "queues.testaddress", "queue12", null, false);
      createQueue(3, "queues.testaddress", "queue13", null, false);
      createQueue(4, "queues.testaddress", "queue14", null, false);

      createQueue(0, "queues.testaddress", "queue15", null, false);
      createQueue(1, "queues.testaddress", "queue15", null, false);
      createQueue(2, "queues.testaddress", "queue15", null, false);
      createQueue(3, "queues.testaddress", "queue15", null, false);
      createQueue(4, "queues.testaddress", "queue15", null, false);

      createQueue(2, "queues.testaddress", "queue16", null, false);
      createQueue(3, "queues.testaddress", "queue16", null, false);
      createQueue(4, "queues.testaddress", "queue16", null, false);

      createQueue(0, "queues.testaddress", "queue17", null, false);
      createQueue(1, "queues.testaddress", "queue17", null, false);
      createQueue(4, "queues.testaddress", "queue17", null, false);

      createQueue(3, "queues.testaddress", "queue18", filter2, false);
      createQueue(4, "queues.testaddress", "queue18", null, false);

      addConsumer(0, 0, "queue0", null);
      addConsumer(1, 1, "queue1", filter1);
      addConsumer(2, 2, "queue2", null);
      addConsumer(3, 3, "queue3", filter2);
      addConsumer(4, 4, "queue4", null);

      addConsumer(5, 0, "queue5", filter1);
      addConsumer(6, 1, "queue6", null);
      addConsumer(7, 2, "queue7", filter2);
      addConsumer(8, 3, "queue8", null);
      addConsumer(9, 4, "queue9", filter1);

      addConsumer(10, 0, "queue10", null);
      addConsumer(11, 1, "queue11", filter2);
      addConsumer(12, 2, "queue12", null);
      addConsumer(13, 3, "queue13", null);
      addConsumer(14, 4, "queue14", filter1);

      addConsumer(15, 0, "queue15", filter1);
      addConsumer(16, 1, "queue15", filter1);
      addConsumer(17, 2, "queue15", null);
      addConsumer(18, 3, "queue15", filter2);
      addConsumer(19, 4, "queue15", filter2);

      addConsumer(20, 2, "queue16", filter1);
      addConsumer(21, 3, "queue16", null);
      addConsumer(22, 4, "queue16", null);

      addConsumer(23, 0, "queue17", null);
      addConsumer(24, 1, "queue17", null);
      addConsumer(25, 4, "queue17", null);

      addConsumer(26, 3, "queue18", filter2);
      addConsumer(27, 4, "queue18", null);

      waitForBindings(0, "queues.testaddress", 5, 5, true);
      waitForBindings(1, "queues.testaddress", 5, 5, true);
      waitForBindings(2, "queues.testaddress", 5, 5, true);
      waitForBindings(3, "queues.testaddress", 6, 6, true);
      waitForBindings(4, "queues.testaddress", 7, 7, true);

      waitForBindings(0, "queues.testaddress", 23, 23, false);
      waitForBindings(1, "queues.testaddress", 23, 23, false);
      waitForBindings(2, "queues.testaddress", 23, 23, false);
      waitForBindings(3, "queues.testaddress", 22, 22, false);
      waitForBindings(4, "queues.testaddress", 21, 21, false);

      send(0, "queues.testaddress", 10, false, filter1);

      verifyReceiveAll(10, 0, 1, 2, 4, 5, 6, 8, 9, 10, 12, 13, 14, 27);

      verifyReceiveRoundRobinInSomeOrder(10, 15, 16, 17);

      verifyReceiveRoundRobinInSomeOrder(10, 20, 21, 22);

      verifyReceiveRoundRobinInSomeOrder(10, 23, 24, 25);

      send(0, "queues.testaddress", 10, false, filter2);

      verifyReceiveAll(10, 0, 2, 3, 4, 6, 7, 8, 10, 11, 12, 13);

      verifyReceiveRoundRobinInSomeOrder(10, 17, 18, 19);

      verifyReceiveRoundRobinInSomeOrder(10, 21, 22);

      verifyReceiveRoundRobinInSomeOrder(10, 23, 24, 25);

      verifyReceiveRoundRobinInSomeOrder(10, 26, 27);

      send(0, "queues.testaddress", 10, false, null);

      verifyReceiveAll(10, 0, 2, 4, 6, 8, 10, 12, 13, 17, 27);

      verifyReceiveRoundRobinInSomeOrder(10, 21, 22);

      verifyReceiveRoundRobinInSomeOrder(10, 23, 24, 25);
   }

   @Test
   public void testRouteWhenNoConsumersTrueLoadBalancedQueues() throws Exception {
      setupCluster(MessageLoadBalancingType.STRICT);

      startServers();

      setupSessionFactory(0, isNetty());
      setupSessionFactory(1, isNetty());
      setupSessionFactory(2, isNetty());
      setupSessionFactory(3, isNetty());
      setupSessionFactory(4, isNetty());

      createQueue(0, "queues.testaddress", "queue0", null, false);
      createQueue(1, "queues.testaddress", "queue0", null, false);
      createQueue(2, "queues.testaddress", "queue0", null, false);
      createQueue(3, "queues.testaddress", "queue0", null, false);
      createQueue(4, "queues.testaddress", "queue0", null, false);

      waitForBindings(0, "queues.testaddress", 1, 0, true);
      waitForBindings(1, "queues.testaddress", 1, 0, true);
      waitForBindings(2, "queues.testaddress", 1, 0, true);
      waitForBindings(3, "queues.testaddress", 1, 0, true);
      waitForBindings(4, "queues.testaddress", 1, 0, true);

      waitForBindings(0, "queues.testaddress", 4, 0, false);
      waitForBindings(1, "queues.testaddress", 4, 0, false);
      waitForBindings(2, "queues.testaddress", 4, 0, false);
      waitForBindings(3, "queues.testaddress", 4, 0, false);
      waitForBindings(4, "queues.testaddress", 4, 0, false);

      send(0, "queues.testaddress", 10, false, null);

      addConsumer(0, 0, "queue0", null);
      addConsumer(1, 1, "queue0", null);
      addConsumer(2, 2, "queue0", null);
      addConsumer(3, 3, "queue0", null);
      addConsumer(4, 4, "queue0", null);

      waitForBindings(0, "queues.testaddress", 1, 1, true);
      waitForBindings(1, "queues.testaddress", 1, 1, true);
      waitForBindings(2, "queues.testaddress", 1, 1, true);
      waitForBindings(3, "queues.testaddress", 1, 1, true);
      waitForBindings(4, "queues.testaddress", 1, 1, true);

      waitForBindings(0, "queues.testaddress", 4, 4, false);
      waitForBindings(1, "queues.testaddress", 4, 4, false);
      waitForBindings(2, "queues.testaddress", 4, 4, false);
      waitForBindings(3, "queues.testaddress", 4, 4, false);
      waitForBindings(4, "queues.testaddress", 4, 4, false);

      verifyReceiveRoundRobinInSomeOrder(10, 0, 1, 2, 3, 4);
   }

   @Test
   public void testRouteWhenNoConsumersFalseLocalConsumerLoadBalancedQueues() throws Exception {
      setupCluster(MessageLoadBalancingType.ON_DEMAND);

      startServers();

      setupSessionFactory(0, isNetty());
      setupSessionFactory(1, isNetty());
      setupSessionFactory(2, isNetty());
      setupSessionFactory(3, isNetty());
      setupSessionFactory(4, isNetty());

      createQueue(0, "queues.testaddress", "queue0", null, false);
      createQueue(1, "queues.testaddress", "queue0", null, false);
      createQueue(2, "queues.testaddress", "queue0", null, false);
      createQueue(3, "queues.testaddress", "queue0", null, false);
      createQueue(4, "queues.testaddress", "queue0", null, false);

      addConsumer(0, 0, "queue0", null);

      waitForBindings(0, "queues.testaddress", 1, 1, true);
      waitForBindings(1, "queues.testaddress", 1, 0, true);
      waitForBindings(2, "queues.testaddress", 1, 0, true);
      waitForBindings(3, "queues.testaddress", 1, 0, true);
      waitForBindings(4, "queues.testaddress", 1, 0, true);

      waitForBindings(0, "queues.testaddress", 4, 0, false);
      waitForBindings(1, "queues.testaddress", 4, 1, false);
      waitForBindings(2, "queues.testaddress", 4, 1, false);
      waitForBindings(3, "queues.testaddress", 4, 1, false);
      waitForBindings(4, "queues.testaddress", 4, 1, false);

      send(0, "queues.testaddress", 10, false, null);

      addConsumer(1, 1, "queue0", null);
      addConsumer(2, 2, "queue0", null);
      addConsumer(3, 3, "queue0", null);
      addConsumer(4, 4, "queue0", null);

      waitForBindings(0, "queues.testaddress", 1, 1, true);
      waitForBindings(1, "queues.testaddress", 1, 1, true);
      waitForBindings(2, "queues.testaddress", 1, 1, true);
      waitForBindings(3, "queues.testaddress", 1, 1, true);
      waitForBindings(4, "queues.testaddress", 1, 1, true);

      waitForBindings(0, "queues.testaddress", 4, 4, false);
      waitForBindings(1, "queues.testaddress", 4, 4, false);
      waitForBindings(2, "queues.testaddress", 4, 4, false);
      waitForBindings(3, "queues.testaddress", 4, 4, false);
      waitForBindings(4, "queues.testaddress", 4, 4, false);

      verifyReceiveAll(10, 0);
   }

   @Test
   public void testRouteWhenNoConsumersFalseNonLoadBalancedQueues2() throws Exception {
      setupCluster(MessageLoadBalancingType.ON_DEMAND);

      startServers();

      setupSessionFactory(0, isNetty());
      setupSessionFactory(1, isNetty());
      setupSessionFactory(2, isNetty());
      setupSessionFactory(3, isNetty());
      setupSessionFactory(4, isNetty());

      createQueue(0, "queues.testaddress", "queue0", null, false);
      createQueue(1, "queues.testaddress", "queue0", null, false);
      createQueue(2, "queues.testaddress", "queue0", null, false);
      createQueue(3, "queues.testaddress", "queue0", null, false);
      createQueue(4, "queues.testaddress", "queue0", null, false);

      waitForBindings(0, "queues.testaddress", 1, 0, true);
      waitForBindings(1, "queues.testaddress", 1, 0, true);
      waitForBindings(2, "queues.testaddress", 1, 0, true);
      waitForBindings(3, "queues.testaddress", 1, 0, true);
      waitForBindings(4, "queues.testaddress", 1, 0, true);

      waitForBindings(0, "queues.testaddress", 4, 0, false);
      waitForBindings(1, "queues.testaddress", 4, 0, false);
      waitForBindings(2, "queues.testaddress", 4, 0, false);
      waitForBindings(3, "queues.testaddress", 4, 0, false);
      waitForBindings(4, "queues.testaddress", 4, 0, false);

      send(0, "queues.testaddress", 10, false, null);

      addConsumer(0, 0, "queue0", null);
      addConsumer(1, 1, "queue0", null);
      addConsumer(2, 2, "queue0", null);
      addConsumer(3, 3, "queue0", null);
      addConsumer(4, 4, "queue0", null);

      waitForBindings(0, "queues.testaddress", 1, 1, true);
      waitForBindings(1, "queues.testaddress", 1, 1, true);
      waitForBindings(2, "queues.testaddress", 1, 1, true);
      waitForBindings(3, "queues.testaddress", 1, 1, true);
      waitForBindings(4, "queues.testaddress", 1, 1, true);

      waitForBindings(0, "queues.testaddress", 4, 4, false);
      waitForBindings(1, "queues.testaddress", 4, 4, false);
      waitForBindings(2, "queues.testaddress", 4, 4, false);
      waitForBindings(3, "queues.testaddress", 4, 4, false);
      waitForBindings(4, "queues.testaddress", 4, 4, false);

      verifyReceiveAll(10, 0);
   }

   @Test
   public void testRouteWhenNoConsumersFalseNonLoadBalancedQueues() throws Exception {
      setupCluster(MessageLoadBalancingType.ON_DEMAND);

      startServers();

      setupSessionFactory(0, isNetty());
      setupSessionFactory(1, isNetty());
      setupSessionFactory(2, isNetty());
      setupSessionFactory(3, isNetty());
      setupSessionFactory(4, isNetty());

      createQueue(0, "queues.testaddress", "queue0", null, false);
      createQueue(1, "queues.testaddress", "queue1", null, false);
      createQueue(2, "queues.testaddress", "queue2", null, false);
      createQueue(3, "queues.testaddress", "queue3", null, false);
      createQueue(4, "queues.testaddress", "queue4", null, false);

      waitForBindings(0, "queues.testaddress", 1, 0, true);
      waitForBindings(1, "queues.testaddress", 1, 0, true);
      waitForBindings(2, "queues.testaddress", 1, 0, true);
      waitForBindings(3, "queues.testaddress", 1, 0, true);
      waitForBindings(4, "queues.testaddress", 1, 0, true);

      waitForBindings(0, "queues.testaddress", 4, 0, false);
      waitForBindings(1, "queues.testaddress", 4, 0, false);
      waitForBindings(2, "queues.testaddress", 4, 0, false);
      waitForBindings(3, "queues.testaddress", 4, 0, false);
      waitForBindings(4, "queues.testaddress", 4, 0, false);

      send(0, "queues.testaddress", 10, false, null);

      addConsumer(0, 0, "queue0", null);
      addConsumer(1, 1, "queue1", null);
      addConsumer(2, 2, "queue2", null);
      addConsumer(3, 3, "queue3", null);
      addConsumer(4, 4, "queue4", null);

      waitForBindings(0, "queues.testaddress", 1, 1, true);
      waitForBindings(1, "queues.testaddress", 1, 1, true);
      waitForBindings(2, "queues.testaddress", 1, 1, true);
      waitForBindings(3, "queues.testaddress", 1, 1, true);
      waitForBindings(4, "queues.testaddress", 1, 1, true);

      waitForBindings(0, "queues.testaddress", 4, 4, false);
      waitForBindings(1, "queues.testaddress", 4, 4, false);
      waitForBindings(2, "queues.testaddress", 4, 4, false);
      waitForBindings(3, "queues.testaddress", 4, 4, false);
      waitForBindings(4, "queues.testaddress", 4, 4, false);

      verifyReceiveAll(10, 0, 1, 2, 3, 4);
   }

   @Test
   public void testRouteWhenNoConsumersTrueNonLoadBalancedQueues() throws Exception {
      setupCluster(MessageLoadBalancingType.STRICT);

      startServers();

      setupSessionFactory(0, isNetty());
      setupSessionFactory(1, isNetty());
      setupSessionFactory(2, isNetty());
      setupSessionFactory(3, isNetty());
      setupSessionFactory(4, isNetty());

      createQueue(0, "queues.testaddress", "queue0", null, false);
      createQueue(1, "queues.testaddress", "queue1", null, false);
      createQueue(2, "queues.testaddress", "queue2", null, false);
      createQueue(3, "queues.testaddress", "queue3", null, false);
      createQueue(4, "queues.testaddress", "queue4", null, false);

      waitForBindings(0, "queues.testaddress", 1, 0, true);
      waitForBindings(1, "queues.testaddress", 1, 0, true);
      waitForBindings(2, "queues.testaddress", 1, 0, true);
      waitForBindings(3, "queues.testaddress", 1, 0, true);
      waitForBindings(4, "queues.testaddress", 1, 0, true);

      waitForBindings(0, "queues.testaddress", 4, 0, false);
      waitForBindings(1, "queues.testaddress", 4, 0, false);
      waitForBindings(2, "queues.testaddress", 4, 0, false);
      waitForBindings(3, "queues.testaddress", 4, 0, false);
      waitForBindings(4, "queues.testaddress", 4, 0, false);

      send(0, "queues.testaddress", 10, false, null);

      addConsumer(0, 0, "queue0", null);
      addConsumer(1, 1, "queue1", null);
      addConsumer(2, 2, "queue2", null);
      addConsumer(3, 3, "queue3", null);
      addConsumer(4, 4, "queue4", null);

      waitForBindings(0, "queues.testaddress", 1, 1, true);
      waitForBindings(1, "queues.testaddress", 1, 1, true);
      waitForBindings(2, "queues.testaddress", 1, 1, true);
      waitForBindings(3, "queues.testaddress", 1, 1, true);
      waitForBindings(4, "queues.testaddress", 1, 1, true);

      waitForBindings(0, "queues.testaddress", 4, 4, false);
      waitForBindings(1, "queues.testaddress", 4, 4, false);
      waitForBindings(2, "queues.testaddress", 4, 4, false);
      waitForBindings(3, "queues.testaddress", 4, 4, false);
      waitForBindings(4, "queues.testaddress", 4, 4, false);

      verifyReceiveAll(10, 0, 1, 2, 3, 4);
   }

   @Test
   public void testNoLocalQueueNonLoadBalancedQueues() throws Exception {
      setupCluster(MessageLoadBalancingType.STRICT);

      startServers();

      setupSessionFactory(0, isNetty());
      setupSessionFactory(1, isNetty());
      setupSessionFactory(2, isNetty());
      setupSessionFactory(3, isNetty());
      setupSessionFactory(4, isNetty());

      createQueue(1, "queues.testaddress", "queue1", null, false);
      createQueue(2, "queues.testaddress", "queue2", null, false);
      createQueue(3, "queues.testaddress", "queue3", null, false);
      createQueue(4, "queues.testaddress", "queue4", null, false);

      addConsumer(1, 1, "queue1", null);
      addConsumer(2, 2, "queue2", null);
      addConsumer(3, 3, "queue3", null);
      addConsumer(4, 4, "queue4", null);

      waitForBindings(1, "queues.testaddress", 1, 1, true);
      waitForBindings(2, "queues.testaddress", 1, 1, true);
      waitForBindings(3, "queues.testaddress", 1, 1, true);
      waitForBindings(4, "queues.testaddress", 1, 1, true);

      waitForBindings(0, "queues.testaddress", 4, 4, false);
      waitForBindings(1, "queues.testaddress", 3, 3, false);
      waitForBindings(2, "queues.testaddress", 3, 3, false);
      waitForBindings(3, "queues.testaddress", 3, 3, false);
      waitForBindings(4, "queues.testaddress", 3, 3, false);

      send(0, "queues.testaddress", 10, false, null);

      verifyReceiveAll(10, 1, 2, 3, 4);
   }

   @Test
   public void testNoLocalQueueLoadBalancedQueues() throws Exception {
      setupCluster(MessageLoadBalancingType.STRICT);

      startServers();

      setupSessionFactory(0, isNetty());
      setupSessionFactory(1, isNetty());
      setupSessionFactory(2, isNetty());
      setupSessionFactory(3, isNetty());
      setupSessionFactory(4, isNetty());

      createQueue(1, "queues.testaddress", "queue1", null, false);
      createQueue(2, "queues.testaddress", "queue1", null, false);
      createQueue(3, "queues.testaddress", "queue1", null, false);
      createQueue(4, "queues.testaddress", "queue1", null, false);

      addConsumer(1, 1, "queue1", null);
      addConsumer(2, 2, "queue1", null);
      addConsumer(3, 3, "queue1", null);
      addConsumer(4, 4, "queue1", null);

      waitForBindings(1, "queues.testaddress", 1, 1, true);
      waitForBindings(2, "queues.testaddress", 1, 1, true);
      waitForBindings(3, "queues.testaddress", 1, 1, true);
      waitForBindings(4, "queues.testaddress", 1, 1, true);

      waitForBindings(0, "queues.testaddress", 4, 4, false);
      waitForBindings(1, "queues.testaddress", 3, 3, false);
      waitForBindings(2, "queues.testaddress", 3, 3, false);
      waitForBindings(3, "queues.testaddress", 3, 3, false);
      waitForBindings(4, "queues.testaddress", 3, 3, false);

      send(0, "queues.testaddress", 10, false, null);

      verifyReceiveRoundRobinInSomeOrder(10, 1, 2, 3, 4);
   }

   public void _testStartStopServers() throws Exception {
      doTestStartStopServers(1, 3000);
   }

   public void doTestStartStopServers(long pauseBeforeServerRestarts, long pauseAfterServerRestarts) throws Exception {
      setupCluster();

      startServers();

      setupSessionFactory(0, isNetty());
      setupSessionFactory(1, isNetty());
      setupSessionFactory(2, isNetty());
      setupSessionFactory(3, isNetty());
      setupSessionFactory(4, isNetty());

      createQueue(0, "queues.testaddress", "queue0", null, false);
      createQueue(1, "queues.testaddress", "queue1", null, false);
      createQueue(2, "queues.testaddress", "queue2", null, false);
      createQueue(3, "queues.testaddress", "queue3", null, false);
      createQueue(4, "queues.testaddress", "queue4", null, false);

      createQueue(0, "queues.testaddress", "queue5", null, false);
      createQueue(1, "queues.testaddress", "queue6", null, false);
      createQueue(2, "queues.testaddress", "queue7", null, false);
      createQueue(3, "queues.testaddress", "queue8", null, false);
      createQueue(4, "queues.testaddress", "queue9", null, false);

      createQueue(0, "queues.testaddress", "queue10", null, false);
      createQueue(1, "queues.testaddress", "queue11", null, false);
      createQueue(2, "queues.testaddress", "queue12", null, false);
      createQueue(3, "queues.testaddress", "queue13", null, false);
      createQueue(4, "queues.testaddress", "queue14", null, false);

      createQueue(0, "queues.testaddress", "queue15", null, false);
      createQueue(1, "queues.testaddress", "queue15", null, false);
      createQueue(2, "queues.testaddress", "queue15", null, false);
      createQueue(3, "queues.testaddress", "queue15", null, false);
      createQueue(4, "queues.testaddress", "queue15", null, false);

      createQueue(2, "queues.testaddress", "queue16", null, false);
      createQueue(3, "queues.testaddress", "queue16", null, false);
      createQueue(4, "queues.testaddress", "queue16", null, false);

      createQueue(0, "queues.testaddress", "queue17", null, false);
      createQueue(1, "queues.testaddress", "queue17", null, false);
      createQueue(4, "queues.testaddress", "queue17", null, false);

      createQueue(3, "queues.testaddress", "queue18", null, false);
      createQueue(4, "queues.testaddress", "queue18", null, false);

      addConsumer(0, 0, "queue0", null);
      addConsumer(1, 1, "queue1", null);
      addConsumer(2, 2, "queue2", null);
      addConsumer(3, 3, "queue3", null);
      addConsumer(4, 4, "queue4", null);

      addConsumer(5, 0, "queue5", null);
      addConsumer(6, 1, "queue6", null);
      addConsumer(7, 2, "queue7", null);
      addConsumer(8, 3, "queue8", null);
      addConsumer(9, 4, "queue9", null);

      addConsumer(10, 0, "queue10", null);
      addConsumer(11, 1, "queue11", null);
      addConsumer(12, 2, "queue12", null);
      addConsumer(13, 3, "queue13", null);
      addConsumer(14, 4, "queue14", null);

      addConsumer(15, 0, "queue15", null);
      addConsumer(16, 1, "queue15", null);
      addConsumer(17, 2, "queue15", null);
      addConsumer(18, 3, "queue15", null);
      addConsumer(19, 4, "queue15", null);

      addConsumer(20, 2, "queue16", null);
      addConsumer(21, 3, "queue16", null);
      addConsumer(22, 4, "queue16", null);

      addConsumer(23, 0, "queue17", null);
      addConsumer(24, 1, "queue17", null);
      addConsumer(25, 4, "queue17", null);

      addConsumer(26, 3, "queue18", null);
      addConsumer(27, 4, "queue18", null);

      waitForBindings(0, "queues.testaddress", 5, 5, true);
      waitForBindings(1, "queues.testaddress", 5, 5, true);
      waitForBindings(2, "queues.testaddress", 5, 5, true);
      waitForBindings(3, "queues.testaddress", 6, 6, true);
      waitForBindings(4, "queues.testaddress", 7, 7, true);

      waitForBindings(0, "queues.testaddress", 23, 23, false);
      waitForBindings(1, "queues.testaddress", 23, 23, false);
      waitForBindings(2, "queues.testaddress", 23, 23, false);
      waitForBindings(3, "queues.testaddress", 22, 22, false);
      waitForBindings(4, "queues.testaddress", 21, 21, false);

      send(0, "queues.testaddress", 10, false, null);

      verifyReceiveAll(10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);

      verifyReceiveRoundRobinInSomeOrder(10, 15, 16, 17, 18, 19);

      verifyReceiveRoundRobinInSomeOrder(10, 20, 21, 22);

      verifyReceiveRoundRobinInSomeOrder(10, 23, 24, 25);

      verifyReceiveRoundRobinInSomeOrder(10, 26, 27);

      removeConsumer(0);
      removeConsumer(5);
      removeConsumer(10);
      removeConsumer(15);
      removeConsumer(23);
      removeConsumer(3);
      removeConsumer(8);
      removeConsumer(13);
      removeConsumer(18);
      removeConsumer(21);
      removeConsumer(26);

      closeSessionFactory(0);
      closeSessionFactory(3);

      stopServers(0, 3);

      Thread.sleep(pauseBeforeServerRestarts);

      startServers(3, 0);

      Thread.sleep(pauseAfterServerRestarts);

      setupSessionFactory(0, isNetty());
      setupSessionFactory(3, isNetty());

      createQueue(0, "queues.testaddress", "queue0", null, false);
      createQueue(3, "queues.testaddress", "queue3", null, false);

      createQueue(0, "queues.testaddress", "queue5", null, false);
      createQueue(3, "queues.testaddress", "queue8", null, false);

      createQueue(0, "queues.testaddress", "queue10", null, false);
      createQueue(3, "queues.testaddress", "queue13", null, false);

      createQueue(0, "queues.testaddress", "queue15", null, false);
      createQueue(3, "queues.testaddress", "queue15", null, false);

      createQueue(3, "queues.testaddress", "queue16", null, false);

      createQueue(0, "queues.testaddress", "queue17", null, false);

      createQueue(3, "queues.testaddress", "queue18", null, false);

      addConsumer(0, 0, "queue0", null);
      addConsumer(3, 3, "queue3", null);

      addConsumer(5, 0, "queue5", null);
      addConsumer(8, 3, "queue8", null);

      addConsumer(10, 0, "queue10", null);
      addConsumer(13, 3, "queue13", null);

      addConsumer(15, 0, "queue15", null);
      addConsumer(18, 3, "queue15", null);

      addConsumer(21, 3, "queue16", null);

      addConsumer(23, 0, "queue17", null);

      addConsumer(26, 3, "queue18", null);

      waitForBindings(0, "queues.testaddress", 5, 5, true);
      waitForBindings(1, "queues.testaddress", 5, 5, true);
      waitForBindings(2, "queues.testaddress", 5, 5, true);
      waitForBindings(3, "queues.testaddress", 6, 6, true);
      waitForBindings(4, "queues.testaddress", 7, 7, true);

      waitForBindings(0, "queues.testaddress", 23, 23, false);
      waitForBindings(1, "queues.testaddress", 23, 23, false);
      waitForBindings(2, "queues.testaddress", 23, 23, false);
      waitForBindings(3, "queues.testaddress", 22, 22, false);
      waitForBindings(4, "queues.testaddress", 21, 21, false);

      send(0, "queues.testaddress", 10, false, null);

      verifyReceiveAll(10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);

      verifyReceiveRoundRobinInSomeOrder(10, 15, 16, 17, 18, 19);

      verifyReceiveRoundRobinInSomeOrder(10, 20, 21, 22);

      verifyReceiveRoundRobinInSomeOrder(10, 23, 24, 25);

      verifyReceiveRoundRobinInSomeOrder(10, 26, 27);
   }

   @Test
   public void testStopSuccessiveServers() throws Exception {
      setupCluster();

      startServers();

      setupSessionFactory(0, isNetty());
      setupSessionFactory(1, isNetty());
      setupSessionFactory(2, isNetty());
      setupSessionFactory(3, isNetty());
      setupSessionFactory(4, isNetty());

      createQueue(0, "queues.testaddress", "queue0", null, false);
      createQueue(1, "queues.testaddress", "queue1", null, false);
      createQueue(2, "queues.testaddress", "queue2", null, false);
      createQueue(3, "queues.testaddress", "queue3", null, false);
      createQueue(4, "queues.testaddress", "queue4", null, false);

      createQueue(0, "queues.testaddress", "queue5", null, false);
      createQueue(1, "queues.testaddress", "queue6", null, false);
      createQueue(2, "queues.testaddress", "queue7", null, false);
      createQueue(3, "queues.testaddress", "queue8", null, false);
      createQueue(4, "queues.testaddress", "queue9", null, false);

      createQueue(0, "queues.testaddress", "queue10", null, false);
      createQueue(1, "queues.testaddress", "queue11", null, false);
      createQueue(2, "queues.testaddress", "queue12", null, false);
      createQueue(3, "queues.testaddress", "queue13", null, false);
      createQueue(4, "queues.testaddress", "queue14", null, false);

      createQueue(0, "queues.testaddress", "queue15", null, false);
      createQueue(1, "queues.testaddress", "queue15", null, false);
      createQueue(2, "queues.testaddress", "queue15", null, false);
      createQueue(3, "queues.testaddress", "queue15", null, false);
      createQueue(4, "queues.testaddress", "queue15", null, false);

      createQueue(2, "queues.testaddress", "queue16", null, false);
      createQueue(3, "queues.testaddress", "queue16", null, false);
      createQueue(4, "queues.testaddress", "queue16", null, false);

      createQueue(0, "queues.testaddress", "queue17", null, false);
      createQueue(1, "queues.testaddress", "queue17", null, false);
      createQueue(4, "queues.testaddress", "queue17", null, false);

      createQueue(3, "queues.testaddress", "queue18", null, false);
      createQueue(4, "queues.testaddress", "queue18", null, false);

      addConsumer(0, 0, "queue0", null);
      addConsumer(1, 1, "queue1", null);
      addConsumer(2, 2, "queue2", null);
      addConsumer(3, 3, "queue3", null);
      addConsumer(4, 4, "queue4", null);

      addConsumer(5, 0, "queue5", null);
      addConsumer(6, 1, "queue6", null);
      addConsumer(7, 2, "queue7", null);
      addConsumer(8, 3, "queue8", null);
      addConsumer(9, 4, "queue9", null);

      addConsumer(10, 0, "queue10", null);
      addConsumer(11, 1, "queue11", null);
      addConsumer(12, 2, "queue12", null);
      addConsumer(13, 3, "queue13", null);
      addConsumer(14, 4, "queue14", null);

      addConsumer(15, 0, "queue15", null);
      addConsumer(16, 1, "queue15", null);
      addConsumer(17, 2, "queue15", null);
      addConsumer(18, 3, "queue15", null);
      addConsumer(19, 4, "queue15", null);

      addConsumer(20, 2, "queue16", null);
      addConsumer(21, 3, "queue16", null);
      addConsumer(22, 4, "queue16", null);

      addConsumer(23, 0, "queue17", null);
      addConsumer(24, 1, "queue17", null);
      addConsumer(25, 4, "queue17", null);

      addConsumer(26, 3, "queue18", null);
      addConsumer(27, 4, "queue18", null);

      waitForBindings(0, "queues.testaddress", 5, 5, true);
      waitForBindings(1, "queues.testaddress", 5, 5, true);
      waitForBindings(2, "queues.testaddress", 5, 5, true);
      waitForBindings(3, "queues.testaddress", 6, 6, true);
      waitForBindings(4, "queues.testaddress", 7, 7, true);

      waitForBindings(0, "queues.testaddress", 23, 23, false);
      waitForBindings(1, "queues.testaddress", 23, 23, false);
      waitForBindings(2, "queues.testaddress", 23, 23, false);
      waitForBindings(3, "queues.testaddress", 22, 22, false);
      waitForBindings(4, "queues.testaddress", 21, 21, false);

      send(0, "queues.testaddress", 10, false, null);

      verifyReceiveAll(10, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);

      verifyReceiveRoundRobinInSomeOrder(10, 15, 16, 17, 18, 19);

      verifyReceiveRoundRobinInSomeOrder(10, 20, 21, 22);

      verifyReceiveRoundRobinInSomeOrder(10, 23, 24, 25);

      verifyReceiveRoundRobinInSomeOrder(10, 26, 27);

      // stop server 0
      removeConsumer(0);
      removeConsumer(5);
      removeConsumer(10);
      removeConsumer(15);
      removeConsumer(23);

      closeSessionFactory(0);

      stopServers(0);

      waitForBindings(1, "queues.testaddress", 5, 5, true);
      waitForBindings(2, "queues.testaddress", 5, 5, true);
      waitForBindings(3, "queues.testaddress", 6, 6, true);
      waitForBindings(4, "queues.testaddress", 7, 7, true);

      waitForBindings(1, "queues.testaddress", 18, 18, false);
      waitForBindings(2, "queues.testaddress", 18, 18, false);
      waitForBindings(3, "queues.testaddress", 17, 17, false);
      waitForBindings(4, "queues.testaddress", 16, 16, false);

      // stop server 1
      removeConsumer(1);
      removeConsumer(6);
      removeConsumer(11);
      removeConsumer(16);
      removeConsumer(24);

      closeSessionFactory(1);

      stopServers(1);

      waitForBindings(2, "queues.testaddress", 5, 5, true);
      waitForBindings(3, "queues.testaddress", 6, 6, true);
      waitForBindings(4, "queues.testaddress", 7, 7, true);

      waitForBindings(2, "queues.testaddress", 13, 13, false);
      waitForBindings(3, "queues.testaddress", 12, 12, false);
      waitForBindings(4, "queues.testaddress", 11, 11, false);

      // stop server 2
      removeConsumer(2);
      removeConsumer(7);
      removeConsumer(12);
      removeConsumer(17);
      removeConsumer(20);

      closeSessionFactory(2);

      stopServers(2);

      waitForBindings(3, "queues.testaddress", 6, 6, true);
      waitForBindings(4, "queues.testaddress", 7, 7, true);

      waitForBindings(3, "queues.testaddress", 7, 7, false);
      waitForBindings(4, "queues.testaddress", 6, 6, false);

      // stop server 3
      removeConsumer(3);
      removeConsumer(8);
      removeConsumer(13);
      removeConsumer(18);
      removeConsumer(21);
      removeConsumer(26);

      closeSessionFactory(3);

      stopServers(3);

      waitForBindings(4, "queues.testaddress", 7, 7, true);

      waitForBindings(4, "queues.testaddress", 0, 0, false);
   }

   @Test
   /**
    * This test verifies that addresses matching a simple string filter such as 'jms' result in bindings being created
    * on appropriate nodes in the cluster.  It also verifies that addresses not matching the simple string filter do not
    * result in bindings being created.
    */ public void testClusterAddressCreatesBindingsForSimpleStringAddressFilters() throws Exception {
      setupCluster("test", "test", "test", "test", "test");
      startServers();

      setupSessionFactory(0, isNetty());
      setupSessionFactory(1, isNetty());
      setupSessionFactory(2, isNetty());
      setupSessionFactory(3, isNetty());
      setupSessionFactory(4, isNetty());

      createQueue(0, "test.1", "queue0", null, false);
      createQueue(1, "test.1", "queue0", null, false);
      createQueue(2, "test.1", "queue0", null, false);
      createQueue(3, "test.1", "queue0", null, false);
      createQueue(4, "test.1", "queue0", null, false);

      createQueue(0, "foo.queues.test.1", "queue1", null, false);
      createQueue(1, "foo.queues.test.1", "queue1", null, false);
      createQueue(2, "foo.queues.test.1", "queue1", null, false);
      createQueue(3, "foo.queues.test.1", "queue1", null, false);
      createQueue(4, "foo.queues.test.1", "queue1", null, false);

      waitForBindings(0, "test.1", 4, 0, false);
      waitForBindings(1, "test.1", 4, 0, false);
      waitForBindings(2, "test.1", 4, 0, false);
      waitForBindings(3, "test.1", 4, 0, false);
      waitForBindings(4, "test.1", 4, 0, false);

      waitForBindings(0, "foo.queues.test.1", 0, 0, false);
      waitForBindings(1, "foo.queues.test.1", 0, 0, false);
      waitForBindings(2, "foo.queues.test.1", 0, 0, false);
      waitForBindings(3, "foo.queues.test.1", 0, 0, false);
      waitForBindings(4, "foo.queues.test.1", 0, 0, false);
   }

   @Test
   /**
    * This test verifies that a string exclude filter '!jms.eu.uk' results in bindings not being created for this
    * address for nodes in a cluster.  But ensures that other addresses are matched and bindings created.
    */ public void testClusterAddressDoesNotCreatesBindingsForStringExcludesAddressFilters() throws Exception {
      setupCluster("jms.eu.de,!jms.eu.uk", "jms.eu.de,!jms.eu.uk", "jms.eu.de,!jms.eu.uk", "jms.eu.de,!jms.eu.uk", "jms.eu.de,!jms.eu.uk");
      startServers();

      setupSessionFactory(0, isNetty());
      setupSessionFactory(1, isNetty());
      setupSessionFactory(2, isNetty());
      setupSessionFactory(3, isNetty());
      setupSessionFactory(4, isNetty());

      createQueue(0, "jms.eu.uk", "queue0", null, false);
      createQueue(1, "jms.eu.uk", "queue0", null, false);
      createQueue(2, "jms.eu.uk", "queue0", null, false);
      createQueue(3, "jms.eu.uk", "queue0", null, false);
      createQueue(4, "jms.eu.uk", "queue0", null, false);

      createQueue(0, "jms.eu.de", "queue1", null, false);
      createQueue(1, "jms.eu.de", "queue1", null, false);
      createQueue(2, "jms.eu.de", "queue1", null, false);
      createQueue(3, "jms.eu.de", "queue1", null, false);
      createQueue(4, "jms.eu.de", "queue1", null, false);

      waitForBindings(0, "jms.eu.de", 4, 0, false);
      waitForBindings(1, "jms.eu.de", 4, 0, false);
      waitForBindings(2, "jms.eu.de", 4, 0, false);
      waitForBindings(3, "jms.eu.de", 4, 0, false);
      waitForBindings(4, "jms.eu.de", 4, 0, false);

      waitForBindings(0, "jms.eu.uk", 0, 0, false);
      waitForBindings(1, "jms.eu.uk", 0, 0, false);
      waitForBindings(2, "jms.eu.uk", 0, 0, false);
      waitForBindings(3, "jms.eu.uk", 0, 0, false);
      waitForBindings(4, "jms.eu.uk", 0, 0, false);
   }

   /**
    * This test verifies that remote bindings are only created for queues that match jms.eu or jms.us excluding
    * jms.eu.uk and jms.us.bos.  Represented by the address filter 'jms.eu,!jms.eu.uk,jms.us,!jms.us.bos'
    *
    * @throws Exception
    */
   @Test
   public void testClusterAddressFiltersExcludesAndIncludesAddressesInList() throws Exception {
      setupCluster("jms.eu,!jms.eu.uk,jms.us,!jms.us.bos", "jms.eu,!jms.eu.uk,jms.us,!jms.us.bos", "jms.eu,!jms.eu.uk,jms.us,!jms.us.bos", "jms.eu,!jms.eu.uk,jms.us,!jms.us.bos", "jms.eu,!jms.eu.uk,jms.us,!jms.us.bos");

      startServers();

      setupSessionFactory(0, isNetty());
      setupSessionFactory(1, isNetty());
      setupSessionFactory(2, isNetty());
      setupSessionFactory(3, isNetty());
      setupSessionFactory(4, isNetty());

      createQueue(0, "jms.eu.uk", "queue0", null, false);
      createQueue(1, "jms.eu.uk", "queue0", null, false);
      createQueue(2, "jms.eu.uk", "queue0", null, false);
      createQueue(3, "jms.eu.uk", "queue0", null, false);
      createQueue(4, "jms.eu.uk", "queue0", null, false);

      createQueue(0, "jms.eu.de", "queue1", null, false);
      createQueue(1, "jms.eu.de", "queue1", null, false);
      createQueue(2, "jms.eu.de", "queue1", null, false);
      createQueue(3, "jms.eu.de", "queue1", null, false);
      createQueue(4, "jms.eu.de", "queue1", null, false);

      createQueue(0, "jms.eu.fr", "queue2", null, false);
      createQueue(1, "jms.eu.fr", "queue2", null, false);
      createQueue(2, "jms.eu.fr", "queue2", null, false);
      createQueue(3, "jms.eu.fr", "queue2", null, false);
      createQueue(4, "jms.eu.fr", "queue2", null, false);

      createQueue(0, "jms.us.ca", "queue4", null, false);
      createQueue(1, "jms.us.ca", "queue4", null, false);
      createQueue(2, "jms.us.ca", "queue4", null, false);
      createQueue(3, "jms.us.ca", "queue4", null, false);
      createQueue(4, "jms.us.ca", "queue4", null, false);

      createQueue(0, "jms.us.se", "queue5", null, false);
      createQueue(1, "jms.us.se", "queue5", null, false);
      createQueue(2, "jms.us.se", "queue5", null, false);
      createQueue(3, "jms.us.se", "queue5", null, false);
      createQueue(4, "jms.us.se", "queue5", null, false);

      createQueue(0, "jms.us.ny", "queue6", null, false);
      createQueue(1, "jms.us.ny", "queue6", null, false);
      createQueue(2, "jms.us.ny", "queue6", null, false);
      createQueue(3, "jms.us.ny", "queue6", null, false);
      createQueue(4, "jms.us.ny", "queue6", null, false);

      waitForBindings(0, "jms.eu.de", 4, 0, false);
      waitForBindings(1, "jms.eu.de", 4, 0, false);
      waitForBindings(2, "jms.eu.de", 4, 0, false);
      waitForBindings(3, "jms.eu.de", 4, 0, false);
      waitForBindings(4, "jms.eu.de", 4, 0, false);

      waitForBindings(0, "jms.eu.fr", 4, 0, false);
      waitForBindings(1, "jms.eu.fr", 4, 0, false);
      waitForBindings(2, "jms.eu.fr", 4, 0, false);
      waitForBindings(3, "jms.eu.fr", 4, 0, false);
      waitForBindings(4, "jms.eu.fr", 4, 0, false);

      waitForBindings(0, "jms.eu.uk", 0, 0, false);
      waitForBindings(1, "jms.eu.uk", 0, 0, false);
      waitForBindings(2, "jms.eu.uk", 0, 0, false);
      waitForBindings(3, "jms.eu.uk", 0, 0, false);
      waitForBindings(4, "jms.eu.uk", 0, 0, false);

      waitForBindings(0, "jms.us.ca", 4, 0, false);
      waitForBindings(1, "jms.us.ca", 4, 0, false);
      waitForBindings(2, "jms.us.ca", 4, 0, false);
      waitForBindings(3, "jms.us.ca", 4, 0, false);
      waitForBindings(4, "jms.us.ca", 4, 0, false);

      waitForBindings(0, "jms.us.ny", 4, 0, false);
      waitForBindings(1, "jms.us.ny", 4, 0, false);
      waitForBindings(2, "jms.us.ny", 4, 0, false);
      waitForBindings(3, "jms.us.ny", 4, 0, false);
      waitForBindings(4, "jms.us.ny", 4, 0, false);

      waitForBindings(0, "jms.us.bos", 0, 0, false);
      waitForBindings(1, "jms.us.bos", 0, 0, false);
      waitForBindings(2, "jms.us.bos", 0, 0, false);
      waitForBindings(3, "jms.us.bos", 0, 0, false);
      waitForBindings(4, "jms.us.bos", 0, 0, false);
   }

   protected void setupCluster(String addr1, String addr2, String addr3, String addr4, String addr5) throws Exception {
      setupClusterConnection("cluster0", addr1, MessageLoadBalancingType.STRICT, 1, isNetty(), 0, 1, 2, 3, 4);

      setupClusterConnection("cluster1", addr2, MessageLoadBalancingType.STRICT, 1, isNetty(), 1, 0, 2, 3, 4);

      setupClusterConnection("cluster2", addr3, MessageLoadBalancingType.STRICT, 1, isNetty(), 2, 0, 1, 3, 4);

      setupClusterConnection("cluster3", addr4, MessageLoadBalancingType.STRICT, 1, isNetty(), 3, 0, 1, 2, 4);
      setupClusterConnection("cluster4", addr5, MessageLoadBalancingType.STRICT, 1, isNetty(), 4, 0, 1, 2, 3);
   }

   protected void setupCluster() throws Exception {
      setupCluster(MessageLoadBalancingType.ON_DEMAND);
   }

   protected void setupCluster(final MessageLoadBalancingType messageLoadBalancingType) throws Exception {
      setupClusterConnection("cluster0", "queues", messageLoadBalancingType, 1, isNetty(), 0, 1, 2, 3, 4);

      setupClusterConnection("cluster1", "queues", messageLoadBalancingType, 1, isNetty(), 1, 0, 2, 3, 4);

      setupClusterConnection("cluster2", "queues", messageLoadBalancingType, 1, isNetty(), 2, 0, 1, 3, 4);

      setupClusterConnection("cluster3", "queues", messageLoadBalancingType, 1, isNetty(), 3, 0, 1, 2, 4);

      setupClusterConnection("cluster4", "queues", messageLoadBalancingType, 1, isNetty(), 4, 0, 1, 2, 3);
   }

   protected void setupServers() throws Exception {
      setupServer(0, isFileStorage(), isNetty());
      setupServer(1, isFileStorage(), isNetty());
      setupServer(2, isFileStorage(), isNetty());
      setupServer(3, isFileStorage(), isNetty());
      setupServer(4, isFileStorage(), isNetty());
   }

   protected void startServers() throws Exception {
      startServers(0, 1, 2, 3, 4);
   }

   protected void stopServers() throws Exception {
      closeAllConsumers();

      closeAllSessionFactories();

      closeAllServerLocatorsFactories();

      stopServers(0, 1, 2, 3, 4);
   }

   @Override
   protected boolean isFileStorage() {
      return false;
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/journal/ShrinkDataOnStartTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.journal;

import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.utils.Wait;
import org.junit.Assert;
import org.junit.Test;

public class ShrinkDataOnStartTest extends ActiveMQTestBase {

   @Test
   public void shrinkDataOnStart() throws Exception {

      ActiveMQServer server = addServer(createServer(true));
      server.getConfiguration().setJournalMinFiles(10);
      server.getConfiguration().setJournalPoolFiles(2);
      server.start();
      Wait.waitFor(server::isActive);
      Assert.assertEquals(10, server.getStorageManager().getMessageJournal().getFileFactory().listFiles("amq").size());
      server.stop();
      server.getConfiguration().setJournalMinFiles(2);
      server.getConfiguration().setJournalPoolFiles(2);
      server.start();
      Assert.assertEquals(2, server.getStorageManager().getMessageJournal().getFileFactory().listFiles("amq").size());
   }

}


<|start_filename|>tests/compatibility-tests/src/main/resources/clients/artemisClientAMQP.groovy<|end_filename|>
package clients
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Create a client connection factory

// This differs from artemisClient.groovy as you can possibly use AMQP as the producer

import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.tests.compatibility.GroovyRun;

if (serverArg[0].startsWith("HORNETQ")) {
    cf = new ActiveMQConnectionFactory("tcp://localhost:61616?protocolManagerFactoryStr=org.apache.activemq.artemis.core.protocol.hornetq.client.HornetQClientProtocolManagerFactory&confirmationWindowSize=1048576&blockOnDurableSend=false&reconnectAttempts=-1&retryInterval=100");
} else {
    if ("AMQP".equals(serverArg[1])) {
        cf = new org.apache.qpid.jms.JmsConnectionFactory("amqp://localhost:61616?confirmationWindowSize=1048576&blockOnDurableSend=false&ha=true&reconnectAttempts=-1&retryInterval=100");
    } else {
        cf = new ActiveMQConnectionFactory("tcp://localhost:61616?confirmationWindowSize=1048576&blockOnDurableSend=false&ha=true&reconnectAttempts=-1&retryInterval=100");
    }
}

if (!"AMQP".equals(serverArg[1])) {
    GroovyRun.assertTrue(!cf.getServerLocator().isBlockOnDurableSend());
    GroovyRun.assertEquals(1048576, cf.getServerLocator().getConfirmationWindowSize());
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/security/JMSXUserIDPluginTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.security;


import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.ActiveMQServers;
import org.apache.activemq.artemis.core.server.ServerSession;
import org.apache.activemq.artemis.core.server.plugin.ActiveMQServerPlugin;
import org.apache.activemq.artemis.core.transaction.Transaction;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.qpid.jms.JmsConnectionFactory;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import javax.jms.Connection;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import java.util.Map;

public class JMSXUserIDPluginTest extends ActiveMQTestBase {

   private ActiveMQServer server;
   private SimpleString ADDRESS = new SimpleString("TestQueue");

   @Override
   @Before
   public void setUp() throws Exception {
      super.setUp();

      server = addServer(ActiveMQServers.newActiveMQServer(createDefaultNettyConfig(), true));

      JMSXUserIDPlugin plugin = new JMSXUserIDPlugin();
      plugin.setPopulateValidatedUser("testuser");

      server.registerBrokerPlugin(plugin);
      server.start();
      server.createQueue(new QueueConfiguration(ADDRESS).setRoutingType(RoutingType.ANYCAST));
   }

   @Test
   public void testAddValidatedUserCore() throws Exception {
      ServerLocator locator = createNettyNonHALocator();
      ClientSessionFactory sf = createSessionFactory(locator);
      ClientSession session = sf.createSession(false, true, true);
      ClientProducer producer = session.createProducer(ADDRESS.toString());
      producer.send(session.createMessage(true));
      ClientConsumer consumer = session.createConsumer(ADDRESS.toString());
      session.start();
      ClientMessage clientMessage = consumer.receiveImmediate();
      Assert.assertNotNull(clientMessage);
      Assert.assertEquals(clientMessage.getValidatedUserID(), "testuser");
   }

   @Test
   public void testAddValidatedUserAMQP() throws Exception {
      JmsConnectionFactory factory = new JmsConnectionFactory("amqp://127.0.0.1:61616");
      Connection connection = factory.createConnection();
      Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
      javax.jms.Queue queue = session.createQueue(ADDRESS.toString());
      MessageProducer producer = session.createProducer(queue);
      producer.send(session.createMessage());
      connection.close();

      server.stop();
      server.start();

      connection = factory.createConnection();
      session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
      connection.start();
      MessageConsumer consumer = session.createConsumer(queue);
      Message message = consumer.receive(5000);
      Assert.assertNotNull(message);
      Assert.assertEquals(message.getStringProperty("_AMQ_VALIDATED_USER"), "testuser");
      connection.close();
   }


   private static class JMSXUserIDPlugin implements ActiveMQServerPlugin {

      private static String POPULATE_VALIDATED_USER = "POPULATE_VALIDATED_USER";

      private String populateValidatedUser;

      /**
       * used to pass configured properties to Plugin
       *
       * @param properties
       */
      @Override
      public void init(Map<String, String> properties) {
         populateValidatedUser = properties.getOrDefault(POPULATE_VALIDATED_USER, null);
      }

      @Override
      public void beforeSend(ServerSession session, Transaction tx, org.apache.activemq.artemis.api.core.Message message, boolean direct, boolean noAutoCreateQueue) throws ActiveMQException {
         if (populateValidatedUser != null && !message.containsProperty(org.apache.activemq.artemis.api.core.Message.HDR_VALIDATED_USER)) {
            message.messageChanged();
            message.putStringProperty(org.apache.activemq.artemis.api.core.Message.HDR_VALIDATED_USER, populateValidatedUser);
         }
      }

      public String getPopulateValidatedUser() {
         return populateValidatedUser;
      }

      public void setPopulateValidatedUser(String populateValidatedUser) {
         this.populateValidatedUser = populateValidatedUser;
      }
   }

}


<|start_filename|>artemis-core-client/src/main/java/org/apache/activemq/artemis/spi/core/remoting/ssl/SSLContextConfig.java<|end_filename|>
/*
 * Copyright 2021 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.spi.core.remoting.ssl;

import java.util.Objects;

import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants;

/**
 * This class holds configuration parameters for SSL context initialization.
 * To be used with {@link SSLContextFactory} and {@link OpenSSLContextFactory}.
 * <br>
 * Use {@link SSLContextConfig#builder()} to create new immutable instances.
 */
public final class SSLContextConfig {

   public static final class Builder {
      private String keystorePath = TransportConstants.DEFAULT_KEYSTORE_PATH;
      private String keystoreType = TransportConstants.DEFAULT_KEYSTORE_TYPE;
      private String keystorePassword = TransportConstants.DEFAULT_KEYSTORE_PASSWORD;
      private String keystoreProvider = TransportConstants.DEFAULT_KEYSTORE_PROVIDER;
      private String truststorePath = TransportConstants.DEFAULT_TRUSTSTORE_PATH;
      private String truststoreType = TransportConstants.DEFAULT_TRUSTSTORE_TYPE;
      private String truststorePassword = TransportConstants.DEFAULT_TRUSTSTORE_PASSWORD;
      private String truststoreProvider = TransportConstants.DEFAULT_TRUSTSTORE_PROVIDER;
      private String crlPath = TransportConstants.DEFAULT_CRL_PATH;
      private String trustManagerFactoryPlugin = TransportConstants.DEFAULT_TRUST_MANAGER_FACTORY_PLUGIN;
      private boolean trustAll = TransportConstants.DEFAULT_TRUST_ALL;

      private Builder() {
      }

      public Builder from(final SSLContextConfig config) {
         if (config == null)
            return this;

         keystorePath = config.getKeystorePath();
         keystoreType = config.getKeystoreType();
         keystorePassword = config.getKeystorePassword();
         keystoreProvider = config.getKeystoreProvider();
         truststorePath = config.getTruststorePath();
         truststoreType = config.getTruststoreType();
         truststorePassword = config.getTruststorePassword();
         crlPath = config.getCrlPath();
         truststoreProvider = config.getTruststoreProvider();
         trustAll = config.trustAll;
         return this;
      }

      public SSLContextConfig build() {
         return new SSLContextConfig(
            keystoreProvider, keystorePath, keystoreType, keystorePassword,
            truststoreProvider, truststorePath, truststoreType, truststorePassword,
            crlPath, trustManagerFactoryPlugin, trustAll
         );
      }

      public Builder keystorePath(final String keystorePath) {
         this.keystorePath = keystorePath;
         return this;
      }

      public Builder keystoreType(final String keystoreType) {
         this.keystoreType = keystoreType;
         return this;
      }

      public Builder keystorePassword(final String keystorePassword) {
         this.keystorePassword = keystorePassword;
         return this;
      }

      public Builder keystoreProvider(final String keystoreProvider) {
         this.keystoreProvider = keystoreProvider;
         return this;
      }

      public Builder truststorePath(final String truststorePath) {
         this.truststorePath = truststorePath;
         return this;
      }

      public Builder truststoreType(final String truststoreType) {
         this.truststoreType = truststoreType;
         return this;
      }

      public Builder truststorePassword(final String truststorePassword) {
         this.truststorePassword = <PASSWORD>;
         return this;
      }

      public Builder truststoreProvider(final String truststoreProvider) {
         this.truststoreProvider = truststoreProvider;
         return this;
      }

      public Builder crlPath(final String crlPath) {
         this.crlPath = crlPath;
         return this;
      }

      public Builder trustAll(final boolean trustAll) {
         this.trustAll = trustAll;
         return this;
      }

      public Builder trustManagerFactoryPlugin(final String trustManagerFactoryPlugin) {
         this.trustManagerFactoryPlugin = trustManagerFactoryPlugin;
         return this;
      }
   }

   public static  Builder builder() {
      return new Builder();
   }

   private final String keystorePath;
   private final String keystoreType;
   private final String keystorePassword;
   private final String keystoreProvider;
   private final String truststorePath;
   private final String truststoreType;
   private final String truststorePassword;
   private final String truststoreProvider;
   private final String trustManagerFactoryPlugin;
   private final String crlPath;
   private final boolean trustAll;
   private final int hashCode;

   private SSLContextConfig(final String keystoreProvider,
                            final String keystorePath,
                            final String keystoreType,
                            final String keystorePassword,
                            final String truststoreProvider,
                            final String truststorePath,
                            final String truststoreType,
                            final String truststorePassword,
                            final String crlPath,
                            final String trustManagerFactoryPlugin,
                            final boolean trustAll) {
      this.keystorePath = keystorePath;
      this.keystoreType = keystoreType;
      this.keystoreProvider = keystoreProvider;
      this.keystorePassword = <PASSWORD>;
      this.truststorePath = truststorePath;
      this.truststoreType = truststoreType;
      this.truststorePassword = <PASSWORD>;
      this.truststoreProvider = truststoreProvider;
      this.trustManagerFactoryPlugin = trustManagerFactoryPlugin;
      this.crlPath = crlPath;
      this.trustAll = trustAll;
      hashCode = Objects.hash(
         keystorePath, keystoreType, keystoreProvider,
         truststorePath, truststoreType, truststoreProvider,
         crlPath, trustManagerFactoryPlugin, trustAll
      );
   }

   @Override
   public boolean equals(final Object obj) {
      if (this == obj)
         return true;
      if (obj == null || getClass() != obj.getClass())
         return false;
      final SSLContextConfig other = (SSLContextConfig) obj;
      return Objects.equals(keystorePath, other.keystorePath)
         && Objects.equals(keystoreType, other.keystoreType)
         && Objects.equals(keystoreProvider, other.keystoreProvider)
         && Objects.equals(truststorePath, other.truststorePath)
         && Objects.equals(truststoreType, other.truststoreType)
         && Objects.equals(truststoreProvider, other.truststoreProvider)
         && Objects.equals(crlPath, other.crlPath)
         && Objects.equals(trustManagerFactoryPlugin, other.trustManagerFactoryPlugin)
         && trustAll == other.trustAll;
   }

   public String getCrlPath() {
      return crlPath;
   }

   public String getKeystorePassword() {
      return keystorePassword;
   }

   public String getKeystorePath() {
      return keystorePath;
   }

   public String getKeystoreType() {
      return keystoreType;
   }

   public String getKeystoreProvider() {
      return keystoreProvider;
   }

   public String getTrustManagerFactoryPlugin() {
      return trustManagerFactoryPlugin;
   }

   public String getTruststorePassword() {
      return truststorePassword;
   }

   public String getTruststorePath() {
      return truststorePath;
   }

   public String getTruststoreType() {
      return truststoreType;
   }

   public String getTruststoreProvider() {
      return truststoreProvider;
   }

   @Override
   public int hashCode() {
      return hashCode;
   }

   public boolean isTrustAll() {
      return trustAll;
   }

   @Override
   public String toString() {
      return "SSLSupport [" +
         "keystoreProvider=" + keystoreProvider +
         ", keystorePath=" + keystorePath +
         ", keystoreType=" + keystoreType +
         ", keystorePassword=" + (keystorePassword == null ? null : "******") +
         ", truststoreProvider=" + truststoreProvider +
         ", truststorePath=" + truststorePath +
         ", truststoreType=" + truststoreType +
         ", truststorePassword=" + (truststorePassword == null ? null : "******") +
         ", crlPath=" + crlPath +
         ", trustAll=" + trustAll +
         ", trustManagerFactoryPlugin=" + trustManagerFactoryPlugin +
         "]";
   }
}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/cursor/impl/LivePageCacheImpl.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.paging.cursor.impl;

import org.apache.activemq.artemis.core.paging.PagedMessage;
import org.apache.activemq.artemis.core.paging.cursor.LivePageCache;
import org.apache.activemq.artemis.core.paging.cursor.PagePosition;
import org.apache.activemq.artemis.utils.collections.ConcurrentAppendOnlyChunkedList;
import org.jboss.logging.Logger;

/**
 * This is the same as PageCache, however this is for the page that's being currently written.
 */
public final class LivePageCacheImpl implements LivePageCache {

   private static final Logger logger = Logger.getLogger(LivePageCacheImpl.class);

   private static final int CHUNK_SIZE = 32;

   private final PagedMessage[] initialMessages;

   private final ConcurrentAppendOnlyChunkedList<PagedMessage> liveMessages;

   private final long pageId;

   private volatile boolean isLive = true;

   public LivePageCacheImpl(final long pageId) {
      this.pageId = pageId;
      this.liveMessages = new ConcurrentAppendOnlyChunkedList<>(CHUNK_SIZE);
      this.initialMessages = null;
   }

   public LivePageCacheImpl(final long pageId, PagedMessage[] initialMessages) {
      this.pageId = pageId;
      this.liveMessages = new ConcurrentAppendOnlyChunkedList<>(CHUNK_SIZE);
      this.initialMessages = initialMessages;
   }

   private int initialMessagesSize() {
      final PagedMessage[] initialMessages = this.initialMessages;
      return initialMessages == null ? 0 : initialMessages.length;
   }

   @Override
   public long getPageId() {
      return pageId;
   }

   @Override
   public int getNumberOfMessages() {
      return initialMessagesSize() + liveMessages.size();
   }

   @Override
   public PagedMessage getMessage(PagePosition pagePosition) {
      final int messageNr = pagePosition.getMessageNr();
      if (messageNr < 0) {
         return null;
      }
      final int initialOffset = initialMessagesSize();
      if (messageNr < initialOffset) {
         return initialMessages[messageNr];
      }
      final int index = messageNr - initialOffset;
      return liveMessages.get(index);
   }

   @Override
   public boolean isLive() {
      return isLive;
   }

   @Override
   public void addLiveMessage(PagedMessage message) {
      message.getMessage().usageUp();
      liveMessages.add(message);
   }

   @Override
   public void close() {
      logger.tracef("Closing %s", this);
      this.isLive = false;
   }

   @Override
   public PagedMessage[] getMessages() {
      final PagedMessage[] pagedMessages = liveMessages.toArray(size -> new PagedMessage[initialMessagesSize() + size], initialMessagesSize());
      final PagedMessage[] initialMessages = this.initialMessages;
      if (initialMessages != null) {
         System.arraycopy(initialMessages, 0, pagedMessages, 0, initialMessages.length);
      }
      return pagedMessages;
   }

   @Override
   public String toString() {
      return "LivePacheCacheImpl::page=" + pageId + " number of messages=" + getNumberOfMessages() + " isLive = " + isLive;
   }
}


<|start_filename|>artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/MechanismFinder.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.protocol.amqp.sasl;

import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.ServiceLoader;

public class MechanismFinder {

   private static final Map<String, ServerSASLFactory> FACTORY_MAP = new HashMap<>();
   private static final Comparator<? super ServerSASLFactory> PRECEDENCE_COMPARATOR =
      (f1, f2) -> Integer.compare(f1.getPrecedence(), f2.getPrecedence());
   private static final String[] DEFAULT_MECHANISMS;

   static {
      ServiceLoader<ServerSASLFactory> serviceLoader =
               ServiceLoader.load(ServerSASLFactory.class, MechanismFinder.class.getClassLoader());
      for (ServerSASLFactory factory : serviceLoader) {
         FACTORY_MAP.merge(factory.getMechanism(), factory, (f1, f2) -> {
            if (f2.getPrecedence() > f1.getPrecedence()) {
               return f2;
            } else {
               return f1;
            }
         });
      }
      DEFAULT_MECHANISMS = FACTORY_MAP.values()
                                      .stream()
                                      .filter(ServerSASLFactory::isDefaultPermitted)
                                      .sorted(PRECEDENCE_COMPARATOR.reversed())
                                      .map(ServerSASLFactory::getMechanism)
                                      .toArray(String[]::new);
   }

   public static String[] getDefaultMechanisms() {
      return DEFAULT_MECHANISMS;
   }

   public static ServerSASLFactory getFactory(String mechanism) {
      return FACTORY_MAP.get(mechanism);
   }
}


<|start_filename|>artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/v11/StompFrameHandlerV11.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.protocol.stomp.v11;

import static org.apache.activemq.artemis.core.protocol.stomp.ActiveMQStompProtocolMessageBundle.BUNDLE;

import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;

import org.apache.activemq.artemis.api.core.ActiveMQSecurityException;
import org.apache.activemq.artemis.core.protocol.stomp.ActiveMQStompException;
import org.apache.activemq.artemis.core.protocol.stomp.FrameEventListener;
import org.apache.activemq.artemis.core.protocol.stomp.SimpleBytes;
import org.apache.activemq.artemis.core.protocol.stomp.Stomp;
import org.apache.activemq.artemis.core.protocol.stomp.StompConnection;
import org.apache.activemq.artemis.core.protocol.stomp.StompDecoder;
import org.apache.activemq.artemis.core.protocol.stomp.StompFrame;
import org.apache.activemq.artemis.core.protocol.stomp.VersionedStompFrameHandler;
import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants;
import org.apache.activemq.artemis.core.remoting.server.impl.RemotingServiceImpl;
import org.apache.activemq.artemis.core.server.ActiveMQScheduledComponent;
import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
import org.apache.activemq.artemis.spi.core.protocol.ConnectionEntry;
import org.apache.activemq.artemis.utils.ExecutorFactory;

public class StompFrameHandlerV11 extends VersionedStompFrameHandler implements FrameEventListener {

   protected static final char ESC_CHAR = '\\';

   private HeartBeater heartBeater;

   public StompFrameHandlerV11(StompConnection connection,
                               ScheduledExecutorService scheduledExecutorService,
                               ExecutorFactory executorFactory) {
      super(connection, scheduledExecutorService, executorFactory);
      connection.addStompEventListener(this);
      decoder = new StompDecoderV11(this);
      decoder.init();
   }

   public ActiveMQScheduledComponent getHeartBeater() {
      return heartBeater;
   }

   @Override
   public StompFrame onConnect(StompFrame frame) {
      StompFrame response = null;
      Map<String, String> headers = frame.getHeadersMap();
      String login = headers.get(Stomp.Headers.Connect.LOGIN);
      String passcode = headers.get(Stomp.Headers.Connect.PASSCODE);
      String clientID = headers.get(Stomp.Headers.Connect.CLIENT_ID);
      String requestID = headers.get(Stomp.Headers.Connect.REQUEST_ID);

      try {
         connection.setClientID(clientID);
         connection.setLogin(login);
         connection.setPasscode(passcode);
         // Create session which will validate user - this will cache the session in the protocol manager
         connection.getSession();
         connection.setValid(true);

         response = this.createStompFrame(Stomp.Responses.CONNECTED);

         // version
         response.addHeader(Stomp.Headers.Connected.VERSION, connection.getVersion());

         // session
         response.addHeader(Stomp.Headers.Connected.SESSION, connection.getID().toString());

         // server
         Object disableServerHeader = connection.getAcceptorUsed().getConfiguration().get(TransportConstants.DISABLE_STOMP_SERVER_HEADER);
         if (disableServerHeader == null || !Boolean.parseBoolean(disableServerHeader.toString())) {
            response.addHeader(Stomp.Headers.Connected.SERVER, connection.getActiveMQServerName());
         }

         if (requestID != null) {
            response.addHeader(Stomp.Headers.Connected.RESPONSE_ID, requestID);
         }

         // heart-beat. We need to start after connected frame has been sent.
         // otherwise the client may receive heart-beat before it receives
         // connected frame.
         String heartBeat = headers.get(Stomp.Headers.Connect.HEART_BEAT);

         if (heartBeat != null) {
            handleHeartBeat(heartBeat);
            if (heartBeater == null) {
               response.addHeader(Stomp.Headers.Connected.HEART_BEAT, "0,0");
            } else {
               response.addHeader(Stomp.Headers.Connected.HEART_BEAT, heartBeater.serverPingPeriod + "," + heartBeater.clientPingResponse);
            }
         }
      } catch (ActiveMQSecurityException e) {
         response = getFailedAuthenticationResponse(login);
      } catch (ActiveMQStompException e) {
         response = e.getFrame();
      }

      return response;
   }

   @Override
   protected StompFrame getFailedAuthenticationResponse(String login) {
      StompFrame response = super.getFailedAuthenticationResponse(login);
      response.addHeader(Stomp.Headers.CONTENT_TYPE, "text/plain");
      return response;
   }

   private void handleHeartBeat(String heartBeatHeader) throws ActiveMQStompException {
      String[] params = heartBeatHeader.split(",");
      if (params.length != 2) {
         throw new ActiveMQStompException(connection, "Incorrect heartbeat header " + heartBeatHeader);
      }

      //client ping
      long minPingInterval = Long.valueOf(params[0]);
      //client receive ping
      long minAcceptInterval = Long.valueOf(params[1]);

      if (heartBeater == null) {
         heartBeater = new HeartBeater(scheduledExecutorService, executorFactory.getExecutor(), minPingInterval, minAcceptInterval);
      }
   }

   @Override
   public StompFrame onDisconnect(StompFrame frame) {
      disconnect();
      return null;
   }

   @Override
   protected void disconnect() {
      if (this.heartBeater != null) {
         heartBeater.shutdown();
      }
   }

   @Override
   public StompFrame onUnsubscribe(StompFrame request) {
      StompFrame response = null;
      //unsubscribe in 1.1 only needs id header
      String id = request.getHeader(Stomp.Headers.Unsubscribe.ID);
      String durableSubscriptionName = request.getHeader(Stomp.Headers.Unsubscribe.DURABLE_SUBSCRIBER_NAME);
      if (durableSubscriptionName == null) {
         durableSubscriptionName = request.getHeader(Stomp.Headers.Unsubscribe.DURABLE_SUBSCRIPTION_NAME);
      }
      if (durableSubscriptionName == null) {
         durableSubscriptionName = request.getHeader(Stomp.Headers.Unsubscribe.ACTIVEMQ_DURABLE_SUBSCRIPTION_NAME);
      }

      String subscriptionID = null;
      if (id != null) {
         subscriptionID = id;
      } else if (durableSubscriptionName == null) {
         response = BUNDLE.needSubscriptionID().setHandler(this).getFrame();
         return response;
      }

      try {
         connection.unsubscribe(subscriptionID, durableSubscriptionName);
      } catch (ActiveMQStompException e) {
         response = e.getFrame();
      }
      return response;
   }

   @Override
   public StompFrame onAck(StompFrame request) {
      StompFrame response = null;

      String messageID = request.getHeader(Stomp.Headers.Ack.MESSAGE_ID);
      String txID = request.getHeader(Stomp.Headers.TRANSACTION);
      String subscriptionID = request.getHeader(Stomp.Headers.Ack.SUBSCRIPTION);

      if (txID != null) {
         ActiveMQServerLogger.LOGGER.stompTXAckNorSupported();
      }

      if (subscriptionID == null) {
         response = BUNDLE.needSubscriptionID().setHandler(this).getFrame();
         return response;
      }

      try {
         connection.acknowledge(messageID, subscriptionID);
      } catch (ActiveMQStompException e) {
         response = e.getFrame();
      }

      return response;
   }

   @Override
   public StompFrame onStomp(StompFrame request) {
      if (!connection.isValid()) {
         return onConnect(request);
      }
      return null;
   }

   @Override
   public StompFrame onNack(StompFrame request) {
      //this eventually means discard the message (it never be redelivered again).
      //we can consider supporting redeliver to a different sub.
      return onAck(request);
   }

   @Override
   public void replySent(StompFrame reply) {
      if (reply.getCommand().equals(Stomp.Responses.CONNECTED)) {
         //kick off the pinger
         startHeartBeat();
      }

      if (reply.needsDisconnect()) {
         connection.disconnect(false);
      } else {
         //update ping
         if (heartBeater != null) {
            heartBeater.pinged();
         }
      }
   }

   private void startHeartBeat() {
      if (heartBeater != null && heartBeater.serverPingPeriod != 0) {
         heartBeater.start();
      }
   }

   public StompFrame createPingFrame() {
      StompFrame frame = createStompFrame(Stomp.Commands.STOMP);
      frame.setPing(true);
      return frame;
   }

   /*
    * HeartBeater functions:
    * (a) server ping: if server hasn't sent any frame within serverPingPeriod interval, send a ping
    * (b) configure connection ttl so that org.apache.activemq.artemis.core.remoting.server.impl.RemotingServiceImpl.FailureCheckAndFlushThread
    *     can deal with closing connections which go stale
    */
   private class HeartBeater extends ActiveMQScheduledComponent {

      private static final int MIN_SERVER_PING = 500;

      long serverPingPeriod = 0;
      long clientPingResponse;
      volatile boolean shutdown = false;
      AtomicLong lastPingTimestamp = new AtomicLong(0);
      ConnectionEntry connectionEntry;

      private HeartBeater(ScheduledExecutorService scheduledExecutorService,
                          Executor executor,
                          final long clientPing,
                          final long clientAcceptPing) {
         super(scheduledExecutorService, executor, clientAcceptPing > MIN_SERVER_PING ? clientAcceptPing : MIN_SERVER_PING, TimeUnit.MILLISECONDS, false);

         if (clientAcceptPing != 0) {
            serverPingPeriod = super.getPeriod();
         }

         connectionEntry = ((RemotingServiceImpl) connection.getManager().getServer().getRemotingService()).getConnectionEntry(connection.getID());

         if (connectionEntry != null) {
            String heartBeatToTtlModifierStr = (String) connection.getAcceptorUsed().getConfiguration().get(TransportConstants.HEART_BEAT_TO_CONNECTION_TTL_MODIFIER);
            double heartBeatToTtlModifier = heartBeatToTtlModifierStr == null ? 2 : Double.valueOf(heartBeatToTtlModifierStr);

            // the default response to the client
            clientPingResponse = (long) (connectionEntry.ttl / heartBeatToTtlModifier);

            if (clientPing != 0) {
               clientPingResponse = clientPing;
               String ttlMaxStr = (String) connection.getAcceptorUsed().getConfiguration().get(TransportConstants.CONNECTION_TTL_MAX);
               long ttlMax = ttlMaxStr == null ? Long.MAX_VALUE : Long.valueOf(ttlMaxStr);

               String ttlMinStr = (String) connection.getAcceptorUsed().getConfiguration().get(TransportConstants.CONNECTION_TTL_MIN);
               long ttlMin = ttlMinStr == null ? 1000 : Long.valueOf(ttlMinStr);

               /* The connection's TTL should be one of the following:
                *   1) clientPing * heartBeatToTtlModifier
                *   2) ttlMin
                *   3) ttlMax
                */
               long connectionTtl = (long) (clientPing * heartBeatToTtlModifier);
               if (connectionTtl < ttlMin) {
                  connectionTtl = ttlMin;
                  clientPingResponse = (long) (ttlMin / heartBeatToTtlModifier);
               } else if (connectionTtl > ttlMax) {
                  connectionTtl = ttlMax;
                  clientPingResponse = (long) (ttlMax / heartBeatToTtlModifier);
               }
               if (ActiveMQServerLogger.LOGGER.isDebugEnabled()) {
                  ActiveMQServerLogger.LOGGER.debug("Setting STOMP client TTL to: " + connectionTtl);
               }
               connectionEntry.ttl = connectionTtl;
            }
         }

      }

      public void shutdown() {
         this.stop();

      }

      public void pinged() {
         lastPingTimestamp.set(System.currentTimeMillis());
      }

      @Override
      public void run() {
         lastPingTimestamp.set(System.currentTimeMillis());
         connection.ping(createPingFrame());
      }
   }

   @Override
   public void requestAccepted(StompFrame request) {
   }

   @Override
   public StompFrame createStompFrame(String command) {
      return new StompFrameV11(command);
   }

   @Override
   public void initDecoder(VersionedStompFrameHandler existingHandler) {
      decoder.init(existingHandler.getDecoder());
   }

   protected class StompDecoderV11 extends StompDecoder {

      protected boolean isEscaping = false;
      protected SimpleBytes holder = new SimpleBytes(1024);

      public StompDecoderV11(StompFrameHandlerV11 handler) {
         super(handler);
      }

      @Override
      public void init(StompDecoder decoder) {
         this.data = decoder.data;
         this.workingBuffer = decoder.workingBuffer;
         this.pos = decoder.pos;
         this.command = decoder.command;
      }

      @Override
      public void init() {
         super.init();
         isEscaping = false;
         holder.reset();
      }

      @Override
      protected boolean parseCommand() throws ActiveMQStompException {
         int offset = 0;
         boolean nextChar = false;

         //check for ping
         // Some badly behaved STOMP clients add a \n *after* the terminating NUL char at the end of the
         // STOMP frame this can manifest as an extra \n at the beginning when the
         // next STOMP frame is read - we need to deal with this.
         // Besides, Stomp 1.2 allows for extra EOLs after NULL (i.e.
         // either "[\r]\n"s or "\n"s)
         while (true) {
            if (workingBuffer[offset] == NEW_LINE) {
               //client ping
               nextChar = false;
            } else if (workingBuffer[offset] == CR) {
               if (nextChar)
                  throw BUNDLE.invalidTwoCRs().setHandler(handler);
               nextChar = true;
            } else {
               break;
            }
            offset++;
            if (offset == data)
               return false; //no more bytes
         }

         if (nextChar) {
            throw BUNDLE.badCRs().setHandler(handler);
         }

         //if some EOLs have been processed, drop those bytes before parsing command
         if (offset > 0) {
            System.arraycopy(workingBuffer, offset, workingBuffer, 0, data - offset);
            data = data - offset;
            offset = 0;
         }

         if (data < 4) {
            // Need at least four bytes to identify the command
            // - up to 3 bytes for the command name + potentially another byte for a leading \n
            return false;
         }

         byte b = workingBuffer[offset];

         switch (b) {
            case A: {
               if (workingBuffer[offset + 1] == StompDecoder.B) {
                  if (!tryIncrement(offset + COMMAND_ABORT_LENGTH + eolLen)) {
                     return false;
                  }

                  // ABORT
                  command = COMMAND_ABORT;
               } else {
                  if (!tryIncrement(offset + COMMAND_ACK_LENGTH + eolLen)) {
                     return false;
                  }

                  // ACK
                  command = COMMAND_ACK;
               }
               break;
            }
            case B: {
               if (!tryIncrement(offset + COMMAND_BEGIN_LENGTH + eolLen)) {
                  return false;
               }

               // BEGIN
               command = COMMAND_BEGIN;

               break;
            }
            case C: {
               if (workingBuffer[offset + 2] == M) {
                  if (!tryIncrement(offset + COMMAND_COMMIT_LENGTH + eolLen)) {
                     return false;
                  }

                  // COMMIT
                  command = COMMAND_COMMIT;
               } else if (workingBuffer[offset + 7] == E) {
                  if (!tryIncrement(offset + COMMAND_CONNECTED_LENGTH + eolLen)) {
                     return false;
                  }

                  // CONNECTED
                  command = COMMAND_CONNECTED;
               } else {
                  if (!tryIncrement(offset + COMMAND_CONNECT_LENGTH + eolLen)) {
                     return false;
                  }

                  // CONNECT
                  command = COMMAND_CONNECT;
               }
               break;
            }
            case D: {
               if (!tryIncrement(offset + COMMAND_DISCONNECT_LENGTH + eolLen)) {
                  return false;
               }

               // DISCONNECT
               command = COMMAND_DISCONNECT;

               break;
            }
            case R: {
               if (!tryIncrement(offset + COMMAND_RECEIPT_LENGTH + eolLen)) {
                  return false;
               }

               // RECEIPT
               command = COMMAND_RECEIPT;

               break;
            }
            /**** added by meddy, 27 april 2011, handle header parser for reply to websocket protocol ****/
            case E: {
               if (!tryIncrement(offset + COMMAND_ERROR_LENGTH + eolLen)) {
                  return false;
               }

               // ERROR
               command = COMMAND_ERROR;

               break;
            }
            case M: {
               if (!tryIncrement(offset + COMMAND_MESSAGE_LENGTH + eolLen)) {
                  return false;
               }

               // MESSAGE
               command = COMMAND_MESSAGE;

               break;
            }
            /**** end ****/
            case S: {
               if (workingBuffer[offset + 1] == E) {
                  if (!tryIncrement(offset + COMMAND_SEND_LENGTH + eolLen)) {
                     return false;
                  }

                  // SEND
                  command = COMMAND_SEND;
               } else if (workingBuffer[offset + 1] == U) {
                  if (!tryIncrement(offset + COMMAND_SUBSCRIBE_LENGTH + eolLen)) {
                     return false;
                  }

                  // SUBSCRIBE
                  command = COMMAND_SUBSCRIBE;
               } else {
                  if (!tryIncrement(offset + StompDecoder.COMMAND_STOMP_LENGTH + eolLen)) {
                     return false;
                  }

                  // SUBSCRIBE
                  command = COMMAND_STOMP;
               }
               break;
            }
            case U: {
               if (!tryIncrement(offset + COMMAND_UNSUBSCRIBE_LENGTH + eolLen)) {
                  return false;
               }

               // UNSUBSCRIBE
               command = COMMAND_UNSUBSCRIBE;

               break;
            }
            case N: {
               if (!tryIncrement(offset + COMMAND_NACK_LENGTH + eolLen)) {
                  return false;
               }
               //NACK
               command = COMMAND_NACK;
               break;
            }
            default: {
               throwInvalid();
            }
         }

         checkEol();

         return true;
      }

      protected void checkEol() throws ActiveMQStompException {
         if (workingBuffer[pos - 1] != NEW_LINE) {
            throwInvalid();
         }
      }

      protected void throwUndefinedEscape(byte b) throws ActiveMQStompException {
         ActiveMQStompException error = BUNDLE.undefinedEscapeSequence(new String(new char[]{ESC_CHAR, (char) b})).setHandler(handler);
         error.setCode(ActiveMQStompException.UNDEFINED_ESCAPE);
         throw error;
      }

      @Override
      protected boolean parseHeaders() throws ActiveMQStompException {

      outer:
         while (true) {
            byte b = workingBuffer[pos++];

            switch (b) {
               //escaping
               case ESC_CHAR: {
                  if (isEscaping) {
                     //this is a backslash
                     holder.append(b);
                     isEscaping = false;
                  } else {
                     //begin escaping
                     isEscaping = true;
                  }
                  break;
               }
               case HEADER_SEPARATOR: {
                  if (inHeaderName) {
                     headerName = holder.getString();

                     holder.reset();

                     inHeaderName = false;

                     headerValueWhitespace = true;
                  }

                  whiteSpaceOnly = false;

                  break;
               }
               case StompDecoder.LN: {
                  if (isEscaping) {
                     holder.append(StompDecoder.NEW_LINE);
                     isEscaping = false;
                  } else {
                     holder.append(b);
                  }
                  break;
               }
               case StompDecoder.c: {
                  if (isEscaping) {
                     holder.append(StompDecoder.HEADER_SEPARATOR);
                     isEscaping = false;
                  } else {
                     holder.append(b);
                  }
                  break;
               }
               case StompDecoder.NEW_LINE: {
                  if (whiteSpaceOnly) {
                     // Headers are terminated by a blank line
                     readingHeaders = false;

                     break outer;
                  }

                  String headerValue = holder.getString();
                  holder.reset();

                  headers.put(headerName, headerValue);

                  if (headerName.equals(Stomp.Headers.CONTENT_LENGTH)) {
                     contentLength = Integer.parseInt(headerValue);
                  }

                  if (headerName.equals(Stomp.Headers.CONTENT_TYPE)) {
                     contentType = headerValue;
                  }

                  whiteSpaceOnly = true;

                  inHeaderName = true;

                  headerValueWhitespace = false;

                  break;
               }
               default: {
                  whiteSpaceOnly = false;

                  headerValueWhitespace = false;

                  if (isEscaping) {
                     throwUndefinedEscape(b);
                  }
                  holder.append(b);
               }
            }
            if (pos == data) {
               // Run out of data
               return false;
            }
         }
         return true;
      }

      @Override
      protected StompFrame parseBody() throws ActiveMQStompException {
         byte[] content = null;

         if (contentLength != -1) {
            if (pos + contentLength + 1 > data) {
               // Need more bytes
            } else {
               content = new byte[contentLength];

               System.arraycopy(workingBuffer, pos, content, 0, contentLength);

               pos += contentLength;

               //drain all the rest
               if (bodyStart == -1) {
                  bodyStart = pos;
               }

               while (pos < data) {
                  if (workingBuffer[pos++] == 0) {
                     break;
                  }
               }
            }
         } else {
            // Need to scan for terminating NUL

            if (bodyStart == -1) {
               bodyStart = pos;
            }

            while (pos < data) {
               if (workingBuffer[pos++] == 0) {
                  content = new byte[pos - bodyStart - 1];

                  System.arraycopy(workingBuffer, bodyStart, content, 0, content.length);

                  break;
               }
            }
         }

         if (content != null) {
            if (data > pos) {
               if (workingBuffer[pos] == NEW_LINE)
                  pos++;

               if (data > pos)
                  // More data still in the buffer from the next packet
                  System.arraycopy(workingBuffer, pos, workingBuffer, 0, data - pos);
            }

            data = data - pos;

            // reset

            StompFrame ret = new StompFrameV11(command, headers, content);

            init();

            return ret;
         } else {
            return null;
         }
      }
   }
}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ConnectionView.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.management.impl.view;

import javax.json.JsonObjectBuilder;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.core.management.impl.view.predicate.ConnectionFilterPredicate;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.ServerSession;
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.utils.JsonLoader;
import org.apache.activemq.artemis.utils.StringUtil;

public class ConnectionView extends ActiveMQAbstractView<RemotingConnection> {

   private static final String defaultSortColumn = ConnectionField.CONNECTION_ID.getName();

   private final ActiveMQServer server;

   public ConnectionView(ActiveMQServer server) {
      super();
      this.server = server;
      this.predicate = new ConnectionFilterPredicate(server);
   }

   @Override
   public Class getClassT() {
      return RemotingConnection.class;
   }

   @Override
   public JsonObjectBuilder toJson(RemotingConnection connection) {

      List<ServerSession> sessions = server.getSessions(connection.getID().toString());
      Set<String> users = new TreeSet<>();
      String jmsSessionClientID = null;
      for (ServerSession session : sessions) {
         String username = session.getUsername() == null ? "" : session.getUsername();
         users.add(username);
         //for the special case for JMS
         if (session.getMetaData(ClientSession.JMS_SESSION_IDENTIFIER_PROPERTY) != null) {
            jmsSessionClientID = session.getMetaData("jms-client-id");
         }
      }

      return JsonLoader.createObjectBuilder()
         .add(ConnectionField.CONNECTION_ID.getName(), toString(connection.getID()))
         .add(ConnectionField.REMOTE_ADDRESS.getName(), toString(connection.getRemoteAddress()))
         .add(ConnectionField.USERS.getName(), StringUtil.joinStringList(users, ","))
         .add(ConnectionField.CREATION_TIME.getName(), new Date(connection.getCreationTime()).toString())
         .add(ConnectionField.IMPLEMENTATION.getName(), toString(connection.getClass().getSimpleName()))
         .add(ConnectionField.PROTOCOL.getName(), toString(connection.getProtocolName()))
         .add(ConnectionField.CLIENT_ID.getName(), toString(connection.getClientID() != null ? connection.getClientID() : jmsSessionClientID))
         .add(ConnectionField.LOCAL_ADDRESS.getName(), toString(connection.getTransportLocalAddress()))
         .add(ConnectionField.SESSION_COUNT.getName(), sessions.size());
   }

   @Override
   public Object getField(RemotingConnection connection, String fieldName) {
      ConnectionField field = ConnectionField.valueOfName(fieldName);

      switch (field) {
         case CONNECTION_ID:
            return connection.getID();
         case REMOTE_ADDRESS:
            return connection.getRemoteAddress();
         case USERS:
            Set<String> users = new TreeSet<>();
            List<ServerSession> sessions = server.getSessions(connection.getID().toString());
            for (ServerSession session : sessions) {
               String username = session.getUsername() == null ? "" : session.getUsername();
               users.add(username);
            }
            return StringUtil.joinStringList(users, ",");
         case CREATION_TIME:
            return new Date(connection.getCreationTime());
         case IMPLEMENTATION:
            return connection.getClass().getSimpleName();
         case PROTOCOL:
            return connection.getProtocolName();
         case CLIENT_ID:
            return connection.getClientID();
         case LOCAL_ADDRESS:
            return connection.getTransportLocalAddress();
         case SESSION_COUNT:
            return server.getSessions(connection.getID().toString()).size();
         default:
            throw new IllegalArgumentException("Unsupported field, " + fieldName);
      }
   }

   @Override
   public String getDefaultOrderColumn() {
      return defaultSortColumn;
   }
}


<|start_filename|>artemis-rest/src/test/java/org/apache/activemq/artemis/rest/test/MessageTestBase.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.rest.test;

import java.lang.reflect.Field;

import org.apache.activemq.artemis.rest.MessageServiceManager;
import org.apache.activemq.artemis.rest.util.LinkHeaderLinkStrategy;
import org.apache.activemq.artemis.rest.util.LinkStrategy;
import org.jboss.resteasy.client.ClientExecutor;
import org.jboss.resteasy.client.ClientResponse;
import org.jboss.resteasy.client.core.BaseClientResponse;
import org.jboss.resteasy.spi.Link;
import org.junit.AfterClass;
import org.junit.BeforeClass;

public class MessageTestBase {

   public static EmbeddedTestServer server;
   public static MessageServiceManager manager;
   private static Field executorField;

   static {
      try {
         executorField = BaseClientResponse.class.getDeclaredField("executor");
      } catch (NoSuchFieldException e) {
         throw new RuntimeException(e);
      }
      executorField.setAccessible(true);
   }

   @BeforeClass
   public static void setupActiveMQServerAndManager() throws Exception {
      server = new EmbeddedTestServer();
      server.start();
      manager = server.getManager();
   }

   @AfterClass
   public static void shutdownActiveMQServerAndManager() throws Exception {
      manager = null;
      server.stop();
      server = null;
   }

   public static Link getLinkByTitle(LinkStrategy strategy, ClientResponse response, String title) {
      if (strategy instanceof LinkHeaderLinkStrategy) {
         return response.getLinkHeader().getLinkByTitle(title);
      } else {
         String headerName = "msg-" + title;
         String href = (String) response.getHeaders().getFirst(headerName);
         if (href == null)
            return null;
         //log.debug(headerName + ": " + href);
         Link l = new Link(title, null, href, null, null);
         try {
            l.setExecutor((ClientExecutor) executorField.get(response));
         } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
         }
         return l;
      }
   }

}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/config/brokerConnectivity/BrokerConnectConfiguration.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.config.brokerConnectivity;

import java.io.Serializable;

/** This is an extension point for outgoing broker configuration.
 *  This is a new feature that at the time we introduced, is only being used for AMQP.
 *  Where the broker will create a connection towards another broker using a specific protocol.
 *  */
public abstract class BrokerConnectConfiguration implements Serializable {
   private static final long serialVersionUID = 8026604526022462048L;

   private String name;
   private String uri;
   private String user;
   private String password;
   private int reconnectAttempts = -1;
   private int retryInterval = 5000;
   private boolean autostart = true;

   public BrokerConnectConfiguration(String name, String uri) {
      this.name = name;
      this.uri = uri;
   }

   public abstract void parseURI() throws Exception;



   public int getReconnectAttempts() {
      return reconnectAttempts;
   }

   public BrokerConnectConfiguration setReconnectAttempts(int reconnectAttempts) {
      this.reconnectAttempts = reconnectAttempts;
      return this;
   }


   public String getUser() {
      return user;
   }

   public BrokerConnectConfiguration setUser(String user) {
      this.user = user;
      return this;
   }


   public String getPassword() {
      return password;
   }

   public BrokerConnectConfiguration setPassword(String password) {
      this.password = password;
      return this;
   }

   public int getRetryInterval() {
      return retryInterval;
   }

   public BrokerConnectConfiguration setRetryInterval(int retryInterval) {
      this.retryInterval = retryInterval;
      return this;
   }

   public String getUri() {
      return uri;
   }

   public BrokerConnectConfiguration setUri(String uri) {
      this.uri = uri;
      return this;
   }


   public String getName() {
      return name;
   }

   public BrokerConnectConfiguration setName(String name) {
      this.name = name;
      return this;
   }

   public boolean isAutostart() {
      return autostart;
   }

   public BrokerConnectConfiguration setAutostart(boolean autostart) {
      this.autostart = autostart;
      return this;
   }
}


<|start_filename|>examples/features/standard/security-keycloak/src/main/java/org/apache/activemq/artemis/jms/example/KeycloakSecurityExample.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.jms.example;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.Session;
import javax.jms.Queue;
import javax.naming.InitialContext;

import java.util.concurrent.TimeUnit;

public class KeycloakSecurityExample {

   public static void main(final String[] args) throws Exception {

      boolean result = true;
      Connection connection = null;

      InitialContext initialContext = null;

      try {
         // Step 1. Create an initial context to perform the JNDI lookup.
         initialContext = new InitialContext();

         // Step 2. perform lookup on the topics
         Queue genericTopic = (Queue) initialContext.lookup("queue/Info");

         // Step 3. perform a lookup on the Connection Factory
         ConnectionFactory cf = (ConnectionFactory) initialContext.lookup("ConnectionFactory");


         // Step 4. block till we make a connection as mdoe
         System.out.println("------------------------blocking on connection creation----------------");

         while (connection == null) {
            try {
               connection = createConnection("mdoe", "password", cf);
               connection.start();
            } catch (JMSException expectedTillInfraStarted) {
               System.out.println("---- expected error on connect till broker starts: " + expectedTillInfraStarted + ", retry in 10s");
               TimeUnit.SECONDS.sleep(10);
            }
         }

         // Step 5. block till we get a message
         System.out.println("------------------------blocking on message receipt from console----------------");
         System.out.println("------------------------send to address Info as user: jdoe password: password----------------");

         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
         MessageConsumer consumer = session.createConsumer(genericTopic);

         Message receivedMsg = null;
         while (receivedMsg == null) {
            receivedMsg = consumer.receive(10000);
            if (receivedMsg != null) {
               String validatedUser = receivedMsg.getStringProperty(org.apache.activemq.artemis.api.core.Message.HDR_VALIDATED_USER.toString());
               System.out.println("---------------------from: " + validatedUser + " -------------------------");
               System.out.println("---------------------reveived: " + receivedMsg);
               System.out.println("---------------------all done!------------------------------------------");
            }
         }

         session.close();

         System.out.println("-------------------------------------------------------------------------------------");

      } finally {
         if (connection != null) {
            connection.close();
         }
      }
   }

   private static Connection createConnection(final String username,
                                              final String password,
                                              final ConnectionFactory cf) throws JMSException {
      return cf.createConnection(username, password);
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cli/RecoverTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.tests.integration.cli;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;

import org.apache.activemq.artemis.cli.commands.tools.RecoverMessages;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.server.JournalType;
import org.apache.activemq.artemis.nativo.jlibaio.LibaioContext;
import org.apache.activemq.artemis.tests.util.CFUtil;
import org.apache.activemq.artemis.tests.util.JMSTestBase;
import org.apache.activemq.artemis.utils.Wait;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class RecoverTest extends JMSTestBase {

   boolean useTX;
   String protocol;
   boolean paging;
   boolean large;
   String journalType;

   public RecoverTest(boolean useTX, String protocol, boolean paging, boolean large, String journalType) {
      this.useTX = useTX;
      this.protocol = protocol;
      this.paging = paging;
      this.large = large;
      this.journalType = journalType;
   }

   @Parameterized.Parameters(name = "useTX={0}, protocol={1}, paging={2}, largeMessage={3}, journal-type={4}")
   public static Collection<Object[]> data() {
      Object[] journalType;
      if (LibaioContext.isLoaded()) {
         journalType = new Object[]{"AIO", "NIO", "MAPPED"};
      } else {
         journalType = new Object[]{"NIO", "MAPPED"};
      }
      return combine(new Object[]{true, false}, new Object[]{"AMQP", "CORE", "OPENWIRE"}, new Object[]{true, false}, new Object[]{true, false}, journalType);
   }

   protected static Collection<Object[]> combine(Object[] one, Object[] two, Object[] three, Object[] four, Object[] five) {
      ArrayList<Object[]> combinations = new ArrayList<>();
      for (Object o1 : one) {
         for (Object o2 : two) {
            for (Object o3 : three) {
               for (Object o4 : four) {
                  for (Object o5 : five) {
                     combinations.add(new Object[]{o1, o2, o3, o4, o5});
                  }
               }
            }
         }
      }

      return combinations;
   }

   @Override
   protected Configuration createDefaultConfig(boolean netty) throws Exception {
      Configuration configuration = super.createDefaultConfig(netty).setJMXManagementEnabled(true);
      configuration.setJournalRetentionDirectory(getTestDir() + "/historyJournal");
      switch (journalType) {
         case "NIO":
            configuration.setJournalType(JournalType.NIO);
            break;
         case "MAPPED":
            configuration.setJournalType(JournalType.MAPPED);
            break;
         case "AIO":
            configuration.setJournalType(JournalType.ASYNCIO);
            break;
      }
      return configuration;
   }

   @Override
   protected boolean usePersistence() {
      return true;
   }

   @Test
   public void testRecover() throws Exception {

      createQueue(true, "TestQueue");
      org.apache.activemq.artemis.core.server.Queue serverQueue = server.locateQueue("TestQueue");
      if (paging) {
         serverQueue.getPagingStore().startPaging();
      }
      ConnectionFactory factory = CFUtil.createConnectionFactory(protocol, "tcp://localhost:61616");
      Connection connection = factory.createConnection();
      Session session = connection.createSession(useTX, useTX ? Session.SESSION_TRANSACTED : Session.AUTO_ACKNOWLEDGE);
      Queue queue = session.createQueue("TestQueue");
      MessageProducer producer = session.createProducer(queue);
      String messageBody;
      {
         StringBuffer stringBuffer = new StringBuffer();
         if (large) {
            int i = 0;
            while (stringBuffer.length() < 110 * 1024) {
               //stringBuffer.append("this is " + (i++));
               stringBuffer.append(" ");
            }
         } else {
            stringBuffer.append("hello");
         }
         messageBody = stringBuffer.toString();
      }
      int maxMessage = large ? 10 : 1000;
      for (int i = 0; i < maxMessage; i++) {
         producer.send(session.createTextMessage(i + messageBody));
      }

      if (useTX) {
         session.commit();
      }

      // Using compacting here, will kind of duplicate all the records into reclaimed files
      // this might cause extra challenges on recovering the data
      server.getStorageManager().getMessageJournal().scheduleCompactAndBlock(60_000);

      MessageConsumer consumer = session.createConsumer(queue);
      connection.start();

      for (int i = 0; i < maxMessage; i++) {
         TextMessage message = (TextMessage) consumer.receive(5000);
         Assert.assertNotNull(message);
         if (!protocol.equals("OPENWIRE")) {
            // openwire won't support large message or its conversions
            Assert.assertEquals(i + messageBody, message.getText());
         }
      }

      if (useTX) {
         session.commit();
      }

      connection.close();

      // need to wait no paging, otherwise an eventual page cleanup would remove large message bodies from the recovery
      Wait.assertFalse(serverQueue.getPagingStore()::isPaging);

      server.stop();

      File newJournalLocation = new File(server.getConfiguration().getJournalLocation().getParentFile(), "recovered");

      RecoverMessages.recover(server.getConfiguration(), server.getConfiguration().getJournalRetentionDirectory(), newJournalLocation, server.getConfiguration().getLargeMessagesLocation(), false);

      if (large) {
         File[] largeMessageFiles = server.getConfiguration().getLargeMessagesLocation().listFiles();
         Assert.assertEquals(maxMessage, largeMessageFiles.length);
         for (File f : largeMessageFiles) {
            Assert.assertTrue("File length was " + f.length(), f.length() > 0);
         }
      }

      server.getConfiguration().setJournalDirectory(newJournalLocation.getAbsolutePath());

      server.start();

      factory = CFUtil.createConnectionFactory(protocol, "tcp://localhost:61616");
      connection = factory.createConnection();
      session = connection.createSession(useTX, useTX ? Session.SESSION_TRANSACTED : Session.AUTO_ACKNOWLEDGE);

      connection.start();

      consumer = session.createConsumer(queue);

      for (int i = 0; i < maxMessage; i++) {
         TextMessage message = (TextMessage) consumer.receive(5000);
         Assert.assertNotNull(message);
         if (!protocol.equals("OPENWIRE")) {
            // openwire won't support large message or its conversions
            Assert.assertEquals(i + messageBody, message.getText());
         }
      }

      Assert.assertNull(consumer.receiveNoWait());

      if (useTX) {
         session.commit();
      }

      connection.close();
   }

}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/AmqpReferenceDeliveryAnnotationTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.amqp;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.MessageReference;
import org.apache.activemq.artemis.core.server.ServerConsumer;
import org.apache.activemq.artemis.core.server.plugin.ActiveMQServerMessagePlugin;
import org.apache.activemq.artemis.tests.util.RandomUtil;
import org.apache.activemq.transport.amqp.client.AmqpClient;
import org.apache.activemq.transport.amqp.client.AmqpConnection;
import org.apache.activemq.transport.amqp.client.AmqpMessage;
import org.apache.activemq.transport.amqp.client.AmqpReceiver;
import org.apache.activemq.transport.amqp.client.AmqpSender;
import org.apache.activemq.transport.amqp.client.AmqpSession;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.messaging.DeliveryAnnotations;
import org.junit.Assert;
import org.junit.Test;

/**
 * Test broker behavior when creating AMQP senders
 */
public class AmqpReferenceDeliveryAnnotationTest extends AmqpClientTestSupport {

   @Override
   protected void addAdditionalAcceptors(ActiveMQServer server) throws Exception {
   }

   @Test
   public void testReceiveAnnotations() throws Exception {
      internalReceiveAnnotations(false, false);
   }

   @Test
   public void testReceiveAnnotationsLargeMessage() throws Exception {
      internalReceiveAnnotations(true, false);
   }

   @Test
   public void testReceiveAnnotationsReboot() throws Exception {
      internalReceiveAnnotations(false, true);
   }

   @Test
   public void testReceiveAnnotationsLargeMessageReboot() throws Exception {
      internalReceiveAnnotations(true, true);
   }

   public void internalReceiveAnnotations(boolean largeMessage, boolean reboot) throws Exception {

      final String uuid = RandomUtil.randomString();

      server.getConfiguration().registerBrokerPlugin(new ActiveMQServerMessagePlugin() {

         @Override
         public void beforeDeliver(ServerConsumer consumer, MessageReference reference) throws ActiveMQException {
            Map<Symbol, Object> symbolObjectMap = new HashMap<>();
            DeliveryAnnotations deliveryAnnotations = new DeliveryAnnotations(symbolObjectMap);
            symbolObjectMap.put(Symbol.getSymbol("KEY"), uuid);
            reference.setProtocolData(deliveryAnnotations);
         }
      });

      AmqpClient client = createAmqpClient();
      AmqpConnection connection = addConnection(client.connect());
      AmqpSession session = connection.createSession();

      AmqpSender sender = session.createSender(getQueueName());

      AmqpMessage message = new AmqpMessage();

      String body;
      if (largeMessage) {
         StringBuffer buffer = new StringBuffer();
         for (int i = 0; i < 1024 * 1024; i++) {
            buffer.append("*");
         }
         body = buffer.toString();
      } else {
         body = "test-message";
      }

      message.setMessageId("msg" + 1);
      message.setText(body);
      message.setDurable(true);
      sender.send(message);

      message = new AmqpMessage();
      message.setMessageId("msg" + 2);
      message.setDurable(true);
      message.setText(body);
      sender.send(message);
      sender.close();

      if (reboot) {
         connection.close();
         server.stop();
         server.start();
         client = createAmqpClient();
         connection = addConnection(client.connect());
         session = connection.createSession();
      }

      AmqpReceiver receiver = session.createReceiver(getQueueName());
      receiver.flow(2);
      AmqpMessage received = receiver.receive(10, TimeUnit.SECONDS);
      assertNotNull("Should have read message", received);
      assertEquals("msg1", received.getMessageId());
      assertEquals(uuid, received.getDeliveryAnnotation("KEY"));
      received.accept();

      received = receiver.receive(10, TimeUnit.SECONDS);
      assertNotNull("Should have read message", received);
      assertEquals("msg2", received.getMessageId());
      assertEquals(uuid, received.getDeliveryAnnotation("KEY"));
      received.accept();

      Assert.assertNull(receiver.receiveNoWait());

      receiver.close();

      connection.close();
   }
}

<|start_filename|>tests/performance-jmh/src/main/java/org/apache/activemq/artemis/tests/performance/jmh/DuplicateIDCacheBenchmark.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.performance.jmh;

import java.util.SplittableRandom;

import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.persistence.impl.nullpm.NullStorageManager;
import org.apache.activemq.artemis.core.postoffice.DuplicateIDCache;
import org.apache.activemq.artemis.core.postoffice.impl.DuplicateIDCaches;
import org.apache.activemq.artemis.utils.RandomUtil;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.TearDown;
import org.openjdk.jmh.annotations.Warmup;

@State(Scope.Benchmark)
@Fork(2)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 8, time = 1)
public class DuplicateIDCacheBenchmark {

   @Param({"20000"})
   private int size;
   @Param({"false", "true"})
   private boolean persist;

   private DuplicateIDCache cache;

   private byte[][] ids;
   private int idsMask;
   private int missingIdsMask;
   private long nextId;
   private byte[][] randomEvictedIds;

   @Setup
   public void init() throws Exception {
      cache = persist ?
         DuplicateIDCaches.persistent(SimpleString.toSimpleString("benchmark"), size, new NullStorageManager()) :
         DuplicateIDCaches.inMemory(SimpleString.toSimpleString("benchmark"), size);
      final int idSize = findNextHigherPowerOf2(size);
      idsMask = idSize - 1;
      nextId = 0;
      ids = new byte[idSize][];
      // fill the cache
      for (int i = 0; i < size; i++) {
         final byte[] id = RandomUtil.randomBytes();
         ids[i] = id;
         cache.addToCache(id, null, true);
      }
      // evict the first (idSize - size) elements on the ids array.
      // Given that being a FIFO cache isn't a stable contract it's going to validate it too.
      final int evicted = idSize - size;
      for (int i = 0; i < evicted; i++) {
         final byte[] id = RandomUtil.randomBytes();
         ids[size + i] = id;
         cache.addToCache(id, null, true);
         // check correctness of eviction policy
         if (cache.contains(ids[i])) {
            throw new AssertionError("This cache isn't using anymore a FIFO eviction strategy or its real capacity is > " + size);
         }
      }
      // always use the same seed!
      SplittableRandom random = new SplittableRandom(0);
      // set it big enough to trick branch predictors
      final int evictedIdsLength = findNextPowerOf2(Math.max(1024, evicted));
      missingIdsMask = evictedIdsLength - 1;
      randomEvictedIds = new byte[evictedIdsLength][];
      for (int i = 0; i < evictedIdsLength; i++) {
         final int id = random.nextInt(0, evicted);
         randomEvictedIds[i] = ids[id];
         // check correctness of eviction policy
         if (cache.contains(ids[id])) {
            throw new AssertionError("This cache isn't using anymore a FIFO eviction strategy");
         }
      }
   }

   // it isn't checking what's the max power of 2 number nor if size > 0
   private static int findNextHigherPowerOf2(int size) {
      final int nextPow2 = findNextPowerOf2(size);
      if (nextPow2 > size) {
         return nextPow2;
      }
      return nextPow2 * 2;
   }

   private static int findNextPowerOf2(int size) {
      return 1 << (32 - Integer.numberOfLeadingZeros(size - 1));
   }

   private byte[] nextId() {
      final long seq = nextId;
      final int index = (int) (seq & idsMask);
      nextId = seq + 1;
      return ids[index];
   }

   private byte[] nextMissingId() {
      final long seq = nextId;
      final int index = (int) (seq & missingIdsMask);
      nextId = seq + 1;
      return randomEvictedIds[index];
   }

   @Benchmark
   public boolean atomicVerify() throws Exception {
      return cache.atomicVerify(nextId(), null);
   }

   @Benchmark
   public boolean containsMissingId() {
      return cache.contains(nextMissingId());
   }

   @TearDown
   public void clear() throws Exception {
      cache.clear();
   }

}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/discovery/DiscoveryTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.discovery;

import java.io.File;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.List;
import java.util.concurrent.TimeUnit;

import org.apache.activemq.artemis.api.core.BroadcastEndpoint;
import org.apache.activemq.artemis.api.core.BroadcastEndpointFactory;
import org.apache.activemq.artemis.api.core.JGroupsFileBroadcastEndpointFactory;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.core.UDPBroadcastEndpointFactory;
import org.apache.activemq.artemis.api.core.jgroups.JChannelManager;
import org.apache.activemq.artemis.api.core.management.CoreNotificationType;
import org.apache.activemq.artemis.core.cluster.DiscoveryEntry;
import org.apache.activemq.artemis.core.cluster.DiscoveryGroup;
import org.apache.activemq.artemis.core.server.ActiveMQComponent;
import org.apache.activemq.artemis.core.server.cluster.BroadcastGroup;
import org.apache.activemq.artemis.core.server.cluster.impl.BroadcastGroupImpl;
import org.apache.activemq.artemis.core.server.management.Notification;
import org.apache.activemq.artemis.tests.integration.SimpleNotificationService;
import org.apache.activemq.artemis.utils.RandomUtil;
import org.apache.activemq.artemis.utils.UUIDGenerator;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

/**
 * This will test Discovery test on JGroups and UDP.
 * <br>
 * In some configurations IPV6 may be a challenge. To make sure this test works, you may add this
 * property to your JVM settings: {@literal -Djgroups.bind_addr=::1}
 * <br>
 * Or ultimately you may also turn off IPV6: {@literal -Djava.net.preferIPv4Stack=true}
 * <br>
 * Note when you are not sure about your IP settings of your test machine, you should make sure
 * that the jgroups.bind_addr and java.net.preferXXStack by defining them explicitly, for example
 * if you would like to use IPV6, set BOTH properties to your JVM like the following:
 * -Djgroups.bind_addr=::1 -Djava.net.preferIPv6Addresses=true
 * <br>
 * or if you prefer IPV4:
 * -Djgroups.bind_addr=localhost -Djava.net.preferIPv4Stack=true
 * <br>
 * Also: Make sure you add integration-tests/src/tests/resources to your project path on the
 * tests/integration-tests
 */
public class DiscoveryTest extends DiscoveryBaseTest {

   private static final String TEST_JGROUPS_CONF_FILE = "test-jgroups-file_ping.xml";

   BroadcastGroup bg = null, bg1 = null, bg2 = null, bg3 = null;
   DiscoveryGroup dg = null, dg1 = null, dg2 = null, dg3 = null;

   @Before
   public void prepareLoopback() {
      JChannelManager.getInstance().setLoopbackMessages(true);
   }

   @Override
   @After
   public void tearDown() throws Exception {
      JChannelManager.getInstance().clear().setLoopbackMessages(false);
      /** This file path is defined at {@link #TEST_JGROUPS_CONF_FILE} */
      deleteDirectory(new File("./target/tmp/amqtest.ping.dir"));
      for (ActiveMQComponent component : new ActiveMQComponent[]{bg, bg1, bg2, bg3, dg, dg1, dg2, dg3}) {
         stopComponent(component);
      }
      super.tearDown();
   }

   @Test
   public void testSimpleBroadcast() throws Exception {
      final InetAddress groupAddress = InetAddress.getByName(address1);
      final int groupPort = getUDPDiscoveryPort();
      final int timeout = 500;

      final String nodeID = RandomUtil.randomString();

      bg = new BroadcastGroupImpl(new FakeNodeManager(nodeID), RandomUtil.randomString(), 0, null, new UDPBroadcastEndpointFactory().setGroupAddress(address1).setGroupPort(groupPort));

      bg.start();

      TransportConfiguration live1 = generateTC();

      bg.addConnector(live1);

      dg = newDiscoveryGroup(RandomUtil.randomString(), RandomUtil.randomString(), null, groupAddress, groupPort, timeout);

      dg.start();

      verifyBroadcast(bg, dg);

      List<DiscoveryEntry> entries = dg.getDiscoveryEntries();
      assertEqualsDiscoveryEntries(Arrays.asList(live1), entries);
   }

   @Test
   public void testSimpleBroadcastJGropus() throws Exception {
      final String nodeID = RandomUtil.randomString();

      bg = new BroadcastGroupImpl(new FakeNodeManager(nodeID), "broadcast", 100, null, new JGroupsFileBroadcastEndpointFactory().setChannelName("tst").setFile(TEST_JGROUPS_CONF_FILE));

      bg.start();

      TransportConfiguration live1 = generateTC();

      bg.addConnector(live1);

      dg = new DiscoveryGroup(nodeID + "1", "broadcast", 5000L, new JGroupsFileBroadcastEndpointFactory().setChannelName("tst").setFile(TEST_JGROUPS_CONF_FILE), null);

      dg.start();

      verifyBroadcast(bg, dg);
      List<DiscoveryEntry> entries = dg.getDiscoveryEntries();
      assertEqualsDiscoveryEntries(Arrays.asList(live1), entries);
   }

   /**
    * Create one broadcaster and 100 receivers. Make sure broadcasting works.
    * Then stop 99 of the receivers, the last one could still be working.
    *
    * @throws Exception
    */
   @Test
   public void testJGropusChannelReferenceCounting() throws Exception {
      BroadcastEndpointFactory factory = new JGroupsFileBroadcastEndpointFactory().setChannelName("tst").setFile(TEST_JGROUPS_CONF_FILE);
      BroadcastEndpoint broadcaster = factory.createBroadcastEndpoint();
      broadcaster.openBroadcaster();

      try {

         int num = 100;
         BroadcastEndpoint[] receivers = new BroadcastEndpoint[num];
         for (int i = 0; i < num; i++) {
            receivers[i] = factory.createBroadcastEndpoint();
            receivers[i].openClient();
         }

         final byte[] data = new byte[]{1, 2, 3, 4, 5};
         broadcaster.broadcast(data);

         for (int i = 0; i < num; i++) {
            byte[] received = receivers[i].receiveBroadcast(5000, TimeUnit.MILLISECONDS);
            assertNotNull(received);
            assertEquals(5, received.length);
            assertEquals(1, received[0]);
            assertEquals(2, received[1]);
            assertEquals(3, received[2]);
            assertEquals(4, received[3]);
            assertEquals(5, received[4]);
         }

         for (int i = 0; i < num - 1; i++) {
            receivers[i].close(false);
         }

         byte[] data1 = receivers[num - 1].receiveBroadcast(5, TimeUnit.SECONDS);
         assertNull(data1);

         broadcaster.broadcast(data);
         data1 = receivers[num - 1].receiveBroadcast(5, TimeUnit.SECONDS);

         assertNotNull(data1);
         assertEquals(5, data1.length);
         assertEquals(1, data1[0]);
         assertEquals(2, data1[1]);
         assertEquals(3, data1[2]);
         assertEquals(4, data1[3]);
         assertEquals(5, data1[4]);

         receivers[num - 1].close(false);
      } finally {
         broadcaster.close(true);
      }
   }

   /**
    * Create one broadcaster and 50 receivers. Make sure broadcasting works.
    * Then stop all of the receivers, and create 50 new ones. Make sure the
    * 50 new ones are receiving data from the broadcasting.
    *
    * @throws Exception
    */
   @Test
   public void testJGropusChannelReferenceCounting1() throws Exception {
      BroadcastEndpointFactory factory = new JGroupsFileBroadcastEndpointFactory().setChannelName("tst").setFile(TEST_JGROUPS_CONF_FILE);
      BroadcastEndpoint broadcaster = factory.createBroadcastEndpoint();
      broadcaster.openBroadcaster();
      int num = 50;
      BroadcastEndpoint[] receivers = new BroadcastEndpoint[num];
      for (int i = 0; i < num; i++) {
         receivers[i] = factory.createBroadcastEndpoint();
         receivers[i].openClient();
      }

      try {

         final byte[] data = new byte[]{1, 2, 3, 4, 5};
         broadcaster.broadcast(data);

         for (int i = 0; i < num; i++) {
            byte[] received = receivers[i].receiveBroadcast(5000, TimeUnit.MILLISECONDS);
            assertNotNull(received);
            assertEquals(5, received.length);
            assertEquals(1, received[0]);
            assertEquals(2, received[1]);
            assertEquals(3, received[2]);
            assertEquals(4, received[3]);
            assertEquals(5, received[4]);
         }

         for (int i = 0; i < num; i++) {
            receivers[i].close(false);
         }

         //new ones
         for (int i = 0; i < num; i++) {
            receivers[i] = factory.createBroadcastEndpoint();
            receivers[i].openClient();
         }

         broadcaster.broadcast(data);

         for (int i = 0; i < num; i++) {
            byte[] received = receivers[i].receiveBroadcast(5000, TimeUnit.MILLISECONDS);
            assertNotNull(received);
            assertEquals(5, received.length);
            assertEquals(1, received[0]);
            assertEquals(2, received[1]);
            assertEquals(3, received[2]);
            assertEquals(4, received[3]);
            assertEquals(5, received[4]);
         }

      } finally {
         for (int i = 0; i < num; i++) {
            receivers[i].close(false);
         }
         broadcaster.close(true);
      }
   }

   /**
    * Create one broadcaster and 50 receivers. Then stop half of the receivers.
    * Then add the half back, plus some more. Make sure all receivers receive data.
    *
    * @throws Exception
    */
   @Test
   public void testJGropusChannelReferenceCounting2() throws Exception {
      BroadcastEndpointFactory factory = new JGroupsFileBroadcastEndpointFactory().setChannelName("tst").setFile(TEST_JGROUPS_CONF_FILE);
      BroadcastEndpoint broadcaster = factory.createBroadcastEndpoint();
      broadcaster.openBroadcaster();

      int num = 50;
      BroadcastEndpoint[] receivers = new BroadcastEndpoint[num];
      for (int i = 0; i < num; i++) {
         receivers[i] = factory.createBroadcastEndpoint();
         receivers[i].openClient();
      }

      for (int i = 0; i < num / 2; i++) {
         receivers[i].close(false);
      }

      for (int i = 0; i < num / 2; i++) {
         receivers[i] = factory.createBroadcastEndpoint();
         receivers[i].openClient();
      }

      int num2 = 10;
      BroadcastEndpoint[] moreReceivers = new BroadcastEndpoint[num2];

      for (int i = 0; i < num2; i++) {
         moreReceivers[i] = factory.createBroadcastEndpoint();
         moreReceivers[i].openClient();
      }

      final byte[] data = new byte[]{1, 2, 3, 4, 5};
      broadcaster.broadcast(data);

      for (int i = 0; i < num; i++) {
         byte[] received = receivers[i].receiveBroadcast(5000, TimeUnit.MILLISECONDS);
         assertNotNull(received);
         assertEquals(5, received.length);
         assertEquals(1, received[0]);
         assertEquals(2, received[1]);
         assertEquals(3, received[2]);
         assertEquals(4, received[3]);
         assertEquals(5, received[4]);
      }

      for (int i = 0; i < num2; i++) {
         byte[] received = moreReceivers[i].receiveBroadcast(5000, TimeUnit.MILLISECONDS);
         assertNotNull(received);
         assertEquals(5, received.length);
         assertEquals(1, received[0]);
         assertEquals(2, received[1]);
         assertEquals(3, received[2]);
         assertEquals(4, received[3]);
         assertEquals(5, received[4]);
      }

      for (int i = 0; i < num; i++) {
         receivers[i].close(false);
      }

      for (int i = 0; i < num2; i++) {
         moreReceivers[i].close(false);
      }

      broadcaster.close(true);
   }

   @Test
   public void testStraightSendReceiveJGroups() throws Exception {
      BroadcastEndpoint broadcaster = null;
      BroadcastEndpoint client = null;
      try {
         JGroupsFileBroadcastEndpointFactory endpointFactory = new JGroupsFileBroadcastEndpointFactory().setChannelName("tst").setFile(TEST_JGROUPS_CONF_FILE);
         broadcaster = endpointFactory.createBroadcastEndpoint();

         broadcaster.openBroadcaster();

         client = endpointFactory.createBroadcastEndpoint();

         client.openClient();

         Thread.sleep(1000);

         byte[] randomBytes = "PQP".getBytes();

         broadcaster.broadcast(randomBytes);

         byte[] btreceived = client.receiveBroadcast(5, TimeUnit.SECONDS);

         instanceLog.debug("BTReceived = " + Arrays.toString(btreceived));

         assertNotNull(btreceived);

         assertEquals(randomBytes.length, btreceived.length);

         for (int i = 0; i < randomBytes.length; i++) {
            assertEquals(randomBytes[i], btreceived[i]);
         }
      } finally {
         try {
            if (broadcaster != null)
               broadcaster.close(true);

            if (client != null)
               client.close(false);
         } catch (Exception ignored) {
            ignored.printStackTrace();
         }
      }

   }

   @Test
   public void testSimpleBroadcastSpecificNIC() throws Exception {
      final InetAddress groupAddress = InetAddress.getByName(address1);
      final int groupPort = getUDPDiscoveryPort();
      final int timeout = 500;

      final String nodeID = RandomUtil.randomString();

      // We need to choose a real NIC on the local machine - note this will silently pass if the machine
      // has no usable NIC!

      Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces();

      InetAddress localAddress = InetAddress.getLoopbackAddress();

      instanceLog.debug("Local address is " + localAddress);

      bg = newBroadcast(nodeID, RandomUtil.randomString(), localAddress, -1, groupAddress, groupPort);

      bg.start();

      TransportConfiguration live1 = generateTC();

      bg.addConnector(live1);

      dg = newDiscoveryGroup(RandomUtil.randomString(), RandomUtil.randomString(), localAddress, groupAddress, groupPort, timeout);

      dg.start();

      verifyBroadcast(bg, dg);

      List<DiscoveryEntry> entries = dg.getDiscoveryEntries();
      assertEqualsDiscoveryEntries(Arrays.asList(live1), entries);

   }

   @Test
   public void testSimpleBroadcastWithStopStartDiscoveryGroup() throws Exception {
      final InetAddress groupAddress = InetAddress.getByName(address1);
      final int groupPort = getUDPDiscoveryPort();
      final int timeout = 500;

      final String nodeID = RandomUtil.randomString();

      bg = newBroadcast(nodeID, RandomUtil.randomString(), null, -1, groupAddress, groupPort);

      bg.start();

      TransportConfiguration live1 = generateTC();

      bg.addConnector(live1);

      dg = newDiscoveryGroup(RandomUtil.randomString(), RandomUtil.randomString(), null, groupAddress, groupPort, timeout);

      dg.start();

      verifyBroadcast(bg, dg);
      List<DiscoveryEntry> entries = dg.getDiscoveryEntries();
      assertEqualsDiscoveryEntries(Arrays.asList(live1), entries);

      bg.stop();

      dg.stop();

      dg.start();

      bg.start();

      verifyBroadcast(bg, dg);
      entries = dg.getDiscoveryEntries();
      assertEqualsDiscoveryEntries(Arrays.asList(live1), entries);
   }

   @Test
   public void testIgnoreTrafficFromOwnNode() throws Exception {
      final InetAddress groupAddress = InetAddress.getByName(address1);
      final int groupPort = getUDPDiscoveryPort();
      final int timeout = 500;

      String nodeID = RandomUtil.randomString();

      bg = newBroadcast(nodeID, RandomUtil.randomString(), null, -1, groupAddress, groupPort);

      bg.start();

      TransportConfiguration live1 = generateTC();

      bg.addConnector(live1);

      dg = newDiscoveryGroup(nodeID, RandomUtil.randomString(), null, groupAddress, groupPort, timeout);

      dg.start();

      verifyNonBroadcast(bg, dg);
      List<DiscoveryEntry> entries = dg.getDiscoveryEntries();

      Assert.assertNotNull(entries);

      Assert.assertEquals(0, entries.size());

   }

   @Test
   public void testSimpleBroadcastDifferentPort() throws Exception {
      final InetAddress groupAddress = InetAddress.getByName(getUDPDiscoveryAddress());
      final int groupPort = getUDPDiscoveryPort();
      final int timeout = 500;

      bg = newBroadcast(RandomUtil.randomString(), RandomUtil.randomString(), null, -1, groupAddress, groupPort);

      bg.start();

      TransportConfiguration live1 = generateTC();

      bg.addConnector(live1);

      final int port2 = getUDPDiscoveryPort(1);

      dg = newDiscoveryGroup(RandomUtil.randomString(), RandomUtil.randomString(), null, groupAddress, port2, timeout);

      dg.start();

      verifyNonBroadcast(bg, dg);
   }

   @Test
   public void testSimpleBroadcastDifferentAddressAndPort() throws Exception {
      final InetAddress groupAddress = InetAddress.getByName(address1);
      final int groupPort = getUDPDiscoveryPort();
      final int timeout = 500;

      bg = newBroadcast(RandomUtil.randomString(), RandomUtil.randomString(), null, -1, groupAddress, groupPort);

      bg.start();

      TransportConfiguration live1 = generateTC();

      bg.addConnector(live1);

      final InetAddress groupAddress2 = InetAddress.getByName(address2);
      final int port2 = getUDPDiscoveryPort(1);

      dg = newDiscoveryGroup(RandomUtil.randomString(), RandomUtil.randomString(), null, groupAddress2, port2, timeout);

      dg.start();

      verifyNonBroadcast(bg, dg);
   }

   @Test
   public void testMultipleGroups() throws Exception {
      final int groupPort1 = getUDPDiscoveryPort();

      final int groupPort2 = getUDPDiscoveryPort(1);

      final int groupPort3 = getUDPDiscoveryPort(2);

      final InetAddress groupAddress1 = InetAddress.getByName(address1);

      final InetAddress groupAddress2 = InetAddress.getByName(address2);

      final InetAddress groupAddress3 = InetAddress.getByName(address3);

      final int timeout = 5000;

      String node1 = UUIDGenerator.getInstance().generateStringUUID();

      String node2 = UUIDGenerator.getInstance().generateStringUUID();

      String node3 = UUIDGenerator.getInstance().generateStringUUID();

      bg1 = newBroadcast(node1, RandomUtil.randomString(), null, -1, groupAddress1, groupPort1);

      bg2 = newBroadcast(node2, RandomUtil.randomString(), null, -1, groupAddress2, groupPort2);

      bg3 = newBroadcast(node3, RandomUtil.randomString(), null, -1, groupAddress3, groupPort3);

      bg2.start();
      bg1.start();
      bg3.start();

      TransportConfiguration live1 = generateTC("live1");

      TransportConfiguration live2 = generateTC("live2");

      TransportConfiguration live3 = generateTC("live3");

      bg1.addConnector(live1);
      bg2.addConnector(live2);
      bg3.addConnector(live3);

      dg1 = newDiscoveryGroup("group-1::" + RandomUtil.randomString(), "group-1::" + RandomUtil.randomString(), null, groupAddress1, groupPort1, timeout);
      dg1.start();

      dg2 = newDiscoveryGroup("group-2::" + RandomUtil.randomString(), "group-2::" + RandomUtil.randomString(), null, groupAddress2, groupPort2, timeout);
      dg2.start();

      dg3 = newDiscoveryGroup("group-3::" + RandomUtil.randomString(), "group-3::" + RandomUtil.randomString(), null, groupAddress3, groupPort3, timeout);
      dg3.start();

      bg1.broadcastConnectors();

      bg2.broadcastConnectors();

      bg3.broadcastConnectors();

      boolean ok = dg1.waitForBroadcast(timeout);
      Assert.assertTrue(ok);
      List<DiscoveryEntry> entries = dg1.getDiscoveryEntries();
      assertEqualsDiscoveryEntries(Arrays.asList(live1), entries);

      ok = dg2.waitForBroadcast(timeout);
      Assert.assertTrue(ok);
      entries = dg2.getDiscoveryEntries();
      assertEqualsDiscoveryEntries(Arrays.asList(live2), entries);

      ok = dg3.waitForBroadcast(timeout);
      Assert.assertTrue(ok);
      entries = dg3.getDiscoveryEntries();
      assertEqualsDiscoveryEntries(Arrays.asList(live3), entries);
   }

   // -- fix this test
   // public void testBroadcastNullBackup() throws Exception
   // {
   // final InetAddress groupAddress = InetAddress.getByName(address1);
   // final int groupPort = getUDPDiscoveryPort();
   // final int timeout = 500;
   //
   // String nodeID = RandomUtil.randomString();
   //
   // BroadcastGroup bg = new BroadcastGroupImpl(nodeID,
   // RandomUtil.randomString(),
   // null,
   // -1,
   // groupAddress,
   // groupPort,
   // true);
   //
   // bg.start();
   //
   // TransportConfiguration live1 = generateTC();
   //
   // Pair<TransportConfiguration, TransportConfiguration> connectorPair = new Pair<TransportConfiguration,
   // TransportConfiguration>(live1,
   // null);
   //
   // bg.addConnectorPair(connectorPair);
   //
   // DiscoveryGroup dg = new DiscoveryGroup(RandomUtil.randomString(),
   // RandomUtil.randomString(),
   // null,
   // groupAddress,
   // groupPort,
   // timeout,
   // Executors.newFixedThreadPool(1));
   //
   // dg.start();
   //
   // bg.broadcastConnectors();
   //
   // boolean ok = dg.waitForBroadcast(1000);
   //
   // Assert.assertTrue(ok);
   // }

   @Test
   public void testDiscoveryListenersCalled() throws Exception {
      final InetAddress groupAddress = InetAddress.getByName(address1);
      final int groupPort = getUDPDiscoveryPort();
      final int timeout = 500;

      String nodeID = RandomUtil.randomString();

      bg = newBroadcast(nodeID, RandomUtil.randomString(), null, -1, groupAddress, groupPort);

      bg.start();

      TransportConfiguration live1 = generateTC();

      bg.addConnector(live1);

      dg = newDiscoveryGroup(RandomUtil.randomString(), RandomUtil.randomString(), null, groupAddress, groupPort, timeout);

      MyListener listener1 = new MyListener();
      MyListener listener2 = new MyListener();
      MyListener listener3 = new MyListener();

      dg.registerListener(listener1);
      dg.registerListener(listener2);
      dg.registerListener(listener3);

      dg.start();

      verifyBroadcast(bg, dg);

      Assert.assertTrue(listener1.called);
      Assert.assertTrue(listener2.called);
      Assert.assertTrue(listener3.called);

      listener1.called = false;
      listener2.called = false;
      listener3.called = false;

      verifyBroadcast(bg, dg);

      // Won't be called since connectors haven't changed
      Assert.assertFalse(listener1.called);
      Assert.assertFalse(listener2.called);
      Assert.assertFalse(listener3.called);
   }

   @Test
   public void testConnectorsUpdatedMultipleBroadcasters() throws Exception {
      final InetAddress groupAddress = InetAddress.getByName(address1);
      final int groupPort = getUDPDiscoveryPort();
      final int timeout = 500;

      String node1 = RandomUtil.randomString();
      String node2 = RandomUtil.randomString();
      String node3 = RandomUtil.randomString();

      bg1 = newBroadcast(node1, RandomUtil.randomString(), null, -1, groupAddress, groupPort);
      bg1.start();

      bg2 = newBroadcast(node2, RandomUtil.randomString(), null, -1, groupAddress, groupPort);
      bg2.start();

      bg3 = newBroadcast(node3, RandomUtil.randomString(), null, -1, groupAddress, groupPort);
      bg3.start();

      TransportConfiguration live1 = generateTC();
      bg1.addConnector(live1);

      TransportConfiguration live2 = generateTC();
      bg2.addConnector(live2);

      TransportConfiguration live3 = generateTC();
      bg3.addConnector(live3);

      dg = newDiscoveryGroup(RandomUtil.randomString(), RandomUtil.randomString(), null, groupAddress, groupPort, timeout);

      MyListener listener1 = new MyListener();
      dg.registerListener(listener1);
      MyListener listener2 = new MyListener();
      dg.registerListener(listener2);

      dg.start();

      verifyBroadcast(bg1, dg);
      List<DiscoveryEntry> entries = dg.getDiscoveryEntries();
      assertEqualsDiscoveryEntries(Arrays.asList(live1), entries);
      Assert.assertTrue(listener1.called);
      Assert.assertTrue(listener2.called);
      listener1.called = false;
      listener2.called = false;

      verifyBroadcast(bg2, dg);
      entries = dg.getDiscoveryEntries();
      assertEqualsDiscoveryEntries(Arrays.asList(live1, live2), entries);
      Assert.assertTrue(listener1.called);
      Assert.assertTrue(listener2.called);
      listener1.called = false;
      listener2.called = false;

      verifyBroadcast(bg3, dg);
      entries = dg.getDiscoveryEntries();
      assertEqualsDiscoveryEntries(Arrays.asList(live1, live2, live3), entries);
      Assert.assertTrue(listener1.called);
      Assert.assertTrue(listener2.called);
      listener1.called = false;
      listener2.called = false;

      verifyBroadcast(bg1, dg);
      entries = dg.getDiscoveryEntries();
      assertEqualsDiscoveryEntries(Arrays.asList(live1, live2, live3), entries);
      Assert.assertFalse(listener1.called);
      Assert.assertFalse(listener2.called);
      listener1.called = false;
      listener2.called = false;

      verifyBroadcast(bg2, dg);
      entries = dg.getDiscoveryEntries();
      assertEqualsDiscoveryEntries(Arrays.asList(live1, live2, live3), entries);
      Assert.assertFalse(listener1.called);
      Assert.assertFalse(listener2.called);
      listener1.called = false;
      listener2.called = false;

      verifyBroadcast(bg3, dg);
      entries = dg.getDiscoveryEntries();
      assertEqualsDiscoveryEntries(Arrays.asList(live1, live2, live3), entries);
      Assert.assertFalse(listener1.called);
      Assert.assertFalse(listener2.called);
      listener1.called = false;
      listener2.called = false;

      bg2.removeConnector(live2);
      verifyBroadcast(bg2, dg);

      // Connector2 should still be there since not timed out yet

      entries = dg.getDiscoveryEntries();
      assertEqualsDiscoveryEntries(Arrays.asList(live1, live2, live3), entries);
      Assert.assertFalse(listener1.called);
      Assert.assertFalse(listener2.called);
      listener1.called = false;
      listener2.called = false;

      Thread.sleep(timeout * 2);

      bg1.broadcastConnectors();
      boolean ok = dg.waitForBroadcast(1000);
      bg2.broadcastConnectors();
      ok = dg.waitForBroadcast(1000);
      bg3.broadcastConnectors();
      ok = dg.waitForBroadcast(1000);

      entries = dg.getDiscoveryEntries();
      assertEqualsDiscoveryEntries(Arrays.asList(live1, live3), entries);
      Assert.assertTrue(listener1.called);
      Assert.assertTrue(listener2.called);
      listener1.called = false;
      listener2.called = false;

      bg1.removeConnector(live1);
      bg3.removeConnector(live3);

      Thread.sleep(timeout * 2);

      bg1.broadcastConnectors();
      ok = dg.waitForBroadcast(1000);
      bg2.broadcastConnectors();
      ok = dg.waitForBroadcast(1000);
      bg3.broadcastConnectors();
      ok = dg.waitForBroadcast(1000);

      entries = dg.getDiscoveryEntries();
      Assert.assertNotNull(entries);
      Assert.assertEquals(0, entries.size());
      Assert.assertTrue(listener1.called);
      Assert.assertTrue(listener2.called);
      listener1.called = false;
      listener2.called = false;

      bg1.broadcastConnectors();
      ok = dg.waitForBroadcast(1000);
      bg2.broadcastConnectors();
      ok = dg.waitForBroadcast(1000);
      bg3.broadcastConnectors();
      ok = dg.waitForBroadcast(1000);

      entries = dg.getDiscoveryEntries();
      Assert.assertNotNull(entries);
      Assert.assertEquals(0, entries.size());
      Assert.assertFalse(listener1.called);
      Assert.assertFalse(listener2.called);
   }

   @Test
   public void testMultipleDiscoveryGroups() throws Exception {
      final InetAddress groupAddress = InetAddress.getByName(address1);
      final int groupPort = getUDPDiscoveryPort();
      final int timeout = 500;

      String nodeID = RandomUtil.randomString();

      bg = newBroadcast(nodeID, RandomUtil.randomString(), null, -1, groupAddress, groupPort);

      bg.start();

      TransportConfiguration live1 = generateTC();

      bg.addConnector(live1);

      dg1 = newDiscoveryGroup(RandomUtil.randomString(), RandomUtil.randomString(), null, groupAddress, groupPort, timeout);

      dg2 = newDiscoveryGroup(RandomUtil.randomString(), RandomUtil.randomString(), null, groupAddress, groupPort, timeout);

      dg3 = newDiscoveryGroup(RandomUtil.randomString(), RandomUtil.randomString(), null, groupAddress, groupPort, timeout);

      dg1.start();
      dg2.start();
      dg3.start();

      bg.broadcastConnectors();

      boolean ok = dg1.waitForBroadcast(1000);
      Assert.assertTrue(ok);
      List<DiscoveryEntry> entries = dg1.getDiscoveryEntries();
      assertEqualsDiscoveryEntries(Arrays.asList(live1), entries);

      ok = dg2.waitForBroadcast(1000);
      Assert.assertTrue(ok);
      entries = dg2.getDiscoveryEntries();
      assertEqualsDiscoveryEntries(Arrays.asList(live1), entries);

      ok = dg3.waitForBroadcast(1000);
      Assert.assertTrue(ok);
      entries = dg3.getDiscoveryEntries();
      assertEqualsDiscoveryEntries(Arrays.asList(live1), entries);

      bg.stop();

      dg1.stop();
      dg2.stop();
      dg3.stop();
   }

   @Test
   public void testDiscoveryGroupNotifications() throws Exception {
      SimpleNotificationService notifService = new SimpleNotificationService();
      SimpleNotificationService.Listener notifListener = new SimpleNotificationService.Listener();
      notifService.addNotificationListener(notifListener);

      final InetAddress groupAddress = InetAddress.getByName(address1);
      final int groupPort = getUDPDiscoveryPort();
      final int timeout = 500;

      dg = newDiscoveryGroup(RandomUtil.randomString(), RandomUtil.randomString(), null, groupAddress, groupPort, timeout, notifService);

      Assert.assertEquals(0, notifListener.getNotifications().size());

      dg.start();

      Assert.assertEquals(1, notifListener.getNotifications().size());
      Notification notif = notifListener.getNotifications().get(0);
      Assert.assertEquals(CoreNotificationType.DISCOVERY_GROUP_STARTED, notif.getType());
      Assert.assertEquals(dg.getName(), notif.getProperties().getSimpleStringProperty(new SimpleString("name")).toString());

      dg.stop();

      Assert.assertEquals(2, notifListener.getNotifications().size());
      notif = notifListener.getNotifications().get(1);
      Assert.assertEquals(CoreNotificationType.DISCOVERY_GROUP_STOPPED, notif.getType());
      Assert.assertEquals(dg.getName(), notif.getProperties().getSimpleStringProperty(new SimpleString("name")).toString());
   }

   @Test
   public void testBroadcastGroupNotifications() throws Exception {
      SimpleNotificationService notifService = new SimpleNotificationService();
      SimpleNotificationService.Listener notifListener = new SimpleNotificationService.Listener();
      notifService.addNotificationListener(notifListener);

      final InetAddress groupAddress = InetAddress.getByName(address1);
      final int groupPort = getUDPDiscoveryPort();

      bg = newBroadcast(RandomUtil.randomString(), RandomUtil.randomString(), null, -1, groupAddress, groupPort);

      bg.setNotificationService(notifService);

      Assert.assertEquals(0, notifListener.getNotifications().size());

      bg.start();

      Assert.assertEquals(1, notifListener.getNotifications().size());
      Notification notif = notifListener.getNotifications().get(0);
      Assert.assertEquals(CoreNotificationType.BROADCAST_GROUP_STARTED, notif.getType());
      Assert.assertEquals(bg.getName(), notif.getProperties().getSimpleStringProperty(new SimpleString("name")).toString());

      bg.stop();

      Assert.assertEquals(2, notifListener.getNotifications().size());
      notif = notifListener.getNotifications().get(1);
      Assert.assertEquals(CoreNotificationType.BROADCAST_GROUP_STOPPED, notif.getType());
      Assert.assertEquals(bg.getName(), notif.getProperties().getSimpleStringProperty(new SimpleString("name")).toString());
   }
}


<|start_filename|>tests/compatibility-tests/src/main/resources/clients/artemisFail.groovy<|end_filename|>
package clients

import org.apache.activemq.artemis.api.core.ActiveMQException
import org.apache.activemq.artemis.api.core.client.FailoverEventListener
import org.apache.activemq.artemis.api.core.client.FailoverEventType
import org.apache.activemq.artemis.jms.client.ActiveMQConnection

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// Create a client connection factory

import org.apache.activemq.artemis.tests.compatibility.GroovyRun

import java.util.concurrent.CountDownLatch
import java.util.concurrent.TimeUnit;

if (ActiveMQConnection.class.equals(connectionToFail.getClass())) {
    CountDownLatch latch = new CountDownLatch(1);
    ((ActiveMQConnection)connectionToFail).setFailoverListener(new FailoverEventListener() {
        @Override
        void failoverEvent(FailoverEventType eventType) {
            latch.countDown();
        }
    })
    ((ActiveMQConnection)connectionToFail).getSessionFactory().getConnection().fail(new ActiveMQException("fail"));
    GroovyRun.assertTrue(latch.await(10, TimeUnit.SECONDS));
}


<|start_filename|>artemis-journal/src/test/java/org/apache/activemq/artemis/core/journal/impl/ObjIntIntArrayListTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.journal.impl;

import java.util.ArrayList;
import java.util.List;

import org.junit.Assert;
import org.junit.Test;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;

public class ObjIntIntArrayListTest {

   @Test
   public void addShouldAppendTuplesInOrder() {
      List<Integer> expectedAList = new ArrayList<>();
      List<Integer> expectedBList = new ArrayList<>();
      List<Integer> expectedCList = new ArrayList<>();
      ObjIntIntArrayList<Integer> list = new ObjIntIntArrayList<>(0);
      final int elementsToAdd = 10;
      assertEquals(0, list.size());
      for (int i = 0; i < elementsToAdd; i++) {
         Integer a = i;
         Integer b = i + 1;
         Integer c = i + 2;
         list.add(a, b, c);
         assertEquals(i + 1, list.size());
         expectedAList.add(a);
         expectedBList.add(b);
         expectedCList.add(c);
      }
      List<Integer> aList = new ArrayList<>();
      List<Integer> bList = new ArrayList<>();
      List<Integer> cList = new ArrayList<>();
      final Object expectedArg = new Object();
      list.forEach((a, b, c, arg) -> {
         aList.add(a);
         bList.add(b);
         cList.add(c);
         Assert.assertSame(expectedArg, arg);
      }, expectedArg);
      assertThat(aList, equalTo(expectedAList));
      assertThat(bList, equalTo(expectedBList));
      assertThat(cList, equalTo(expectedCList));
   }

   @Test(expected = NullPointerException.class)
   public void addShouldFailAppendNull() {
      ObjIntIntArrayList<Integer> list = new ObjIntIntArrayList<>(0);
      list.add(null, 1, 2);
   }

   @Test(expected = IllegalArgumentException.class)
   public void addShouldFailAppendNegativeA() {
      ObjIntIntArrayList<Integer> list = new ObjIntIntArrayList<>(0);
      list.add(0, -1, 1);
   }

   @Test(expected = IllegalArgumentException.class)
   public void addShouldFailAppendNegativeB() {
      ObjIntIntArrayList<Integer> list = new ObjIntIntArrayList<>(0);
      list.add(0, 1, -1);
   }

   @Test
   public void clearShouldDeleteAllElements() {
      ObjIntIntArrayList<Integer> list = new ObjIntIntArrayList<>(0);
      list.add(1, 3, 3);
      assertEquals(1, list.size());
      list.clear();
      assertEquals(0, list.size());
      list.forEach((a, b, c, ignored) -> {
         Assert.fail("the list should be empty");
      }, null);
   }

   @Test
   public void updateIfMatchShouldReturnFalseOnMissingElement() {
      ObjIntIntArrayList<Integer> list = new ObjIntIntArrayList<>(0);
      Integer e = 1;
      list.add(e, 2, 3);
      Assert.assertFalse(list.addToIntsIfMatch(0, 2, 1, 1));
      list.forEach((a, b, c, ignored) -> {
         Assert.assertEquals(e, a);
         Assert.assertEquals(2, b);
         Assert.assertEquals(3, c);
      }, null);
   }

   @Test
   public void updateIfMatchShouldReturnFalseOnOverflowOfA() {
      ObjIntIntArrayList<Integer> list = new ObjIntIntArrayList<>(0);
      Integer e = 1;
      list.add(e, Integer.MAX_VALUE, 3);
      Assert.assertFalse(list.addToIntsIfMatch(0, e, Integer.MAX_VALUE, 1));
      list.forEach((a, b, c, ignored) -> {
         Assert.assertEquals(e, a);
         Assert.assertEquals(Integer.MAX_VALUE, b);
         Assert.assertEquals(3, c);
      }, null);
   }

   @Test
   public void updateIfMatchShouldReturnFalseOnOverflowOfB() {
      ObjIntIntArrayList<Integer> list = new ObjIntIntArrayList<>(0);
      Integer e = 1;
      list.add(e, 2, Integer.MAX_VALUE);
      Assert.assertFalse(list.addToIntsIfMatch(0, e, 1, Integer.MAX_VALUE));
      list.forEach((a, b, c, ignored) -> {
         Assert.assertEquals(e, a);
         Assert.assertEquals(2, b);
         Assert.assertEquals(Integer.MAX_VALUE, c);
      }, null);
   }

   @Test(expected = IndexOutOfBoundsException.class)
   public void updateIfMatchShouldFailOnNegativeIndex() {
      ObjIntIntArrayList<Integer> list = new ObjIntIntArrayList<>(0);
      list.addToIntsIfMatch(-1, 1, 1, 1);
   }

   @Test(expected = IndexOutOfBoundsException.class)
   public void updateIfMatchShouldFailBeyondSize() {
      ObjIntIntArrayList<Integer> list = new ObjIntIntArrayList<>(0);
      list.addToIntsIfMatch(0, 1, 1, 1);
   }

   @Test(expected = NullPointerException.class)
   public void updateIfMatchShouldFailOnNull() {
      ObjIntIntArrayList<Integer> list = new ObjIntIntArrayList<>(0);
      list.add(1, 2, 3);
      list.addToIntsIfMatch(0, null, 1, 1);
   }

   @Test(expected = IllegalArgumentException.class)
   public void updateIfMatchShouldFailOnNegativeDeltaA() {
      ObjIntIntArrayList<Integer> list = new ObjIntIntArrayList<>(0);
      Integer e = 1;
      list.add(1, 2, 3);
      list.addToIntsIfMatch(0, e, -1, 1);
   }

   @Test(expected = IllegalArgumentException.class)
   public void updateIfMatchShouldFailOnNegativeDeltaB() {
      ObjIntIntArrayList<Integer> list = new ObjIntIntArrayList<>(0);
      Integer e = 1;
      list.add(e, 2, 3);
      list.addToIntsIfMatch(0, e, 1, -1);
   }

   @Test
   public void updateIfMatchShouldModifyExistingTuple() {
      ObjIntIntArrayList<Integer> list = new ObjIntIntArrayList<>(0);
      list.add(1, 2, 3);
      list.add(2, 3, 4);
      list.add(3, 4, 5);
      Assert.assertTrue(list.addToIntsIfMatch(0, 1, 1, 1));
      Assert.assertTrue(list.addToIntsIfMatch(1, 2, 1, 1));
      Assert.assertTrue(list.addToIntsIfMatch(2, 3, 1, 1));
      Assert.assertEquals(3, list.size());
      List<Integer> eList = new ArrayList<>();
      List<Integer> aList = new ArrayList<>();
      List<Integer> bList = new ArrayList<>();
      list.forEach((e, a, b, ignore) -> {
         eList.add(e);
         aList.add(a);
         bList.add(b);
      }, null);
      Assert.assertEquals(3, eList.size());
      Assert.assertEquals(3, aList.size());
      Assert.assertEquals(3, bList.size());
      for (int i = 0; i < 3; i++) {
         final int index = i;
         final Integer expectedE = index + 1;
         final Integer expectedA = expectedE + 2;
         final Integer expectedB = expectedE + 3;
         Assert.assertEquals(expectedE, eList.get(index));
         Assert.assertEquals(expectedA, aList.get(index));
         Assert.assertEquals(expectedB, bList.get(index));
      }
   }

}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/transaction/TransactionOperation.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.transaction;

import java.util.List;

import org.apache.activemq.artemis.core.server.MessageReference;

/**
 * A TransactionOperation
 */
public interface TransactionOperation {

   void beforePrepare(Transaction tx) throws Exception;

   /**
    * After prepare shouldn't throw any exception.
    * <p>
    * Any verification has to be done on before prepare
    */
   void afterPrepare(Transaction tx);

   void beforeCommit(Transaction tx) throws Exception;

   /**
    * After commit shouldn't throw any exception.
    * <p>
    * Any verification has to be done on before commit
    */
   void afterCommit(Transaction tx);

   void beforeRollback(Transaction tx) throws Exception;

   /**
    * After rollback shouldn't throw any exception.
    * <p>
    * Any verification has to be done on before rollback
    */
   void afterRollback(Transaction tx);

   List<MessageReference> getRelatedMessageReferences();

   List<MessageReference> getListOnConsumer(long consumerID);

}


<|start_filename|>artemis-core-client/src/main/java/org/apache/activemq/artemis/core/config/federation/FederationStreamConfiguration.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.config.federation;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

import org.apache.activemq.artemis.api.core.ActiveMQBuffer;

public abstract class FederationStreamConfiguration <T extends FederationStreamConfiguration<T>> implements Serializable {

   private String name;

   private FederationConnectionConfiguration connectionConfiguration = new FederationConnectionConfiguration();
   private Set<String> policyRefs = new HashSet<>();

   public String getName() {
      return name;
   }

   public T setName(String name) {
      this.name = name;
      return (T) this;
   }

   public Set<String> getPolicyRefs() {
      return policyRefs;
   }

   public T addPolicyRef(String name) {
      policyRefs.add(name);
      return (T) this;
   }

   public T addPolicyRefs(Collection<String> names) {
      policyRefs.addAll(names);
      return (T) this;
   }

   public FederationConnectionConfiguration getConnectionConfiguration() {
      return connectionConfiguration;
   }

   @Override
   public boolean equals(Object o) {
      if (this == o)
         return true;
      if (!(o instanceof FederationStreamConfiguration))
         return false;
      FederationStreamConfiguration that = (FederationStreamConfiguration) o;
      return Objects.equals(name, that.name) && Objects.equals(connectionConfiguration, that.connectionConfiguration) && Objects.equals(policyRefs, that.policyRefs);
   }

   @Override
   public int hashCode() {
      return Objects.hash(name, connectionConfiguration, policyRefs);
   }

   public void encode(ActiveMQBuffer buffer) {
      buffer.writeString(name);
      connectionConfiguration.encode(buffer);

      buffer.writeInt(policyRefs == null ? 0 : policyRefs.size());
      for (String policyRef : policyRefs) {
         buffer.writeString(policyRef);
      }
   }

   public void decode(ActiveMQBuffer buffer) {
      name = buffer.readString();
      connectionConfiguration.decode(buffer);
      int policyRefNum = buffer.readInt();
      for (int i = 0; i < policyRefNum; i++) {
         policyRefs.add(buffer.readString());
      }
   }
}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/PrincipalConversionLoginModule.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.spi.core.security.jaas;

import javax.security.auth.Subject;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginException;
import java.security.Principal;
import java.util.Map;

import org.jboss.logging.Logger;

/**
 * populate an empty (no UserPrincipal) subject with UserPrincipal seeded from existing principal
 * Useful when a third party login module generated principal needs to be accepted as-is by the broker
 */
public class PrincipalConversionLoginModule implements AuditLoginModule {

   private static final Logger logger = Logger.getLogger(PrincipalConversionLoginModule.class);

   public static final String PRINCIPAL_CLASS_LIST = "principalClassList";
   private Subject subject;
   private String principalClazzList;
   private Principal principal;

   @Override
   public void initialize(Subject subject,
                          CallbackHandler callbackHandler,
                          Map<String, ?> sharedState,
                          Map<String, ?> options) {
      this.subject = subject;
      this.principalClazzList = (String) options.get(PRINCIPAL_CLASS_LIST);
   }

   @Override
   public boolean login() throws LoginException {
      logger.debug("login ok!");
      return true;
   }

   @Override
   public boolean commit() throws LoginException {

      if (subject == null || !subject.getPrincipals(UserPrincipal.class).isEmpty()) {
         return false;
      }

      if (principalClazzList != null) {
         String[] principalClasses = principalClazzList.split(",");
         for (String principalClass : principalClasses) {
            String trimmedCandidateClassName = principalClass.trim();
            for (Principal candidatePrincipal : subject.getPrincipals()) {
               logger.debug("Checking principal class name:" + candidatePrincipal.getClass().getName() + ", " + candidatePrincipal);
               if (candidatePrincipal.getClass().getName().equals(trimmedCandidateClassName)) {
                  logger.debug("converting: " + candidatePrincipal);
                  principal = new UserPrincipal(candidatePrincipal.getName());
                  subject.getPrincipals().add(principal);
                  break;
               }
            }
         }
      }
      logger.debug("commit, result: " + (principal != null));
      return principal != null;
   }

   @Override
   public boolean abort() throws LoginException {
      registerFailureForAudit(principal != null ? principal.getName() : null);
      clear();
      logger.debug("abort");
      return true;
   }

   private void clear() {
      principal = null;
   }

   @Override
   public boolean logout() throws LoginException {
      if (subject != null) {
         subject.getPrincipals().remove(principal);
      }
      clear();
      logger.debug("logout");
      return true;
   }

}

<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/ManualReconnectionToSingleServerTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.jms;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.ExceptionListener;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import java.util.ArrayList;
import java.util.Date;
import java.util.concurrent.CountDownLatch;

import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import static java.util.concurrent.TimeUnit.SECONDS;

public class ManualReconnectionToSingleServerTest extends ActiveMQTestBase {

   // Constants -----------------------------------------------------

   public static final String BROKER_URL = "tcp://localhost:61616?minLargeMessageSize=10000&HA=true&retryInterval=100&reconnectAttempts=20&producerWindowSize=10000";

   private Connection connection;

   private MessageConsumer consumer;

   private CountDownLatch exceptionLatch;
   private CountDownLatch reconnectionLatch;
   private CountDownLatch allMessagesReceived;

   private static final String QUEUE_NAME = ManualReconnectionToSingleServerTest.class.getSimpleName() + ".queue";

   private static final int NUM = 20;

   private final ExceptionListener exceptionListener = new ExceptionListener() {
      @Override
      public void onException(final JMSException e) {
         exceptionLatch.countDown();
         disconnect();
         connect();
         reconnectionLatch.countDown();
      }
   };

   private Listener listener;

   private ActiveMQServer server;

   @Test
   public void testExceptionListener() throws Exception {
      connect();

      ConnectionFactory cf = new ActiveMQConnectionFactory(BROKER_URL);

      Destination dest = (Destination) ActiveMQJMSClient.createQueue(QUEUE_NAME);
      Connection conn = cf.createConnection();
      Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
      MessageProducer prod = sess.createProducer(dest);

      for (int i = 0; i < NUM; i++) {
         Message message = sess.createTextMessage(new Date().toString());
         message.setIntProperty("counter", i + 1);
         prod.send(message);

         if (i == NUM / 2) {
            conn.close();
            server.stop();
            server.start();
            cf =  new ActiveMQConnectionFactory(BROKER_URL);
            dest = (Destination) ActiveMQJMSClient.createQueue(QUEUE_NAME);
            conn = cf.createConnection();
            sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
            prod = sess.createProducer(dest);
         }
      }

      conn.close();

      boolean gotException = exceptionLatch.await(10, SECONDS);
      Assert.assertTrue(gotException);

      boolean clientReconnected = reconnectionLatch.await(10, SECONDS);

      Assert.assertTrue("client did not reconnect after server was restarted", clientReconnected);

      boolean gotAllMessages = allMessagesReceived.await(10, SECONDS);
      Assert.assertTrue(gotAllMessages);

      connection.close();

   }

   // Package protected ---------------------------------------------

   // Protected -----------------------------------------------------

   @Override
   @Before
   public void setUp() throws Exception {
      super.setUp();

      server = createServer(false, createDefaultNettyConfig());

      Configuration configuration = new ConfigurationImpl();

      configuration.getQueueConfigs().add(new QueueConfiguration(QUEUE_NAME));

      ArrayList<TransportConfiguration> configs = new ArrayList<>();
      configs.add(new TransportConfiguration(NETTY_CONNECTOR_FACTORY));
      server.start();

      listener = new Listener();

      exceptionLatch = new CountDownLatch(1);
      reconnectionLatch = new CountDownLatch(1);
      allMessagesReceived = new CountDownLatch(1);
   }

   // Private -------------------------------------------------------

   // Inner classes -------------------------------------------------

   protected void disconnect() {
      instanceLog.debug("calling disconnect");
      if (connection == null) {
         instanceLog.debug("connection is null");
         return;
      }

      try {
         connection.setExceptionListener(null);
         instanceLog.debug("closing the connection");
         connection.close();
         connection = null;
         instanceLog.debug("connection closed");
      } catch (Exception e) {
         instanceLog.debug("** got exception");
         e.printStackTrace();
      }
   }

   protected void connect() {
      int retries = 0;
      final int retryLimit = 1000;
      try {
         ConnectionFactory cf;
         while (true) {
            try {
               cf = new ActiveMQConnectionFactory(BROKER_URL);
               break;
            } catch (Exception e) {
               if (retries++ > retryLimit)
                  throw e;
               // retry until server is up
               Thread.sleep(100);
            }
         }
         connection = cf.createConnection();
         connection.setExceptionListener(exceptionListener);
         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
         Queue queue = session.createQueue(QUEUE_NAME);
         consumer = session.createConsumer(queue);
         consumer.setMessageListener(listener);
         connection.start();
      } catch (Exception e) {
         if (connection != null) {
            try {
               connection.close();
            } catch (JMSException e1) {
               e1.printStackTrace();
            }
         }
      }
   }

   private class Listener implements MessageListener {

      private int count = 0;

      @Override
      public void onMessage(final Message msg) {
         count++;

         try {
            msg.getIntProperty("counter");
         } catch (JMSException e) {
            e.printStackTrace();
         }
         if (count == NUM) {
            allMessagesReceived.countDown();
         }
      }
   }

}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/plugin/JvmMetricsTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * <br>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <br>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.tests.integration.plugin;

import io.micrometer.core.instrument.Meter;
import org.apache.activemq.artemis.core.config.MetricsConfiguration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.metrics.plugins.SimpleMetricsPlugin;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.junit.Before;
import org.junit.Test;

public class JvmMetricsTest extends ActiveMQTestBase {

   @Override
   @Before
   public void setUp() throws Exception {
      super.setUp();
   }

   @Test
   public void testJvmMemoryMetricsPositive() throws Exception {
      internalTestMetrics(true, true, false, false, "jvm.memory");
   }

   @Test
   public void testJvmMemoryMetricsNegative() throws Exception {
      internalTestMetrics(false, false, false, false, "jvm.memory");
   }

   @Test
   public void testJvmGcMetricsPositive() throws Exception {
      internalTestMetrics(true, false, true, false, "jvm.gc");
   }

   @Test
   public void testJvmGcMetricsNegative() throws Exception {
      internalTestMetrics(false, false, false, false, "jvm.gc");
   }

   @Test
   public void testJvmThreadMetricsPositive() throws Exception {
      internalTestMetrics(true, false, false, true, "jvm.thread");
   }

   @Test
   public void testJvmThreadMetricsNegative() throws Exception {
      internalTestMetrics(false, false, false, false, "jvm.thread");
   }

   private void internalTestMetrics(boolean found, boolean memory, boolean gc, boolean thread, String match) throws Exception {
      ActiveMQServer server = createServer(false, createDefaultInVMConfig()
         .setMetricsConfiguration(new MetricsConfiguration()
                                     .setPlugin(new SimpleMetricsPlugin().init(null))
                                     .setJvmMemory(memory)
                                     .setJvmGc(gc)
                                     .setJvmThread(thread)));
      server.start();
      boolean result = false;
      for (Meter.Id meterId : MetricsPluginTest.getMetrics(server).keySet()) {
         if (meterId.getName().startsWith(match)) {
            result = true;
            break;
         }
      }

      assertEquals(found, result);
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/rest/RestDeserializationTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.rest;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Session;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;
import java.io.File;
import java.io.Serializable;
import java.io.StringReader;

import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.apache.activemq.artemis.jms.client.ActiveMQDestination;
import org.apache.activemq.artemis.jms.client.ActiveMQJMSConnectionFactory;
import org.apache.activemq.artemis.rest.HttpHeaderProperty;
import org.apache.activemq.artemis.tests.integration.rest.util.RestAMQConnection;
import org.apache.activemq.artemis.tests.integration.rest.util.RestMessageContext;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import static org.apache.activemq.artemis.jms.client.ActiveMQDestination.QUEUE_QUALIFIED_PREFIX;
import static org.apache.activemq.artemis.jms.client.ActiveMQDestination.TOPIC_QUALIFIED_PREFIX;

public class RestDeserializationTest extends RestTestBase {

   private RestAMQConnection restConnection;

   @Before
   @Override
   public void setUp() throws Exception {
      super.setUp();
      createJettyServer("localhost", 12345);
   }

   @After
   @Override
   public void tearDown() throws Exception {
      if (restConnection != null) {
         restConnection.close();
      }
      super.tearDown();
   }

   @Test
   public void testWithoutBlackWhiteListQueue() throws Exception {
      deployAndconfigureRESTService("rest-test.war");

      Order order = new Order();
      order.setName("Bill");
      order.setItem("iPhone4");
      order.setAmount("$199.99");

      jmsSendMessage(order, "orders", true);

      String received = restReceiveQueueMessage("orders");

      Object object = xmlToObject(received);

      assertEquals(order, object);
   }

   @Test
   public void testWithoutBlackWhiteListTopic() throws Exception {

      jmsServer.getActiveMQServer().addAddressInfo(new AddressInfo(SimpleString.toSimpleString("ordersTopic"), RoutingType.MULTICAST));

      deployAndconfigureRESTService("rest-test.war");

      RestMessageContext topicContext = restConnection.createTopicContext("ordersTopic");
      topicContext.initPullConsumers();

      Order order = new Order();
      order.setName("Bill");
      order.setItem("iPhone4");
      order.setAmount("$199.99");

      jmsSendMessage(order, "ordersTopic", false);

      String received = topicContext.pullMessage();

      Object object = xmlToObject(received);

      assertEquals(order, object);
   }

   @Test
   public void testBlackWhiteListQueuePull() throws Exception {
      deployAndconfigureRESTService("rest-test-bwlist.war");

      Order order = new Order();
      order.setName("Bill");
      order.setItem("iPhone4");
      order.setAmount("$199.99");

      jmsSendMessage(order, "orders", true);

      try {
         String received = restReceiveQueueMessage("orders");
         fail("Object should be rejected by blacklist, but " + received);
      } catch (IllegalStateException e) {
         String error = e.getMessage();
         assertTrue(error, error.contains("ClassNotFoundException"));
      }
   }

   @Test
   public void testBlackWhiteListTopicPull() throws Exception {
      deployAndconfigureRESTService("rest-test-bwlist.war");

      RestMessageContext topicContext = restConnection.createTopicContext("ordersTopic");
      topicContext.initPullConsumers();

      Order order = new Order();
      order.setName("Bill");
      order.setItem("iPhone4");
      order.setAmount("$199.99");

      jmsSendMessage(order, "ordersTopic", false);

      try {
         String received = topicContext.pullMessage();
         fail("object should have been rejected but: " + received);
      } catch (IllegalStateException e) {
         String error = e.getMessage();
         assertTrue(error, error.contains("ClassNotFoundException"));
      }
   }

   private void deployAndconfigureRESTService(String warFileName) throws Exception {
      jmsServer.createTopic(false, "ordersTopic", (String[]) null);
      File warFile = getResourceFile("/rest/" + warFileName, warFileName);
      deployWebApp("/restapp", warFile);
      server.start();
      String uri = server.getURI().toASCIIString();

      restConnection = new RestAMQConnection(uri);
   }

   private Object xmlToObject(String xmlString) throws JAXBException {
      JAXBContext jc = JAXBContext.newInstance(Order.class);
      Unmarshaller unmarshaller = jc.createUnmarshaller();
      StringReader reader = new StringReader(xmlString);
      return unmarshaller.unmarshal(reader);
   }

   private String restReceiveQueueMessage(String destName) throws Exception {
      RestMessageContext restContext = restConnection.createQueueContext(destName);
      String val = restContext.pullMessage();
      return val;
   }

   private void jmsSendMessage(Serializable value, String destName, boolean isQueue) throws JMSException {
      ConnectionFactory factory = new ActiveMQJMSConnectionFactory("tcp://localhost:61616");
      String jmsDest;
      if (isQueue) {
         jmsDest = QUEUE_QUALIFIED_PREFIX + destName;
      } else {
         jmsDest = TOPIC_QUALIFIED_PREFIX + destName;
      }
      Destination destination = ActiveMQDestination.fromPrefixedName(jmsDest);

      Connection conn = factory.createConnection();
      try {
         Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
         MessageProducer producer = session.createProducer(destination);
         ObjectMessage message = session.createObjectMessage();
         message.setStringProperty(HttpHeaderProperty.CONTENT_TYPE, "application/xml");
         message.setObject(value);
         producer.send(message);
      } finally {
         conn.close();
      }
   }
}


<|start_filename|>tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/util/ObjectInputStreamWithClassLoaderTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.unit.util;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

import org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1.EnclosingClass;
import org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1.TestClass1;
import org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1.TestClass2;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.utils.ObjectInputStreamWithClassLoader;
import org.junit.Assert;
import org.junit.Test;

public class ObjectInputStreamWithClassLoaderTest extends ActiveMQTestBase {

   // Constants -----------------------------------------------------

   // Attributes ----------------------------------------------------

   // Static --------------------------------------------------------

   public static ClassLoader newClassLoader(final Class... userClasses) throws Exception {

      Set<URL> userClassUrls = new HashSet<>();
      for (Class anyUserClass : userClasses) {
         ProtectionDomain protectionDomain = anyUserClass.getProtectionDomain();
         CodeSource codeSource = protectionDomain.getCodeSource();
         URL classLocation = codeSource.getLocation();
         userClassUrls.add(classLocation);
      }
      StringTokenizer tokenString = new StringTokenizer(System.getProperty("java.class.path"), File.pathSeparator);
      String pathIgnore = System.getProperty("java.home");
      if (pathIgnore == null) {
         pathIgnore = userClassUrls.iterator().next().toString();
      }

      List<URL> urls = new ArrayList<>();
      while (tokenString.hasMoreElements()) {
         String value = tokenString.nextToken();
         URL itemLocation = new File(value).toURI().toURL();
         if (!userClassUrls.contains(itemLocation) && itemLocation.toString().indexOf(pathIgnore) >= 0) {
            urls.add(itemLocation);
         }
      }
      URL[] urlArray = urls.toArray(new URL[urls.size()]);

      ClassLoader masterClassLoader = URLClassLoader.newInstance(urlArray, null);
      ClassLoader appClassLoader = URLClassLoader.newInstance(userClassUrls.toArray(new URL[0]), masterClassLoader);
      return appClassLoader;
   }

   // Constructors --------------------------------------------------

   // Public --------------------------------------------------------

   @Test
   public void testClassLoaderIsolation() throws Exception {

      ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
      try {
         AnObject obj = new AnObjectImpl();
         byte[] bytes = ObjectInputStreamWithClassLoaderTest.toBytes(obj);

         //Class.isAnonymousClass() call used in ObjectInputStreamWithClassLoader
         //need to access the enclosing class and its parent class of the obj
         //i.e. ActiveMQTestBase and Assert.
         ClassLoader testClassLoader = ObjectInputStreamWithClassLoaderTest.newClassLoader(obj.getClass(), ActiveMQTestBase.class, Assert.class);
         Thread.currentThread().setContextClassLoader(testClassLoader);

         ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
         ObjectInputStreamWithClassLoader ois = new ObjectInputStreamWithClassLoader(bais);

         Object deserializedObj = ois.readObject();

         Assert.assertNotSame(obj, deserializedObj);
         Assert.assertNotSame(obj.getClass(), deserializedObj.getClass());
         Assert.assertNotSame(obj.getClass().getClassLoader(), deserializedObj.getClass().getClassLoader());
         Assert.assertSame(testClassLoader, deserializedObj.getClass().getClassLoader());
      } finally {
         Thread.currentThread().setContextClassLoader(originalClassLoader);
      }

   }

   @Test
   public void testClassLoaderIsolationWithProxy() throws Exception {

      ClassLoader originalClassLoader = Thread.currentThread().getContextClassLoader();
      try {
         AnObject originalProxy = (AnObject) Proxy.newProxyInstance(AnObject.class.getClassLoader(), new Class[]{AnObject.class}, new AnObjectInvocationHandler());
         originalProxy.setMyInt(100);
         byte[] bytes = ObjectInputStreamWithClassLoaderTest.toBytes(originalProxy);

         ClassLoader testClassLoader = ObjectInputStreamWithClassLoaderTest.newClassLoader(this.getClass(), ActiveMQTestBase.class, Assert.class);
         Thread.currentThread().setContextClassLoader(testClassLoader);
         ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
         ObjectInputStreamWithClassLoader ois = new ObjectInputStreamWithClassLoader(bais);

         Runnable toRun = (Runnable) testClassLoader.loadClass(ProxyReader.class.getName()).newInstance();
         toRun.getClass().getField("ois").set(toRun, ois);
         toRun.getClass().getField("testClassLoader").set(toRun, testClassLoader);
         toRun.getClass().getField("originalProxy").set(toRun, originalProxy);

         toRun.run();

      } finally {
         Thread.currentThread().setContextClassLoader(originalClassLoader);
      }

   }

   @Test
   public void testWhiteBlackList() throws Exception {
      File serailizeFile = new File(temporaryFolder.getRoot(), "testclass.bin");
      ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(serailizeFile));
      try {
         outputStream.writeObject(new TestClass1());
         outputStream.flush();
      } finally {
         outputStream.close();
      }

      //default
      assertNull(readSerializedObject(null, null, serailizeFile));

      //white list
      String whiteList = "org.apache.activemq.artemis.tests.unit.util.deserialization";
      assertNull(readSerializedObject(whiteList, null, serailizeFile));
      whiteList = "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1";
      assertNull(readSerializedObject(whiteList, null, serailizeFile));

      whiteList = "some.other.package";
      Exception result = readSerializedObject(whiteList, null, serailizeFile);
      assertTrue(result instanceof ClassNotFoundException);

      //blacklist
      String blackList = "org.apache.activemq.artemis.tests.unit.util";
      result = readSerializedObject(null, blackList, serailizeFile);
      assertTrue(result instanceof ClassNotFoundException);

      blackList = "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1";
      result = readSerializedObject(null, blackList, serailizeFile);
      assertTrue(result instanceof ClassNotFoundException);

      blackList = "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg2";
      result = readSerializedObject(null, blackList, serailizeFile);
      assertNull(result);

      blackList = "some.other.package";
      whiteList = "some.other.package1";
      result = readSerializedObject(whiteList, blackList, serailizeFile);
      assertTrue(result instanceof ClassNotFoundException);

      //blacklist priority
      blackList = "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1, some.other.package";
      whiteList = "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1";
      result = readSerializedObject(whiteList, blackList, serailizeFile);
      assertTrue(result instanceof ClassNotFoundException);

      blackList = "org.apache.activemq.artemis.tests.unit, some.other.package";
      whiteList = "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1";
      result = readSerializedObject(whiteList, blackList, serailizeFile);
      assertTrue(result instanceof ClassNotFoundException);

      blackList = "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1.pkg2, some.other.package";
      whiteList = "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1";
      result = readSerializedObject(whiteList, blackList, serailizeFile);
      assertNull(result);

      blackList = "some.other.package, org.apache.activemq.artemis.tests.unit.util.deserialization.pkg2";
      whiteList = "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1";
      result = readSerializedObject(whiteList, blackList, serailizeFile);
      assertNull(result);

      //wildcard
      blackList = "*";
      whiteList = "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1";
      result = readSerializedObject(whiteList, blackList, serailizeFile);
      assertTrue(result instanceof ClassNotFoundException);

      blackList = "*";
      whiteList = "*";
      result = readSerializedObject(whiteList, blackList, serailizeFile);
      assertTrue(result instanceof ClassNotFoundException);
      result = readSerializedObject(whiteList, null, serailizeFile);
      assertNull(result);
   }

   @Test
   public void testWhiteBlackListAgainstArrayObject() throws Exception {
      File serailizeFile = new File(temporaryFolder.getRoot(), "testclass.bin");
      TestClass1[] sourceObject = new TestClass1[]{new TestClass1()};

      ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(serailizeFile));
      try {
         outputStream.writeObject(sourceObject);
         outputStream.flush();
      } finally {
         outputStream.close();
      }

      //default ok
      String blackList = null;
      String whiteList = null;

      Object result = readSerializedObject(whiteList, blackList, serailizeFile);
      assertNull(result);

      //now blacklist TestClass1
      blackList = "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1.TestClass1";
      whiteList = null;

      result = readSerializedObject(whiteList, blackList, serailizeFile);
      assertTrue(result instanceof ClassNotFoundException);

      //now whitelist TestClass1, it should pass.
      blackList = null;
      whiteList = "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1.TestClass1";

      result = readSerializedObject(whiteList, blackList, serailizeFile);
      assertNull(result);
   }

   @Test
   public void testWhiteBlackListAgainstListObject() throws Exception {
      File serailizeFile = new File(temporaryFolder.getRoot(), "testclass.bin");
      List<TestClass1> sourceObject = new ArrayList<>();
      sourceObject.add(new TestClass1());

      ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(serailizeFile));
      try {
         outputStream.writeObject(sourceObject);
         outputStream.flush();
      } finally {
         outputStream.close();
      }

      //default ok
      String blackList = null;
      String whiteList = null;

      Object result = readSerializedObject(whiteList, blackList, serailizeFile);
      assertNull(result);

      //now blacklist TestClass1
      blackList = "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1.TestClass1";
      whiteList = null;

      result = readSerializedObject(whiteList, blackList, serailizeFile);
      assertTrue(result instanceof ClassNotFoundException);

      //now whitelist TestClass1, should fail because the List type is not allowed
      blackList = null;
      whiteList = "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1.TestClass1";

      result = readSerializedObject(whiteList, blackList, serailizeFile);
      assertTrue(result instanceof ClassNotFoundException);

      //now add List to white list, it should pass
      blackList = null;
      whiteList = "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1.TestClass1," + "java.util.ArrayList";
      result = readSerializedObject(whiteList, blackList, serailizeFile);
      assertNull(result);

   }

   @Test
   public void testWhiteBlackListAgainstListMapObject() throws Exception {
      File serailizeFile = new File(temporaryFolder.getRoot(), "testclass.bin");
      Map<TestClass1, TestClass2> sourceObject = new HashMap<>();
      sourceObject.put(new TestClass1(), new TestClass2());

      ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(serailizeFile));
      try {
         outputStream.writeObject(sourceObject);
         outputStream.flush();
      } finally {
         outputStream.close();
      }

      String blackList = null;
      String whiteList = null;

      Object result = readSerializedObject(whiteList, blackList, serailizeFile);
      assertNull(result);

      //now blacklist the key
      blackList = "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1.TestClass1";
      whiteList = null;

      result = readSerializedObject(whiteList, blackList, serailizeFile);
      assertTrue(result instanceof ClassNotFoundException);

      //now blacklist the value
      blackList = "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1.TestClass2";
      whiteList = null;

      result = readSerializedObject(whiteList, blackList, serailizeFile);
      assertTrue(result instanceof ClassNotFoundException);

      //now white list the key, should fail too because value is forbidden
      blackList = null;
      whiteList = "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1.TestClass1";

      result = readSerializedObject(whiteList, blackList, serailizeFile);
      assertTrue(result instanceof ClassNotFoundException);

      //now white list the value, should fail too because the key is forbidden
      blackList = null;
      whiteList = "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1.TestClass2";

      result = readSerializedObject(whiteList, blackList, serailizeFile);
      assertTrue(result instanceof ClassNotFoundException);

      //both key and value are in the whitelist, it should fail because HashMap not permitted
      blackList = null;
      whiteList = "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1.TestClass1," + "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1.TestClass2";

      result = readSerializedObject(whiteList, blackList, serailizeFile);
      assertTrue(result instanceof ClassNotFoundException);

      //now add HashMap, test should pass.
      blackList = null;
      whiteList = "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1.TestClass1," +
         "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1.TestClass2," +
         "java.util.HashMap";

      result = readSerializedObject(whiteList, blackList, serailizeFile);
      assertNull(result);

   }

   @Test
   public void testWhiteBlackListAnonymousObject() throws Exception {
      File serailizeFile = new File(temporaryFolder.getRoot(), "testclass.bin");
      ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(serailizeFile));
      try {
         Serializable object = EnclosingClass.anonymousObject;
         assertTrue(object.getClass().isAnonymousClass());
         outputStream.writeObject(object);
         outputStream.flush();
      } finally {
         outputStream.close();
      }

      //default
      String blackList = null;
      String whiteList = null;
      assertNull(readSerializedObject(whiteList, blackList, serailizeFile));

      //forbidden by specifying the enclosing class
      blackList = "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1.EnclosingClass";
      Object result = readSerializedObject(whiteList, blackList, serailizeFile);
      assertTrue(result instanceof ClassNotFoundException);

      //do it in whiteList
      blackList = null;
      whiteList = "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1.EnclosingClass";
      result = readSerializedObject(whiteList, blackList, serailizeFile);
      assertNull(result);
   }

   @Test
   public void testWhiteBlackListLocalObject() throws Exception {
      File serailizeFile = new File(temporaryFolder.getRoot(), "testclass.bin");
      ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(serailizeFile));
      try {
         Object object = EnclosingClass.getLocalObject();
         assertTrue(object.getClass().isLocalClass());
         outputStream.writeObject(object);
         outputStream.flush();
      } finally {
         outputStream.close();
      }

      //default
      String blackList = null;
      String whiteList = null;
      assertNull(readSerializedObject(whiteList, blackList, serailizeFile));

      //forbidden by specifying the enclosing class
      blackList = "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1.EnclosingClass";
      Object result = readSerializedObject(whiteList, blackList, serailizeFile);
      assertTrue(result instanceof ClassNotFoundException);

      //do it in whiteList
      blackList = null;
      whiteList = "org.apache.activemq.artemis.tests.unit.util.deserialization.pkg1.EnclosingClass";
      result = readSerializedObject(whiteList, blackList, serailizeFile);
      assertNull(result);
   }

   @Test
   public void testWhiteBlackListSystemProperty() throws Exception {

      File serailizeFile = new File(temporaryFolder.getRoot(), "testclass.bin");
      ObjectOutputStream outputStream = new ObjectOutputStream(new FileOutputStream(serailizeFile));
      try {
         outputStream.writeObject(new TestClass1());
         outputStream.flush();
      } finally {
         outputStream.close();
      }

      System.setProperty(ObjectInputStreamWithClassLoader.BLACKLIST_PROPERTY, "system.defined.black.list");
      System.setProperty(ObjectInputStreamWithClassLoader.WHITELIST_PROPERTY, "system.defined.white.list");
      try {
         ObjectInputStreamWithClassLoader ois = new ObjectInputStreamWithClassLoader(new FileInputStream(serailizeFile));
         String bList = ois.getBlackList();
         String wList = ois.getWhiteList();
         assertEquals("wrong black list: " + bList, "system.defined.black.list", bList);
         assertEquals("wrong white list: " + wList, "system.defined.white.list", wList);
         ois.close();
      } finally {
         System.clearProperty(ObjectInputStreamWithClassLoader.BLACKLIST_PROPERTY);
         System.clearProperty(ObjectInputStreamWithClassLoader.WHITELIST_PROPERTY);
      }
   }

   private Exception readSerializedObject(String whiteList, String blackList, File serailizeFile) {
      Exception result = null;

      ObjectInputStreamWithClassLoader ois = null;

      try {
         ois = new ObjectInputStreamWithClassLoader(new FileInputStream(serailizeFile));
         ois.setWhiteList(whiteList);
         ois.setBlackList(blackList);
         ois.readObject();
      } catch (Exception e) {
         result = e;
      } finally {
         try {
            ois.close();
         } catch (IOException e) {
            result = e;
         }
      }
      return result;
   }

   // Package protected ---------------------------------------------

   // Protected -----------------------------------------------------

   // Private -------------------------------------------------------

   public static class ProxyReader implements Runnable {

      public java.io.ObjectInputStream ois;
      public Object originalProxy;
      public ClassLoader testClassLoader;

      // We don't have access to the junit framework on the classloader where this is running
      void myAssertNotSame(Object obj, Object obj2) {
         if (obj == obj2) {
            throw new RuntimeException("Expected to be different objects");
         }
      }

      // We don't have access to the junit framework on the classloader where this is running
      void myAssertSame(Object obj, Object obj2) {
         if (obj != obj2) {
            throw new RuntimeException("Expected to be the same objects");
         }
      }

      @Override
      public void run() {

         try {
            Object deserializedObj = ois.readObject();

            // cannot use logging here, as this test is playing with classLoading here.
            System.out.println("Deserialized Object " + deserializedObj);

            myAssertNotSame(originalProxy, deserializedObj);
            myAssertNotSame(originalProxy.getClass(), deserializedObj.getClass());
            myAssertNotSame(originalProxy.getClass().getClassLoader(), deserializedObj.getClass().getClassLoader());
            myAssertSame(testClassLoader, deserializedObj.getClass().getClassLoader());

            AnObject myInterface = (AnObject) deserializedObj;

            if (myInterface.getMyInt() != 200) {
               throw new RuntimeException("invalid result");
            }
         } catch (ClassNotFoundException e) {
            throw new RuntimeException(e.getMessage(), e);
         } catch (IOException e) {
            throw new RuntimeException(e.getMessage(), e);
         }

      }
   }

   private static byte[] toBytes(final Object obj) throws IOException {
      Assert.assertTrue(obj instanceof Serializable);
      ByteArrayOutputStream baos = new ByteArrayOutputStream();
      ObjectOutputStream oos = new ObjectOutputStream(baos);
      oos.writeObject(obj);
      oos.flush();
      return baos.toByteArray();
   }

   // Inner classes -------------------------------------------------

   private interface AnObject extends Serializable {

      int getMyInt();

      void setMyInt(int value);

      long getMyLong();

      void setMyLong(long value);
   }

   private static class AnObjectImpl implements AnObject {

      private static final long serialVersionUID = -5172742084489525256L;

      int myInt = 0;
      long myLong = 0L;

      @Override
      public int getMyInt() {
         return myInt;
      }

      @Override
      public void setMyInt(int value) {
         this.myInt = value;
      }

      @Override
      public long getMyLong() {
         return myLong;
      }

      @Override
      public void setMyLong(long value) {
         this.myLong = value;
      }
   }

   private static class AnObjectInvocationHandler implements InvocationHandler, Serializable {

      private static final long serialVersionUID = -3875973764178767452L;
      private final AnObject anObject = new AnObjectImpl();

      @Override
      public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
         Object obj = method.invoke(anObject, args);
         if (obj instanceof Integer) {
            return ((Integer) obj).intValue() * 2;
         } else {
            return obj;
         }

      }
   }
}


<|start_filename|>artemis-commons/src/main/java/org/apache/activemq/artemis/utils/RandomUtil.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.utils;

import java.util.Random;

import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.ActiveMQBuffers;
import org.apache.activemq.artemis.api.core.SimpleString;

public class RandomUtil {
   // Constants -----------------------------------------------------

   protected static final Random random = new Random();

   public static Random getRandom() {
      return random;
   }

   // Attributes ----------------------------------------------------

   // Static --------------------------------------------------------

   public static String randomString() {
      return java.util.UUID.randomUUID().toString();
   }

   public static SimpleString randomSimpleString() {
      return new SimpleString(RandomUtil.randomString());
   }

   public static char randomChar() {
      return RandomUtil.randomString().charAt(0);
   }

   public static long randomLong() {
      return RandomUtil.random.nextLong();
   }

   public static long randomPositiveLong() {
      return Math.abs(RandomUtil.randomLong());
   }

   public static int randomInt() {
      return RandomUtil.random.nextInt();
   }

   public static int randomPositiveInt() {
      return Math.abs(RandomUtil.randomInt());
   }

   public static ActiveMQBuffer randomBuffer(final int size, final long... data) {
      ActiveMQBuffer buffer = ActiveMQBuffers.fixedBuffer(size + 8 * data.length);

      for (long d : data) {
         buffer.writeLong(d);
      }

      for (int i = 0; i < size; i++) {
         buffer.writeByte(randomByte());
      }

      return buffer;
   }

   public static int randomInterval(final int min, final int max) {
      if (min == max) return max;
      return min + random.nextInt(max - min);
   }

   public static int randomMax(final int max) {
      assert max > 0;

      int value = randomPositiveInt() % max;

      if (value == 0) {
         value = max;
      }

      return value;
   }

   public static int randomPort() {
      return RandomUtil.random.nextInt(65536);
   }

   public static short randomShort() {
      return (short) RandomUtil.random.nextInt(Short.MAX_VALUE);
   }

   public static byte randomByte() {
      return Integer.valueOf(RandomUtil.random.nextInt()).byteValue();
   }

   public static boolean randomBoolean() {
      return RandomUtil.random.nextBoolean();
   }

   public static byte[] randomBytes() {
      return RandomUtil.randomString().getBytes();
   }

   public static byte[] randomBytes(final int length) {
      byte[] bytes = new byte[length];
      for (int i = 0; i < bytes.length; i++) {
         bytes[i] = RandomUtil.randomByte();
      }
      return bytes;
   }

   public static double randomDouble() {
      return RandomUtil.random.nextDouble();
   }

   public static float randomFloat() {
      return RandomUtil.random.nextFloat();
   }

   // Constructors --------------------------------------------------

   // Public --------------------------------------------------------

   // Package protected ---------------------------------------------

   // Protected -----------------------------------------------------

   // Private -------------------------------------------------------

   // Inner classes -------------------------------------------------
}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/server/metrics/NettyPooledAllocatorMetrics.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.server.metrics;

import java.util.List;
import java.util.function.Function;

import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.binder.MeterBinder;
import io.netty.buffer.PoolChunkListMetric;
import io.netty.buffer.PoolChunkMetric;
import io.netty.buffer.PoolSubpageMetric;
import io.netty.buffer.PooledByteBufAllocatorMetric;
import io.micrometer.core.instrument.FunctionCounter;
import io.netty.buffer.PoolArenaMetric;

public final class NettyPooledAllocatorMetrics implements MeterBinder {

   private static final String BYTES_UNIT = "bytes";
   private final PooledByteBufAllocatorMetric metric;

   public NettyPooledAllocatorMetrics(final PooledByteBufAllocatorMetric pooledAllocatorMetric) {
      this.metric = pooledAllocatorMetric;
   }

   @Override
   public void bindTo(final MeterRegistry registry) {

      Gauge.builder("netty.pooled.used.memory", this.metric, metric -> metric.usedDirectMemory())
         .tags("type", "direct")
         .description("The used memory")
         .baseUnit(BYTES_UNIT).register(registry);

      Gauge.builder("netty.pooled.used.memory", this.metric, metric -> metric.usedHeapMemory())
         .tags("type", "heap")
         .description("The used memory")
         .baseUnit(BYTES_UNIT).register(registry);

      Gauge.builder("netty.pooled.arenas.num", this.metric, metric -> metric.numDirectArenas())
         .tags("type", "direct")
         .description("The number of arenas")
         .register(registry);

      Gauge.builder("netty.pooled.arenas.num", this.metric, metric -> metric.numHeapArenas())
         .tags("type", "heap").description("The number or arenas")
         .register(registry);

      Gauge.builder("netty.pooled.cachesize", this.metric, metric -> metric.tinyCacheSize())
         .tags("type", "tiny")
         .description("The cachesize used by this netty allocator")
         .register(registry);

      Gauge.builder("netty.pooled.cachesize", this.metric, metric -> metric.smallCacheSize())
         .tags("type", "small")
         .description("The cachesize used by this netty allocator")
         .register(registry);

      Gauge.builder("netty.pooled.cachesize", this.metric, metric -> metric.normalCacheSize())
         .tags("type", "normal")
         .description("The cachesize used by this netty allocator")
         .register(registry);

      Gauge.builder("netty.pooled.threadlocalcache.num", this.metric, metric -> metric.numThreadLocalCaches())
         .description("The number of thread local caches used by this netty allocator")
         .register(registry);

      Gauge.builder("netty.pooled.chunk.size", this.metric, metric -> metric.chunkSize())
         .description("The arena chunk size of this netty allocator")
         .baseUnit(BYTES_UNIT)
         .register(registry);

      {
         int i = 0;
         for (final PoolArenaMetric poolArenaMetric : metric.directArenas()) {
            metricsOfPoolArena(registry, poolArenaMetric, i++, "direct");
         }
      }
      {
         int i = 0;
         for (final PoolArenaMetric poolArenaMetric : metric.heapArenas()) {
            metricsOfPoolArena(registry, poolArenaMetric, i++, "heap");
         }
      }
   }

   private void metricsOfPoolArena(final MeterRegistry registry,
                                   final PoolArenaMetric poolArenaMetric,
                                   final int poolArenaIndex,
                                   final String poolArenaType) {
      /**
       * the number of thread caches backed by this arena.
       */
      final String poolArenaIndexString = Integer.toString(poolArenaIndex);
      Gauge.builder("netty.pooled.arena.threadcaches.num", poolArenaMetric, metric -> metric.numThreadCaches())
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndexString)
         .description("The number of thread caches backed by this arena")
         .register(registry);

      FunctionCounter.builder("netty.pooled.arena.allocations.num", poolArenaMetric,
         metric -> metric.numAllocations())
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndexString, "size", "all")
         .description("The number of allocations done via the arena. This includes all sizes")
         .register(registry);

      FunctionCounter.builder("netty.pooled.arena.allocations.num", poolArenaMetric,
         metric -> metric.numTinyAllocations())
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndexString, "size", "tiny")
         .description("The number of tiny allocations done via the arena")
         .register(registry);

      FunctionCounter.builder("netty.pooled.arena.allocations.num", poolArenaMetric,
         metric -> metric.numSmallAllocations())
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndexString, "size", "small")
         .description("The number of small allocations done via the arena")
         .register(registry);

      FunctionCounter.builder("netty.pooled.arena.allocations.num", poolArenaMetric,
         metric -> metric.numNormalAllocations())
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndexString, "size", "normal")
         .description("The number of normal allocations done via the arena")
         .register(registry);

      FunctionCounter.builder("netty.pooled.arena.allocations.num", poolArenaMetric,
         metric -> metric.numHugeAllocations())
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndexString, "size", "huge")
         .description("The number of huge allocations done via the arena")
         .register(registry);

      FunctionCounter.builder("netty.pooled.arena.deallocations.num", poolArenaMetric,
         metric -> metric.numDeallocations())
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndexString, "size", "all")
         .description("The number of deallocations done via the arena. This includes all sizes")
         .register(registry);

      FunctionCounter.builder("netty.pooled.arena.deallocations.num", poolArenaMetric,
         metric -> metric.numTinyDeallocations())
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndexString, "size", "tiny")
         .description("The number of tiny deallocations done via the arena")
         .register(registry);

      FunctionCounter.builder("netty.pooled.arena.deallocations.num", poolArenaMetric,
         metric -> metric.numSmallDeallocations())
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndexString, "size", "small")
         .description("The number of small deallocations done via the arena")
         .register(registry);

      FunctionCounter.builder("netty.pooled.arena.deallocations.num", poolArenaMetric,
         metric -> metric.numNormalDeallocations())
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndexString, "size", "normal")
         .description("The number of normal deallocations done via the arena")
         .register(registry);

      FunctionCounter.builder("netty.pooled.arena.deallocations.num", poolArenaMetric,
         metric -> metric.numHugeDeallocations())
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndexString, "size", "huge")
         .description("The number of huge deallocations done via the arena")
         .register(registry);

      Gauge.builder("netty.pooled.arena.active.allocations.num", poolArenaMetric,
         metric -> metric.numActiveAllocations())
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndexString, "size", "all")
         .description("The number of currently active allocations")
         .register(registry);

      Gauge.builder("netty.pooled.arena.active.allocations.num", poolArenaMetric,
         metric -> metric.numActiveTinyAllocations())
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndexString, "size", "tiny")
         .description("The number of currently active tiny allocations")
         .register(registry);

      Gauge.builder("netty.pooled.arena.active.allocations.num", poolArenaMetric,
         metric -> metric.numActiveSmallAllocations())
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndexString, "size", "small")
         .description("The number of currently active small allocations")
         .register(registry);

      Gauge.builder("netty.pooled.arena.active.allocations.num", poolArenaMetric,
         metric -> metric.numActiveNormalAllocations())
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndexString, "size", "normal")
         .description("The number of currently active normal allocations")
         .register(registry);

      Gauge.builder("netty.pooled.arena.active.allocations.num", poolArenaMetric,
         metric -> metric.numActiveHugeAllocations())
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndexString, "size", "huge")
         .description("The number of currently active huge allocations")
         .register(registry);

      Gauge.builder("netty.pooled.arena.active.allocated.num", poolArenaMetric,
         metric -> metric.numActiveBytes())
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndexString)
         .description("The number of active bytes that are currently allocated by the arena")
         .baseUnit(BYTES_UNIT).register(registry);

      Gauge.builder("netty.pooled.arena.chunk.num", poolArenaMetric,
         metric -> metric.numChunkLists())
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndexString)
         .description("The number of chunk lists for the arena")
         .register(registry);

      Gauge.builder("netty.pooled.arena.subpages.num", poolArenaMetric,
         metric -> metric.numTinySubpages())
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndexString, "size", "tiny")
         .description("The number of tiny sub-pages for the arena")
         .register(registry);

      Gauge.builder("netty.pooled.arena.subpages.num", poolArenaMetric,
         metric -> metric.numSmallSubpages())
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndexString, "size", "small")
         .description("The number of small sub-pages for the arena")
         .register(registry);

      List<PoolChunkListMetric> poolChunkListMetrics = poolArenaMetric.chunkLists();
      assert poolChunkListMetrics.size() == 6;
      for (PoolChunkListMetric poolChunkListMetric : poolChunkListMetrics) {
         final String poolChunkListType = usageTypeOf(poolChunkListMetric);
         metricsOfPoolChunkListMetric(registry, poolChunkListMetric, poolArenaIndexString, poolArenaType, poolChunkListType);
      }
      // smallSubpages metrics
      metricsOfPoolSubpageMetric(registry, poolArenaMetric, PoolArenaMetric::smallSubpages,
                                 poolArenaIndexString, poolArenaType, "small");
      // tinySubpages metrics
      metricsOfPoolSubpageMetric(registry, poolArenaMetric, PoolArenaMetric::tinySubpages,
                                 poolArenaIndexString, poolArenaType, "tiny");



   }

   private void metricsOfPoolSubpageMetric(final MeterRegistry registry,
                                           final PoolArenaMetric poolArenaMetric,
                                           final Function<? super PoolArenaMetric, List<PoolSubpageMetric>> poolSubpageMetricProvider,
                                           final String poolArenaIndex,
                                           final String poolArenaType,
                                           final String size) {
      Gauge.builder("netty.pooled.arena.subpages.count", poolArenaMetric, metric -> {
         long total = 0;
         for (PoolSubpageMetric poolSubpageMetric : poolSubpageMetricProvider.apply(metric)) {
            total++;
         }
         return total;
      })
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndex, "size", size)
         .description("The total count of subpages")
         .register(registry);

      Gauge.builder("netty.pooled.arena.subpages.elementsize", poolArenaMetric, metric -> {
         long total = 0;
         for (PoolSubpageMetric poolSubpageMetric : poolSubpageMetricProvider.apply(metric)) {
            total += poolSubpageMetric.elementSize();
         }
         return total;
      })
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndex, "size", size)
         .description("The total size (in bytes) of the elements that will be allocated")
         .baseUnit(BYTES_UNIT)
         .register(registry);

      Gauge.builder("netty.pooled.arena.subpages.maxnumelements", poolArenaMetric, metric -> {
         long total = 0;
         for (PoolSubpageMetric poolSubpageMetric : poolSubpageMetricProvider.apply(metric)) {
            total += poolSubpageMetric.maxNumElements();
         }
         return total;
      })
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndex, "size", size)
         .description("The total number of maximal elements that can be allocated out of the sub-page.")
         .register(registry);

      Gauge.builder("netty.pooled.arena.subpages.numavailable", poolArenaMetric, metric -> {
         long total = 0;
         for (PoolSubpageMetric poolSubpageMetric : poolSubpageMetricProvider.apply(metric)) {
            total += poolSubpageMetric.numAvailable();
         }
         return total;
      })
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndex, "size", size)
         .description("The total number of available elements to be allocated")
         .register(registry);
      Gauge.builder("netty.pooled.arena.subpages.pagesize", poolArenaMetric, metric -> {
         long total = 0;
         for (PoolSubpageMetric poolSubpageMetric : poolSubpageMetricProvider.apply(metric)) {
            total += poolSubpageMetric.pageSize();
         }
         return total;
      })
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndex, "size", size)
         .description("The total size (in bytes) of the pages")
         .baseUnit(BYTES_UNIT)
         .register(registry);
   }

   private static String usageTypeOf(PoolChunkListMetric metric) {
      // metrics.add(qInit); 0~25%     -> new PoolChunkList<T>(this, q000, Integer.MIN_VALUE, 25, chunkSize);
      // metrics.add(q000); 0~50%      -> new PoolChunkList<T>(this, q025, 1, 50, chunkSize);
      // metrics.add(q025); 25~75%     -> new PoolChunkList<T>(this, q050, 25, 75, chunkSize);
      // metrics.add(q050); 50~100%    -> new PoolChunkList<T>(this, q075, 50, 100, chunkSize);
      // metrics.add(q075); 75~100%    -> new PoolChunkList<T>(this, q100, 75, 100, chunkSize);
      // metrics.add(q100); 100%       -> new PoolChunkList<T>(this, null, 100, Integer.MAX_VALUE, chunkSize);
      final StringBuilder builder = new StringBuilder("75~100%".length());
      int minUsage = metric.minUsage();
      if (minUsage <= 1) {
         minUsage = 0;
      }
      builder.append(minUsage);
      int maxUsage = metric.maxUsage();
      if (maxUsage != minUsage) {
         builder.append('~').append(maxUsage);
      }
      builder.append('%');
      return builder.toString();
   }

   private void metricsOfPoolChunkListMetric(final MeterRegistry registry,
                                             final PoolChunkListMetric poolChunkListMetrics,
                                             final String poolArenaIndex,
                                             final String poolArenaType,
                                             final String poolChunkListType) {
      Gauge.builder("netty.pooled.arena.chunk.list.capacity", poolChunkListMetrics, metric -> {
         long total = 0;
         for (PoolChunkMetric poolChunkMetric : poolChunkListMetrics) {
            total += poolChunkMetric.chunkSize();
         }
         return total;
      })
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndex, "pool_chunk_list_type", poolChunkListType)
         .description("The total capacity in bytes of the chunks in the list")
         .baseUnit(BYTES_UNIT)
         .register(registry);
      Gauge.builder("netty.pooled.arena.chunk.list.free", poolChunkListMetrics, metric -> {
         long total = 0;
         for (PoolChunkMetric poolChunkMetric : poolChunkListMetrics) {
            total += poolChunkMetric.freeBytes();
         }
         return total;
      })
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndex, "pool_chunk_list_type", poolChunkListType)
         .description("The total free bytes of the chunks in the list")
         .baseUnit(BYTES_UNIT)
         .register(registry);

      Gauge.builder("netty.pooled.arena.chunk.list.count", poolChunkListMetrics, metric -> {
         long total = 0;
         for (PoolChunkMetric poolChunkMetric : poolChunkListMetrics) {
            total++;
         }
         return total;
      })
         .tags("pool_arena_type", poolArenaType, "pool_arena_index", poolArenaIndex, "pool_chunk_list_type", poolChunkListType)
         .description("The number of chunks in the list")
         .register(registry);
   }

}

<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cluster/JdbcNodeManagerTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.cluster;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicBoolean;

import org.apache.activemq.artemis.core.config.storage.DatabaseStorageConfiguration;
import org.apache.activemq.artemis.core.server.NodeManager;
import org.apache.activemq.artemis.core.server.impl.jdbc.JdbcNodeManager;
import org.apache.activemq.artemis.utils.ExecutorFactory;
import org.apache.activemq.artemis.utils.actors.OrderedExecutorFactory;
import org.junit.Assert;

public class JdbcNodeManagerTest extends NodeManagerTest {

   @Override
   public void performWork(NodeManagerAction... actions) throws Exception {
      List<NodeRunner> nodeRunners = new ArrayList<>();
      final ThreadFactory daemonThreadFactory = t -> {
         final Thread th = new Thread(t);
         th.setDaemon(true);
         return th;
      };
      Thread[] threads = new Thread[actions.length];
      List<ExecutorService> executors = new ArrayList<>(actions.length);
      List<NodeManager> nodeManagers = new ArrayList<>(actions.length * 2);
      AtomicBoolean failedRenew = new AtomicBoolean(false);
      for (NodeManagerAction action : actions) {
         final ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor(daemonThreadFactory);
         final ExecutorService executor = Executors.newFixedThreadPool(2, daemonThreadFactory);
         final DatabaseStorageConfiguration dbConf = createDefaultDatabaseStorageConfiguration();
         final ExecutorFactory executorFactory = new OrderedExecutorFactory(executor);
         JdbcNodeManager nodeManager = JdbcNodeManager.with(dbConf, scheduledExecutorService, executorFactory);
         nodeManager.start();
         NodeRunner nodeRunner = new NodeRunner(nodeManager, action);
         nodeRunners.add(nodeRunner);
         nodeManagers.add(nodeManager);
         executors.add(scheduledExecutorService);
         executors.add(executor);
      }
      for (int i = 0, nodeRunnersSize = nodeRunners.size(); i < nodeRunnersSize; i++) {
         NodeRunner nodeRunner = nodeRunners.get(i);
         threads[i] = new Thread(nodeRunner);
         threads[i].start();
      }
      boolean isDebug = isDebug();
      for (Thread thread : threads) {
         try {
            if (isDebug) {
               thread.join();
            } else {
               thread.join(60_000);
            }
         } catch (InterruptedException e) {
            //
         }
         if (thread.isAlive()) {
            thread.interrupt();
            fail("thread still running");
         }
      }
      // forcibly stop node managers
      nodeManagers.forEach(nodeManager -> {
         try {
            nodeManager.stop();
         } catch (Exception e) {
            // won't prevent the test to complete
            e.printStackTrace();
         }
      });

      // stop executors
      executors.forEach(ExecutorService::shutdownNow);

      for (NodeRunner nodeRunner : nodeRunners) {
         if (nodeRunner.e != null) {
            nodeRunner.e.printStackTrace();
            fail(nodeRunner.e.getMessage());
         }
      }
      Assert.assertFalse("Some of the lease locks has failed to renew the locks", failedRenew.get());
   }

}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cluster/failover/MultipleBackupsFailoverTestBase.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.cluster.failover;

import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.client.impl.ClientSessionFactoryInternal;
import org.apache.activemq.artemis.core.client.impl.ServerLocatorImpl;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.jms.client.ActiveMQTextMessage;
import org.apache.activemq.artemis.tests.integration.cluster.util.TestableServer;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.junit.Assert;

public abstract class MultipleBackupsFailoverTestBase extends ActiveMQTestBase {

   protected abstract boolean isNetty();

   protected int waitForNewLive(long seconds,
                                boolean waitForNewBackup,
                                Map<Integer, TestableServer> servers,
                                int... nodes) {
      long time = System.currentTimeMillis();
      long toWait = seconds * 1000;
      int newLive = -1;
      while (true) {
         for (int node : nodes) {
            TestableServer backupServer = servers.get(node);
            if (newLive == -1 && backupServer.isActive()) {
               newLive = node;
            } else if (newLive != -1) {
               if (waitForNewBackup) {
                  if (node != newLive && servers.get(node).isStarted()) {
                     return newLive;
                  }
               } else {
                  return newLive;
               }
            }
         }

         try {
            Thread.sleep(100);
         } catch (InterruptedException e) {
            // ignore
         }
         if (System.currentTimeMillis() > (time + toWait)) {
            Assert.fail("backup server never started");
         }
      }
   }

   protected ClientSession sendAndConsume(final ClientSessionFactory sf, final boolean createQueue) throws Exception {
      ClientSession session = sf.createSession(false, true, true);

      if (createQueue) {
         session.createQueue(new QueueConfiguration(FailoverTestBase.ADDRESS).setDurable(false));
      }

      ClientProducer producer = session.createProducer(FailoverTestBase.ADDRESS);

      final int numMessages = 1000;

      for (int i = 0; i < numMessages; i++) {
         ClientMessage message = session.createMessage(ActiveMQTextMessage.TYPE, false, 0, System.currentTimeMillis(), (byte) 1);
         message.putIntProperty(new SimpleString("count"), i);
         message.getBodyBuffer().writeString("aardvarks");
         producer.send(message);
      }

      ClientConsumer consumer = session.createConsumer(FailoverTestBase.ADDRESS);

      session.start();

      for (int i = 0; i < numMessages; i++) {
         ClientMessage message2 = consumer.receive(10000);

         Assert.assertNotNull(message2);

         Assert.assertEquals("aardvarks", message2.getBodyBuffer().readString());

         Assert.assertEquals(i, message2.getObjectProperty(new SimpleString("count")));

         message2.acknowledge();
      }

      ClientMessage message3 = consumer.receiveImmediate();

      Assert.assertNull(message3);

      return session;
   }

   protected ClientSessionFactoryInternal createSessionFactoryAndWaitForTopology(ServerLocator locator,
                                                                                 int topologyMembers) throws Exception {
      return createSessionFactoryAndWaitForTopology(locator, topologyMembers, null);
   }

   protected ClientSessionFactoryInternal createSessionFactoryAndWaitForTopology(ServerLocator locator,
                                                                                 int topologyMembers,
                                                                                 ActiveMQServer server) throws Exception {
      ClientSessionFactoryInternal sf;
      CountDownLatch countDownLatch = new CountDownLatch(topologyMembers);

      FailoverTestBase.LatchClusterTopologyListener topListener = new FailoverTestBase.LatchClusterTopologyListener(countDownLatch);
      locator.addClusterTopologyListener(topListener);

      sf = (ClientSessionFactoryInternal) locator.createSessionFactory();
      addSessionFactory(sf);

      boolean ok = countDownLatch.await(5, TimeUnit.SECONDS);
      locator.removeClusterTopologyListener(topListener);
      if (!ok) {
         if (server != null) {
            instanceLog.warn("failed topology, Topology on server = " + server.getClusterManager().describe());
         }
      }
      Assert.assertTrue("expected " + topologyMembers + " members", ok);
      return sf;
   }

   public ServerLocator getServerLocator(int... nodes) {
      TransportConfiguration[] configs = new TransportConfiguration[nodes.length];
      for (int i = 0, configsLength = configs.length; i < configsLength; i++) {
         configs[i] = createTransportConfiguration(isNetty(), false, generateParams(nodes[i], isNetty()));
      }
      return addServerLocator(new ServerLocatorImpl(true, configs));
   }
}


<|start_filename|>artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/RefCountMessage.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.api.core;

import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;

// import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet; -- #ifdef DEBUG

public class RefCountMessage {

   private static final AtomicIntegerFieldUpdater<RefCountMessage> DURABLE_REF_COUNT_UPDATER = AtomicIntegerFieldUpdater.newUpdater(RefCountMessage.class, "durableRefCount");
   private static final AtomicIntegerFieldUpdater<RefCountMessage> REF_COUNT_UPDATER = AtomicIntegerFieldUpdater.newUpdater(RefCountMessage.class, "refCount");
   private static final AtomicIntegerFieldUpdater<RefCountMessage> REF_USAGE_UPDATER = AtomicIntegerFieldUpdater.newUpdater(RefCountMessage.class, "usageCount");

   private volatile int durableRefCount = 0;

   private volatile int refCount = 0;

   private volatile int usageCount = 0;

   private volatile boolean fired = false;

   public int getRefCount() {
      return REF_COUNT_UPDATER.get(this);
   }

   public int getUsage() {
      return REF_USAGE_UPDATER.get(this);
   }

   public int getDurableCount() {
      return DURABLE_REF_COUNT_UPDATER.get(this);
   }

   /**
    * in certain cases the large message is copied from another LargeServerMessage
    * and the ref count needs to be on that place.
    */
   private volatile RefCountMessage parentRef;

   public RefCountMessage getParentRef() {
      return parentRef;
   }
   // I am usually against keeping commented out code
   // However this is very useful for me to debug referencing counting.
   // Uncomment out anything between #ifdef DEBUG and #endif

   // #ifdef DEBUG -- comment out anything before endif if you want to debug REFERENCE COUNTS
   //final ConcurrentHashSet<Exception> upSet = new ConcurrentHashSet<>();
   // #endif

   private void onUp() {
      // #ifdef DEBUG -- comment out anything before endif if you want to debug REFERENCE COUNTS
      // upSet.add(new Exception("upEvent(" + debugString() + ")"));
      // #endif
   }

   private void onDown() {
      // #ifdef DEBUG -- comment out anything before endif if you want to debug REFERENCE COUNTS
      // upSet.add(new Exception("upEvent(" + debugString() + ")"));
      // #endif
      if (getRefCount() <= 0 && getUsage() <= 0 && getDurableCount() <= 0 && !fired) {

         debugRefs();
         fired = true;
         releaseComplete();
      }
   }
   /**
    *
    * This method will be useful if you remove commented out code around #ifdef AND #endif COMMENTS
    * */
   public final void debugRefs() {
      // #ifdef DEBUG -- comment out anything before endif if you want to debug REFERENCE COUNTS
      //   try {
      //      System.err.println("************************************************************************************************************************");
      //      System.err.println("Printing refcounts for " + debugString() + " this = " + this);
      //      for (Exception e : upSet) {
      //         e.printStackTrace();
      //      }
      //      System.err.println("************************************************************************************************************************");
      //   } catch (Throwable e) {
      //      e.printStackTrace();
      //   }
      // #ifdef DEBUG -- comment out anything before endif if you want to debug REFERENCE COUNTS
   }



   public String debugString() {
      return "refCount=" + getRefCount() + ", durableRefCount=" + getDurableCount() + ", usageCount=" + getUsage() + ", parentRef=" + this.parentRef;
   }
   public void setParentRef(RefCountMessage origin) {
      // if copy of a copy.. just go to the parent:
      if (origin.getParentRef() != null) {
         this.parentRef = origin.getParentRef();
      } else {
         this.parentRef = origin;
      }
   }

   protected void releaseComplete() {
   }

   public int usageUp() {
      if (parentRef != null) {
         return parentRef.usageUp();
      }
      int count = REF_USAGE_UPDATER.incrementAndGet(this);
      onUp();
      return count;
   }
   public int usageDown() {
      if (parentRef != null) {
         return parentRef.usageDown();
      }
      int count = REF_USAGE_UPDATER.decrementAndGet(this);
      onDown();
      return count;
   }

   public int durableUp() {
      if (parentRef != null) {
         return parentRef.durableUp();
      }
      int count = DURABLE_REF_COUNT_UPDATER.incrementAndGet(this);
      onUp();
      return count;
   }

   public int durableDown() {
      if (parentRef != null) {
         return parentRef.durableDown();
      }
      int count = DURABLE_REF_COUNT_UPDATER.decrementAndGet(this);
      onDown();
      return count;
   }

   public int refDown() {
      if (parentRef != null) {
         return parentRef.refDown();
      }
      int count = REF_COUNT_UPDATER.decrementAndGet(this);
      onDown();
      return count;
   }

   public int refUp() {
      if (parentRef != null) {
         return parentRef.refUp();
      }
      int count = REF_COUNT_UPDATER.incrementAndGet(this);
      onUp();
      return count;
   }

}


<|start_filename|>examples/features/standard/security-manager/src/main/java/org/apache/activemq/artemis/jms/example/JAASSecurityManagerWrapper.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.jms.example;

import javax.security.auth.Subject;
import java.util.Map;
import java.util.Set;

import org.apache.activemq.artemis.core.security.CheckType;
import org.apache.activemq.artemis.core.security.Role;
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager;
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager5;

public class JAASSecurityManagerWrapper implements ActiveMQSecurityManager5 {
   ActiveMQJAASSecurityManager activeMQJAASSecurityManager;

   @Override
   public Subject authenticate(String user, String password, RemotingConnection remotingConnection, String securityDomain) {
      System.out.println("authenticate(" + user + ", " + password + ", " + remotingConnection.getRemoteAddress() + ", " + securityDomain + ")");
      return activeMQJAASSecurityManager.authenticate(user, password, remotingConnection, securityDomain);
   }

   @Override
   public boolean authorize(Subject subject,
                            Set<Role> roles,
                            CheckType checkType,
                            String address) {
      System.out.println("authorize(" + subject + ", " + roles + ", " + checkType + ", " + address + ")");
      return activeMQJAASSecurityManager.authorize(subject, roles, checkType, address);
   }

   @Override
   public String getDomain() {
      return activeMQJAASSecurityManager.getDomain();
   }

   @Override
   public boolean validateUser(String user, String password) {
      return activeMQJAASSecurityManager.validateUser(user, password);
   }

   @Override
   public boolean validateUserAndRole(String user, String password, Set<Role> roles, CheckType checkType) {
      return activeMQJAASSecurityManager.validateUserAndRole(user, password, roles, checkType);
   }

   @Override
   public ActiveMQSecurityManager init(Map<String, String> properties) {
      activeMQJAASSecurityManager = new ActiveMQJAASSecurityManager(properties.get("domain"));
      return this;
   }

}


<|start_filename|>artemis-jdbc-store/src/main/java/org/apache/activemq/artemis/jdbc/store/logging/LoggingResultSet.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.jdbc.store.logging;

import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.net.URL;
import java.sql.Array;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Date;
import java.sql.NClob;
import java.sql.Ref;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.RowId;
import java.sql.SQLException;
import java.sql.SQLType;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Statement;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Map;

import org.jboss.logging.Logger;

public class LoggingResultSet implements ResultSet {

   private final ResultSet resultSet;

   private final String resultSetID;

   private final Logger logger;

   private static final Logger.Level level = Logger.Level.TRACE;

   public LoggingResultSet(ResultSet resultSet, Logger logger) {
      this.resultSet = resultSet;
      this.logger = logger;
      this.resultSetID = LoggingUtil.getID(resultSet);
   }

   public ResultSet getResultSet() {
      return resultSet;
   }

   public String getResultSetID() {
      return resultSetID;
   }

   @Override
   public boolean next() throws SQLException {
      boolean b = resultSet.next();
      logger.logf(level, "%s.next() = %s", resultSetID, b);
      return b;
   }

   @Override
   public void close() throws SQLException {
      logger.logf(level, "%s.close()", resultSetID);
      resultSet.close();
   }

   @Override
   public boolean wasNull() throws SQLException {
      boolean b = resultSet.wasNull();
      logger.logf(level, "%s.wasNull() = %s", resultSetID, b);
      return b;
   }

   @Override
   public String getString(int columnIndex) throws SQLException {
      String x = resultSet.getString(columnIndex);
      logger.logf(level, "%s.getString(%s) = %s", resultSetID, columnIndex, x);
      return x;
   }

   @Override
   public boolean getBoolean(int columnIndex) throws SQLException {
      boolean x = resultSet.getBoolean(columnIndex);
      logger.logf(level, "%s.getBoolean(%s) = %s", resultSetID, columnIndex, x);
      return x;
   }

   @Override
   public byte getByte(int columnIndex) throws SQLException {
      byte x = resultSet.getByte(columnIndex);
      logger.logf(level, "%s.getByte(%s) = %s", resultSetID, columnIndex, x);
      return x;
   }

   @Override
   public short getShort(int columnIndex) throws SQLException {
      short x = resultSet.getShort(columnIndex);
      logger.logf(level, "%s.getShort(%s) = %s", resultSetID, columnIndex, x);
      return x;
   }

   @Override
   public int getInt(int columnIndex) throws SQLException {
      int x = resultSet.getInt(columnIndex);
      logger.logf(level, "%s.getInt(%s) = %s", resultSetID, columnIndex, x);
      return x;
   }

   @Override
   public long getLong(int columnIndex) throws SQLException {
      long x = resultSet.getLong(columnIndex);
      logger.logf(level, "%s.getLong(%s) = %s", resultSetID, columnIndex, x);
      return x;
   }

   @Override
   public float getFloat(int columnIndex) throws SQLException {
      float x = resultSet.getFloat(columnIndex);
      logger.logf(level, "%s.getFloat(%s) = %s", resultSetID, columnIndex, x);
      return x;
   }

   @Override
   public double getDouble(int columnIndex) throws SQLException {
      double x = resultSet.getDouble(columnIndex);
      logger.logf(level, "%s.getDouble(%s) = %s", resultSetID, columnIndex, x);
      return x;
   }

   @Override
   public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
      BigDecimal x = resultSet.getBigDecimal(columnIndex);
      logger.logf(level, "%s.getBigDecimal(%s) = %s", resultSetID, columnIndex, x);
      return x;
   }

   @Override
   public byte[] getBytes(int columnIndex) throws SQLException {
      byte[] x = resultSet.getBytes(columnIndex);
      logger.logf(level, "%s.getBytes(%s) = %s", resultSetID, columnIndex, Arrays.toString(x));
      return x;
   }

   @Override
   public Date getDate(int columnIndex) throws SQLException {
      Date x = resultSet.getDate(columnIndex);
      logger.logf(level, "%s.getDate(%s) = %s", resultSetID, columnIndex, x);
      return x;
   }

   @Override
   public Time getTime(int columnIndex) throws SQLException {
      Time x = resultSet.getTime(columnIndex);
      logger.logf(level, "%s.getTime(%s) = %s", resultSetID, columnIndex, x);
      return x;
   }

   @Override
   public Timestamp getTimestamp(int columnIndex) throws SQLException {
      Timestamp x = resultSet.getTimestamp(columnIndex);
      logger.logf(level, "%s.getTimestamp(%s) = %s", resultSetID, columnIndex, x);
      return x;
   }

   @Override
   public InputStream getAsciiStream(int columnIndex) throws SQLException {
      InputStream x = resultSet.getAsciiStream(columnIndex);
      logger.logf(level, "%s.getAsciiStream(%s) = %s", resultSetID, columnIndex, x);
      return x;
   }

   @Override
   public InputStream getUnicodeStream(int columnIndex) throws SQLException {
      InputStream x = resultSet.getUnicodeStream(columnIndex);
      logger.logf(level, "%s.getUnicodeStream(%s) = %s", resultSetID, columnIndex, x);
      return x;
   }

   @Override
   public InputStream getBinaryStream(int columnIndex) throws SQLException {
      InputStream x = resultSet.getBinaryStream(columnIndex);
      logger.logf(level, "%s.getBinaryStream(%s) = %s", resultSetID, columnIndex, x);
      return x;
   }

   @Override
   public String getString(String columnLabel) throws SQLException {
      String x = resultSet.getString(columnLabel);
      logger.logf(level, "%s.getString(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public boolean getBoolean(String columnLabel) throws SQLException {
      boolean x = resultSet.getBoolean(columnLabel);
      logger.logf(level, "%s.getBoolean(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public byte getByte(String columnLabel) throws SQLException {
      byte x = resultSet.getByte(columnLabel);
      logger.logf(level, "%s.getByte(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public short getShort(String columnLabel) throws SQLException {
      short x = resultSet.getShort(columnLabel);
      logger.logf(level, "%s.getShort(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public int getInt(String columnLabel) throws SQLException {
      int x = resultSet.getInt(columnLabel);
      logger.logf(level, "%s.getInt(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public long getLong(String columnLabel) throws SQLException {
      long x = resultSet.getLong(columnLabel);
      logger.logf(level, "%s.getLong(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public float getFloat(String columnLabel) throws SQLException {
      float x = resultSet.getFloat(columnLabel);
      logger.logf(level, "%s.getFloat(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public double getDouble(String columnLabel) throws SQLException {
      double x = resultSet.getDouble(columnLabel);
      logger.logf(level, "%s.getDouble(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException {
      BigDecimal x = resultSet.getBigDecimal(columnLabel);
      logger.logf(level, "%s.getBigDecimal(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public byte[] getBytes(String columnLabel) throws SQLException {
      byte[] x = resultSet.getBytes(columnLabel);
      logger.logf(level, "%s.getBytes(%s) = %s", resultSetID, columnLabel, Arrays.toString(x));
      return x;
   }

   @Override
   public Date getDate(String columnLabel) throws SQLException {
      Date x = resultSet.getDate(columnLabel);
      logger.logf(level, "%s.getDate(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public Time getTime(String columnLabel) throws SQLException {
      Time x = resultSet.getTime(columnLabel);
      logger.logf(level, "%s.getTime(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public Timestamp getTimestamp(String columnLabel) throws SQLException {
      Timestamp x = resultSet.getTimestamp(columnLabel);
      logger.logf(level, "%s.getTimestamp(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public InputStream getAsciiStream(String columnLabel) throws SQLException {
      InputStream x = resultSet.getAsciiStream(columnLabel);
      logger.logf(level, "%s.getAsciiStream(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public InputStream getUnicodeStream(String columnLabel) throws SQLException {
      InputStream x = resultSet.getUnicodeStream(columnLabel);
      logger.logf(level, "%s.getUnicodeStream(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public InputStream getBinaryStream(String columnLabel) throws SQLException {
      InputStream x = resultSet.getBinaryStream(columnLabel);
      logger.logf(level, "%s.getBinaryStream(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public SQLWarning getWarnings() throws SQLException {
      SQLWarning x = resultSet.getWarnings();
      logger.logf(level, "%s.getWarnings) = %s", resultSetID, x);
      return x;
   }

   @Override
   public void clearWarnings() throws SQLException {
      logger.logf(level, "%s.clearWarnings()", resultSetID);
      resultSet.clearWarnings();
   }

   @Override
   public String getCursorName() throws SQLException {
      String x = resultSet.getCursorName();
      logger.logf(level, "%s.getCursorName() = %s", resultSetID, x);
      return x;
   }

   @Override
   public ResultSetMetaData getMetaData() throws SQLException {
      ResultSetMetaData x = resultSet.getMetaData();
      logger.logf(level, "%s.getMetaData() = %s", resultSetID, x);
      return x;
   }

   @Override
   public Object getObject(int columnIndex) throws SQLException {
      String x = resultSet.getString(columnIndex);
      logger.logf(level, "%s.getString(%s) = %s", resultSetID, columnIndex, x);
      return x;
   }

   @Override
   public Object getObject(String columnLabel) throws SQLException {
      Object x = resultSet.getObject(columnLabel);
      logger.logf(level, "%s.getObject(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public int findColumn(String columnLabel) throws SQLException {
      int x = resultSet.findColumn(columnLabel);
      logger.logf(level, "%s.findColumn(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public Reader getCharacterStream(int columnIndex) throws SQLException {
      Reader x = resultSet.getCharacterStream(columnIndex);
      logger.logf(level, "%s.getCharacterStream(%s) = %s", resultSetID, columnIndex, x);
      return x;
   }

   @Override
   public Reader getCharacterStream(String columnLabel) throws SQLException {
      Reader x = resultSet.getCharacterStream(columnLabel);
      logger.logf(level, "%s.getCharacterStream(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
      BigDecimal x = resultSet.getBigDecimal(columnIndex);
      logger.logf(level, "%s.getBigDecimal(%s) = %s", resultSetID, columnIndex, x);
      return x;
   }

   @Override
   public BigDecimal getBigDecimal(String columnLabel) throws SQLException {
      BigDecimal x = resultSet.getBigDecimal(columnLabel);
      logger.logf(level, "%s.getBigDecimal(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public boolean isBeforeFirst() throws SQLException {
      boolean x = resultSet.isBeforeFirst();
      logger.logf(level, "%s.isBeforeFirst() = %s", resultSetID, x);
      return x;
   }

   @Override
   public boolean isAfterLast() throws SQLException {
      boolean x = resultSet.isAfterLast();
      logger.logf(level, "%s.isAfterLast() = %s", resultSetID, x);
      return x;
   }

   @Override
   public boolean isFirst() throws SQLException {
      boolean x = resultSet.isFirst();
      logger.logf(level, "%s.isFirst() = %s", resultSetID, x);
      return x;
   }

   @Override
   public boolean isLast() throws SQLException {
      boolean x = resultSet.isLast();
      logger.logf(level, "%s.isLast() = %s", resultSetID, x);
      return x;
   }

   @Override
   public void beforeFirst() throws SQLException {
      logger.logf(level, "%s.beforeFirst()", resultSetID);
      resultSet.beforeFirst();
   }

   @Override
   public void afterLast() throws SQLException {
      logger.logf(level, "%s.afterLast()", resultSetID);
      resultSet.afterLast();
   }

   @Override
   public boolean first() throws SQLException {
      boolean x = resultSet.first();
      logger.logf(level, "%s.first() = %s", resultSetID, x);
      return x;
   }

   @Override
   public boolean last() throws SQLException {
      boolean x = resultSet.last();
      logger.logf(level, "%s.last() = %s", resultSetID, x);
      return x;
   }

   @Override
   public int getRow() throws SQLException {
      int x = resultSet.getRow();
      logger.logf(level, "%s.getRow() = %s", resultSetID, x);
      return x;
   }

   @Override
   public boolean absolute(int row) throws SQLException {
      boolean x = resultSet.absolute(row);
      logger.logf(level, "%s.absolute(%s) = %s", resultSetID, row, x);
      return x;
   }

   @Override
   public boolean relative(int rows) throws SQLException {
      boolean x = resultSet.relative(rows);
      logger.logf(level, "%s.relative(%s) = %s", resultSetID, rows, x);
      return x;
   }

   @Override
   public boolean previous() throws SQLException {
      boolean x = resultSet.previous();
      logger.logf(level, "%s.previous() = %s", resultSetID, x);
      return x;
   }

   @Override
   public void setFetchDirection(int direction) throws SQLException {
      logger.logf(level, "%s.setFetchDirection(%s)", resultSetID, direction);
      resultSet.setFetchDirection(direction);
   }

   @Override
   public int getFetchDirection() throws SQLException {
      int x = resultSet.getFetchDirection();
      logger.logf(level, "%s.getFetchDirection() = %s", resultSetID, x);
      return x;
   }

   @Override
   public void setFetchSize(int rows) throws SQLException {
      logger.logf(level, "%s.setFetchSize(%s)", resultSetID, rows);
      resultSet.setFetchSize(rows);
   }

   @Override
   public int getFetchSize() throws SQLException {
      int x = resultSet.getFetchSize();
      logger.logf(level, "%s.getFetchSize() = %s", resultSetID, x);
      return x;
   }

   @Override
   public int getType() throws SQLException {
      int x = resultSet.getType();
      logger.logf(level, "%s.getType() = %s", resultSetID, x);
      return x;
   }

   @Override
   public int getConcurrency() throws SQLException {
      int x = resultSet.getConcurrency();
      logger.logf(level, "%s.getConcurrency() = %s", resultSetID, x);
      return x;
   }

   @Override
   public boolean rowUpdated() throws SQLException {
      boolean x = resultSet.rowUpdated();
      logger.logf(level, "%s.rowUpdated() = %s", resultSetID, x);
      return x;
   }

   @Override
   public boolean rowInserted() throws SQLException {
      boolean x = resultSet.rowInserted();
      logger.logf(level, "%s.rowInserted() = %s", resultSetID, x);
      return x;
   }

   @Override
   public boolean rowDeleted() throws SQLException {
      boolean x = resultSet.rowDeleted();
      logger.logf(level, "%s.rowDeleted() = %s", resultSetID, x);
      return x;
   }

   @Override
   public void updateNull(int columnIndex) throws SQLException {
      logger.logf(level, "%s.updateNull(%s)", resultSetID, columnIndex);
      resultSet.updateNull(columnIndex);
   }

   @Override
   public void updateBoolean(int columnIndex, boolean x) throws SQLException {
      logger.logf(level, "%s.updateBoolean(%s, %s)", resultSetID, columnIndex, x);
      resultSet.updateBoolean(columnIndex, x);
   }

   @Override
   public void updateByte(int columnIndex, byte x) throws SQLException {
      logger.logf(level, "%s.updateByte(%s, %s)", resultSetID, columnIndex, x);
      resultSet.updateByte(columnIndex, x);
   }

   @Override
   public void updateShort(int columnIndex, short x) throws SQLException {
      logger.logf(level, "%s.updateShort(%s, %s)", resultSetID, columnIndex, x);
      resultSet.updateShort(columnIndex, x);
   }

   @Override
   public void updateInt(int columnIndex, int x) throws SQLException {
      logger.logf(level, "%s.updateInt(%s, %s)", resultSetID, columnIndex, x);
      resultSet.updateInt(columnIndex, x);
   }

   @Override
   public void updateLong(int columnIndex, long x) throws SQLException {
      logger.logf(level, "%s.updateLong(%s, %s)", resultSetID, columnIndex, x);
      resultSet.updateLong(columnIndex, x);
   }

   @Override
   public void updateFloat(int columnIndex, float x) throws SQLException {
      logger.logf(level, "%s.updateFloat(%s, %s)", resultSetID, columnIndex, x);
      resultSet.updateFloat(columnIndex, x);
   }

   @Override
   public void updateDouble(int columnIndex, double x) throws SQLException {
      logger.logf(level, "%s.updateDouble(%s, %s)", resultSetID, columnIndex, x);
      resultSet.updateDouble(columnIndex, x);
   }

   @Override
   public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException {
      logger.logf(level, "%s.updateBigDecimal(%s, %s)", resultSetID, columnIndex, x);
      resultSet.updateBigDecimal(columnIndex, x);
   }

   @Override
   public void updateString(int columnIndex, String x) throws SQLException {
      logger.logf(level, "%s.updateString(%s, %s)", resultSetID, columnIndex, x);
      resultSet.updateString(columnIndex, x);
   }

   @Override
   public void updateBytes(int columnIndex, byte[] x) throws SQLException {
      logger.logf(level, "%s.updateBytes(%s, %s)", resultSetID, columnIndex, x);
      resultSet.updateBytes(columnIndex, x);
   }

   @Override
   public void updateDate(int columnIndex, Date x) throws SQLException {
      logger.logf(level, "%s.updateDate(%s, %s)", resultSetID, columnIndex, x);
      resultSet.updateDate(columnIndex, x);
   }

   @Override
   public void updateTime(int columnIndex, Time x) throws SQLException {
      logger.logf(level, "%s.updateTime(%s, %s)", resultSetID, columnIndex, x);
      resultSet.updateTime(columnIndex, x);
   }

   @Override
   public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException {
      logger.logf(level, "%s.updateTimestamp(%s, %s)", resultSetID, columnIndex, x);
      resultSet.updateTimestamp(columnIndex, x);
   }

   @Override
   public void updateAsciiStream(int columnIndex, InputStream x, int length) throws SQLException {
      logger.logf(level, "%s.updateAsciiStream(%s, %s, %s)", resultSetID, columnIndex, x, length);
      resultSet.updateAsciiStream(columnIndex, x, length);
   }

   @Override
   public void updateBinaryStream(int columnIndex, InputStream x, int length) throws SQLException {
      logger.logf(level, "%s.updateBinaryStream(%s, %s, %s)", resultSetID, columnIndex, x, length);
      resultSet.updateBinaryStream(columnIndex, x, length);
   }

   @Override
   public void updateCharacterStream(int columnIndex, Reader x, int length) throws SQLException {
      logger.logf(level, "%s.updateCharacterStream(%s, %s, %s)", resultSetID, columnIndex, x, length);
      resultSet.updateCharacterStream(columnIndex, x, length);
   }

   @Override
   public void updateObject(int columnIndex, Object x, int scaleOrLength) throws SQLException {
      logger.logf(level, "%s.updateObject(%s, %s, %s)", resultSetID, columnIndex, x, scaleOrLength);
      resultSet.updateObject(columnIndex, x, scaleOrLength);
   }

   @Override
   public void updateObject(int columnIndex, Object x) throws SQLException {
      logger.logf(level, "%s.updateObject(%s, %s)", resultSetID, columnIndex, x);
      resultSet.updateObject(columnIndex, x);
   }

   @Override
   public void updateNull(String columnLabel) throws SQLException {
      logger.logf(level, "%s.updateNull(%s)", resultSetID, columnLabel);
      resultSet.updateNull(columnLabel);
   }

   @Override
   public void updateBoolean(String columnLabel, boolean x) throws SQLException {
      logger.logf(level, "%s.updateBoolean(%s, %s)", resultSetID, columnLabel, x);
      resultSet.updateBoolean(columnLabel, x);
   }

   @Override
   public void updateByte(String columnLabel, byte x) throws SQLException {
      logger.logf(level, "%s.updateByte(%s, %s)", resultSetID, columnLabel, x);
      resultSet.updateByte(columnLabel, x);
   }

   @Override
   public void updateShort(String columnLabel, short x) throws SQLException {
      logger.logf(level, "%s.updateShort(%s, %s)", resultSetID, columnLabel, x);
      resultSet.updateShort(columnLabel, x);
   }

   @Override
   public void updateInt(String columnLabel, int x) throws SQLException {
      logger.logf(level, "%s.updateInt(%s, %s)", resultSetID, columnLabel, x);
      resultSet.updateInt(columnLabel, x);
   }

   @Override
   public void updateLong(String columnLabel, long x) throws SQLException {
      logger.logf(level, "%s.updateLong(%s, %s)", resultSetID, columnLabel, x);
      resultSet.updateLong(columnLabel, x);
   }

   @Override
   public void updateFloat(String columnLabel, float x) throws SQLException {
      logger.logf(level, "%s.updateFloat(%s, %s)", resultSetID, columnLabel, x);
      resultSet.updateFloat(columnLabel, x);
   }

   @Override
   public void updateDouble(String columnLabel, double x) throws SQLException {
      logger.logf(level, "%s.updateDouble(%s, %s)", resultSetID, columnLabel, x);
      resultSet.updateDouble(columnLabel, x);
   }

   @Override
   public void updateBigDecimal(String columnLabel, BigDecimal x) throws SQLException {
      logger.logf(level, "%s.updateBigDecimal(%s, %s)", resultSetID, columnLabel, x);
      resultSet.updateBigDecimal(columnLabel, x);
   }

   @Override
   public void updateString(String columnLabel, String x) throws SQLException {
      logger.logf(level, "%s.updateString(%s, %s)", resultSetID, columnLabel, x);
      resultSet.updateString(columnLabel, x);
   }

   @Override
   public void updateBytes(String columnLabel, byte[] x) throws SQLException {
      logger.logf(level, "%s.updateBytes(%s, %s)", resultSetID, columnLabel, x);
      resultSet.updateBytes(columnLabel, x);
   }

   @Override
   public void updateDate(String columnLabel, Date x) throws SQLException {
      logger.logf(level, "%s.updateDate(%s, %s)", resultSetID, columnLabel, x);
      resultSet.updateDate(columnLabel, x);
   }

   @Override
   public void updateTime(String columnLabel, Time x) throws SQLException {
      logger.logf(level, "%s.updateTime(%s, %s)", resultSetID, columnLabel, x);
      resultSet.updateTime(columnLabel, x);
   }

   @Override
   public void updateTimestamp(String columnLabel, Timestamp x) throws SQLException {
      logger.logf(level, "%s.updateTimestamp(%s, %s)", resultSetID, columnLabel, x);
      resultSet.updateTimestamp(columnLabel, x);
   }

   @Override
   public void updateAsciiStream(String columnLabel, InputStream x, int length) throws SQLException {
      logger.logf(level, "%s.updateAsciiStream(%s, %s, %s)", resultSetID, columnLabel, x, length);
      resultSet.updateAsciiStream(columnLabel, x, length);
   }

   @Override
   public void updateBinaryStream(String columnLabel, InputStream x, int length) throws SQLException {
      logger.logf(level, "%s.updateBinaryStream(%s, %s, %s)", resultSetID, columnLabel, x, length);
      resultSet.updateBinaryStream(columnLabel, x, length);
   }

   @Override
   public void updateCharacterStream(String columnLabel, Reader x, int length) throws SQLException {
      logger.logf(level, "%s.updateCharacterStream(%s, %s, %s)", resultSetID, columnLabel, x, length);
      resultSet.updateCharacterStream(columnLabel, x, length);
   }

   @Override
   public void updateObject(String columnLabel, Object x, int scaleOrLength) throws SQLException {
      logger.logf(level, "%s.updateObject(%s, %s, %s)", resultSetID, columnLabel, x, scaleOrLength);
      resultSet.updateObject(columnLabel, x, scaleOrLength);
   }

   @Override
   public void updateObject(String columnLabel, Object x) throws SQLException {
      logger.logf(level, "%s.updateObject(%s, %s)", resultSetID, columnLabel, x);
      resultSet.updateObject(columnLabel, x);
   }

   @Override
   public void insertRow() throws SQLException {
      logger.logf(level, "%s.insertRow()", resultSetID);
      resultSet.insertRow();
   }

   @Override
   public void updateRow() throws SQLException {
      logger.logf(level, "%s.updateRow()", resultSetID);
      resultSet.updateRow();
   }

   @Override
   public void deleteRow() throws SQLException {
      logger.logf(level, "%s.deleteRow()", resultSetID);
      resultSet.deleteRow();
   }

   @Override
   public void refreshRow() throws SQLException {
      logger.logf(level, "%s.refreshRow()", resultSetID);
      resultSet.refreshRow();
   }

   @Override
   public void cancelRowUpdates() throws SQLException {
      logger.logf(level, "%s.cancelRowUpdates()", resultSetID);
      resultSet.cancelRowUpdates();
   }

   @Override
   public void moveToInsertRow() throws SQLException {
      logger.logf(level, "%s.moveToInsertRow()", resultSetID);
      resultSet.moveToInsertRow();
   }

   @Override
   public void moveToCurrentRow() throws SQLException {
      logger.logf(level, "%s.moveToCurrentRow()", resultSetID);
      resultSet.moveToCurrentRow();
   }

   @Override
   public Statement getStatement() throws SQLException {
      Statement x = resultSet.getStatement();
      logger.logf(level, "%s.getStatement() = %s", resultSetID, x);
      return x;
   }

   @Override
   public Object getObject(int columnIndex, Map<String, Class<?>> map) throws SQLException {
      Object x = resultSet.getObject(columnIndex, map);
      logger.logf(level, "%s.getObject(%s, %s) = %s", resultSetID, columnIndex, map, x);
      return x;
   }

   @Override
   public Ref getRef(int columnIndex) throws SQLException {
      Ref x = resultSet.getRef(columnIndex);
      logger.logf(level, "%s.getRef(%s) = %s", resultSetID, columnIndex, x);
      return x;
   }

   @Override
   public Blob getBlob(int columnIndex) throws SQLException {
      Blob x = resultSet.getBlob(columnIndex);
      logger.logf(level, "%s.getBlob(%s) = %s (length: %d)", resultSetID, columnIndex, x, x == null ? null : x.length());
      return x;
   }

   @Override
   public Clob getClob(int columnIndex) throws SQLException {
      Clob x = resultSet.getClob(columnIndex);
      logger.logf(level, "%s.getClob(%s) = %s (length: %d)", resultSetID, columnIndex, x, x == null ? null : x.length());
      return x;
   }

   @Override
   public Array getArray(int columnIndex) throws SQLException {
      Array x = resultSet.getArray(columnIndex);
      logger.logf(level, "%s.getArray(%s) = %s", resultSetID, columnIndex, x);
      return x;
   }

   @Override
   public Object getObject(String columnLabel, Map<String, Class<?>> map) throws SQLException {
      Object x = resultSet.getObject(columnLabel, map);
      logger.logf(level, "%s.getObject(%s, %s) = %s", resultSetID, columnLabel, map, x);
      return x;
   }

   @Override
   public Ref getRef(String columnLabel) throws SQLException {
      Ref x = resultSet.getRef(columnLabel);
      logger.logf(level, "%s.getRef(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public Blob getBlob(String columnLabel) throws SQLException {
      Blob x = resultSet.getBlob(columnLabel);
      logger.logf(level, "%s.getBlob(%s) = %s (length: %d)", resultSetID, columnLabel, x, x == null ? null : x.length());
      return x;
   }

   @Override
   public Clob getClob(String columnLabel) throws SQLException {
      Clob x = resultSet.getClob(columnLabel);
      logger.logf(level, "%s.getClob(%s) = %s (length: %d)", resultSetID, columnLabel, x, x == null ? null : x.length());
      return x;
   }

   @Override
   public Array getArray(String columnLabel) throws SQLException {
      Array x = resultSet.getArray(columnLabel);
      logger.logf(level, "%s.getArray(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public Date getDate(int columnLabel, Calendar cal) throws SQLException {
      Date x = resultSet.getDate(columnLabel, cal);
      logger.logf(level, "%s.getDate(%s) = %s", resultSetID, columnLabel, cal, x);
      return x;
   }

   @Override
   public Date getDate(String columnLabel, Calendar cal) throws SQLException {
      Date x = resultSet.getDate(columnLabel, cal);
      logger.logf(level, "%s.getDate(%s) = %s", resultSetID, columnLabel, cal, x);
      return x;
   }

   @Override
   public Time getTime(int columnLabel, Calendar cal) throws SQLException {
      Time x = resultSet.getTime(columnLabel, cal);
      logger.logf(level, "%s.getTime(%s) = %s", resultSetID, columnLabel, cal, x);
      return x;
   }

   @Override
   public Time getTime(String columnLabel, Calendar cal) throws SQLException {
      Time x = resultSet.getTime(columnLabel, cal);
      logger.logf(level, "%s.getTime(%s) = %s", resultSetID, columnLabel, cal, x);
      return x;
   }

   @Override
   public Timestamp getTimestamp(int columnLabel, Calendar cal) throws SQLException {
      Timestamp x = resultSet.getTimestamp(columnLabel, cal);
      logger.logf(level, "%s.getTimestamp(%s) = %s", resultSetID, columnLabel, cal, x);
      return x;
   }

   @Override
   public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException {
      Timestamp x = resultSet.getTimestamp(columnLabel, cal);
      logger.logf(level, "%s.getTimestamp(%s) = %s", resultSetID, columnLabel, cal, x);
      return x;
   }

   @Override
   public URL getURL(int columnLabel) throws SQLException {
      URL x = resultSet.getURL(columnLabel);
      logger.logf(level, "%s.getURL(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public URL getURL(String columnLabel) throws SQLException {
      URL x = resultSet.getURL(columnLabel);
      logger.logf(level, "%s.getURL(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public void updateRef(int columnIndex, Ref x) throws SQLException {
      logger.logf(level, "%s.updateRef(%s, %s)", resultSetID, columnIndex, x);
      resultSet.updateRef(columnIndex, x);
   }

   @Override
   public void updateRef(String columnLabel, Ref x) throws SQLException {
      logger.logf(level, "%s.updateRef(%s, %s)", resultSetID, columnLabel, x);
      resultSet.updateRef(columnLabel, x);
   }

   @Override
   public void updateBlob(int columnIndex, Blob x) throws SQLException {
      logger.logf(level, "%s.updateBlob(%s, %s)", resultSetID, columnIndex, x);
      resultSet.updateBlob(columnIndex, x);
   }

   @Override
   public void updateBlob(String columnLabel, Blob x) throws SQLException {
      logger.logf(level, "%s.updateBlob(%s, %s)", resultSetID, columnLabel, x);
      resultSet.updateBlob(columnLabel, x);
   }

   @Override
   public void updateClob(int columnIndex, Clob x) throws SQLException {
      logger.logf(level, "%s.updateClob(%s, %s)", resultSetID, columnIndex, x);
      resultSet.updateClob(columnIndex, x);
   }

   @Override
   public void updateClob(String columnLabel, Clob x) throws SQLException {
      logger.logf(level, "%s.updateClob(%s, %s)", resultSetID, columnLabel, x);
      resultSet.updateClob(columnLabel, x);
   }

   @Override
   public void updateArray(int columnIndex, Array x) throws SQLException {
      logger.logf(level, "%s.updateArray(%s, %s)", resultSetID, columnIndex, x);
      resultSet.updateArray(columnIndex, x);
   }

   @Override
   public void updateArray(String columnLabel, Array x) throws SQLException {
      logger.logf(level, "%s.updateArray(%s, %s)", resultSetID, columnLabel, x);
      resultSet.updateArray(columnLabel, x);
   }

   @Override
   public RowId getRowId(int columnIndex) throws SQLException {
      RowId x = resultSet.getRowId(columnIndex);
      logger.logf(level, "%s.getRowId(%s) = %s", resultSetID, columnIndex, x);
      return x;
   }

   @Override
   public RowId getRowId(String columnLabel) throws SQLException {
      RowId x = resultSet.getRowId(columnLabel);
      logger.logf(level, "%s.getRowId(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public void updateRowId(int columnIndex, RowId x) throws SQLException {
      logger.logf(level, "%s.updateRowId(%s, %s)", resultSetID, columnIndex, x);
      resultSet.updateRowId(columnIndex, x);
   }

   @Override
   public void updateRowId(String columnLabel, RowId x) throws SQLException {
      logger.logf(level, "%s.updateRowId(%s, %s)", resultSetID, columnLabel, x);
      resultSet.updateRowId(columnLabel, x);
   }

   @Override
   public int getHoldability() throws SQLException {
      int x = resultSet.getHoldability();
      logger.logf(level, "%s.getHoldability() = %s", resultSetID, x);
      return x;
   }

   @Override
   public boolean isClosed() throws SQLException {
      boolean x = resultSet.isClosed();
      logger.logf(level, "%s.isClosed() = %s", resultSetID, x);
      return x;
   }

   @Override
   public void updateNString(int columnIndex, String x) throws SQLException {
      logger.logf(level, "%s.updateNString(%s, %s)", resultSetID, columnIndex, x);
      resultSet.updateNString(columnIndex, x);
   }

   @Override
   public void updateNString(String columnLabel, String x) throws SQLException {
      logger.logf(level, "%s.updateNString(%s, %s)", resultSetID, columnLabel, x);
      resultSet.updateNString(columnLabel, x);
   }

   @Override
   public void updateNClob(int columnIndex, NClob x) throws SQLException {
      logger.logf(level, "%s.updateNClob(%s, %s)", resultSetID, columnIndex, x);
      resultSet.updateNClob(columnIndex, x);
   }

   @Override
   public void updateNClob(String columnLabel, NClob x) throws SQLException {
      logger.logf(level, "%s.updateNClob(%s, %s)", resultSetID, columnLabel, x);
      resultSet.updateNClob(columnLabel, x);
   }

   @Override
   public NClob getNClob(int columnIndex) throws SQLException {
      NClob x = resultSet.getNClob(columnIndex);
      logger.logf(level, "%s.getNClob(%s) = %s", resultSetID, columnIndex, x);
      return x;
   }

   @Override
   public NClob getNClob(String columnLabel) throws SQLException {
      NClob x = resultSet.getNClob(columnLabel);
      logger.logf(level, "%s.getNClob(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public SQLXML getSQLXML(int columnIndex) throws SQLException {
      SQLXML x = resultSet.getSQLXML(columnIndex);
      logger.logf(level, "%s.getSQLXML(%s) = %s", resultSetID, columnIndex, x);
      return x;
   }

   @Override
   public SQLXML getSQLXML(String columnLabel) throws SQLException {
      SQLXML x = resultSet.getSQLXML(columnLabel);
      logger.logf(level, "%s.getSQLXML(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public void updateSQLXML(int columnIndex, SQLXML x) throws SQLException {
      logger.logf(level, "%s.updateSQLXML(%s, %s)", resultSetID, columnIndex, x);
      resultSet.updateSQLXML(columnIndex, x);
   }

   @Override
   public void updateSQLXML(String columnLabel, SQLXML x) throws SQLException {
      logger.logf(level, "%s.updateSQLXML(%s, %s)", resultSetID, columnLabel, x);
      resultSet.updateSQLXML(columnLabel, x);
   }

   @Override
   public String getNString(int columnIndex) throws SQLException {
      String x = resultSet.getNString(columnIndex);
      logger.logf(level, "%s.getNString(%s) = %s", resultSetID, columnIndex, x);
      return x;
   }

   @Override
   public String getNString(String columnLabel) throws SQLException {
      String x = resultSet.getNString(columnLabel);
      logger.logf(level, "%s.getNString(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public Reader getNCharacterStream(int columnIndex) throws SQLException {
      Reader x = resultSet.getNCharacterStream(columnIndex);
      logger.logf(level, "%s.getNCharacterStream(%s) = %s", resultSetID, columnIndex, x);
      return x;
   }

   @Override
   public Reader getNCharacterStream(String columnLabel) throws SQLException {
      Reader x = resultSet.getNCharacterStream(columnLabel);
      logger.logf(level, "%s.getNCharacterStream(%s) = %s", resultSetID, columnLabel, x);
      return x;
   }

   @Override
   public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException {
      logger.logf(level, "%s.updateNCharacterStream(%s, %s, %s)", resultSetID, columnIndex, x, length);
      resultSet.updateNCharacterStream(columnIndex, x, length);
   }

   @Override
   public void updateNCharacterStream(String columnLabel, Reader reader, long length) throws SQLException {
      logger.logf(level, "%s.updateNCharacterStream(%s, %s, %s)", resultSetID, columnLabel, reader, length);
      resultSet.updateNCharacterStream(columnLabel, reader, length);
   }

   @Override
   public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException {
      logger.logf(level, "%s.updateAsciiStream(%s, %s, %s)", resultSetID, columnIndex, x, length);
      resultSet.updateAsciiStream(columnIndex, x, length);
   }

   @Override
   public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException {
      logger.logf(level, "%s.updateBinaryStream(%s, %s, %s)", resultSetID, columnIndex, x, length);
      resultSet.updateBinaryStream(columnIndex, x, length);
   }

   @Override
   public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException {
      logger.logf(level, "%s.updateCharacterStream(%s, %s, %s)", resultSetID, columnIndex, x, length);
      resultSet.updateCharacterStream(columnIndex, x, length);
   }

   @Override
   public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException {
      logger.logf(level, "%s.updateAsciiStream(%s, %s, %s)", resultSetID, columnLabel, x, length);
      resultSet.updateAsciiStream(columnLabel, x, length);
   }

   @Override
   public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException {
      logger.logf(level, "%s.updateBinaryStream(%s, %s, %s)", resultSetID, columnLabel, x, length);
      resultSet.updateBinaryStream(columnLabel, x, length);
   }

   @Override
   public void updateCharacterStream(String columnLabel, Reader reader, long length) throws SQLException {
      logger.logf(level, "%s.updateCharacterStream(%s, %s, %s)", resultSetID, columnLabel, reader, length);
      resultSet.updateCharacterStream(columnLabel, reader);
   }

   @Override
   public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException {
      logger.logf(level, "%s.updateBlob(%s, %s, %s)", resultSetID, columnIndex, inputStream, length);
      resultSet.updateBlob(columnIndex, inputStream, length);
   }

   @Override
   public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException {
      logger.logf(level, "%s.updateBlob(%s, %s, %s)", resultSetID, columnLabel, inputStream, length);
      resultSet.updateBlob(columnLabel, inputStream, length);
   }

   @Override
   public void updateClob(int columnIndex, Reader reader, long length) throws SQLException {
      logger.logf(level, "%s.updateClob(%s, %s, %s)", resultSetID, columnIndex, reader, length);
      resultSet.updateClob(columnIndex, reader, length);
   }

   @Override
   public void updateClob(String columnLabel, Reader reader, long length) throws SQLException {
      logger.logf(level, "%s.updateClob(%s, %s, %s)", resultSetID, columnLabel, reader, length);
      resultSet.updateClob(columnLabel, reader, length);
   }

   @Override
   public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException {
      logger.logf(level, "%s.updateNClob(%s, %s, %s)", resultSetID, columnIndex, reader, length);
      resultSet.updateNClob(columnIndex, reader, length);
   }

   @Override
   public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException {
      logger.logf(level, "%s.updateNClob(%s, %s, %s)", resultSetID, columnLabel, reader, length);
      resultSet.updateNClob(columnLabel, reader, length);
   }

   @Override
   public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException {
      logger.logf(level, "%s.updateNCharacterStream(%s, %s)", resultSetID, columnIndex, x);
      resultSet.updateNCharacterStream(columnIndex, x);
   }

   @Override
   public void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException {
      logger.logf(level, "%s.updateNCharacterStream(%s, %s)", resultSetID, columnLabel, reader);
      resultSet.updateNCharacterStream(columnLabel, reader);
   }

   @Override
   public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException {
      logger.logf(level, "%s.updateAsciiStream(%s, %s)", resultSetID, columnIndex, x);
      resultSet.updateAsciiStream(columnIndex, x);
   }

   @Override
   public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException {
      logger.logf(level, "%s.updateBinaryStream(%s, %s)", resultSetID, columnIndex, x);
      resultSet.updateBinaryStream(columnIndex, x);
   }

   @Override
   public void updateCharacterStream(int columnIndex, Reader x) throws SQLException {
      logger.logf(level, "%s.updateCharacterStream(%s, %s)", resultSetID, columnIndex, x);
      resultSet.updateCharacterStream(columnIndex, x);
   }

   @Override
   public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException {
      logger.logf(level, "%s.updateAsciiStream(%s, %s)", resultSetID, columnLabel, x);
      resultSet.updateAsciiStream(columnLabel, x);
   }

   @Override
   public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException {
      logger.logf(level, "%s.updateBinaryStream(%s, %s)", resultSetID, columnLabel, x);
      resultSet.updateBinaryStream(columnLabel, x);
   }

   @Override
   public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException {
      logger.logf(level, "%s.updateCharacterStream(%s, %s)", resultSetID, columnLabel, reader);
      resultSet.updateCharacterStream(columnLabel, reader);
   }

   @Override
   public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException {
      logger.logf(level, "%s.updateBlob(%s, %s)", resultSetID, columnIndex, inputStream);
      resultSet.updateBlob(columnIndex, inputStream);
   }

   @Override
   public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException {
      logger.logf(level, "%s.updateBlob(%s, %s)", resultSetID, columnLabel, inputStream);
      resultSet.updateBlob(columnLabel, inputStream);
   }

   @Override
   public void updateClob(int columnIndex, Reader reader) throws SQLException {
      logger.logf(level, "%s.updateClob(%s, %s)", resultSetID, columnIndex, reader);
      resultSet.updateClob(columnIndex, reader);
   }

   @Override
   public void updateClob(String columnLabel, Reader reader) throws SQLException {
      logger.logf(level, "%s.updateClob(%s, %s)", resultSetID, columnLabel, reader);
      resultSet.updateClob(columnLabel, reader);
   }

   @Override
   public void updateNClob(int columnIndex, Reader reader) throws SQLException {
      logger.logf(level, "%s.updateNClob(%s, %s)", resultSetID, columnIndex, reader);
      resultSet.updateNClob(columnIndex, reader);
   }

   @Override
   public void updateNClob(String columnLabel, Reader reader) throws SQLException {
      logger.logf(level, "%s.updateNClob(%s, %s)", resultSetID, columnLabel, reader);
      resultSet.updateNClob(columnLabel, reader);
   }

   @Override
   public <T> T getObject(int columnIndex, Class<T> type) throws SQLException {
      T x = resultSet.getObject(columnIndex, type);
      logger.logf(level, "%s.getObject(%s, %s) = %s", resultSetID, columnIndex, type, x);
      return x;
   }

   @Override
   public <T> T getObject(String columnLabel, Class<T> type) throws SQLException {
      T x = resultSet.getObject(columnLabel, type);
      logger.logf(level, "%s.getObject(%s, %s) = %s", resultSetID, columnLabel, type, x);
      return x;
   }

   @Override
   public void updateObject(int columnIndex, Object x, SQLType targetSqlType, int scaleOrLength) throws SQLException {
      logger.logf(level, "%s.updateObject(%s, %s, %s, %s)", resultSetID, columnIndex, x, targetSqlType, scaleOrLength);
      resultSet.updateObject(columnIndex, x, targetSqlType);
   }

   @Override
   public void updateObject(String columnLabel,
                            Object x,
                            SQLType targetSqlType,
                            int scaleOrLength) throws SQLException {
      logger.logf(level, "%s.updateObject(%s, %s, %s, %s)", resultSetID, columnLabel, x, targetSqlType, scaleOrLength);
      resultSet.updateObject(columnLabel, x, targetSqlType, scaleOrLength);
   }

   @Override
   public void updateObject(int columnIndex, Object x, SQLType targetSqlType) throws SQLException {
      logger.logf(level, "%s.updateObject(%s, %s, %s)", resultSetID, columnIndex, x, targetSqlType);
      resultSet.updateObject(columnIndex, x, targetSqlType);
   }

   @Override
   public void updateObject(String columnLabel, Object x, SQLType targetSqlType) throws SQLException {
      logger.logf(level, "%s.updateObject(%s, %s, %s)", resultSetID, columnLabel, x, targetSqlType);
      resultSet.updateObject(columnLabel, x, targetSqlType);
   }

   @Override
   public <T> T unwrap(Class<T> iface) throws SQLException {
      T x = resultSet.unwrap(iface);
      logger.logf(level, "%s.unwrap(%s) = %s", resultSetID, iface, x);
      return x;
   }

   @Override
   public boolean isWrapperFor(Class<?> iface) throws SQLException {
      boolean x = resultSet.isWrapperFor(iface);
      logger.logf(level, "%s.isWrapperFor(%s) = %s", resultSetID, iface, x);
      return x;
   }
}


<|start_filename|>tests/extra-tests/src/test/java/org/apache/activemq/artemis/tests/extras/jms/bridge/FailingTransactionManager.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.extras.jms.bridge;

import com.arjuna.ats.arjuna.common.Uid;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import javax.transaction.HeuristicMixedException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.InvalidTransactionException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.Synchronization;
import javax.transaction.SystemException;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import javax.transaction.xa.XAResource;

public class FailingTransactionManager implements TransactionManager {

   private final TransactionManager tm;
   private int calls;
   private final int limit;
   private final AtomicInteger failures = new AtomicInteger(0);
   private final Map<Uid, FailingTransaction> transactions = Collections.synchronizedMap(new HashMap<>(10));

   public FailingTransactionManager(TransactionManager tm, int limit) {
      this.tm = tm;
      this.calls = 0;
      this.limit = limit;
   }

   @Override
   public void begin() throws NotSupportedException, SystemException {
      tm.begin();
   }

   @Override
   public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, IllegalStateException, SystemException {
      transactions.remove(((com.arjuna.ats.jta.transaction.Transaction) tm.getTransaction()).get_uid()).commit();
   }

   @Override
   public void rollback() throws IllegalStateException, SecurityException, SystemException {
      transactions.remove(((com.arjuna.ats.jta.transaction.Transaction) tm.getTransaction()).get_uid()).rollback();
   }

   @Override
   public void setRollbackOnly() throws IllegalStateException, SystemException {
      tm.setRollbackOnly();
   }

   @Override
   public int getStatus() throws SystemException {
      return tm.getStatus();
   }

   @Override
   public Transaction getTransaction() throws SystemException {
      com.arjuna.ats.jta.transaction.Transaction real =  (com.arjuna.ats.jta.transaction.Transaction) tm.getTransaction();
      if (transactions.containsKey(real.get_uid())) {
         return transactions.get(real.get_uid());
      }
      FailingTransaction tx = new FailingTransaction(real, calls++);
      transactions.put(real.get_uid(), tx);
      return tx;
   }

   @Override
   public void setTransactionTimeout(int i) throws SystemException {
      tm.setTransactionTimeout(i);
   }

   @Override
   public Transaction suspend() throws SystemException {
      Transaction real = tm.suspend();
      if (real == null) {
         return null;
      }
      return transactions.get(((com.arjuna.ats.jta.transaction.Transaction) real).get_uid());
   }

   public int getFailures() {
      return failures.get();
   }

   @Override
   public void resume(Transaction transaction) throws InvalidTransactionException, IllegalStateException, SystemException {
      tm.resume(((FailingTransaction)transaction).transaction);
   }

   private final class FailingTransaction implements Transaction {

      private final com.arjuna.ats.jta.transaction.Transaction transaction;
      private final int number;

      private FailingTransaction(com.arjuna.ats.jta.transaction.Transaction transaction, int number) {
         this.transaction = transaction;
         this.number = number;
      }

      @Override
      public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, IllegalStateException, SystemException {
         if (number < limit) {
            transaction.commit();
            transactions.remove(transaction.get_uid());
         } else {
            int fails = failures.incrementAndGet();
            RollbackException ex = new RollbackException("Expected rollback for test");
            throw ex;
         }
      }


      @Override
      public boolean delistResource(XAResource arg0, int arg1) throws IllegalStateException, SystemException {
         return transaction.delistResource(arg0, arg1);
      }

      @Override
      public boolean enlistResource(XAResource arg0) throws RollbackException, IllegalStateException, SystemException {
         return transaction.enlistResource(arg0);
      }

      @Override
      public int getStatus() throws SystemException {
         return transaction.getStatus();
      }

      @Override
      public void registerSynchronization(Synchronization arg0) throws RollbackException, IllegalStateException, SystemException {
         transaction.registerSynchronization(arg0);
      }

      @Override
      public void rollback() throws IllegalStateException, SystemException {
         transaction.rollback();
         transactions.remove(transaction.get_uid());
      }

      @Override
      public void setRollbackOnly() throws IllegalStateException, SystemException {
         transaction.setRollbackOnly();
      }

      @Override
      public String toString() {
         return "FailingTransaction{" + "transaction=" + transaction.get_uid() + ", number=" + number + '}';
      }
   }

}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/LargeMessageAvoidLargeMessagesTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.client;

import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.config.StoreConfiguration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.junit.Assert;
import org.junit.Test;

/**
 * The test extends the LargeMessageTest and tests
 * the functionality of option avoid-large-messages
 */
public class LargeMessageAvoidLargeMessagesTest extends LargeMessageTest {

   public LargeMessageAvoidLargeMessagesTest(StoreConfiguration.StoreType storeType) {
      super(storeType);
      isCompressedTest = true;
   }

   @Override
   protected void validateLargeMessageComplete(ActiveMQServer server) throws Exception {
   }

   @Override
   protected boolean isNetty() {
      return false;
   }

   @Override
   protected ServerLocator createFactory(final boolean isNetty) throws Exception {
      return super.createFactory(isNetty).setMinLargeMessageSize(10240).setCompressLargeMessage(true);
   }

   @Test
   public void testSimpleSendOnAvoid() throws Exception {
      ActiveMQServer server = createServer(true, isNetty());
      server.start();

      ClientSessionFactory sf = createSessionFactory(locator);

      ClientSession session = addClientSession(sf.createSession(false, true, true));

      session.createQueue(new QueueConfiguration(ADDRESS));

      ClientProducer producer = session.createProducer(ADDRESS);

      int minLargeSize = locator.getMinLargeMessageSize();

      TestLargeMessageInputStream input = new TestLargeMessageInputStream(minLargeSize);

      ClientMessage clientFile = session.createMessage(true);
      clientFile.setBodyInputStream(input.clone());

      producer.send(clientFile);

      session.start();

      //no file should be in the dir as we send it as regular
      validateNoFilesOnLargeDir();

      ClientConsumer consumer = session.createConsumer(ADDRESS);

      ClientMessage msg1 = consumer.receive(1000);
      Assert.assertNotNull(msg1);

      for (int i = 0; i < input.getSize(); i++) {
         byte b = msg1.getBodyBuffer().readByte();
         Assert.assertEquals("incorrect char ", input.getChar(i), b);
      }
      msg1.acknowledge();
      consumer.close();

      session.close();
   }

   //send some messages that can be compressed into regular size.
   @Test
   public void testSendRegularAfterCompression() throws Exception {
      ActiveMQServer server = createServer(true, isNetty());
      server.start();

      ClientSessionFactory sf = createSessionFactory(locator);

      ClientSession session = addClientSession(sf.createSession(false, true, true));

      session.createQueue(new QueueConfiguration(ADDRESS).setAddress(ADDRESS).setDurable(false).setTemporary(true));

      ClientProducer producer = session.createProducer(ADDRESS);

      int minLargeSize = locator.getMinLargeMessageSize();

      TestLargeMessageInputStream input = new TestLargeMessageInputStream(minLargeSize);
      adjustLargeCompression(true, input, 1024);

      int num = 1;
      for (int i = 0; i < num; i++) {
         ClientMessage clientFile = session.createMessage(true);
         clientFile.setBodyInputStream(input.clone());

         producer.send(clientFile);
      }

      session.start();

      //no file should be in the dir as we send it as regular
      validateNoFilesOnLargeDir();

      ClientConsumer consumer = session.createConsumer(ADDRESS);
      for (int j = 0; j < num; j++) {
         ClientMessage msg1 = consumer.receive(1000);
         Assert.assertNotNull(msg1);

         for (int i = 0; i < input.getSize(); i++) {
            byte b = msg1.getBodyBuffer().readByte();
            Assert.assertEquals("incorrect char ", input.getChar(i), b);
         }
         msg1.acknowledge();
      }

      session.commit();
      consumer.close();

      session.close();
   }

   //send some messages that cannot be compressed into regular messages
   @Test
   public void testSendLargeAfterUnableToSendRegular() throws Exception {
      ActiveMQServer server = createServer(true, isNetty());
      server.start();

      //reduce the minLargeMessageSize to make the test faster
      locator.setMinLargeMessageSize(5 * 1024);
      ClientSessionFactory sf = createSessionFactory(locator);

      ClientSession session = addClientSession(sf.createSession(false, false, false));

      session.createQueue(new QueueConfiguration(ADDRESS).setAddress(ADDRESS).setDurable(false).setTemporary(true));

      ClientProducer producer = session.createProducer(ADDRESS);

      int minLargeSize = locator.getMinLargeMessageSize();
      TestLargeMessageInputStream input = new TestLargeMessageInputStream(minLargeSize);
      input.setSize(80 * minLargeSize);
      adjustLargeCompression(false, input, 40 * minLargeSize);

      int num = 10;
      for (int i = 0; i < num; i++) {
         ClientMessage clientFile = session.createMessage(true);
         clientFile.setBodyInputStream(input.clone());

         producer.send(clientFile);
      }

      session.commit();

      session.start();

      //no file should be in the dir as we send it as regular
      validateNoFilesOnLargeDir(server.getConfiguration().getLargeMessagesDirectory(), num);

      ClientConsumer consumer = session.createConsumer(ADDRESS);
      for (int j = 0; j < num; j++) {
         ClientMessage msg1 = consumer.receive(1000);
         Assert.assertNotNull(msg1);

         for (int i = 0; i < input.getSize(); i++) {
            byte b = msg1.getBodyBuffer().readByte();
            Assert.assertEquals("incorrect char", input.getChar(i), b);
         }
         msg1.acknowledge();
      }

      session.commit();
      consumer.close();

      session.close();
   }

   @Test
   public void testMixedCompressionSendReceive() throws Exception {
      ActiveMQServer server = createServer(true, isNetty());
      server.start();

      ClientSessionFactory sf = createSessionFactory(locator);

      ClientSession session = addClientSession(sf.createSession(false, false, false));

      session.createQueue(new QueueConfiguration(ADDRESS).setAddress(ADDRESS).setDurable(false).setTemporary(true));

      ClientProducer producer = session.createProducer(ADDRESS);

      final int minLargeSize = locator.getMinLargeMessageSize();
      TestLargeMessageInputStream regularInput = new TestLargeMessageInputStream(minLargeSize);
      adjustLargeCompression(true, regularInput, 1024);

      TestLargeMessageInputStream largeInput = new TestLargeMessageInputStream(minLargeSize);
      largeInput.setSize(100 * minLargeSize);
      adjustLargeCompression(false, largeInput, 50 * minLargeSize);

      int num = 6;
      for (int i = 0; i < num; i++) {
         ClientMessage clientFile = session.createMessage(true);
         if (i % 2 == 0) {
            clientFile.setBodyInputStream(regularInput.clone());
         } else {
            clientFile.setBodyInputStream(largeInput.clone());
         }

         producer.send(clientFile);
      }

      session.commit();

      session.start();

      //half the messages are sent as large
      validateNoFilesOnLargeDir(server.getConfiguration().getLargeMessagesDirectory(), num / 2);

      ClientConsumer consumer = session.createConsumer(ADDRESS);
      for (int j = 0; j < num; j++) {
         ClientMessage msg1 = consumer.receive(1000);
         Assert.assertNotNull(msg1);

         if (j % 2 == 0) {
            for (int i = 0; i < regularInput.getSize(); i++) {
               byte b = msg1.getBodyBuffer().readByte();
               Assert.assertEquals("incorrect char ", regularInput.getChar(i), b);
            }
         } else {
            for (int i = 0; i < largeInput.getSize(); i++) {
               byte b = msg1.getBodyBuffer().readByte();
               Assert.assertEquals("incorrect char ", largeInput.getChar(i), b);
            }
         }
         msg1.acknowledge();
      }

      session.commit();
      consumer.close();

      session.close();
   }

   //this test won't leave any large messages in the large-messages dir
   //because after compression, the messages are regulars at server.
   @Override
   @Test
   public void testDLALargeMessage() throws Exception {
      final int messageSize = (int) (3.5 * ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE);

      ClientSession session = null;

      ActiveMQServer server = createServer(true, isNetty());

      server.start();

      ClientSessionFactory sf = addSessionFactory(createSessionFactory(locator));

      session = addClientSession(sf.createSession(false, false, false));

      session.createQueue(new QueueConfiguration(ADDRESS));
      session.createQueue(new QueueConfiguration(ADDRESS.concat("-2")).setAddress(ADDRESS));

      SimpleString ADDRESS_DLA = ADDRESS.concat("-dla");

      AddressSettings addressSettings = new AddressSettings().setDeadLetterAddress(ADDRESS_DLA).setMaxDeliveryAttempts(1);

      server.getAddressSettingsRepository().addMatch("*", addressSettings);

      session.createQueue(new QueueConfiguration(ADDRESS_DLA));

      ClientProducer producer = session.createProducer(ADDRESS);

      Message clientFile = createLargeClientMessageStreaming(session, messageSize, true);

      producer.send(clientFile);

      session.commit();

      session.start();

      ClientConsumer consumer = session.createConsumer(ADDRESS_DLA);

      ClientConsumer consumerRollback = session.createConsumer(ADDRESS);
      ClientMessage msg1 = consumerRollback.receive(1000);
      Assert.assertNotNull(msg1);
      msg1.acknowledge();
      session.rollback();
      consumerRollback.close();

      msg1 = consumer.receive(10000);

      Assert.assertNotNull(msg1);

      for (int i = 0; i < messageSize; i++) {
         Assert.assertEquals(ActiveMQTestBase.getSamplebyte(i), msg1.getBodyBuffer().readByte());
      }

      session.close();
      server.stop();

      server = createServer(true, isNetty());

      server.start();

      sf = createSessionFactory(locator);

      session = sf.createSession(false, false, false);

      session.start();

      consumer = session.createConsumer(ADDRESS_DLA);

      msg1 = consumer.receive(10000);

      Assert.assertNotNull(msg1);

      for (int i = 0; i < messageSize; i++) {
         Assert.assertEquals(ActiveMQTestBase.getSamplebyte(i), msg1.getBodyBuffer().readByte());
      }

      msg1.acknowledge();

      session.commit();

      //large message becomes a regular at server.
      validateNoFilesOnLargeDir(server.getConfiguration().getLargeMessagesDirectory(), 0);

      consumer = session.createConsumer(ADDRESS.concat("-2"));

      msg1 = consumer.receive(10000);

      Assert.assertNotNull(msg1);

      for (int i = 0; i < messageSize; i++) {
         Assert.assertEquals(ActiveMQTestBase.getSamplebyte(i), msg1.getBodyBuffer().readByte());
      }

      msg1.acknowledge();

      session.commit();

      session.close();

      validateNoFilesOnLargeDir();
   }

   @Override
   @Test
   public void testSendServerMessage() throws Exception {
      // doesn't make sense as compressed
   }

}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cluster/failover/QuorumResultWaitTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.cluster.failover;

import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
import org.apache.activemq.artemis.core.config.ha.ReplicaPolicyConfiguration;
import org.apache.activemq.artemis.core.config.ha.ReplicatedPolicyConfiguration;
import org.apache.activemq.artemis.core.server.cluster.ha.ReplicatedPolicy;
import org.apache.activemq.artemis.utils.RetryMethod;
import org.apache.activemq.artemis.utils.RetryRule;
import org.junit.Rule;
import org.junit.Test;

public class QuorumResultWaitTest extends StaticClusterWithBackupFailoverTest {

   @Rule
   public RetryRule retryRule = new RetryRule(0);

   public static final int QUORUM_VOTE_WAIT_CONFIGURED_TIME_SEC = 12;
   @Override
   protected void setupServers() throws Exception {
      super.setupServers();
      //we need to know who is connected to who
      ((ReplicatedPolicyConfiguration) servers[0].getConfiguration().getHAPolicyConfiguration()).setGroupName("group0");
      ((ReplicatedPolicyConfiguration) servers[1].getConfiguration().getHAPolicyConfiguration()).setGroupName("group1");
      ((ReplicatedPolicyConfiguration) servers[2].getConfiguration().getHAPolicyConfiguration()).setGroupName("group2");
      ((ReplicaPolicyConfiguration) servers[4].getConfiguration().getHAPolicyConfiguration()).setGroupName("group1");
      ((ReplicaPolicyConfiguration) servers[5].getConfiguration().getHAPolicyConfiguration()).setGroupName("group2");
      ReplicatedPolicyConfiguration replicatedPolicyConf = new ReplicatedPolicyConfiguration().setQuorumVoteWait(QUORUM_VOTE_WAIT_CONFIGURED_TIME_SEC);
      replicatedPolicyConf.setGroupName("group0");
      replicatedPolicyConf.setVoteRetries(5);
      replicatedPolicyConf.setVoteRetryWait(100);
      servers[3].getConfiguration().setHAPolicyConfiguration(replicatedPolicyConf);
   }

   @RetryMethod(retries = 2)
   @Test
   public void testQuorumVotingResultWait() throws Exception {
      setupCluster();
      try {
         startServers(0, 1, 2);
         startServers(3, 4, 5);
         //Assert if the default time 30 sec is used
         assertEquals(ActiveMQDefaultConfiguration.getDefaultQuorumVoteWait(), ((ReplicatedPolicy) (servers[0].getHAPolicy())).getQuorumVoteWait());
         //Assert if the configured time is used.
         assertEquals(QUORUM_VOTE_WAIT_CONFIGURED_TIME_SEC, ((ReplicatedPolicy) (servers[3].getHAPolicy())).getQuorumVoteWait());
      } finally {
         stopServers(0, 1, 2, 3, 4, 5);
      }
   }

   @Override
   protected boolean isSharedStorage() {
      return false;
   }
}


<|start_filename|>tests/compatibility-tests/src/main/resources/jmsReplyToQueue/receiveMessages.groovy<|end_filename|>
package jmsReplyToQueue

import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory
import org.apache.activemq.artemis.tests.compatibility.GroovyRun

import javax.jms.*

/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory("tcp://localhost:61616");
try {
    cf.setEnable1xPrefixes(true);
} catch (Throwable totallyIgnored) {
    // older versions will not have this method, dont even bother about seeing the stack trace or exception
}
Connection connection = cf.createConnection();
Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
Queue myQueue = session.createQueue("myQueue");
MessageConsumer queueConsumer = session.createConsumer(myQueue);
consumerCreated.countDown();
connection.start()

Message message = queueConsumer.receive(5000);
GroovyRun.assertNotNull(message)
session.commit();
queueConsumer.close();

MessageProducer producer = session.createProducer(message.getJMSReplyTo());
message = session.createMessage();
producer.send(message);
session.commit();

connection.close();

latch.countDown();





<|start_filename|>artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/SCRAMClientSASL.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.protocol.amqp.sasl.scram;

import java.nio.charset.StandardCharsets;
import java.util.Objects;
import java.util.UUID;

import org.apache.activemq.artemis.protocol.amqp.sasl.ClientSASL;
import org.apache.activemq.artemis.protocol.amqp.sasl.scram.ScramClientFunctionality.State;
import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
import org.apache.qpid.proton.codec.DecodeException;

/**
 * implements the client part of SASL-SCRAM for broker interconnect
 */
public class SCRAMClientSASL implements ClientSASL {
   private final SCRAM scramType;
   private final ScramClientFunctionalityImpl client;
   private final String username;
   private final String password;

   /**
    * @param scram the SCRAM mechanism to use
    * @param username the username for authentication
    * @param password the password for authentication
    */

   public SCRAMClientSASL(SCRAM scram, String username, String password) {
      this(scram, username, password, UUID.randomUUID().toString());
   }

   protected SCRAMClientSASL(SCRAM scram, String username, String password, String nonce) {
      Objects.requireNonNull(scram);
      Objects.requireNonNull(username);
      Objects.requireNonNull(password);
      this.username = username;
      this.password = password;
      this.scramType = scram;
      client = new ScramClientFunctionalityImpl(scram.getDigest(), scram.getHmac(), nonce);
   }

   @Override
   public String getName() {
      return scramType.getName();
   }

   @Override
   public byte[] getInitialResponse() {
      try {
         String firstMessage = client.prepareFirstMessage(username);
         return firstMessage.getBytes(StandardCharsets.US_ASCII);
      } catch (ScramException e) {
         throw new DecodeException("prepareFirstMessage failed", e);
      }
   }

   @Override
   public byte[] getResponse(byte[] challenge) {
      String msg = new String(challenge, StandardCharsets.US_ASCII);
      if (client.getState() == State.FIRST_PREPARED) {
         try {
            String finalMessage = client.prepareFinalMessage(password, msg);
            return finalMessage.getBytes(StandardCharsets.US_ASCII);
         } catch (ScramException e) {
            throw new DecodeException("prepareFinalMessage failed", e);
         }
      } else if (client.getState() == State.FINAL_PREPARED) {
         try {
            client.checkServerFinalMessage(msg);
         } catch (ScramException e) {
            throw new DecodeException("checkServerFinalMessage failed", e);
         }
      }
      return new byte[0];
   }

   public static boolean isApplicable(String username, String password) {
      return username != null && username.length() > 0 && password != null && password.length() > 0;
   }

}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/DigestCallback.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.spi.core.security.jaas;

import java.security.MessageDigest;

import javax.security.auth.callback.Callback;

/**
 * Callback to obtain a {@link MessageDigest} for login purpose
 */
public class DigestCallback implements Callback {

   private MessageDigest digest;

   /**
    * set the digest to use
    * @param digest the digest
    */
   public void setDigest(MessageDigest digest) {
      this.digest = digest;
   }

   /**
    * @return the digest or <code>null</code> if not known
    */
   public MessageDigest getDigest() {
      return digest;
   }

}


<|start_filename|>artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/components/createAddress.js<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 /// <reference path="tree.component.ts"/>
var Artemis;
(function (Artemis) {
    Artemis._module.component('artemisCreateAddress', {
        template:
            `
             <h1>Create Address
                 <button type="button" class="btn btn-link jvm-title-popover"
                           uib-popover-template="'create-address-instructions.html'" popover-placement="bottom-left"
                           popover-title="Instructions" popover-trigger="'outsideClick'">
                     <span class="pficon pficon-help"></span>
                 </button>
             </h1>
             <form class="form-horizontal">

                 <div class="form-group">
                     <label class="col-sm-2 control-label" for="name-markup">Address name</label>

                     <div class="col-sm-10">
                         <input id="name-markup" class="form-control" type="text" maxlength="300"
                                name="addressName" ng-model="$ctrl.addressName" placeholder="Address name"/>
                     </div>
                 </div>
                 <div class="form-group">
                     <label class="col-sm-2 control-label">Routing type</label>

                     <div class="col-sm-10">
                         <label class="checkbox">
                             <input type="radio" ng-model="$ctrl.routingType" value="Multicast"> Multicast
                         </label>
                         <label class="checkbox">
                             <input type="radio" ng-model="$ctrl.routingType" value="Anycast"> Anycast
                         </label>
                         <label class="checkbox">
                             <input type="radio" ng-model="$ctrl.routingType" value="Both"> Both
                         </label>
                     </div>
                 </div>

                 <div class="form-group">
                     <div class="col-sm-offset-2 col-sm-10">
                         <button type="submit" class="btn btn-primary"
                                 ng-click="$ctrl.createAddress($ctrl.addressName, $ctrl.routingType)"
                                 ng-disabled="!$ctrl.addressName">Create Address
                         </button>
                     </div>
                 </div>

                 <div hawtio-confirm-dialog="$ctrl.createDialog"
                      ok-button-text="Create"
                      cancel-button-text="Cancel"
                      on-ok="$ctrl.createAddress($ctrl.addressName, $ctrl.routingType)">
                     <div class="dialog-body">
                         <p>Address name <b>{{$ctrl.addressName}}</b> contains unrecommended characters: <code>:</code></p>
                         <p>This may cause unexpected problems. Are you really sure to create this {{$ctrl.uncapitalisedDestinationType()}}?</p>
                     </div>
                 </div>

             </form>
             <script type="text/ng-template" id="create-address-instructions.html">
             <div>
                <p>
                    This page allows you to create a new address on the broker, if you want the address to support JMS like
                    queues, i.e. point to point, then choose anycast. If you want your address to support JMS like topic
                    subscriptions, publish/subscribe, then choose multicast.
                </p>
                </div>
             </script>
        `,
        controller: CreateAddressController
    })
    .name;
    Artemis.log.debug("loaded address " + Artemis.addressModule);

    function CreateAddressController($scope, workspace, jolokia, localStorage) {
        Artemis.log.debug("loaded address controller");
        var ctrl = this;
        ctrl.addressName = "";
        ctrl.routingType = "Anycast";
        ctrl.workspace = workspace;
        ctrl.message = "";

        $scope.$watch('workspace.selection', function () {
            workspace.moveIfViewInvalid();
        });

        function operationSuccess() {
            ctrl.addressName = "";
            ctrl.workspace.operationCounter += 1;
            Core.$apply($scope);
            Core.notification("success", $scope.message);
            ctrl.workspace.loadTree();
        }

        function onError(response) {
            Core.notification("error", "Could not create address: " + response.error);
        }

        ctrl.createAddress = function (name, routingType) {
            Artemis.log.debug("creating " + routingType);
            var mbean = Artemis.getBrokerMBean(workspace, jolokia);
            if (mbean) {
                if (routingType == "Multicast") {
                    $scope.message = "Created  Multicast Address " + name;
                    Artemis.log.debug(ctrl.message);
                    jolokia.execute(mbean, "createAddress(java.lang.String,java.lang.String)", name, "MULTICAST",  Core.onSuccess(operationSuccess, { error: onError }));
                }
                else if (routingType == "Anycast") {
                    $scope.message = "Created Anycast Address " + name;
                    Artemis.log.debug(ctrl.message);
                    jolokia.execute(mbean, "createAddress(java.lang.String,java.lang.String)", name, "ANYCAST",  Core.onSuccess(operationSuccess, { error: onError }));
                }
                else {
                    $scope.message = "Created Anycast/Multicast Address " + name;
                    Artemis.log.debug(ctrl.message);
                    jolokia.execute(mbean, "createAddress(java.lang.String,java.lang.String)", name, "ANYCAST,MULTICAST",  Core.onSuccess(operationSuccess, { error: onError }));
                }
            }
        };
    }
    CreateAddressController.$inject = ['$scope', 'workspace', 'jolokia', 'localStorage'];

})(Artemis || (Artemis = {}));


<|start_filename|>artemis-junit/src/main/java/org/apache/activemq/artemis/junit/EmbeddedActiveMQResource.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.junit;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.config.FileDeploymentManager;
import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl;
import org.apache.activemq.artemis.core.config.impl.FileConfiguration;
import org.apache.activemq.artemis.core.remoting.impl.invm.InVMAcceptorFactory;
import org.apache.activemq.artemis.core.remoting.impl.invm.TransportConstants;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.BindingQueryResult;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.junit.rules.ExternalResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * A JUnit Rule that embeds an ActiveMQ Artemis server into a test.
 *
 * This JUnit Rule is designed to simplify using embedded servers in unit tests.  Adding the rule to a test will startup
 * an embedded server, which can then be used by client applications.
 *
 * <pre><code>
 * public class SimpleTest {
 *     &#64;Rule
 *     public EmbeddedActiveMQResource server = new EmbeddedActiveMQResource();
 *
 *     &#64;Test
 *     public void testSomething() throws Exception {
 *         // Use the embedded server here
 *     }
 * }
 * </code></pre>
 */
public class EmbeddedActiveMQResource extends ExternalResource {

   static final String SERVER_NAME = "embedded-server";

   Logger log = LoggerFactory.getLogger(this.getClass());

   boolean useDurableMessage = true;
   boolean useDurableQueue = true;
   long defaultReceiveTimeout = 50;

   Configuration configuration;

   EmbeddedActiveMQ server;

   InternalClient internalClient;

   /**
    * Create a default EmbeddedActiveMQResource
    */
   public EmbeddedActiveMQResource() {
      configuration = new ConfigurationImpl().setName(SERVER_NAME).setPersistenceEnabled(false).setSecurityEnabled(false).addAcceptorConfiguration(new TransportConfiguration(InVMAcceptorFactory.class.getName())).addAddressesSetting("#", new AddressSettings().setDeadLetterAddress(SimpleString.toSimpleString("dla")).setExpiryAddress(SimpleString.toSimpleString("expiry")));
      init();
   }

   /**
    * Create a default EmbeddedActiveMQResource with the specified serverId
    *
    * @param serverId server id
    */
   public EmbeddedActiveMQResource(int serverId) {
      Map<String, Object> params = new HashMap<>();
      params.put(TransportConstants.SERVER_ID_PROP_NAME, serverId);
      TransportConfiguration transportConfiguration = new TransportConfiguration(InVMAcceptorFactory.class.getName(), params);
      configuration = new ConfigurationImpl().setName(SERVER_NAME + "-" + serverId).setPersistenceEnabled(false).setSecurityEnabled(false).addAcceptorConfiguration(transportConfiguration);
      init();
   }

   /**
    * Creates an EmbeddedActiveMQResource using the specified configuration
    *
    * @param configuration ActiveMQServer configuration
    */
   public EmbeddedActiveMQResource(Configuration configuration) {
      this.configuration = configuration;
      init();
   }

   /**
    * Creates an EmbeddedActiveMQResource using the specified configuration file
    *
    * @param filename ActiveMQServer configuration file name
    */
   public EmbeddedActiveMQResource(String filename) {
      if (filename == null) {
         throw new IllegalArgumentException("ActiveMQServer configuration file name cannot be null");
      }
      FileDeploymentManager deploymentManager = new FileDeploymentManager(filename);
      FileConfiguration config = new FileConfiguration();
      deploymentManager.addDeployable(config);
      try {
         deploymentManager.readConfiguration();
      } catch (Exception ex) {
         throw new EmbeddedActiveMQResourceException(String.format("Failed to read configuration file %s", filename), ex);
      }
      this.configuration = config;
      init();
   }

   /**
    * Adds properties to a ClientMessage
    *
    * @param message
    * @param properties
    */
   public static void addMessageProperties(ClientMessage message, Map<String, Object> properties) {
      if (properties != null && properties.size() > 0) {
         for (Map.Entry<String, Object> property : properties.entrySet()) {
            message.putObjectProperty(property.getKey(), property.getValue());
         }
      }
   }

   private void init() {
      if (server == null) {
         server = new EmbeddedActiveMQ().setConfiguration(configuration);
      }
   }

   /**
    * Start the embedded ActiveMQ Artemis server.
    *
    * The server will normally be started by JUnit using the before() method.  This method allows the server to
    * be started manually to support advanced testing scenarios.
    */
   public void start() {
      try {
         server.start();
      } catch (Exception ex) {
         throw new RuntimeException(String.format("Exception encountered starting %s: %s", server.getClass().getName(), this.getServerName()), ex);
      }

      configuration = server.getActiveMQServer().getConfiguration();
   }

   /**
    * Stop the embedded ActiveMQ Artemis server
    *
    * The server will normally be stopped by JUnit using the after() method.  This method allows the server to
    * be stopped manually to support advanced testing scenarios.
    */
   public void stop() {
      if (internalClient != null) {
         internalClient.stop();
         internalClient = null;
      }

      if (server != null) {
         try {
            server.stop();
         } catch (Exception ex) {
            log.warn(String.format("Exception encountered stopping %s: %s", server.getClass().getSimpleName(), this.getServerName()), ex);
         }
      }
   }

   /**
    * Invoked by JUnit to setup the resource - start the embedded ActiveMQ Artemis server
    */
   @Override
   protected void before() throws Throwable {
      log.info("Starting {}: {}", this.getClass().getSimpleName(), getServerName());

      this.start();

      super.before();
   }

   /**
    * Invoked by JUnit to tear down the resource - stops the embedded ActiveMQ Artemis server
    */
   @Override
   protected void after() {
      log.info("Stopping {}: {}", this.getClass().getSimpleName(), getServerName());

      this.stop();

      super.after();
   }

   public boolean isUseDurableMessage() {
      return useDurableMessage;
   }

   /**
    * Disables/Enables creating durable messages.  By default, durable messages are created
    *
    * @param useDurableMessage if true, durable messages will be created
    */
   public void setUseDurableMessage(boolean useDurableMessage) {
      this.useDurableMessage = useDurableMessage;
   }

   public boolean isUseDurableQueue() {
      return useDurableQueue;
   }

   /**
    * Disables/Enables creating durable queues.  By default, durable queues are created
    *
    * @param useDurableQueue if true, durable messages will be created
    */
   public void setUseDurableQueue(boolean useDurableQueue) {
      this.useDurableQueue = useDurableQueue;
   }

   public long getDefaultReceiveTimeout() {
      return defaultReceiveTimeout;
   }

   /**
    * Sets the default timeout in milliseconds used when receiving messages.  Defaults to 50 milliseconds
    *
    * @param defaultReceiveTimeout received timeout in milliseconds
    */
   public void setDefaultReceiveTimeout(long defaultReceiveTimeout) {
      this.defaultReceiveTimeout = defaultReceiveTimeout;
   }

   /**
    * Get the EmbeddedActiveMQ server.
    *
    * This may be required for advanced configuration of the EmbeddedActiveMQ server.
    *
    * @return the embedded ActiveMQ broker
    */
   public EmbeddedActiveMQ getServer() {
      return server;
   }

   /**
    * Get the name of the EmbeddedActiveMQ server
    *
    * @return name of the embedded server
    */
   public String getServerName() {
      String name = "unknown";
      ActiveMQServer activeMQServer = server.getActiveMQServer();
      if (activeMQServer != null) {
         name = activeMQServer.getConfiguration().getName();
      } else if (configuration != null) {
         name = configuration.getName();
      }

      return name;
   }

   /**
    * Get the VM URL for the embedded EmbeddedActiveMQ server
    *
    * @return the VM URL for the embedded server
    */
   public String getVmURL() {
      String vmURL = "vm://0";
      for (TransportConfiguration transportConfiguration : configuration.getAcceptorConfigurations()) {
         Map<String, Object> params = transportConfiguration.getParams();
         if (params != null && params.containsKey(TransportConstants.SERVER_ID_PROP_NAME)) {
            vmURL = "vm://" + params.get(TransportConstants.SERVER_ID_PROP_NAME);
         }
      }

      return vmURL;
   }

   public long getMessageCount(String queueName) {
      return getMessageCount(SimpleString.toSimpleString(queueName));
   }

   /**
    * Get the number of messages in a specific queue.
    *
    * @param queueName the name of the queue
    * @return the number of messages in the queue; -1 if queue is not found
    */
   public long getMessageCount(SimpleString queueName) {
      Queue queue = locateQueue(queueName);
      if (queue == null) {
         log.warn("getMessageCount(queueName) - queue {} not found; returning -1", queueName.toString());
         return -1;
      }

      return queue.getMessageCount();
   }

   public Queue locateQueue(String queueName) {
      return locateQueue(SimpleString.toSimpleString(queueName));
   }

   public Queue locateQueue(SimpleString queueName) {
      return server.getActiveMQServer().locateQueue(queueName);
   }

   public List<Queue> getBoundQueues(String address) {
      return getBoundQueues(SimpleString.toSimpleString(address));
   }

   public List<Queue> getBoundQueues(SimpleString address) {
      if (address == null) {
         throw new IllegalArgumentException("getBoundQueues( address ) - address cannot be null");
      }
      List<Queue> boundQueues = new java.util.LinkedList<>();

      BindingQueryResult bindingQueryResult = null;
      try {
         bindingQueryResult = server.getActiveMQServer().bindingQuery(address);
      } catch (Exception e) {
         throw new EmbeddedActiveMQResourceException(String.format("getBoundQueues( %s ) - bindingQuery( %s ) failed", address.toString(), address.toString()));
      }
      if (bindingQueryResult.isExists()) {
         for (SimpleString queueName : bindingQueryResult.getQueueNames()) {
            boundQueues.add(server.getActiveMQServer().locateQueue(queueName));
         }
      }
      return boundQueues;
   }

   public Queue createQueue(String name) {
      return createQueue(SimpleString.toSimpleString(name), SimpleString.toSimpleString(name));
   }

   public Queue createQueue(String address, String name) {
      return createQueue(SimpleString.toSimpleString(address), SimpleString.toSimpleString(name));
   }

   public Queue createQueue(SimpleString address, SimpleString name) {
      Queue queue = null;
      try {
         queue = server.getActiveMQServer().createQueue(new QueueConfiguration(name).setAddress(address).setDurable(isUseDurableQueue()));
      } catch (Exception ex) {
         throw new EmbeddedActiveMQResourceException(String.format("Failed to create queue: queueName = %s, name = %s", address.toString(), name.toString()), ex);
      }

      return queue;
   }

   public void createSharedQueue(String name, String user) {
      createSharedQueue(SimpleString.toSimpleString(name), SimpleString.toSimpleString(name), SimpleString.toSimpleString(user));
   }

   public void createSharedQueue(String address, String name, String user) {
      createSharedQueue(SimpleString.toSimpleString(address), SimpleString.toSimpleString(name), SimpleString.toSimpleString(user));
   }

   public void createSharedQueue(SimpleString address, SimpleString name, SimpleString user) {
      try {
         server.getActiveMQServer().createSharedQueue(new QueueConfiguration(name).setAddress(address).setRoutingType(RoutingType.MULTICAST).setDurable(isUseDurableQueue()).setUser(user));
      } catch (Exception ex) {
         throw new EmbeddedActiveMQResourceException(String.format("Failed to create shared queue: queueName = %s, name = %s, user = %s", address.toString(), name.toString(), user.toString()), ex);
      }
   }

   /**
    * Create a ClientMessage
    *
    * If useDurableMessage is false, a non-durable message is created.  Otherwise, a durable message is created
    *
    * @return a new ClientMessage
    */
   public ClientMessage createMessage() {
      getInternalClient();
      return internalClient.createMessage(isUseDurableMessage());
   }

   /**
    * Create a ClientMessage with the specified body
    *
    * If useDurableMessage is false, a non-durable message is created.  Otherwise, a durable message is created
    *
    * @param body the body for the new message
    * @return a new ClientMessage with the specified body
    */
   public ClientMessage createMessage(byte[] body) {
      getInternalClient();
      ClientMessage message = internalClient.createMessage(isUseDurableMessage());

      if (body != null) {
         message.writeBodyBufferBytes(body);
      }

      return message;
   }

   /**
    * Create a ClientMessage with the specified body
    *
    * If useDurableMessage is false, a non-durable message is created.  Otherwise, a durable message is created
    *
    * @param body the body for the new message
    * @return a new ClientMessage with the specified body
    */
   public ClientMessage createMessage(String body) {
      getInternalClient();
      ClientMessage message = internalClient.createMessage(isUseDurableMessage());

      if (body != null) {
         message.writeBodyBufferString(body);
      }

      return message;
   }

   /**
    * Create a ClientMessage with the specified message properties
    *
    * If useDurableMessage is false, a non-durable message is created.  Otherwise, a durable message is created
    *
    * @param properties message properties for the new message
    * @return a new ClientMessage with the specified message properties
    */
   public ClientMessage createMessageWithProperties(Map<String, Object> properties) {
      getInternalClient();
      ClientMessage message = internalClient.createMessage(isUseDurableMessage());

      addMessageProperties(message, properties);

      return message;
   }

   /**
    * Create a ClientMessage with the specified body and message properties
    *
    * If useDurableMessage is false, a non-durable message is created.  Otherwise, a durable message is created
    *
    * @param body       the body for the new message
    * @param properties message properties for the new message
    * @return a new ClientMessage with the specified body and message properties
    */
   public ClientMessage createMessageWithProperties(byte[] body, Map<String, Object> properties) {
      ClientMessage message = createMessage(body);

      addMessageProperties(message, properties);

      return message;
   }

   /**
    * Create a ClientMessage with the specified body and message properties
    *
    * If useDurableMessage is false, a non-durable message is created.  Otherwise, a durable message is created
    *
    * @param body       the body for the new message
    * @param properties message properties for the new message
    * @return a new ClientMessage with the specified body and message properties
    */
   public ClientMessage createMessageWithProperties(String body, Map<String, Object> properties) {
      ClientMessage message = createMessage(body);

      addMessageProperties(message, properties);

      return message;
   }

   /**
    * Send a message to an address
    *
    * @param address the target queueName for the message
    * @param message the message to send
    */
   public void sendMessage(String address, ClientMessage message) {
      sendMessage(SimpleString.toSimpleString(address), message);
   }

   /**
    * Create a new message with the specified body, and send the message to an address
    *
    * @param address the target queueName for the message
    * @param body    the body for the new message
    * @return the message that was sent
    */
   public ClientMessage sendMessage(String address, byte[] body) {
      return sendMessage(SimpleString.toSimpleString(address), body);
   }

   /**
    * Create a new message with the specified body, and send the message to an address
    *
    * @param address the target queueName for the message
    * @param body    the body for the new message
    * @return the message that was sent
    */
   public ClientMessage sendMessage(String address, String body) {
      return sendMessage(SimpleString.toSimpleString(address), body);
   }

   /**
    * Create a new message with the specified properties, and send the message to an address
    *
    * @param address    the target queueName for the message
    * @param properties message properties for the new message
    * @return the message that was sent
    */
   public ClientMessage sendMessageWithProperties(String address, Map<String, Object> properties) {
      return sendMessageWithProperties(SimpleString.toSimpleString(address), properties);
   }

   /**
    * Create a new message with the specified body and properties, and send the message to an address
    *
    * @param address    the target queueName for the message
    * @param body       the body for the new message
    * @param properties message properties for the new message
    * @return the message that was sent
    */
   public ClientMessage sendMessageWithProperties(String address, byte[] body, Map<String, Object> properties) {
      return sendMessageWithProperties(SimpleString.toSimpleString(address), body, properties);
   }

   /**
    * Create a new message with the specified body and properties, and send the message to an address
    *
    * @param address    the target queueName for the message
    * @param body       the body for the new message
    * @param properties message properties for the new message
    * @return the message that was sent
    */
   public ClientMessage sendMessageWithProperties(String address, String body, Map<String, Object> properties) {
      return sendMessageWithProperties(SimpleString.toSimpleString(address), body, properties);
   }

   /**
    * Send a message to an queueName
    *
    * @param address the target queueName for the message
    * @param message the message to send
    */
   public void sendMessage(SimpleString address, ClientMessage message) {
      if (address == null) {
         throw new IllegalArgumentException("sendMessage failure - queueName is required");
      } else if (message == null) {
         throw new IllegalArgumentException("sendMessage failure - a ClientMessage is required");
      }

      getInternalClient();
      internalClient.sendMessage(address, message);
   }

   /**
    * Create a new message with the specified body, and send the message to an queueName
    *
    * @param address the target queueName for the message
    * @param body    the body for the new message
    * @return the message that was sent
    */
   public ClientMessage sendMessage(SimpleString address, byte[] body) {
      ClientMessage message = createMessage(body);
      sendMessage(address, message);
      return message;
   }

   /**
    * Create a new message with the specified body, and send the message to an queueName
    *
    * @param address the target queueName for the message
    * @param body    the body for the new message
    * @return the message that was sent
    */
   public ClientMessage sendMessage(SimpleString address, String body) {
      ClientMessage message = createMessage(body);
      sendMessage(address, message);
      return message;
   }

   /**
    * Create a new message with the specified properties, and send the message to an queueName
    *
    * @param address    the target queueName for the message
    * @param properties message properties for the new message
    * @return the message that was sent
    */
   public ClientMessage sendMessageWithProperties(SimpleString address, Map<String, Object> properties) {
      ClientMessage message = createMessageWithProperties(properties);
      sendMessage(address, message);
      return message;
   }

   /**
    * Create a new message with the specified body and properties, and send the message to an queueName
    *
    * @param address    the target queueName for the message
    * @param body       the body for the new message
    * @param properties message properties for the new message
    * @return the message that was sent
    */
   public ClientMessage sendMessageWithProperties(SimpleString address, byte[] body, Map<String, Object> properties) {
      ClientMessage message = createMessageWithProperties(body, properties);
      sendMessage(address, message);
      return message;
   }

   /**
    * Create a new message with the specified body and properties, and send the message to an queueName
    *
    * @param address    the target queueName for the message
    * @param body       the body for the new message
    * @param properties message properties for the new message
    * @return the message that was sent
    */
   public ClientMessage sendMessageWithProperties(SimpleString address, String body, Map<String, Object> properties) {

      ClientMessage message = createMessageWithProperties(body, properties);
      sendMessage(address, message);
      return message;
   }

   /**
    * Receive a message from the specified queue using the default receive timeout
    *
    * @param queueName name of the source queue
    * @return the received ClientMessage, null if the receive timed-out
    */
   public ClientMessage receiveMessage(String queueName) {
      return receiveMessage(SimpleString.toSimpleString(queueName));
   }

   /**
    * Receive a message from the specified queue using the specified receive timeout
    *
    * @param queueName name of the source queue
    * @param timeout   receive timeout in milliseconds
    * @return the received ClientMessage, null if the receive timed-out
    */
   public ClientMessage receiveMessage(String queueName, long timeout) {
      return receiveMessage(SimpleString.toSimpleString(queueName), timeout);
   }

   /**
    * Receive a message from the specified queue using the default receive timeout
    *
    * @param queueName name of the source queue
    * @return the received ClientMessage, null if the receive timed-out
    */
   public ClientMessage receiveMessage(SimpleString queueName) {
      final boolean browseOnly = false;
      return getInternalClient().receiveMessage(queueName, defaultReceiveTimeout, browseOnly);
   }

   /**
    * Receive a message from the specified queue using the specified receive timeout
    *
    * @param queueName name of the source queue
    * @param timeout   receive timeout in milliseconds
    * @return the received ClientMessage, null if the receive timed-out
    */
   public ClientMessage receiveMessage(SimpleString queueName, long timeout) {
      final boolean browseOnly = false;
      return getInternalClient().receiveMessage(queueName, timeout, browseOnly);
   }

   /**
    * Browse a message (receive but do not consume) from the specified queue using the default receive timeout
    *
    * @param queueName name of the source queue
    * @return the received ClientMessage, null if the receive timed-out
    */
   public ClientMessage browseMessage(String queueName) {
      return browseMessage(SimpleString.toSimpleString(queueName), defaultReceiveTimeout);
   }

   /**
    * Browse a message (receive but do not consume) a message from the specified queue using the specified receive timeout
    *
    * @param queueName name of the source queue
    * @param timeout   receive timeout in milliseconds
    * @return the received ClientMessage, null if the receive timed-out
    */
   public ClientMessage browseMessage(String queueName, long timeout) {
      return browseMessage(SimpleString.toSimpleString(queueName), timeout);
   }

   /**
    * Browse a message (receive but do not consume) from the specified queue using the default receive timeout
    *
    * @param queueName name of the source queue
    * @return the received ClientMessage, null if the receive timed-out
    */
   public ClientMessage browseMessage(SimpleString queueName) {
      final boolean browseOnly = true;
      return getInternalClient().receiveMessage(queueName, defaultReceiveTimeout, browseOnly);
   }

   /**
    * Browse a message (receive but do not consume) a message from the specified queue using the specified receive timeout
    *
    * @param queueName name of the source queue
    * @param timeout   receive timeout in milliseconds
    * @return the received ClientMessage, null if the receive timed-out
    */
   public ClientMessage browseMessage(SimpleString queueName, long timeout) {
      final boolean browseOnly = true;
      return getInternalClient().receiveMessage(queueName, timeout, browseOnly);
   }

   private InternalClient getInternalClient() {
      if (internalClient == null) {
         log.info("Creating Internal Client");
         internalClient = new InternalClient();
         internalClient.start();
      }

      return internalClient;
   }

   public static class EmbeddedActiveMQResourceException extends RuntimeException {

      public EmbeddedActiveMQResourceException(String message) {
         super(message);
      }

      public EmbeddedActiveMQResourceException(String message, Exception cause) {
         super(message, cause);
      }
   }

   private class InternalClient {

      ServerLocator serverLocator;
      ClientSessionFactory sessionFactory;
      ClientSession session;
      ClientProducer producer;

      InternalClient() {
      }

      void start() {
         log.info("Starting {}", this.getClass().getSimpleName());
         try {
            serverLocator = ActiveMQClient.createServerLocator(getVmURL());
            sessionFactory = serverLocator.createSessionFactory();
         } catch (RuntimeException runtimeEx) {
            throw runtimeEx;
         } catch (Exception ex) {
            throw new EmbeddedActiveMQResourceException("Internal Client creation failure", ex);
         }

         try {
            session = sessionFactory.createSession();
            producer = session.createProducer((String) null);
            session.start();
         } catch (ActiveMQException amqEx) {
            throw new EmbeddedActiveMQResourceException("Internal Client creation failure", amqEx);
         }
      }

      void stop() {
         if (producer != null) {
            try {
               producer.close();
            } catch (ActiveMQException amqEx) {
               log.warn("ActiveMQException encountered closing InternalClient ClientProducer - ignoring", amqEx);
            } finally {
               producer = null;
            }
         }
         if (session != null) {
            try {
               session.close();
            } catch (ActiveMQException amqEx) {
               log.warn("ActiveMQException encountered closing InternalClient ClientSession - ignoring", amqEx);
            } finally {
               session = null;
            }
         }
         if (sessionFactory != null) {
            sessionFactory.close();
            sessionFactory = null;
         }
         if (serverLocator != null) {
            serverLocator.close();
            serverLocator = null;
         }

      }

      public ClientMessage createMessage(boolean durable) {
         checkSession();

         return session.createMessage(durable);
      }

      public void sendMessage(SimpleString address, ClientMessage message) {
         checkSession();
         if (producer == null) {
            throw new IllegalStateException("ClientProducer is null - has the InternalClient been started?");
         }

         try {
            producer.send(address, message);
         } catch (ActiveMQException amqEx) {
            throw new EmbeddedActiveMQResourceException(String.format("Failed to send message to %s", address.toString()), amqEx);
         }
      }

      public ClientMessage receiveMessage(SimpleString address, long timeout, boolean browseOnly) {
         checkSession();

         ClientConsumer consumer = null;
         try {
            consumer = session.createConsumer(address, browseOnly);
         } catch (ActiveMQException amqEx) {
            throw new EmbeddedActiveMQResourceException(String.format("Failed to create consumer for %s", address.toString()), amqEx);
         }

         ClientMessage message = null;
         if (timeout > 0) {
            try {
               message = consumer.receive(timeout);
            } catch (ActiveMQException amqEx) {
               throw new EmbeddedActiveMQResourceException(String.format("ClientConsumer.receive( timeout = %d ) for %s failed", timeout, address.toString()), amqEx);
            }
         } else if (timeout == 0) {
            try {
               message = consumer.receiveImmediate();
            } catch (ActiveMQException amqEx) {
               throw new EmbeddedActiveMQResourceException(String.format("ClientConsumer.receiveImmediate() for %s failed", address.toString()), amqEx);
            }
         } else {
            try {
               message = consumer.receive();
            } catch (ActiveMQException amqEx) {
               throw new EmbeddedActiveMQResourceException(String.format("ClientConsumer.receive() for %s failed", address.toString()), amqEx);
            }
         }

         return message;
      }

      void checkSession() {
         getInternalClient();
         if (session == null) {
            throw new IllegalStateException("ClientSession is null - has the InternalClient been started?");
         }
      }
   }
}


<|start_filename|>artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/ScramClientFunctionalityImpl.java<|end_filename|>
/*
 * Copyright 2016 <NAME>
 * <p>
 * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.protocol.amqp.sasl.scram;

import java.nio.charset.Charset;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Base64;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.crypto.Mac;

import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
import org.apache.activemq.artemis.spi.core.security.scram.ScramUtils;
import org.apache.activemq.artemis.spi.core.security.scram.StringPrep;

/**
 * Provides building blocks for creating SCRAM authentication client
 */
@SuppressWarnings("unused")
public class ScramClientFunctionalityImpl implements ScramClientFunctionality {
   private static final Pattern SERVER_FIRST_MESSAGE = Pattern.compile("r=([^,]*),s=([^,]*),i=(.*)$");
   private static final Pattern SERVER_FINAL_MESSAGE = Pattern.compile("v=([^,]*)$");

   private static final String GS2_HEADER = "n,,";
   private static final Charset ASCII = Charset.forName("ASCII");

   private final String mDigestName;
   private final String mHmacName;
   private final String mClientNonce;
   private String mClientFirstMessageBare;

   private final boolean mIsSuccessful = false;
   private byte[] mSaltedPassword;
   private String mAuthMessage;

   private State mState = State.INITIAL;

   /**
    * Create new ScramClientFunctionalityImpl
    * @param digestName Digest to be used
    * @param hmacName HMAC to be used
    */
   public ScramClientFunctionalityImpl(String digestName, String hmacName) {
      this(digestName, hmacName, UUID.randomUUID().toString());
   }

   /**
    * Create new ScramClientFunctionalityImpl
    * @param digestName Digest to be used
    * @param hmacName HMAC to be used
    * @param clientNonce Client nonce to be used
    */
   public ScramClientFunctionalityImpl(String digestName, String hmacName, String clientNonce) {
      if (ScramUtils.isNullOrEmpty(digestName)) {
         throw new NullPointerException("digestName cannot be null or empty");
      }
      if (ScramUtils.isNullOrEmpty(hmacName)) {
         throw new NullPointerException("hmacName cannot be null or empty");
      }
      if (ScramUtils.isNullOrEmpty(clientNonce)) {
         throw new NullPointerException("clientNonce cannot be null or empty");
      }

      mDigestName = digestName;
      mHmacName = hmacName;
      mClientNonce = clientNonce;
   }

   /**
    * Prepares first client message You may want to use
    * {@link StringPrep#isContainingProhibitedCharacters(String)} in order to check if the username
    * contains only valid characters
    * @param username Username
    * @return prepared first message
    * @throws ScramException if <code>username</code> contains prohibited characters
    */
   @Override
   public String prepareFirstMessage(String username) throws ScramException {
      if (mState != State.INITIAL) {
         throw new IllegalStateException("You can call this method only once");
      }

      try {
         mClientFirstMessageBare = "n=" + StringPrep.prepAsQueryString(username) + ",r=" + mClientNonce;
         mState = State.FIRST_PREPARED;
         return GS2_HEADER + mClientFirstMessageBare;
      } catch (StringPrep.StringPrepError e) {
         mState = State.ENDED;
         throw new ScramException("Username contains prohibited character");
      }
   }

   @Override
   public String prepareFinalMessage(String password, String serverFirstMessage) throws ScramException {
      if (mState != State.FIRST_PREPARED) {
         throw new IllegalStateException("You can call this method once only after " + "calling prepareFirstMessage()");
      }

      Matcher m = SERVER_FIRST_MESSAGE.matcher(serverFirstMessage);
      if (!m.matches()) {
         mState = State.ENDED;
         return null;
      }

      String nonce = m.group(1);

      if (!nonce.startsWith(mClientNonce)) {
         mState = State.ENDED;
         return null;
      }

      String salt = m.group(2);
      String iterationCountString = m.group(3);
      int iterations = Integer.parseInt(iterationCountString);
      if (iterations <= 0) {
         mState = State.ENDED;
         return null;
      }

      try {
         mSaltedPassword = ScramUtils.generateSaltedPassword(password, Base64.getDecoder().decode(salt), iterations,
                                                             Mac.getInstance(mHmacName));

         String clientFinalMessageWithoutProof =
                  "c=" + Base64.getEncoder().encodeToString(GS2_HEADER.getBytes(ASCII)) + ",r=" + nonce;

         mAuthMessage = mClientFirstMessageBare + "," + serverFirstMessage + "," + clientFinalMessageWithoutProof;

         byte[] clientKey = ScramUtils.computeHmac(mSaltedPassword, mHmacName, "Client Key");
         byte[] storedKey = MessageDigest.getInstance(mDigestName).digest(clientKey);

         byte[] clientSignature = ScramUtils.computeHmac(storedKey, mHmacName, mAuthMessage);

         byte[] clientProof = clientKey.clone();
         for (int i = 0; i < clientProof.length; i++) {
            clientProof[i] ^= clientSignature[i];
         }

         mState = State.FINAL_PREPARED;
         return clientFinalMessageWithoutProof + ",p=" + Base64.getEncoder().encodeToString(clientProof);
      } catch (InvalidKeyException | NoSuchAlgorithmException e) {
         mState = State.ENDED;
         throw new ScramException(e);
      }
   }

   @Override
   public void checkServerFinalMessage(String serverFinalMessage) throws ScramException {
      if (mState != State.FINAL_PREPARED) {
         throw new IllegalStateException("You can call this method only once after " + "calling prepareFinalMessage()");
      }

      Matcher m = SERVER_FINAL_MESSAGE.matcher(serverFinalMessage);
      if (!m.matches()) {
         mState = State.ENDED;
         throw new ScramException("invalid message format");
      }

      byte[] serverSignature = Base64.getDecoder().decode(m.group(1));

      mState = State.ENDED;
      if (!Arrays.equals(serverSignature, getExpectedServerSignature())) {
         throw new ScramException("Server signature missmatch");
      }
   }

   @Override
   public boolean isSuccessful() {
      if (mState == State.ENDED) {
         return mIsSuccessful;
      } else {
         throw new IllegalStateException("You cannot call this method before authentication is ended. " +
                  "Use isEnded() to check that");
      }
   }

   @Override
   public boolean isEnded() {
      return mState == State.ENDED;
   }

   @Override
   public State getState() {
      return mState;
   }

   private byte[] getExpectedServerSignature() throws ScramException {
      try {
         byte[] serverKey = ScramUtils.computeHmac(mSaltedPassword, mHmacName, "Server Key");
         return ScramUtils.computeHmac(serverKey, mHmacName, mAuthMessage);
      } catch (InvalidKeyException | NoSuchAlgorithmException e) {
         mState = State.ENDED;
         throw new ScramException(e);
      }
   }
}


<|start_filename|>tests/smoke-tests/src/test/java/org/apache/activemq/artemis/tests/smoke/console/pages/ArtemisPage.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.tests.smoke.console.pages;

import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

public abstract class ArtemisPage extends ConsolePage {
   private By logoutLocator = By.cssSelector("a[ng-focus='authService.logout()']");
   private By dropdownMenuLocator = By.id("moreDropdown");
   private By userDropdownMenuLocator = By.id("userDropdownMenu");
   private By queuesMenuItemLocator = By.xpath("//a[contains(text(),'Queues')]");

   public ArtemisPage(WebDriver driver) {
      super(driver);
   }

   public String getUser() {
      WebElement logoutWebElement = driver.findElement(logoutLocator);
      WebElement userDropdownMenuWebElement = driver.findElement(userDropdownMenuLocator);

      if (!logoutWebElement.isDisplayed()) {
         userDropdownMenuWebElement.click();
      }

      String logoutText = logoutWebElement.getText();
      Pattern pattern = Pattern.compile("Logout \\(([^\\)]+)\\)");
      Matcher matcher = pattern.matcher(logoutText);

      userDropdownMenuWebElement.click();

      if (matcher.find()) {
         return matcher.group(1);
      }

      return null;
   }

   public QueuesPage getQueuesPage(int timeout) {
      WebElement queuesMenuItem = driver.findElement(queuesMenuItemLocator);

      if (!queuesMenuItem.isDisplayed()) {
         List<WebElement> dropdownMenu = driver.findElements(dropdownMenuLocator);

         if (dropdownMenu.size() > 0) {
            dropdownMenu.get(0).click();
         } else {
            waitForElementToBeVisible(queuesMenuItemLocator, timeout);
         }
      }

      queuesMenuItem.click();

      waitForElementToBeVisible(By.xpath("//h1[contains(text(),'Browse Queues')]"), timeout);

      return new QueuesPage(driver);
   }
}


<|start_filename|>artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/handler/ProtonHandler.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.protocol.amqp.proton.handler;

import javax.security.auth.Subject;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.PooledByteBufAllocator;
import io.netty.channel.EventLoop;
import org.apache.activemq.artemis.api.core.ActiveMQSecurityException;
import org.apache.activemq.artemis.logs.AuditLogger;
import org.apache.activemq.artemis.protocol.amqp.proton.AMQPConnectionContext;
import org.apache.activemq.artemis.protocol.amqp.proton.ProtonInitializable;
import org.apache.activemq.artemis.protocol.amqp.sasl.ClientSASL;
import org.apache.activemq.artemis.protocol.amqp.sasl.SASLResult;
import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASL;
import org.apache.activemq.artemis.spi.core.remoting.ReadyListener;
import org.apache.activemq.artemis.utils.actors.ArtemisExecutor;
import org.apache.qpid.proton.Proton;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.transport.AmqpError;
import org.apache.qpid.proton.amqp.transport.ErrorCondition;
import org.apache.qpid.proton.engine.Collector;
import org.apache.qpid.proton.engine.Connection;
import org.apache.qpid.proton.engine.EndpointState;
import org.apache.qpid.proton.engine.Event;
import org.apache.qpid.proton.engine.Sasl;
import org.apache.qpid.proton.engine.SaslListener;
import org.apache.qpid.proton.engine.Transport;
import org.apache.qpid.proton.engine.impl.TransportInternal;
import org.jboss.logging.Logger;

public class ProtonHandler extends ProtonInitializable implements SaslListener {

   private static final Logger log = Logger.getLogger(ProtonHandler.class);

   private static final byte SASL = 0x03;

   private static final byte BARE = 0x00;

   private final Transport transport = Proton.transport();

   private final Connection connection = Proton.connection();

   private final Collector collector = Proton.collector();

   private List<EventHandler> handlers = new ArrayList<>();

   private ServerSASL chosenMechanism;
   private ClientSASL clientSASLMechanism;

   private final long creationTime;

   private final boolean isServer;

   private SASLResult saslResult;

   protected volatile boolean dataReceived;

   protected boolean receivedFirstPacket = false;

   private final EventLoop workerExecutor;

   private final ArtemisExecutor poolExecutor;

   protected final ReadyListener readyListener;

   boolean inDispatch = false;

   boolean scheduledFlush = false;

   boolean flushInstantly = false;

   /** afterFlush and afterFlushSet properties
    *  are set by afterFlush methods.
    *  This is to be called after the flush loop.
    *  this is usually to be used by flow control events that
    *  have to take place after the incoming bytes are settled.
    *
    *  There is only one afterFlush most of the time, and for that reason
    *   as an optimization we will try to use a single place most of the time
    *   however if more are needed we will use the list.
    *  */
   private Runnable afterFlush;
   protected Set<Runnable> afterFlushSet;

   public void afterFlush(Runnable runnable) {
      requireHandler();
      if (afterFlush == null) {
         afterFlush = runnable;
         return;
      } else {
         if (afterFlush != runnable) {
            if (afterFlushSet == null) {
               afterFlushSet = new HashSet<>();
            }
            afterFlushSet.add(runnable);
         }
      }
   }

   public void runAfterFlush() {
      requireHandler();
      if (afterFlush != null) {
         Runnable toRun = afterFlush;
         afterFlush = null;
         // setting it to null to avoid recursive flushes
         toRun.run();
      }

      if (afterFlushSet != null) {
         // This is not really expected to happen.
         // most of the time we will only have a single Runnable needing after flush
         // as this was written for flow control
         // however in extreme of caution, I'm dealing with a case where more than one is used.
         Set<Runnable> toRun = afterFlushSet;
         // setting it to null to avoid recursive flushes
         afterFlushSet = null;
         for (Runnable runnable : toRun) {
            runnable.run();
         }
      }
   }

   public ProtonHandler(EventLoop workerExecutor, ArtemisExecutor poolExecutor, boolean isServer) {
      this.workerExecutor = workerExecutor;
      this.poolExecutor = poolExecutor;
      this.readyListener = () -> runLater(this::flush);
      this.creationTime = System.currentTimeMillis();
      this.isServer = isServer;

      try {
         ((TransportInternal) transport).setUseReadOnlyOutputBuffer(false);
      } catch (NoSuchMethodError nsme) {
         // using a version at runtime where the optimization isn't available, ignore
         log.trace("Proton output buffer optimisation unavailable");
      }

      transport.bind(connection);
      connection.collect(collector);
   }

   public Long tick(boolean firstTick) {
      requireHandler();
      if (!firstTick) {
         try {
            if (connection.getLocalState() != EndpointState.CLOSED) {
               long rescheduleAt = transport.tick(TimeUnit.NANOSECONDS.toMillis(System.nanoTime()));
               if (transport.isClosed()) {
                  throw new IllegalStateException("Channel was inactive for to long");
               }
               return rescheduleAt;
            }
         } catch (Exception e) {
            log.warn(e.getMessage(), e);
            transport.close();
            connection.setCondition(new ErrorCondition());
         } finally {
            flush();
         }
         return 0L;
      }
      return transport.tick(TimeUnit.NANOSECONDS.toMillis(System.nanoTime()));
   }

   /**
    * We cannot flush until the initial handshake was finished.
    * If this happens before the handshake, the connection response will happen without SASL
    * and the client will respond and fail with an invalid code.
    */
   public void scheduledFlush() {
      if (receivedFirstPacket) {
         flush();
      }
   }

   public int capacity() {
      requireHandler();
      return transport.capacity();
   }

   public boolean isHandler() {
      return workerExecutor.inEventLoop();
   }

   public void requireHandler() {
      if (!workerExecutor.inEventLoop()) {
         throw new IllegalStateException("this method requires to be called within the handler, use the executor");
      }
   }

   public Transport getTransport() {
      return transport;
   }

   public Connection getConnection() {
      return connection;
   }

   public ProtonHandler addEventHandler(EventHandler handler) {
      handlers.add(handler);
      return this;
   }

   public void createServerSASL(String[] mechanisms) {
      requireHandler();
      Sasl sasl = transport.sasl();
      sasl.server();
      sasl.setMechanisms(mechanisms);
      sasl.setListener(this);
   }

   public void instantFlush() {
      this.flushInstantly = true;
      // This will perform event handling, and at some point the flushBytes will be called
      this.flush();
   }

   public void flushBytes() {
      requireHandler();

      if (flushInstantly) {
         flushInstantly = false;
         scheduledFlush = false;
         actualFlush();
      } else {
         // Under regular circunstances, it would be too costly to flush every time,
         // so we flush only once at the end of processing.

         // this decision was made after extensive performance testing.
         if (!scheduledFlush) {
            scheduledFlush = true;
            workerExecutor.execute(this::actualFlush);
         }
      }
   }

   private void actualFlush() {
      requireHandler();

      for (EventHandler handler : handlers) {
         if (!handler.flowControl(readyListener)) {
            scheduledFlush = false;
            return;
         }
      }

      try {
         while (true) {
            ByteBuffer head = transport.head();
            int pending = head.remaining();

            if (pending <= 0) {
               break;
            }

            // We allocated a Pooled Direct Buffer, that will be sent down the stream
            ByteBuf buffer = PooledByteBufAllocator.DEFAULT.directBuffer(pending);
            buffer.writeBytes(head);

            for (EventHandler handler : handlers) {
               handler.pushBytes(buffer);
            }

            transport.pop(pending);
         }
      } finally {
         scheduledFlush = false;
      }
   }

   public SASLResult getSASLResult() {
      return saslResult;
   }

   public void inputBuffer(ByteBuf buffer) {
      requireHandler();
      dataReceived = true;
      while (buffer.readableBytes() > 0) {
         int capacity = transport.capacity();

         if (!receivedFirstPacket) {
            handleFirstPacket(buffer);
            // there is a chance that if SASL Handshake has been carried out that the capacity may change.
            capacity = transport.capacity();
         }

         if (capacity > 0) {
            ByteBuffer tail = transport.tail();
            int min = Math.min(capacity, buffer.readableBytes());
            tail.limit(min);
            buffer.readBytes(tail);

            flush();
         } else {
            if (capacity == 0) {
               log.debugf("abandoning: readableBytes=%d", buffer.readableBytes());
            } else {
               log.debugf("transport closed, discarding: readableBytes=%d, capacity=%d", buffer.readableBytes(), transport.capacity());
            }
            break;
         }
      }
   }

   public boolean checkDataReceived() {
      boolean res = dataReceived;

      dataReceived = false;

      return res;
   }

   public long getCreationTime() {
      return creationTime;
   }

   public void runOnPool(Runnable runnable) {
      poolExecutor.execute(runnable);
   }

   public void runNow(Runnable runnable) {
      if (workerExecutor.inEventLoop()) {
         runnable.run();
      } else {
         workerExecutor.execute(runnable);
      }
   }

   public void runLater(Runnable runnable) {
      workerExecutor.execute(runnable);
   }

   public void flush() {
      if (workerExecutor.inEventLoop()) {
         transport.process();
         dispatch();
      } else {
         runLater(() -> {
            transport.process();
            dispatch();
         });
      }
   }

   public void close(ErrorCondition errorCondition, AMQPConnectionContext connectionContext) {
      runNow(() -> {
         if (errorCondition != null) {
            connection.setCondition(errorCondition);
         }
         connection.close();
         flush();
      });

      /*try {
         Thread.sleep(1000);
      } catch (Exception e) {
         e.printStackTrace();
      } */
      // this needs to be done in two steps
      // we first flush what we have to the client
      // after flushed, we close the local connection
      // otherwise this could close the netty connection before the Writable is complete
      runLater(() -> {
         connectionContext.getConnectionCallback().getTransportConnection().close();
      });
   }

   // server side SASL Listener
   @Override
   public void onSaslInit(Sasl sasl, Transport transport) {
      log.debug("onSaslInit: " + sasl);
      dispatchRemoteMechanismChosen(sasl.getRemoteMechanisms()[0]);

      if (chosenMechanism != null) {

         processPending(sasl);

      } else {
         // no auth available, system error
         saslComplete(sasl, Sasl.SaslOutcome.PN_SASL_SYS);
      }
   }

   private void processPending(Sasl sasl) {
      byte[] dataSASL = new byte[sasl.pending()];

      int received = sasl.recv(dataSASL, 0, dataSASL.length);
      if (log.isTraceEnabled()) {
         log.trace("Working on sasl, length:" + received);
      }

      byte[] response = chosenMechanism.processSASL(received != -1 ? dataSASL : null);
      if (response != null) {
         sasl.send(response, 0, response.length);
      }

      saslResult = chosenMechanism.result();
      if (saslResult != null) {
         if (saslResult.isSuccess()) {
            saslComplete(sasl, Sasl.SaslOutcome.PN_SASL_OK);
         } else {
            saslComplete(sasl, Sasl.SaslOutcome.PN_SASL_AUTH);
         }
      }
   }

   @Override
   public void onSaslResponse(Sasl sasl, Transport transport) {
      log.debug("onSaslResponse: " + sasl);
      processPending(sasl);
   }

   // client SASL Listener
   @Override
   public void onSaslMechanisms(Sasl sasl, Transport transport) {

      dispatchMechanismsOffered(sasl.getRemoteMechanisms());

      if (clientSASLMechanism == null) {
         log.infof("Outbound connection failed - unknown mechanism, offered mechanisms: %s",
                   Arrays.asList(sasl.getRemoteMechanisms()));
         dispatchAuthFailed();
      } else {
         sasl.setMechanisms(clientSASLMechanism.getName());
         byte[] initialResponse = clientSASLMechanism.getInitialResponse();
         if (initialResponse != null) {
            sasl.send(initialResponse, 0, initialResponse.length);
         }
      }
   }

   @Override
   public void onSaslChallenge(Sasl sasl, Transport transport) {
      int challengeSize = sasl.pending();
      byte[] challenge = new byte[challengeSize];
      sasl.recv(challenge, 0, challengeSize);
      byte[] response = clientSASLMechanism.getResponse(challenge);
      sasl.send(response, 0, response.length);
   }

   @Override
   public void onSaslOutcome(Sasl sasl, Transport transport) {
      log.debug("onSaslOutcome: " + sasl);
      switch (sasl.getState()) {
         case PN_SASL_FAIL:
            log.info("Outbound connection failed, authentication failure");
            dispatchAuthFailed();
            break;
         case PN_SASL_PASS:
            log.debug("Outbound connection succeeded");

            if (sasl.pending() != 0) {
               byte[] additionalData = new byte[sasl.pending()];
               sasl.recv(additionalData, 0, additionalData.length);
               clientSASLMechanism.getResponse(additionalData);
            }

            saslResult = new SASLResult() {
               @Override
               public String getUser() {
                  return null;
               }

               @Override
               public Subject getSubject() {
                  return null;
               }

               @Override
               public boolean isSuccess() {
                  return true;
               }
            };

            dispatchAuthSuccess();
            break;

         default:
            break;
      }
   }

   private void saslComplete(Sasl sasl, Sasl.SaslOutcome saslOutcome) {
      log.debug("saslComplete: " + sasl);
      sasl.done(saslOutcome);
      if (chosenMechanism != null) {
         chosenMechanism.done();
         chosenMechanism = null;
      }
   }

   private void dispatchAuthFailed() {
      for (EventHandler h : handlers) {
         h.onAuthFailed(this, getConnection());
      }
   }

   private void dispatchAuthSuccess() {
      for (EventHandler h : handlers) {
         h.onAuthSuccess(this, getConnection());
      }
   }

   private void dispatchMechanismsOffered(final String[] mechs) {
      for (EventHandler h : handlers) {
         h.onSaslMechanismsOffered(this, mechs);
      }
   }
   private void dispatchAuth(boolean sasl) {
      for (EventHandler h : handlers) {
         h.onAuthInit(this, getConnection(), sasl);
      }
   }

   private void dispatchRemoteMechanismChosen(final String mech) {
      for (EventHandler h : handlers) {
         h.onSaslRemoteMechanismChosen(this, mech);
      }
   }

   private void dispatch() {
      Event ev;

      if (inDispatch) {
         // Avoid recursion from events
         return;
      }
      try {
         inDispatch = true;
         if (AuditLogger.isAnyLoggingEnabled()) {
            for (EventHandler h : handlers) {
               AuditLogger.setRemoteAddress(h.getRemoteAddress());
            }
         }
         while ((ev = collector.peek()) != null) {
            for (EventHandler h : handlers) {
               if (log.isTraceEnabled()) {
                  log.trace("Handling " + ev + " towards " + h);
               }
               try {
                  Events.dispatch(ev, h);
               } catch (ActiveMQSecurityException e) {
                  log.warn(e.getMessage(), e);
                  ErrorCondition error = new ErrorCondition();
                  error.setCondition(AmqpError.UNAUTHORIZED_ACCESS);
                  error.setDescription(e.getMessage() == null ? e.getClass().getSimpleName() : e.getMessage());
                  connection.setCondition(error);
                  connection.close();
               } catch (Exception e) {
                  log.warn(e.getMessage(), e);
                  ErrorCondition error = new ErrorCondition();
                  error.setCondition(AmqpError.INTERNAL_ERROR);
                  error.setDescription("Unrecoverable error: " + (e.getMessage() == null ? e.getClass().getSimpleName() : e.getMessage()));
                  connection.setCondition(error);
                  connection.close();
               }
            }

            collector.pop();
         }

      } finally {
         inDispatch = false;
      }

      flushBytes();

      runAfterFlush();
   }


   public void handleError(Exception e) {
      if (workerExecutor.inEventLoop()) {
         internalHandlerError(e);
      } else {
         runLater(() -> internalHandlerError(e));
      }
   }

   private void internalHandlerError(Exception e) {
      log.warn(e.getMessage(), e);
      ErrorCondition error = new ErrorCondition();
      error.setCondition(AmqpError.INTERNAL_ERROR);
      error.setDescription("Unrecoverable error: " + (e.getMessage() == null ? e.getClass().getSimpleName() : e.getMessage()));
      connection.setCondition(error);
      connection.close();
      flush();
   }


   public void open(String containerId, Map<Symbol, Object> connectionProperties) {
      this.transport.open();
      this.connection.setContainer(containerId);
      this.connection.setProperties(connectionProperties);
      this.connection.open();
      flush();
   }

   public void setChosenMechanism(ServerSASL chosenMechanism) {
      this.chosenMechanism = chosenMechanism;
   }

   public void setClientMechanism(final ClientSASL saslClientMech) {
      this.clientSASLMechanism = saslClientMech;
   }

   public void createClientSASL() {
      Sasl sasl = transport.sasl();
      sasl.client();
      sasl.setListener(this);
   }

   private void handleFirstPacket(ByteBuf buffer) {
      try {
         byte auth = buffer.getByte(4);
         if (auth == SASL || auth == BARE) {
            if (isServer) {
               dispatchAuth(auth == SASL);
            } else if (auth == BARE && clientSASLMechanism == null) {
               dispatchAuthSuccess();
            }
         }
      } catch (Throwable e) {
         log.warn(e.getMessage(), e);
      }

      receivedFirstPacket = true;
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/AMQPPrintDataTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.amqp;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.nio.charset.StandardCharsets;

import org.apache.activemq.artemis.cli.commands.tools.PrintData;
import org.apache.activemq.artemis.core.config.FileDeploymentManager;
import org.apache.activemq.artemis.core.config.impl.FileConfiguration;
import org.apache.activemq.artemis.core.config.impl.SecurityConfiguration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl;
import org.apache.activemq.artemis.jms.server.config.impl.FileJMSConfiguration;
import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
import org.apache.activemq.artemis.spi.core.security.jaas.InVMLoginModule;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.tests.util.CFUtil;
import org.apache.activemq.artemis.tests.util.RandomUtil;
import org.junit.Assert;
import org.junit.Test;

public class AMQPPrintDataTest extends ActiveMQTestBase {

   @Test
   public void testPrintDataWithAMQP() throws Exception {
      String random = RandomUtil.randomString();
      ActiveMQServer server = addServer(getActiveMQServer("dataprint/etc/broker.xml"));
      try {
         server.getConfiguration().setPersistenceEnabled(true);
         server.start();
         ConnectionFactory factory = CFUtil.createConnectionFactory("AMQP", "tcp://localhost:61616");
         Connection connection = factory.createConnection();
         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
         MessageProducer producer = session.createProducer(session.createQueue("q1"));
         TextMessage message = session.createTextMessage("hello");
         message.setStringProperty("hello", "world:" + random);
         producer.send(message);
         connection.close();
         server.stop();
         System.setProperty("artemis.instance",
                            this.getClass().getClassLoader().getResource("dataprint").getFile());

         ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
         PrintStream printStream = new PrintStream(byteArrayOutputStream, true,  StandardCharsets.UTF_8.name());
         PrintData.printData(server.getConfiguration().getBindingsLocation().getAbsoluteFile(), server.getConfiguration().getJournalLocation().getAbsoluteFile(), server.getConfiguration().getPagingLocation().getAbsoluteFile(),
                             printStream, false, false);

         Assert.assertTrue(byteArrayOutputStream.toString().contains(random));


      } finally {
         try {
            server.stop();
         } catch (Exception e) {
         }
      }
   }

   protected ActiveMQServer getActiveMQServer(String brokerConfig) throws Exception {
      FileConfiguration fc = new FileConfiguration();
      FileJMSConfiguration fileConfiguration = new FileJMSConfiguration();
      FileDeploymentManager deploymentManager = new FileDeploymentManager(brokerConfig);
      deploymentManager.addDeployable(fc);
      deploymentManager.addDeployable(fileConfiguration);
      deploymentManager.readConfiguration();

      ActiveMQJAASSecurityManager sm = new ActiveMQJAASSecurityManager(InVMLoginModule.class.getName(), new SecurityConfiguration());

      recreateDirectory(fc.getBindingsDirectory());
      recreateDirectory(fc.getJournalDirectory());
      recreateDirectory(fc.getPagingDirectory());
      recreateDirectory(fc.getLargeMessagesDirectory());

      return addServer(new ActiveMQServerImpl(fc, sm));
   }

}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/persistence/config/PersistedRole.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.persistence.config;

import java.util.ArrayList;
import java.util.List;

import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.core.journal.EncodingSupport;
import org.apache.activemq.artemis.utils.BufferHelper;
import org.apache.activemq.artemis.utils.DataConstants;

public class PersistedRole implements EncodingSupport {

   private long storeId;

   private String username;

   private List<String> roles;

   public PersistedRole() {
   }

   public PersistedRole(String username, List<String> roles) {
      this.username = username;
      this.roles = roles;
   }

   public void setStoreId(long id) {
      this.storeId = id;
   }

   public long getStoreId() {
      return storeId;
   }

   public String getUsername() {
      return username;
   }

   public List<String> getRoles() {
      return roles;
   }

   @Override
   public int getEncodeSize() {
      int size = 0;
      size += BufferHelper.sizeOfString(username);
      size += DataConstants.SIZE_INT;
      for (String role : roles) {
         size += BufferHelper.sizeOfString(role);
      }
      return size;
   }

   @Override
   public void encode(ActiveMQBuffer buffer) {
      buffer.writeString(username);
      buffer.writeInt(roles.size());
      for (String user : roles) {
         buffer.writeString(user);
      }
   }

   @Override
   public void decode(ActiveMQBuffer buffer) {
      username = buffer.readString();
      roles = new ArrayList<>();
      int size = buffer.readInt();
      for (int i = 0; i < size; i++) {
         roles.add(buffer.readString());
      }
   }

   /* (non-Javadoc)
    * @see java.lang.Object#toString()
    */
   @Override
   public String toString() {
      StringBuilder result = new StringBuilder();
      result.append("PersistedRole [storeId=").append(storeId);
      result.append(", username=").append(username);
      result.append(", roles [");
      for (int i = 0; i < roles.size(); i++) {
         result.append(roles.get(i));
         if (i < roles.size() - 1) {
            result.append(", ");
         }
      }
      result.append("]]");

      return result.toString();
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/connect/AMQPBridgeDisconnectTest.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.tests.integration.amqp.connect;

import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.core.config.CoreAddressConfiguration;
import org.apache.activemq.artemis.core.config.amqpBrokerConnectivity.AMQPBrokerConnectConfiguration;
import org.apache.activemq.artemis.core.config.amqpBrokerConnectivity.AMQPBrokerConnectionAddressType;
import org.apache.activemq.artemis.core.config.amqpBrokerConnectivity.AMQPBrokerConnectionElement;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.tests.integration.amqp.AmqpClientTestSupport;
import org.apache.activemq.artemis.tests.util.Wait;
import org.apache.activemq.artemis.utils.ExecuteUtil;
import org.apache.activemq.artemis.utils.SpawnedVMSupport;
import org.junit.Assert;
import org.junit.Test;

public class AMQPBridgeDisconnectTest extends AmqpClientTestSupport {

   protected static final int AMQP_PORT_2 = 5673;
   private static String DESTINATION_NAME = "AMQPBridgeReconnectTest";

   public AMQPBridgeDisconnectTest() {
   }

   public static void main(String[] arg) {
      try {
         AMQPBridgeDisconnectTest reconnect = new AMQPBridgeDisconnectTest();
         if (arg[0].equals("client")) {
            reconnect.runExternal(true);
         } else {
            reconnect.runExternal(false);
         }
      } catch (Throwable var2) {
         var2.printStackTrace();
         System.exit(-1);
      }

      System.exit(0);
   }

   public void runExternal(boolean startClient) throws Exception {
      ActiveMQServer externalServer = this.createServer(AMQP_PORT_2, false);
      externalServer.getConfiguration().setPersistenceEnabled(false);
      if (startClient) {
         AMQPBrokerConnectConfiguration connectConfiguration = new AMQPBrokerConnectConfiguration("bridgeTest", "tcp://localhost:" + AMQP_PORT).setRetryInterval(100).setReconnectAttempts(-1);
         connectConfiguration.addElement((new AMQPBrokerConnectionElement()).setType(AMQPBrokerConnectionAddressType.RECEIVER).setQueueName(DESTINATION_NAME));
         externalServer.getConfiguration().addAMQPConnection(connectConfiguration);
      }
      externalServer.start();

      while (true) {
         System.out.println(AMQPBridgeDisconnectTest.class.getName() + " is running a server until someone kills it");
         Thread.sleep(5000L);
      }
   }

   @Override
   protected TransportConfiguration addAcceptorConfiguration(ActiveMQServer server, int port) {
      TransportConfiguration configuration = super.addAcceptorConfiguration(server, port);
      configuration.getExtraParams().put("amqpIdleTimeout", "1000");
      return configuration;
   }

   @Override
   protected ActiveMQServer createServer() throws Exception {
      ActiveMQServer server = this.createServer(AMQP_PORT, false);
      return server;
   }

   @Override
   protected ActiveMQServer createServer(int port, boolean start) throws Exception {
      ActiveMQServer server = super.createServer(port, start);
      server.getConfiguration().setPersistenceEnabled(false);
      server.getConfiguration().addAddressConfiguration((new CoreAddressConfiguration()).setName(DESTINATION_NAME).addRoutingType(RoutingType.ANYCAST));
      server.getConfiguration().addQueueConfiguration((new QueueConfiguration(DESTINATION_NAME)).setAddress(DESTINATION_NAME).setRoutingType(RoutingType.ANYCAST).setDurable(true));
      return server;
   }

   @Test
   public void testClientDisconnectAfterKill() throws Exception {
      this.testDisconnect(false, false);
   }

   @Test
   public void testClientDisconnectAfterPausedProcess() throws Exception {
      this.testDisconnect(true, false);
   }

   @Test
   public void testServerDisconnectAfterKill() throws Exception {
      this.testDisconnect(false, true);
   }

   @Test
   public void testServerDisconnectAfterPausedProcess() throws Exception {
      this.testDisconnect(true, true);
   }

   public void testDisconnect(boolean pause, boolean startClient) throws Exception {
      if (startClient) {
         AMQPBrokerConnectConfiguration connectConfiguration = new AMQPBrokerConnectConfiguration("bridgeTest", "tcp://localhost:" + AMQP_PORT_2 + "?amqpIdleTimeout=1000");
         connectConfiguration.addElement((new AMQPBrokerConnectionElement()).setType(AMQPBrokerConnectionAddressType.SENDER).setQueueName(DESTINATION_NAME)).setRetryInterval(100).setReconnectAttempts(-1);
         this.server.getConfiguration().addAMQPConnection(connectConfiguration);
      }
      this.server.start();
      Process process = SpawnedVMSupport.spawnVM(AMQPBridgeDisconnectTest.class.getName(), true, startClient ? "server" : "client");

      try {
         ActiveMQServer var10000 = this.server;
         Wait.assertTrue(var10000::isActive);
         Queue queue = this.server.locateQueue(DESTINATION_NAME);
         Assert.assertNotNull(queue);
         Wait.assertEquals(1, queue::getConsumerCount);
         Wait.assertEquals(1, () -> {
            return this.server.getRemotingService().getConnections().size();
         });
         if (pause) {
            int pid = ExecuteUtil.getPID(process);
            ExecuteUtil.runCommand(true, new String[]{"kill", "-STOP", Integer.toString(pid)});
         } else {
            process.destroy();
         }

         Wait.assertEquals(0, () -> {
            return this.server.getRemotingService().getConnections().size();
         }, 5000L);
         Wait.assertEquals(0, queue::getConsumerCount, 5000L);
      } finally {
         try {
            process.destroyForcibly();
         } catch (Exception var11) {
         }

      }

   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/addressing/MulticastTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.addressing;

import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.utils.TimeUtils;
import org.junit.Before;
import org.junit.Test;

import java.util.concurrent.TimeUnit;

public class MulticastTest extends ActiveMQTestBase {

   private SimpleString baseAddress = new SimpleString("multicast.address");

   private AddressInfo addressInfo;

   private ActiveMQServer server;

   private ClientSessionFactory sessionFactory;

   @Before
   public void setup() throws Exception {
      server = createServer(true);
      server.start();

      server.waitForActivation(10, TimeUnit.SECONDS);

      ServerLocator sl = ActiveMQClient.createServerLocatorWithoutHA(new TransportConfiguration(INVM_CONNECTOR_FACTORY));
      sessionFactory = sl.createSessionFactory();

      addSessionFactory(sessionFactory);

      addressInfo = new AddressInfo(baseAddress);
      addressInfo.addRoutingType(RoutingType.MULTICAST);
      server.addOrUpdateAddressInfo(addressInfo);
   }

   @Test
   public void testTxCommitReceive() throws Exception {

      Queue q1 = server.createQueue(new QueueConfiguration(baseAddress.concat(".1")).setAddress(baseAddress).setMaxConsumers(Queue.MAX_CONSUMERS_UNLIMITED));
      Queue q2 = server.createQueue(new QueueConfiguration(baseAddress.concat(".2")).setAddress(baseAddress).setMaxConsumers(Queue.MAX_CONSUMERS_UNLIMITED));

      ClientSession session = sessionFactory.createSession(false, false);
      session.start();

      ClientConsumer consumer1 = session.createConsumer(q1.getName());
      ClientConsumer consumer2 = session.createConsumer(q2.getName());

      ClientProducer producer = session.createProducer(baseAddress);

      final int num = 10;

      for (int i = 0; i < num; i++) {
         ClientMessage m = session.createMessage(ClientMessage.TEXT_TYPE, true);
         m.getBodyBuffer().writeString("AnyCast" + i);
         producer.send(m);
      }
      assertNull(consumer1.receive(200));
      assertNull(consumer2.receive(200));
      session.commit();

      assertTrue(TimeUtils.waitOnBoolean(true, 2000, () -> num == q1.getMessageCount()));
      assertTrue(TimeUtils.waitOnBoolean(true, 2000, () -> num == q2.getMessageCount()));

      ClientConsumer[] consumers = new ClientConsumer[] {consumer1, consumer2};
      for (int i = 0; i < consumers.length; i++) {

         for (int j = 0; j < num; j++) {
            ClientMessage m = consumers[i].receive(2000);
            assertNotNull(m);
            instanceLog.debug("consumer" + i + " received: " + m.getBodyBuffer().readString());
         }

         assertNull(consumers[i].receive(200));
         session.commit();

         assertNull(consumers[i].receive(200));
      }

      q1.deleteQueue();
      q2.deleteQueue();
   }

   @Test
   public void testTxRollbackReceive() throws Exception {

      Queue q1 = server.createQueue(new QueueConfiguration(baseAddress.concat(".1")).setAddress(baseAddress).setMaxConsumers(Queue.MAX_CONSUMERS_UNLIMITED));
      Queue q2 = server.createQueue(new QueueConfiguration(baseAddress.concat(".2")).setAddress(baseAddress).setMaxConsumers(Queue.MAX_CONSUMERS_UNLIMITED));

      ClientSession session = sessionFactory.createSession(false, false);
      session.start();

      ClientConsumer consumer1 = session.createConsumer(q1.getName());
      ClientConsumer consumer2 = session.createConsumer(q2.getName());

      ClientProducer producer = session.createProducer(baseAddress);

      final int num = 10;

      for (int i = 0; i < num; i++) {
         ClientMessage m = session.createMessage(ClientMessage.TEXT_TYPE, true);
         m.getBodyBuffer().writeString("AnyCast" + i);
         producer.send(m);
      }
      assertNull(consumer1.receive(200));
      assertNull(consumer2.receive(200));
      session.commit();
      session.close();

      assertTrue(TimeUtils.waitOnBoolean(true, 2000, () -> num == q1.getMessageCount()));
      assertTrue(TimeUtils.waitOnBoolean(true, 2000, () -> num == q2.getMessageCount()));

      ClientSession session1 = sessionFactory.createSession(false, false);
      ClientSession session2 = sessionFactory.createSession(false, false);
      session1.start();
      session2.start();

      consumer1 = session1.createConsumer(q1.getName());
      consumer2 = session2.createConsumer(q2.getName());

      ClientConsumer[] consumers = new ClientConsumer[] {consumer1, consumer2};
      ClientSession[] sessions = new ClientSession[] {session1, session2};
      Queue[] queues = new Queue[] {q1, q2};

      for (int i = 0; i < consumers.length; i++) {

         for (int j = 0; j < num; j++) {
            ClientMessage m = consumers[i].receive(2000);
            assertNotNull(m);
            instanceLog.debug("consumer" + i + " received: " + m.getBodyBuffer().readString());
         }

         assertNull(consumers[i].receive(200));
         sessions[i].rollback();
         sessions[i].close();

         sessions[i] = sessionFactory.createSession(false, false);
         sessions[i].start();

         //receive same after rollback
         consumers[i] = sessions[i].createConsumer(queues[i].getName());

         for (int j = 0; j < num; j++) {
            ClientMessage m = consumers[i].receive(2000);
            assertNotNull(m);
            instanceLog.debug("consumer" + i + " received: " + m.getBodyBuffer().readString());
         }

         assertNull(consumers[i].receive(200));
         sessions[i].commit();

         assertNull(consumers[i].receive(200));
         sessions[i].close();
      }

      q1.deleteQueue();
      q2.deleteQueue();
   }

}


<|start_filename|>tests/smoke-tests/src/test/java/org/apache/activemq/artemis/tests/smoke/console/pages/ConsolePage.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.tests.smoke.console.pages;

import java.time.Duration;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

public abstract class ConsolePage {
   protected WebDriver driver;

   private By titleLocator = By.tagName("h1");

   public ConsolePage(WebDriver driver) {
      this.driver = driver;
   }

   public void refresh(int timeout) {
      driver.navigate().refresh();

      waitForLoading(timeout);
   }

   public void waitForLoading(int timeout) {
      waitForElementToBeVisible(titleLocator, timeout);
   }

   public void waitForElementToBeVisible(final By elementLocator, int timeout) {
      WebDriverWait loadWebDriverWait = new WebDriverWait(
         driver, Duration.ofMillis(timeout).getSeconds());

      loadWebDriverWait.until(ExpectedConditions.visibilityOfElementLocated(elementLocator));
   }

   public void waitForElementToBeClickable(final By elementLocator, int timeout) {
      WebDriverWait loadWebDriverWait = new WebDriverWait(
         driver, Duration.ofMillis(timeout).getSeconds());

      loadWebDriverWait.until(ExpectedConditions.elementToBeClickable(elementLocator));
   }
}


<|start_filename|>artemis-commons/src/main/java/org/apache/activemq/artemis/core/server/NetworkHealthCheck.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.core.server;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.URL;
import java.net.URLConnection;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.apache.activemq.artemis.logs.ActiveMQUtilLogger;
import org.apache.activemq.artemis.utils.ActiveMQThreadFactory;
import org.apache.activemq.artemis.utils.Env;
import org.apache.activemq.artemis.utils.collections.ConcurrentHashSet;
import org.jboss.logging.Logger;

/**
 * This will use {@link InetAddress#isReachable(int)} to determine if the network is alive.
 * It will have a set of addresses, and if any address is reached the network will be considered alive.
 */
public class NetworkHealthCheck extends ActiveMQScheduledComponent {

   private static final Logger logger = Logger.getLogger(NetworkHealthCheck.class);

   private final Set<ActiveMQComponent> componentList = new ConcurrentHashSet<>();
   private final Set<String> addresses = new ConcurrentHashSet<>();
   private final Set<URL> urls = new ConcurrentHashSet<>();
   private NetworkInterface networkInterface;

   public static final String IPV6_DEFAULT_COMMAND = "ping6 -c 1 %2$s";

   public static final String IPV4_DEFAULT_COMMAND = Env.isMacOs() ? "ping -c 1 -t %d %s" : "ping -c 1 -w %d %s";

   private String ipv4Command = IPV4_DEFAULT_COMMAND;

   private String ipv6Command = IPV6_DEFAULT_COMMAND;

   // To be used on tests. As we use the loopback as a valid address on tests.
   private boolean ignoreLoopback = false;

   private boolean ownShutdown = false;

   /**
    * The timeout to be used on isReachable
    */
   private int networkTimeout;

   public NetworkHealthCheck() {
      this(null, 1000, 1000);
   }

   public NetworkHealthCheck(String nicName, long checkPeriod, int networkTimeout) {
      super(null, null, checkPeriod, TimeUnit.MILLISECONDS, false);
      this.networkTimeout = networkTimeout;
      this.setNICName(nicName);
   }

   public NetworkHealthCheck setNICName(String nicName) {
      NetworkInterface netToUse;
      try {
         if (nicName != null) {
            netToUse = NetworkInterface.getByName(nicName);
         } else {
            netToUse = null;
         }
      } catch (Exception e) {
         ActiveMQUtilLogger.LOGGER.failedToSetNIC(e, nicName);
         netToUse = null;
      }

      this.networkInterface = netToUse;
      return this;
   }

   public boolean isIgnoreLoopback() {
      return ignoreLoopback;
   }

   public NetworkHealthCheck setIgnoreLoopback(boolean ignoreLoopback) {
      this.ignoreLoopback = ignoreLoopback;
      return this;
   }

   public Set<String> getAddresses() {
      return addresses;
   }

   public Set<URL> getUrls() {
      return urls;
   }

   public String getNICName() {
      if (networkInterface != null) {
         return networkInterface.getName();
      } else {
         return null;
      }
   }

   public NetworkHealthCheck parseAddressList(String addressList) {
      if (addressList != null) {
         String[] addresses = addressList.split(",");

         for (String address : addresses) {
            if (!address.trim().isEmpty()) {
               try {
                  String strAddress = address.trim();
                  this.addAddress(strAddress);
               } catch (Exception e) {
                  ActiveMQUtilLogger.LOGGER.failedToParseAddressList(e, addressList);
               }
            }
         }
      }

      return this;
   }

   public NetworkHealthCheck parseURIList(String addressList) {
      if (addressList != null) {
         String[] addresses = addressList.split(",");

         for (String address : addresses) {
            if (!address.trim().isEmpty()) {
               try {
                  this.addURL(new URL(address.trim()));
               } catch (Exception e) {
                  ActiveMQUtilLogger.LOGGER.failedToParseUrlList(e, addressList);
               }
            }
         }
      }

      return this;
   }

   @Override
   protected ActiveMQThreadFactory getThreadFactory() {
      return new ActiveMQThreadFactory("NetworkChecker", "Network-Checker-", false, getThisClassLoader());
   }


   private ClassLoader getThisClassLoader() {
      return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
         @Override
         public ClassLoader run() {
            return NetworkHealthCheck.this.getClass().getClassLoader();
         }
      });

   }

   public int getNetworkTimeout() {
      return networkTimeout;
   }

   @Override
   public synchronized NetworkHealthCheck setPeriod(long period) {
      super.setPeriod(period);
      return this;
   }

   @Override
   public synchronized NetworkHealthCheck setTimeUnit(TimeUnit timeUnit) {
      super.setTimeUnit(timeUnit);
      return this;
   }

   public NetworkHealthCheck setNetworkTimeout(int networkTimeout) {
      this.networkTimeout = networkTimeout;
      return this;
   }

   public NetworkHealthCheck addComponent(ActiveMQComponent component) {
      componentList.add(component);
      checkStart();
      return this;
   }

   public NetworkHealthCheck clearComponents() {
      componentList.clear();
      return this;
   }

   public NetworkHealthCheck addAddress(String straddress) {
      InetAddress address = internalCheck(straddress);
      if (address == null) {
         ActiveMQUtilLogger.LOGGER.addressWasntReacheable(straddress);
      }

      if (!ignoreLoopback && address != null && address.isLoopbackAddress()) {
         ActiveMQUtilLogger.LOGGER.addressloopback(straddress);
      } else {
         addresses.add(straddress);
         checkStart();
      }
      return this;
   }

   public NetworkHealthCheck removeAddress(String straddress) {
      addresses.remove(straddress);
      return this;
   }

   public NetworkHealthCheck clearAddresses() {
      addresses.clear();
      return this;
   }

   public NetworkHealthCheck addURL(URL url) {
      if (!check(url)) {
         ActiveMQUtilLogger.LOGGER.urlWasntReacheable(url.toString());
      }
      urls.add(url);
      checkStart();
      return this;
   }

   public NetworkHealthCheck removeURL(URL url) {
      urls.remove(url);
      return this;
   }

   public NetworkHealthCheck clearURL() {
      urls.clear();
      return this;
   }

   public String getIpv4Command() {
      return ipv4Command;
   }

   public NetworkHealthCheck setIpv4Command(String ipv4Command) {
      this.ipv4Command = ipv4Command;
      return this;
   }

   public String getIpv6Command() {
      return ipv6Command;
   }

   public NetworkHealthCheck setIpv6Command(String ipv6Command) {
      this.ipv6Command = ipv6Command;
      return this;
   }

   private void checkStart() {
      if (!isStarted() && (!addresses.isEmpty() || !urls.isEmpty()) && !componentList.isEmpty()) {
         try {
            this.run(); // run the first check immediately, this is to immediately shutdown the server if there's no net
         } finally {
            start();
         }
      }
   }

   @Override
   public void run() {
      boolean healthy = check();

      if (healthy) {
         for (ActiveMQComponent component : componentList) {
            if (!component.isStarted() && ownShutdown) {
               try {
                  ActiveMQUtilLogger.LOGGER.startingService(component.toString());
                  component.start();
               } catch (Exception e) {
                  ActiveMQUtilLogger.LOGGER.errorStartingComponent(e, component.toString());
               }
            }
            ownShutdown = false;
         }
      } else {
         for (ActiveMQComponent component : componentList) {
            if (component.isStarted()) {
               ownShutdown = true;
               try {
                  ActiveMQUtilLogger.LOGGER.stoppingService(component.toString());
                  component.stop();
               } catch (Exception e) {
                  ActiveMQUtilLogger.LOGGER.errorStoppingComponent(e, component.toString());
               }
            }
         }
      }

   }

   /**
    * @return true if no checks were done or if one address/url responds; false if all addresses/urls fail
    */
   public boolean check() {
      if (isEmpty()) {
         return true;
      }

      for (String address : addresses) {
         if (check(address)) {
            return true;
         }
      }

      for (URL url : urls) {
         if (check(url)) {
            return true;
         }
      }

      return false;
   }

   public boolean check(String straddress) {
      if (straddress == null) {
         return false;
      }

      return internalCheck(straddress) != null;
   }

   private InetAddress internalCheck(String straddress) {
      try {
         InetAddress address = InetAddress.getByName(straddress);
         address = InetAddress.getByName(address.getHostName());
         if (check(address)) {
            return address;
         } else {
            return null;
         }
      } catch (Exception e) {
         ActiveMQUtilLogger.LOGGER.failedToCheckAddress(e, straddress);
         return null;
      }
   }

   public boolean check(InetAddress address) throws IOException, InterruptedException {
      if (!hasCustomPingCommand() && isReachable(address)) {
         if (logger.isTraceEnabled()) {
            logger.tracef(address + " OK");
         }
         return true;
      } else {
         return purePing(address);
      }
   }

   protected boolean isReachable(InetAddress address) throws IOException {
      return address.isReachable(networkInterface, 0, networkTimeout);
   }

   public boolean purePing(InetAddress address) throws IOException, InterruptedException {
      long timeout = Math.max(1, TimeUnit.MILLISECONDS.toSeconds(networkTimeout));
      // it did not work with a simple isReachable, it could be because there's no root access, so we will try ping executable

      if (logger.isTraceEnabled()) {
         logger.trace("purePing on canonical address " + address.getCanonicalHostName());
      }
      ProcessBuilder processBuilder;
      if (address instanceof Inet6Address) {
         processBuilder = buildProcess(ipv6Command, timeout, address.getCanonicalHostName());
      } else {
         processBuilder = buildProcess(ipv4Command, timeout, address.getCanonicalHostName());
      }

      Process pingProcess = processBuilder.start();

      readStream(pingProcess.getInputStream(), false);
      readStream(pingProcess.getErrorStream(), true);

      return pingProcess.waitFor() == 0;
   }


   private ProcessBuilder buildProcess(String expressionCommand, long timeout, String host) {
      String command = String.format(expressionCommand, timeout, host);

      if (logger.isDebugEnabled()) {
         logger.debug("executing ping:: " + command);
      }

      ProcessBuilder builder = new ProcessBuilder(command.split(" "));

      return builder;
   }

   private void readStream(InputStream stream, boolean error) throws IOException {
      BufferedReader reader = new BufferedReader(new InputStreamReader(stream));

      String inputLine;
      while ((inputLine = reader.readLine()) != null) {
         if (error) {
            ActiveMQUtilLogger.LOGGER.failedToReadFromStream(inputLine);
         } else {
            logger.debug(inputLine);
         }
      }

      reader.close();
   }

   public boolean check(URL url) {
      if (url == null) {
         return false;
      }

      try {
         URLConnection connection = url.openConnection();
         connection.setReadTimeout(networkTimeout);
         InputStream is = connection.getInputStream();
         is.close();
         return true;
      } catch (Exception e) {
         ActiveMQUtilLogger.LOGGER.failedToCheckURL(e, url.toString());
         return false;
      }
   }

   public boolean isEmpty() {
      return addresses.isEmpty() && urls.isEmpty();
   }

   public boolean hasCustomPingCommand() {
      return !getIpv4Command().equals(IPV4_DEFAULT_COMMAND) || !getIpv6Command().equals(IPV6_DEFAULT_COMMAND);
   }
}


<|start_filename|>artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AmqpReadableBuffer.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.protocol.amqp.broker;

import java.nio.ByteBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.StandardCharsets;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.util.internal.PlatformDependent;
import org.apache.qpid.proton.codec.ReadableBuffer;
import org.apache.qpid.proton.codec.WritableBuffer;

public class AmqpReadableBuffer implements ReadableBuffer {
   private ByteBuffer buffer;

   public AmqpReadableBuffer(ByteBuffer buffer) {
      this.buffer = buffer;
   }

   public ByteBuffer getBuffer() {
      return this.buffer;
   }

   @Override
   public int capacity() {
      return this.buffer.capacity();
   }

   @Override
   public boolean hasArray() {
      return this.buffer.hasArray();
   }

   @Override
   public byte[] array() {
      if (this.buffer.hasArray()) {
         return this.buffer.array();
      } else {
         byte[] bytes = new byte[buffer.remaining()];
         buffer.get(bytes);
         return bytes;
      }
   }

   public void freeDirectBuffer() {
      // releasing direct buffer created from mmap
      PlatformDependent.freeDirectBuffer(buffer);
   }

   @Override
   public int arrayOffset() {
      return this.buffer.arrayOffset();
   }

   @Override
   public ReadableBuffer reclaimRead() {
      return this;
   }

   @Override
   public byte get() {
      return this.buffer.get();
   }

   @Override
   public byte get(int index) {
      return this.buffer.get(index);
   }

   @Override
   public int getInt() {
      return this.buffer.getInt();
   }

   @Override
   public long getLong() {
      return this.buffer.getLong();
   }

   @Override
   public short getShort() {
      return this.buffer.getShort();
   }

   @Override
   public float getFloat() {
      return this.buffer.getFloat();
   }

   @Override
   public double getDouble() {
      return this.buffer.getDouble();
   }

   @Override
   public ReadableBuffer get(byte[] target, int offset, int length) {
      this.buffer.get(target, offset, length);
      return this;
   }

   @Override
   public ReadableBuffer get(byte[] target) {
      this.buffer.get(target);
      return this;
   }

   @Override
   public ReadableBuffer get(WritableBuffer target) {
      int start = target.position();
      if (this.buffer.hasArray()) {
         target.put(this.buffer.array(), this.buffer.arrayOffset() + this.buffer.position(), this.buffer.remaining());
      } else {
         target.put(this.buffer);
      }

      int written = target.position() - start;
      this.buffer.position(this.buffer.position() + written);
      return this;
   }

   @Override
   public ReadableBuffer slice() {
      return new AmqpReadableBuffer(this.buffer.slice());
   }

   @Override
   public ReadableBuffer flip() {
      this.buffer.flip();
      return this;
   }

   @Override
   public ReadableBuffer limit(int limit) {
      this.buffer.limit(limit);
      return this;
   }

   @Override
   public int limit() {
      return this.buffer.limit();
   }

   @Override
   public ReadableBuffer position(int position) {
      this.buffer.position(position);
      return this;
   }

   @Override
   public int position() {
      return this.buffer.position();
   }

   @Override
   public ReadableBuffer mark() {
      this.buffer.mark();
      return this;
   }

   @Override
   public ReadableBuffer reset() {
      this.buffer.reset();
      return this;
   }

   @Override
   public ReadableBuffer rewind() {
      this.buffer.rewind();
      return this;
   }

   @Override
   public ReadableBuffer clear() {
      this.buffer.clear();
      return this;
   }

   @Override
   public int remaining() {
      return this.buffer.remaining();
   }

   @Override
   public boolean hasRemaining() {
      return this.buffer.hasRemaining();
   }

   @Override
   public ReadableBuffer duplicate() {
      return new AmqpReadableBuffer(this.buffer.duplicate());
   }

   @Override
   public ByteBuffer byteBuffer() {
      return this.buffer;
   }

   @Override
   public String readUTF8() throws CharacterCodingException {
      ByteBuf wrappedNetty = Unpooled.wrappedBuffer(buffer);
      return wrappedNetty.toString(StandardCharsets.UTF_8);
   }

   @Override
   public String readString(CharsetDecoder decoder) throws CharacterCodingException {
      ByteBuf wrappedNetty = Unpooled.wrappedBuffer(buffer);
      return wrappedNetty.toString(StandardCharsets.UTF_8);
   }
}


<|start_filename|>artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/ScramServerFunctionalityImpl.java<|end_filename|>
/*
 * Copyright 2016 <NAME>
 * <p>
 * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.protocol.amqp.sasl.scram;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Base64;
import java.util.UUID;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.crypto.Mac;

import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
import org.apache.activemq.artemis.spi.core.security.scram.ScramUtils;
import org.apache.activemq.artemis.spi.core.security.scram.UserData;

/**
 * Provides building blocks for creating SCRAM authentication server
 */
public class ScramServerFunctionalityImpl implements ScramServerFunctionality {
   private static final Pattern CLIENT_FIRST_MESSAGE =
            Pattern.compile("^(([pny])=?([^,]*),([^,]*),)(m?=?[^,]*,?n=([^,]*),r=([^,]*),?.*)$");
   private static final Pattern CLIENT_FINAL_MESSAGE = Pattern.compile("(c=([^,]*),r=([^,]*)),p=(.*)$");

   private final String mServerPartNonce;

   private boolean mIsSuccessful = false;
   private State mState = State.INITIAL;
   private String mClientFirstMessageBare;
   private String mNonce;
   private String mServerFirstMessage;
   private UserData mUserData;
   private final MessageDigest digest;
   private final Mac hmac;

   /**
    * Creates new ScramServerFunctionalityImpl
    * @param digestName Digest to be used
    * @param hmacName HMAC to be used
    * @throws NoSuchAlgorithmException
    */
   public ScramServerFunctionalityImpl(String digestName, String hmacName) throws NoSuchAlgorithmException {
      this(digestName, hmacName, UUID.randomUUID().toString());
   }

   /**
    * /** Creates new ScramServerFunctionalityImpl
    * @param digestName Digest to be used
    * @param hmacName HMAC to be used
    * @param serverPartNonce Server's part of the nonce
    * @throws NoSuchAlgorithmException
    */
   public ScramServerFunctionalityImpl(String digestName, String hmacName,
                                       String serverPartNonce) throws NoSuchAlgorithmException {
      if (ScramUtils.isNullOrEmpty(digestName)) {
         throw new NullPointerException("digestName cannot be null or empty");
      }
      if (ScramUtils.isNullOrEmpty(hmacName)) {
         throw new NullPointerException("hmacName cannot be null or empty");
      }
      if (ScramUtils.isNullOrEmpty(serverPartNonce)) {
         throw new NullPointerException("serverPartNonce cannot be null or empty");
      }
      digest = MessageDigest.getInstance(digestName);
      hmac = Mac.getInstance(hmacName);
      mServerPartNonce = serverPartNonce;
   }

   /**
    * Handles client's first message
    * @param message Client's first message
    * @return username extracted from the client message
    * @throws ScramException
    */
   @Override
   public String handleClientFirstMessage(String message) throws ScramException {
      Matcher m = CLIENT_FIRST_MESSAGE.matcher(message);
      if (!m.matches()) {
         mState = State.ENDED;
         throw new ScramException("Invalid message received");
      }

      mClientFirstMessageBare = m.group(5);
      String username = m.group(6);
      String clientNonce = m.group(7);
      mNonce = clientNonce + mServerPartNonce;

      mState = State.FIRST_CLIENT_MESSAGE_HANDLED;

      return username;
   }

   @Override
   public String prepareFirstMessage(UserData userData) {
      mUserData = userData;
      mState = State.PREPARED_FIRST;
      mServerFirstMessage = String.format("r=%s,s=%s,i=%d", mNonce, userData.salt, userData.iterations);

      return mServerFirstMessage;
   }

   @Override
   public String prepareFinalMessage(String clientFinalMessage) throws ScramException {
      String finalMessage = prepareFinalMessageUnchecked(clientFinalMessage);
      if (!mIsSuccessful) {
         throw new ScramException("client credentials missmatch");
      }
      return finalMessage;
   }

   public String prepareFinalMessageUnchecked(String clientFinalMessage) throws ScramException {
      mState = State.ENDED;
      Matcher m = CLIENT_FINAL_MESSAGE.matcher(clientFinalMessage);
      if (!m.matches()) {
         throw new ScramException("Invalid message received");
      }

      String clientFinalMessageWithoutProof = m.group(1);
      String clientNonce = m.group(3);
      String proof = m.group(4);

      if (!mNonce.equals(clientNonce)) {
         throw new ScramException("Nonce mismatch");
      }

      String authMessage = mClientFirstMessageBare + "," + mServerFirstMessage + "," + clientFinalMessageWithoutProof;

      byte[] storedKeyArr = Base64.getDecoder().decode(mUserData.storedKey);
      byte[] clientSignature = ScramUtils.computeHmac(storedKeyArr, hmac, authMessage);
      byte[] serverSignature =
               ScramUtils.computeHmac(Base64.getDecoder().decode(mUserData.serverKey), hmac, authMessage);
      byte[] clientKey = clientSignature.clone();
      byte[] decodedProof = Base64.getDecoder().decode(proof);
      for (int i = 0; i < clientKey.length; i++) {
         clientKey[i] ^= decodedProof[i];
      }

      byte[] resultKey = digest.digest(clientKey);
      mIsSuccessful = Arrays.equals(storedKeyArr, resultKey);
      return "v=" + Base64.getEncoder().encodeToString(serverSignature);
   }

   @Override
   public boolean isSuccessful() {
      if (mState == State.ENDED) {
         return mIsSuccessful;
      } else {
         throw new IllegalStateException("You cannot call this method before authentication is ended. " +
                  "Use isEnded() to check that");
      }
   }

   @Override
   public boolean isEnded() {
      return mState == State.ENDED;
   }

   @Override
   public State getState() {
      return mState;
   }

   @Override
   public MessageDigest getDigest() {
      try {
         return (MessageDigest) digest.clone();
      } catch (CloneNotSupportedException cns) {
         try {
            return MessageDigest.getInstance(digest.getAlgorithm());
         } catch (NoSuchAlgorithmException nsa) {
            throw new AssertionError(nsa);
         }
      }
   }

   @Override
   public Mac getHmac() {
      try {
         return (Mac) hmac.clone();
      } catch (CloneNotSupportedException cns) {
         try {
            return Mac.getInstance(hmac.getAlgorithm());
         } catch (NoSuchAlgorithmException nsa) {
            throw new AssertionError(nsa);
         }
      }
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/MessageHandlerTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.client;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.MessageHandler;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class MessageHandlerTest extends ActiveMQTestBase {

   private ActiveMQServer server;

   private final SimpleString QUEUE = new SimpleString("ConsumerTestQueue");

   private ServerLocator locator;

   private ClientSessionFactory sf;

   @Override
   @Before
   public void setUp() throws Exception {
      super.setUp();

      server = createServer(false);

      server.start();

      locator = createInVMNonHALocator();
      sf = createSessionFactory(locator);

   }

   @Test
   public void testSetMessageHandlerWithMessagesPending() throws Exception {
      ClientSession session = sf.createSession(false, true, true);

      session.createQueue(new QueueConfiguration(QUEUE).setDurable(false));

      ClientProducer producer = session.createProducer(QUEUE);

      final int numMessages = 100;

      for (int i = 0; i < numMessages; i++) {
         ClientMessage message = createTextMessage(session, "m" + i);
         producer.send(message);
      }

      ClientConsumer consumer = session.createConsumer(QUEUE, null, true);

      session.start();

      Thread.sleep(100);

      // Message should be in consumer

      class MyHandler implements MessageHandler {

         @Override
         public void onMessage(final ClientMessage message) {
            try {
               Thread.sleep(10);

               message.acknowledge();
            } catch (Exception e) {
            }
         }
      }

      consumer.setMessageHandler(new MyHandler());

      // Let a few messages get processed
      Thread.sleep(100);

      // Now set null

      consumer.setMessageHandler(null);

      // Give a bit of time for some queued executors to run

      Thread.sleep(500);

      // Make sure no exceptions were thrown from onMessage
      Assert.assertNull(consumer.getLastException());

      session.close();
   }

   @Test
   public void testSetResetMessageHandler() throws Exception {
      final ClientSession session = sf.createSession(false, true, true);

      session.createQueue(new QueueConfiguration(QUEUE).setDurable(false));

      ClientProducer producer = session.createProducer(QUEUE);

      final int numMessages = 100;

      for (int i = 0; i < numMessages; i++) {
         ClientMessage message = createTextMessage(session, "m" + i);

         message.putIntProperty(new SimpleString("i"), i);

         producer.send(message);
      }

      final ClientConsumer consumer = session.createConsumer(QUEUE);

      CountDownLatch latch = new CountDownLatch(50);

      // Message should be in consumer

      class MyHandler implements MessageHandler {

         int messageReceived = 0;

         boolean failed;

         boolean started = true;

         private final CountDownLatch latch;

         MyHandler(final CountDownLatch latch) {
            this.latch = latch;
         }

         @Override
         public void onMessage(final ClientMessage message) {

            try {
               if (!started) {
                  failed = true;
               }

               messageReceived++;

               latch.countDown();

               if (latch.getCount() == 0) {
                  message.acknowledge();

                  started = false;

                  consumer.setMessageHandler(null);
               }

            } catch (Exception e) {
            }
         }
      }

      MyHandler handler = new MyHandler(latch);

      consumer.setMessageHandler(handler);

      session.start();

      waitForLatch(latch);

      Thread.sleep(100);

      Assert.assertFalse(handler.failed);

      // Make sure no exceptions were thrown from onMessage
      Assert.assertNull(consumer.getLastException());
      latch = new CountDownLatch(50);
      handler = new MyHandler(latch);
      consumer.setMessageHandler(handler);
      session.start();
      Assert.assertTrue("message received " + handler.messageReceived, latch.await(5, TimeUnit.SECONDS));

      Thread.sleep(100);

      Assert.assertFalse(handler.failed);
      Assert.assertNull(consumer.getLastException());
      session.close();
   }

   @Test
   public void testSetUnsetMessageHandler() throws Exception {
      final ClientSession session = sf.createSession(false, true, true);

      session.createQueue(new QueueConfiguration(QUEUE).setDurable(false));

      ClientProducer producer = session.createProducer(QUEUE);

      final int numMessages = 100;

      for (int i = 0; i < numMessages; i++) {
         ClientMessage message = createTextMessage(session, "m" + i);
         message.putIntProperty(new SimpleString("i"), i);
         producer.send(message);
      }

      final ClientConsumer consumer = session.createConsumer(QUEUE);

      session.start();

      CountDownLatch latch = new CountDownLatch(50);

      // Message should be in consumer

      class MyHandler implements MessageHandler {

         int messageReceived = 0;

         boolean failed;

         boolean started = true;

         private final CountDownLatch latch;

         MyHandler(final CountDownLatch latch) {
            this.latch = latch;
         }

         @Override
         public void onMessage(final ClientMessage message) {

            try {
               if (!started) {
                  failed = true;
               }
               messageReceived++;
               latch.countDown();

               if (latch.getCount() == 0) {

                  message.acknowledge();
                  started = false;
                  consumer.setMessageHandler(null);
               }

            } catch (Exception e) {
            }
         }
      }

      MyHandler handler = new MyHandler(latch);

      consumer.setMessageHandler(handler);

      waitForLatch(latch);

      Thread.sleep(100);

      Assert.assertFalse(handler.failed);

      // Make sure no exceptions were thrown from onMessage
      Assert.assertNull(consumer.getLastException());
      consumer.setMessageHandler(null);
      ClientMessage cm = consumer.receiveImmediate();
      Assert.assertNotNull(cm);

      session.close();
   }

   @Test
   public void testSetUnsetResetMessageHandler() throws Exception {
      final ClientSession session = sf.createSession(false, true, true);

      session.createQueue(new QueueConfiguration(QUEUE).setDurable(false));

      ClientProducer producer = session.createProducer(QUEUE);

      final int numMessages = 100;

      for (int i = 0; i < numMessages; i++) {
         ClientMessage message = createTextMessage(session, "m" + i);
         message.putIntProperty(new SimpleString("i"), i);
         producer.send(message);
      }

      final ClientConsumer consumer = session.createConsumer(QUEUE);

      session.start();

      CountDownLatch latch = new CountDownLatch(50);

      // Message should be in consumer

      class MyHandler implements MessageHandler {

         int messageReceived = 0;

         boolean failed;

         boolean started = true;

         private final CountDownLatch latch;

         MyHandler(final CountDownLatch latch) {
            this.latch = latch;
         }

         @Override
         public void onMessage(final ClientMessage message) {

            try {
               if (!started) {
                  failed = true;
               }
               messageReceived++;
               latch.countDown();

               if (latch.getCount() == 0) {

                  message.acknowledge();
                  started = false;
                  consumer.setMessageHandler(null);
               }

            } catch (Exception e) {
            }
         }
      }

      MyHandler handler = new MyHandler(latch);

      consumer.setMessageHandler(handler);

      waitForLatch(latch);

      Thread.sleep(100);

      Assert.assertFalse(handler.failed);

      // Make sure no exceptions were thrown from onMessage
      Assert.assertNull(consumer.getLastException());
      consumer.setMessageHandler(null);
      ClientMessage cm = consumer.receiveImmediate();
      Assert.assertNotNull(cm);
      latch = new CountDownLatch(49);
      handler = new MyHandler(latch);
      consumer.setMessageHandler(handler);
      session.start();
      Assert.assertTrue("message received " + handler.messageReceived, latch.await(5, TimeUnit.SECONDS));

      Thread.sleep(100);

      Assert.assertFalse(handler.failed);
      Assert.assertNull(consumer.getLastException());
      session.close();
   }
}


<|start_filename|>artemis-server/src/test/java/org/apache/activemq/artemis/core/reload/LoggingConfigurationFileReloaderTest.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.core.reload;

import java.util.logging.LogManager;

import org.apache.activemq.artemis.core.server.LoggingConfigurationFileReloader;
import org.apache.activemq.artemis.utils.ClassloadingUtil;
import org.apache.activemq.artemis.utils.SpawnedVMSupport;
import org.jboss.logging.Logger;
import org.junit.Assert;
import org.junit.FixMethodOrder;
import org.junit.Test;
import org.junit.runners.MethodSorters;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

@FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class LoggingConfigurationFileReloaderTest {

   private static final LogManager logManager = LogManager.getLogManager();
   private static final Logger root = Logger.getLogger("");
   private static final Logger test1 = Logger.getLogger("test1");
   private static final Logger test2 = Logger.getLogger("test2");
   private static final Logger test3 = Logger.getLogger("test3");

   public static void main(String[] args) {
      try {
         LoggingConfigurationFileReloaderTest test = new LoggingConfigurationFileReloaderTest();
         test.doTestA();
         System.exit(0);
      } catch (Throwable e) {
         System.exit(1);
      }
   }

   @Test
   public void testA() throws Exception {
      Process p = SpawnedVMSupport.spawnVM(LoggingConfigurationFileReloaderTest.class.getName());
      Assert.assertEquals(0, p.waitFor());
   }

   public void doTestA() throws Exception {

      /** This is making sure we won't mess with the configuration for other tests */
      validateInitialLoggers();

      LoggingConfigurationFileReloader loggingConfigurationFileReloader = new LoggingConfigurationFileReloader();
      loggingConfigurationFileReloader.reload(ClassloadingUtil.findResource("reload-logging-1.properties"));

      assertTrue(root.isEnabled(Logger.Level.ERROR));
      assertTrue(root.isEnabled(Logger.Level.WARN));
      assertFalse(root.isEnabled(Logger.Level.INFO));
      assertFalse(root.isEnabled(Logger.Level.DEBUG));
      assertFalse(root.isEnabled(Logger.Level.TRACE));

      assertTrue(test1.isEnabled(Logger.Level.ERROR));
      assertTrue(test1.isEnabled(Logger.Level.WARN));
      assertTrue(test1.isEnabled(Logger.Level.INFO));
      assertTrue(test1.isEnabled(Logger.Level.DEBUG));
      assertTrue(test1.isEnabled(Logger.Level.TRACE));

      assertTrue(test2.isEnabled(Logger.Level.ERROR));
      assertFalse(test2.isEnabled(Logger.Level.WARN));
      assertFalse(test2.isEnabled(Logger.Level.INFO));
      assertFalse(test2.isEnabled(Logger.Level.DEBUG));
      assertFalse(test2.isEnabled(Logger.Level.TRACE));

      loggingConfigurationFileReloader.reload(ClassloadingUtil.findResource("reload-logging-2.properties"));

      assertTrue(root.isEnabled(Logger.Level.ERROR));
      assertFalse(root.isEnabled(Logger.Level.WARN));
      assertFalse(root.isEnabled(Logger.Level.INFO));
      assertFalse(root.isEnabled(Logger.Level.DEBUG));
      assertFalse(root.isEnabled(Logger.Level.TRACE));

      assertTrue(test1.isEnabled(Logger.Level.ERROR));
      assertTrue(test1.isEnabled(Logger.Level.WARN));
      assertFalse(test1.isEnabled(Logger.Level.INFO));
      assertFalse(test1.isEnabled(Logger.Level.DEBUG));
      assertFalse(test1.isEnabled(Logger.Level.TRACE));

      assertTrue(test3.isEnabled(Logger.Level.ERROR));
      assertTrue(test3.isEnabled(Logger.Level.WARN));
      assertTrue(test3.isEnabled(Logger.Level.INFO));
      assertTrue(test3.isEnabled(Logger.Level.DEBUG));
      assertFalse(test3.isEnabled(Logger.Level.TRACE));
   }

   @Test
   public void testB() {
      validateInitialLoggers();
   }

   public void validateInitialLoggers() {
      // everything defaults to INFO
      assertTrue(root.isEnabled(Logger.Level.ERROR));
      assertTrue(root.isEnabled(Logger.Level.WARN));
      assertFalse(root.isEnabled(Logger.Level.DEBUG));
      assertFalse(root.isEnabled(Logger.Level.TRACE));

      assertTrue(test1.isEnabled(Logger.Level.ERROR));
      assertTrue(test1.isEnabled(Logger.Level.WARN));
      assertFalse(test1.isEnabled(Logger.Level.DEBUG));
      assertFalse(test1.isEnabled(Logger.Level.TRACE));

      assertTrue(test2.isEnabled(Logger.Level.ERROR));
      assertTrue(test2.isEnabled(Logger.Level.WARN));
      assertFalse(test2.isEnabled(Logger.Level.DEBUG));
      assertFalse(test2.isEnabled(Logger.Level.TRACE));
   }
}

<|start_filename|>artemis-commons/src/main/java/org/apache/activemq/artemis/utils/AutomaticLatch.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.utils;

/** An automatic latch has the same semantic as the ReusableLatch
 *  However this class has a replaceable callback that could be called
 *  when the number of elements reach zero.
 *  With that you can either block to wait completion, or to send a callback to be
 *  used when it reaches 0. */
public class AutomaticLatch extends AbstractLatch {

   volatile Runnable afterCompletion;

   public AutomaticLatch() {
   }

   public AutomaticLatch(int count) {
      super(count);
   }

   // it will execute when the counter reaches 0.
   // notice that since the latch is reusable,
   // the runnable will be cleared once it reached 0
   public void afterCompletion(final Runnable newRun) {
      // We first raise one element up
      // to avoid a race on it being called while another thread sets it down to 0
      countUp();
      if (this.afterCompletion != null) {
         // this should not happen really,
         // but just in case it ever happens,
         // I would rather have a runnable depending into other runnables instead of a collection here
         // as the use case I'm after is a single runnable
         final Runnable oldRun = afterCompletion;
         this.afterCompletion = () -> {
            oldRun.run();
            newRun.run();
         };
      } else {
         this.afterCompletion = newRun;
      }
      // then we countDown so it will be instantly 0 if nothing else done it
      // or it then just keep flow as usual
      countDown();
   }

   @Override
   public final void countDown() {
      if (control.releaseShared(1)) {
         doRun();
      }
   }

   private void doRun() {
      Runnable toRun = afterCompletion;
      afterCompletion = null;
      if (toRun != null) {
         toRun.run();
      }
   }

   @Override
   public final void countDown(final int count) {
      if (control.releaseShared(count)) {
         doRun();
      }
   }
}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/server/federation/FederatedAbstract.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.core.server.federation;

import java.util.HashMap;
import java.util.Map;

import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.core.config.WildcardConfiguration;
import org.apache.activemq.artemis.core.config.federation.FederationTransformerConfiguration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
import org.apache.activemq.artemis.core.server.federation.FederatedQueueConsumerImpl.ClientSessionCallback;
import org.apache.activemq.artemis.core.server.plugin.ActiveMQServerBasePlugin;
import org.apache.activemq.artemis.core.server.transformer.Transformer;
import org.jboss.logging.Logger;

public abstract class FederatedAbstract implements ActiveMQServerBasePlugin {

   private static final Logger logger = Logger.getLogger(FederatedAbstract.class);

   private static final WildcardConfiguration DEFAULT_WILDCARD_CONFIGURATION = new WildcardConfiguration();
   protected final Federation federation;
   protected ActiveMQServer server;
   protected FederationUpstream upstream;
   protected WildcardConfiguration wildcardConfiguration;
   protected final Map<FederatedConsumerKey, FederatedQueueConsumer> remoteQueueConsumers = new HashMap<>();
   private boolean started;

   public FederatedAbstract(Federation federation, ActiveMQServer server, FederationUpstream upstream) {
      this.federation = federation;
      this.server = server;
      this.upstream = upstream;
      this.wildcardConfiguration = server.getConfiguration().getWildcardConfiguration() == null ? DEFAULT_WILDCARD_CONFIGURATION : server.getConfiguration().getWildcardConfiguration();
   }

   /**
    * The plugin has been registered with the server
    *
    * @param server The ActiveMQServer the plugin has been registered to
    */
   @Override
   public void registered(ActiveMQServer server) {
      start();
   }

   /**
    * The plugin has been unregistered with the server
    *
    * @param server The ActiveMQServer the plugin has been unregistered to
    */
   @Override
   public void unregistered(ActiveMQServer server) {
      stop();
   }

   public synchronized void stop() {
      for (FederatedQueueConsumer remoteQueueConsumer : remoteQueueConsumers.values()) {
         remoteQueueConsumer.close();
      }
      remoteQueueConsumers.clear();
      started = false;
   }

   public synchronized void start() {
      started = true;
   }

   public boolean isStarted() {
      return started;
   }

   protected Transformer mergeTransformers(Transformer left, Transformer right) {
      if (left == null) {
         return right;
      } else if (right == null) {
         return left;
      } else {
         return (m) -> left.transform(right.transform(m));
      }
   }

   protected Transformer getTransformer(String transformerRef) {
      Transformer transformer = null;
      if (transformerRef != null) {
         FederationTransformerConfiguration federationTransformerConfiguration = federation.getConfig().getTransformerConfigurationMap().get(transformerRef);
         if (federationTransformerConfiguration != null) {
            transformer = server.getServiceRegistry().getFederationTransformer(federationTransformerConfiguration.getName(), federationTransformerConfiguration.getTransformerConfiguration());
         }
      }
      return transformer;
   }

   public synchronized void createRemoteConsumer(FederatedConsumerKey key, Transformer transformer, ClientSessionCallback callback) {
      if (started) {
         FederatedQueueConsumer remoteQueueConsumer = remoteQueueConsumers.get(key);
         if (remoteQueueConsumer == null) {
            if (server.hasBrokerFederationPlugins()) {
               try {
                  server.callBrokerFederationPlugins(plugin -> plugin.beforeCreateFederatedQueueConsumer(key));
               } catch (ActiveMQException t) {
                  ActiveMQServerLogger.LOGGER.federationPluginExecutionError(t, "beforeCreateFederatedQueueConsumer");
                  throw new IllegalStateException(t.getMessage(), t.getCause());
               }
            }
            remoteQueueConsumer = new FederatedQueueConsumerImpl(federation, server, transformer, key, upstream, callback);
            remoteQueueConsumer.start();
            remoteQueueConsumers.put(key, remoteQueueConsumer);

            if (server.hasBrokerFederationPlugins()) {
               try {
                  final FederatedQueueConsumer finalConsumer = remoteQueueConsumer;
                  server.callBrokerFederationPlugins(plugin -> plugin.afterCreateFederatedQueueConsumer(finalConsumer));
               } catch (ActiveMQException t) {
                  ActiveMQServerLogger.LOGGER.federationPluginExecutionError(t, "afterCreateFederatedQueueConsumer");
                  throw new IllegalStateException(t.getMessage(), t.getCause());
               }
            }
         }
         remoteQueueConsumer.incrementCount();
      }
   }


   public synchronized void removeRemoteConsumer(FederatedConsumerKey key) {
      FederatedQueueConsumer remoteQueueConsumer = remoteQueueConsumers.get(key);
      if (remoteQueueConsumer != null) {
         if (server.hasBrokerFederationPlugins()) {
            try {
               server.callBrokerFederationPlugins(plugin -> plugin.beforeCloseFederatedQueueConsumer(remoteQueueConsumer));
            } catch (ActiveMQException t) {
               ActiveMQServerLogger.LOGGER.federationPluginExecutionError(t, "beforeCloseFederatedQueueConsumer");
               throw new IllegalStateException(t.getMessage(), t.getCause());
            }
         }
         if (remoteQueueConsumer.decrementCount() <= 0) {
            remoteQueueConsumer.close();
            remoteQueueConsumers.remove(key);
         }
         if (server.hasBrokerFederationPlugins()) {
            try {
               server.callBrokerFederationPlugins(plugin -> plugin.afterCloseFederatedQueueConsumer(remoteQueueConsumer));
            } catch (ActiveMQException t) {
               ActiveMQServerLogger.LOGGER.federationPluginExecutionError(t, "afterCloseFederatedQueueConsumer");
               throw new IllegalStateException(t.getMessage(), t.getCause());
            }
         }
      }
   }

}


<|start_filename|>examples/features/broker-connection/amqp-sending-messages/src/main/java/org/apache/activemq/artemis/jms/example/BrokerConnectionSender.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.jms.example;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;

import org.apache.qpid.jms.JmsConnectionFactory;

/**
 * This example is demonstrating how messages are transferred from one broker towards another broker
 * through the sender operation on a AMQP Broker Connection.
 */
public class BrokerConnectionSender {

   public static void main(final String[] args) throws Exception {
      Connection connectionOnServer0 = null;
      ConnectionFactory connectionFactoryServer0 = new JmsConnectionFactory("amqp://localhost:5660");

      // Step 1. Create a connection on server0, and send a few messages
      try {

         connectionOnServer0 = connectionFactoryServer0.createConnection();

         Session session = connectionOnServer0.createSession(false, Session.AUTO_ACKNOWLEDGE);

         Queue queue = session.createQueue("exampleQueue");
         MessageProducer sender = session.createProducer(queue);
         for (int i = 0; i < 100; i++) {
            sender.send(session.createTextMessage("Hello world n" + i));
         }
      } finally {
         if (connectionFactoryServer0 != null) {
            connectionOnServer0.close();
         }
      }

      // Step 2. create a connection on server1, and receive a few messages.
      //          the sender on the broker conneciton will take care of the transfer.
      Connection connectionOnServer1 = null;
      ConnectionFactory connectionFactoryServer1 = new JmsConnectionFactory("amqp://localhost:5771");

      try {
         connectionOnServer1 = connectionFactoryServer1.createConnection();
         connectionOnServer1.start();
         Session session = connectionOnServer1.createSession(false, Session.AUTO_ACKNOWLEDGE);
         Queue queue = session.createQueue("exampleQueue");
         MessageConsumer consumer = session.createConsumer(queue);
         for (int i = 0; i < 100; i++) {
            TextMessage message = (TextMessage) consumer.receive(5000);
            System.out.println("Received message " + message.getText());
         }
      } finally {
         if (connectionOnServer1 != null) {
            connectionOnServer1.close();
         }
      }
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/AmqpMessageDivertsTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.amqp;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.server.ComponentConfigurationRoutingType;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.core.server.transformer.Transformer;
import org.apache.activemq.artemis.tests.util.Wait;
import org.apache.activemq.transport.amqp.client.AmqpClient;
import org.apache.activemq.transport.amqp.client.AmqpConnection;
import org.apache.activemq.transport.amqp.client.AmqpMessage;
import org.apache.activemq.transport.amqp.client.AmqpReceiver;
import org.apache.activemq.transport.amqp.client.AmqpSender;
import org.apache.activemq.transport.amqp.client.AmqpSession;
import org.junit.Assert;
import org.junit.Test;

public class AmqpMessageDivertsTest extends AmqpClientTestSupport implements Transformer {

   static final AtomicInteger divertCount = new AtomicInteger(0);

   String largeString = createLargeString();

   protected String createLargeString() {
      StringBuffer bufferLarge = new StringBuffer();
      for (int i = 0; i < 500 * 1024; i++) {
         bufferLarge.append((char) ('a' + (i % 20)));
      }
      String largeString = bufferLarge.toString();
      return largeString;
   }


   @Test(timeout = 60000)
   public void testQueueReceiverReadMessageWithDivert() throws Exception {
      runQueueReceiverReadMessageWithDivert(ComponentConfigurationRoutingType.ANYCAST.toString());
   }

   @Test(timeout = 60000)
   public void testQueueReceiverReadMessageWithDivertDefaultRouting() throws Exception {
      runQueueReceiverReadMessageWithDivert(ActiveMQDefaultConfiguration.getDefaultDivertRoutingType());
   }

   public void runQueueReceiverReadMessageWithDivert(String routingType) throws Exception {
      final String forwardingAddress = getQueueName() + "Divert";
      final SimpleString simpleForwardingAddress = SimpleString.toSimpleString(forwardingAddress);
      server.createQueue(new QueueConfiguration(simpleForwardingAddress).setRoutingType(RoutingType.ANYCAST));
      server.getActiveMQServerControl().createDivert("name", "routingName", getQueueName(), forwardingAddress, true, null, null, routingType);

      sendMessages(getQueueName(), 1);

      AmqpClient client = createAmqpClient();
      AmqpConnection connection = addConnection(client.connect());
      AmqpSession session = connection.createSession();

      AmqpReceiver receiver = session.createReceiver(forwardingAddress);

      Queue queueView = getProxyToQueue(forwardingAddress);
      assertEquals(1, queueView.getMessageCount());

      receiver.flow(1);
      assertNotNull(receiver.receive(5, TimeUnit.SECONDS));
      receiver.close();

      assertEquals(1, queueView.getMessageCount());

      connection.close();
   }

   @Test
   public void testDivertTransformerWithProperties() throws Exception {
      testDivertTransformerWithProperties(false);
   }

   @Test
   public void testDivertTransformerWithPropertiesRebootServer() throws Exception {
      testDivertTransformerWithProperties(true);
   }

   public void testDivertTransformerWithProperties(boolean rebootServer) throws Exception {
      divertCount.set(0);
      final String forwardingAddress = getQueueName() + "Divert";
      final SimpleString simpleForwardingAddress = SimpleString.toSimpleString(forwardingAddress);
      server.createQueue(new QueueConfiguration(simpleForwardingAddress).setRoutingType(RoutingType.ANYCAST));
      server.getActiveMQServerControl().createDivert("name", "routingName", getQueueName(),
                                                     forwardingAddress, true, null, AmqpMessageDivertsTest.class.getName(),
                                                     ComponentConfigurationRoutingType.ANYCAST.toString());

      AmqpClient client = createAmqpClient();
      AmqpConnection connection = addConnection(client.connect());
      AmqpSession session = connection.createSession();

      Queue queueView = getProxyToQueue(forwardingAddress);
      AmqpSender sender = session.createSender(getQueueName());
      AmqpMessage message = new AmqpMessage();
      message.setDurable(true);
      message.setApplicationProperty("addLarge", false);
      message.setApplicationProperty("always", "here");
      message.setBytes(new byte[10]); // one small
      sender.send(message);
      Wait.assertEquals(1, queueView::getMessageCount);

      message = new AmqpMessage();
      message.setDurable(true);
      message.setApplicationProperty("addLarge", false);
      message.setApplicationProperty("always", "here");
      message.setBytes(new byte[300 * 1024]); // one large
      sender.send(message);
      Wait.assertEquals(2, queueView::getMessageCount);

      if (rebootServer) {
         Wait.assertEquals(2, divertCount::get);
         connection.close();
         server.stop();
         server.start();

         // reopen connections
         client = createAmqpClient();
         connection = addConnection(client.connect());
         session = connection.createSession();
      } else {
         message = new AmqpMessage();
         message.setDurable(false);
         message.setBytes(new byte[300 * 1024]); // one large
         message.setApplicationProperty("addLarge", true);
         message.setApplicationProperty("always", "here");
         sender.send(message);
         Wait.assertEquals(3, divertCount::get);
      }


      AmqpReceiver receiver = session.createReceiver(forwardingAddress);

      queueView = getProxyToQueue(forwardingAddress);
      assertEquals(rebootServer ? 2 : 3, queueView.getMessageCount());

      receiver.flow(2);
      for (int i = 0; i < 2; i++) {
         AmqpMessage receivedMessage = receiver.receive(5, TimeUnit.SECONDS);
         Assert.assertNotNull(receivedMessage);
         Assert.assertEquals("here", receivedMessage.getApplicationProperty("always"));
         Assert.assertEquals("mundo", receivedMessage.getApplicationProperty("oi"));
         receivedMessage.accept();
      }

      if (!rebootServer) {
         // if we did not reboot the server a third message was sent
         receiver.flow(1);
         AmqpMessage receivedMessage = receiver.receive(5, TimeUnit.SECONDS);
         receivedMessage.accept();
         Assert.assertEquals("mundo", receivedMessage.getApplicationProperty("oi"));
         Assert.assertEquals(largeString, receivedMessage.getApplicationProperty("largeString"));

      }

      receiver.close();

      Wait.assertEquals(0, queueView::getMessageCount);

      connection.close();
   }

   @Override
   public Message transform(Message message) {
      divertCount.incrementAndGet();
      if (message.getBooleanProperty("addLarge")) {
         message.putStringProperty("largeString", largeString);
      }
      message.putBooleanProperty("oi", true);
      message.putStringProperty("oi", "mundo");
      message.reencode();
      return message;
   }
}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/jdbc/ScheduledLeaseLock.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.core.server.impl.jdbc;

import java.util.concurrent.ScheduledExecutorService;

import org.apache.activemq.artemis.core.server.ActiveMQComponent;
import org.apache.activemq.artemis.core.server.NodeManager.LockListener;
import org.apache.activemq.artemis.utils.actors.ArtemisExecutor;

/**
 * {@link LeaseLock} holder that allows to schedule a {@link LeaseLock#renew} task with a fixed {@link #renewPeriodMillis()} delay.
 */
interface ScheduledLeaseLock extends ActiveMQComponent {

   @Override
   void start();

   @Override
   void stop();

   LeaseLock lock();

   long renewPeriodMillis();

   String lockName();

   static ScheduledLeaseLock of(ScheduledExecutorService scheduledExecutorService,
                                ArtemisExecutor executor,
                                String lockName,
                                LeaseLock lock,
                                long renewPeriodMillis,
                                LockListener lockListener) {
      return new ActiveMQScheduledLeaseLock(scheduledExecutorService, executor, lockName, lock, renewPeriodMillis, lockListener);
   }

}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/scram/UserData.java<|end_filename|>
/*
 * Copyright 2016 <NAME>
 * <p>
 * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.spi.core.security.scram;

/**
 * Wrapper for user data needed for the SCRAM authentication
 */
public class UserData {
   /**
    * Salt
    */
   public final String salt;
   /**
    * Iterations used to salt the password
    */
   public final int iterations;
   /**
    * Server key
    */
   public final String serverKey;
   /**
    * Stored key
    */
   public final String storedKey;

   /**
    * Creates new UserData
    * @param salt Salt
    * @param iterations Iterations for salting
    * @param serverKey Server key
    * @param storedKey Stored key
    */
   public UserData(String salt, int iterations, String serverKey, String storedKey) {
      this.salt = salt;
      this.iterations = iterations;
      this.serverKey = serverKey;
      this.storedKey = storedKey;
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/ProgrammaticRedeployTest.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.tests.integration.jms;

import javax.jms.ConnectionFactory;
import javax.jms.JMSContext;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.postoffice.QueueBinding;
import org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ;
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.junit.Assert;
import org.junit.Test;

public class ProgrammaticRedeployTest extends ActiveMQTestBase {

   @Test
   /**
    * This is basically a copy of org.apache.activemq.artemis.tests.integration.jms.RedeployTest#testRedeployAddressQueue().
    * However, this test disables automatic configuration reload and uses the management API to do it instead.
    */
   public void testRedeployAddressQueue() throws Exception {
      Path brokerXML = getTestDirfile().toPath().resolve("broker.xml");
      URL url1 = ProgrammaticRedeployTest.class.getClassLoader().getResource("reload-address-queues-programmatic.xml");
      URL url2 = ProgrammaticRedeployTest.class.getClassLoader().getResource("reload-address-queues-updated-programmatic.xml");
      Files.copy(url1.openStream(), brokerXML);

      EmbeddedActiveMQ embeddedActiveMQ = new EmbeddedActiveMQ();
      embeddedActiveMQ.setConfigResourcePath(brokerXML.toUri().toString());
      embeddedActiveMQ.start();

      ConnectionFactory connectionFactory = new ActiveMQConnectionFactory();
      try (JMSContext jmsContext = connectionFactory.createContext()) {
         jmsContext.createSharedDurableConsumer(jmsContext.createTopic("config_test_consumer_created_queues"),"mySub").receive(100);
      }

      try {
         Assert.assertTrue(listQueuesNamesForAddress(embeddedActiveMQ, "config_test_consumer_created_queues").contains("mySub"));

         Assert.assertNotNull(getAddressInfo(embeddedActiveMQ, "config_test_address_removal_no_queue"));
         Assert.assertNotNull(getAddressInfo(embeddedActiveMQ, "config_test_address_removal"));
         Assert.assertNotNull(getAddressInfo(embeddedActiveMQ, "config_test_queue_removal"));
         Assert.assertTrue(listQueuesNamesForAddress(embeddedActiveMQ, "config_test_queue_removal").contains("config_test_queue_removal_queue_1"));
         Assert.assertTrue(listQueuesNamesForAddress(embeddedActiveMQ, "config_test_queue_removal").contains("config_test_queue_removal_queue_2"));

         Assert.assertNotNull(getAddressInfo(embeddedActiveMQ, "permanent_test_address_removal"));
         Assert.assertNotNull(getAddressInfo(embeddedActiveMQ, "permanent_test_queue_removal"));
         Assert.assertTrue(listQueuesNamesForAddress(embeddedActiveMQ, "permanent_test_queue_removal").contains("permanent_test_queue_removal_queue_1"));
         Assert.assertTrue(listQueuesNamesForAddress(embeddedActiveMQ, "permanent_test_queue_removal").contains("permanent_test_queue_removal_queue_2"));

         Assert.assertNotNull(getAddressInfo(embeddedActiveMQ, "config_test_queue_change"));
         Assert.assertTrue(listQueuesNamesForAddress(embeddedActiveMQ, "config_test_queue_change").contains("config_test_queue_change_queue"));
         Assert.assertEquals(10, getQueue(embeddedActiveMQ, "config_test_queue_change_queue").getMaxConsumers());
         Assert.assertEquals(false, getQueue(embeddedActiveMQ, "config_test_queue_change_queue").isPurgeOnNoConsumers());

         Files.copy(url2.openStream(), brokerXML, StandardCopyOption.REPLACE_EXISTING);
         brokerXML.toFile().setLastModified(System.currentTimeMillis() + 1000);

         embeddedActiveMQ.getActiveMQServer().reloadConfigurationFile();

         //Ensure queues created by clients (NOT by broker.xml are not removed when we reload).
         Assert.assertTrue(listQueuesNamesForAddress(embeddedActiveMQ, "config_test_consumer_created_queues").contains("mySub"));

         Assert.assertNull(getAddressInfo(embeddedActiveMQ, "config_test_address_removal_no_queue"));
         Assert.assertNull(getAddressInfo(embeddedActiveMQ, "config_test_address_removal"));
         Assert.assertNotNull(getAddressInfo(embeddedActiveMQ, "config_test_queue_removal"));
         Assert.assertTrue(listQueuesNamesForAddress(embeddedActiveMQ, "config_test_queue_removal").contains("config_test_queue_removal_queue_1"));
         Assert.assertFalse(listQueuesNamesForAddress(embeddedActiveMQ, "config_test_queue_removal").contains("config_test_queue_removal_queue_2"));

         Assert.assertNotNull(getAddressInfo(embeddedActiveMQ, "permanent_test_address_removal"));
         Assert.assertNotNull(getAddressInfo(embeddedActiveMQ, "permanent_test_queue_removal"));
         Assert.assertTrue(listQueuesNamesForAddress(embeddedActiveMQ, "permanent_test_queue_removal").contains("permanent_test_queue_removal_queue_1"));
         Assert.assertTrue(listQueuesNamesForAddress(embeddedActiveMQ, "permanent_test_queue_removal").contains("permanent_test_queue_removal_queue_2"));

         Assert.assertNotNull(getAddressInfo(embeddedActiveMQ, "config_test_queue_change"));
         Assert.assertTrue(listQueuesNamesForAddress(embeddedActiveMQ, "config_test_queue_change").contains("config_test_queue_change_queue"));
         Assert.assertEquals(1, getQueue(embeddedActiveMQ, "config_test_queue_change_queue").getMaxConsumers());
         Assert.assertEquals(true, getQueue(embeddedActiveMQ, "config_test_queue_change_queue").isPurgeOnNoConsumers());

         Assert.assertNull(getAddressInfo(embeddedActiveMQ, "config_test_queue_change_queue"));
         Assert.assertNull(getAddressInfo(embeddedActiveMQ, "config_test_queue_removal_queue_1"));
      } finally {
         embeddedActiveMQ.stop();
      }
   }

   private AddressInfo getAddressInfo(EmbeddedActiveMQ embeddedActiveMQ, String address) {
      return embeddedActiveMQ.getActiveMQServer().getPostOffice().getAddressInfo(SimpleString.toSimpleString(address));
   }

   private org.apache.activemq.artemis.core.server.Queue getQueue(EmbeddedActiveMQ embeddedActiveMQ, String queueName) throws Exception {
      QueueBinding queueBinding = (QueueBinding) embeddedActiveMQ.getActiveMQServer().getPostOffice().getBinding(SimpleString.toSimpleString(queueName));
      return queueBinding == null ? null : queueBinding.getQueue();
   }

   private List<String> listQueuesNamesForAddress(EmbeddedActiveMQ embeddedActiveMQ, String address) throws Exception {
      return embeddedActiveMQ.getActiveMQServer().getPostOffice().listQueuesForAddress(SimpleString.toSimpleString(address)).stream().map(
          org.apache.activemq.artemis.core.server.Queue::getName).map(SimpleString::toString).collect(Collectors.toList());
   }

}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/AmqpPurgeOnNoConsumersTest.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.amqp;

import javax.jms.Connection;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import java.io.IOException;
import java.util.concurrent.TimeUnit;

import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.apache.activemq.artemis.core.server.impl.QueueImpl;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.tests.util.Wait;
import org.apache.activemq.transport.amqp.client.AmqpClient;
import org.apache.activemq.transport.amqp.client.AmqpConnection;
import org.apache.activemq.transport.amqp.client.AmqpMessage;
import org.apache.activemq.transport.amqp.client.AmqpReceiver;
import org.apache.activemq.transport.amqp.client.AmqpSession;
import org.junit.Test;

public class AmqpPurgeOnNoConsumersTest extends AmqpClientTestSupport {

   @Override
   protected String getConfiguredProtocols() {
      return "AMQP,OPENWIRE,CORE";
   }

   @Test(timeout = 60000)
   public void testQueueReceiverReadMessage() throws Exception {
      AmqpConnection connection = null;
      String queue = "purgeQueue";
      SimpleString ssQueue = new SimpleString(queue);

      server.addAddressInfo(new AddressInfo(ssQueue, RoutingType.ANYCAST));
      server.createQueue(new QueueConfiguration(ssQueue).setRoutingType(RoutingType.ANYCAST).setMaxConsumers(1).setPurgeOnNoConsumers(true).setAutoCreateAddress(false));

      AmqpClient client = createAmqpClient();
      connection = addConnection(client.connect());
      AmqpSession session = connection.createSession();

      final AmqpReceiver receiver = session.createReceiver(queue);

      QueueImpl queueView = (QueueImpl)getProxyToQueue(queue);
      assertEquals(0L, queueView.getPageSubscription().getPagingStore().getAddressSize());
      assertEquals(0, queueView.getMessageCount());

      sendMessages(queue, 5, null, true);

      Wait.assertEquals(5, queueView::getMessageCount);

      receiver.flow(5);

      for (int i = 0; i < 4; i++) {
         try {
            AmqpMessage receive = receiver.receive(5, TimeUnit.SECONDS);
            receive.accept();
            assertNotNull(receive);
         } catch (Exception e) {
            e.printStackTrace();
         }
      }
      try {
         receiver.close();
      } catch (IOException e) {
         e.printStackTrace();
      }

      Wait.assertEquals(0, queueView::getMessageCount);
      assertEquals(0L, queueView.getPageSubscription().getPagingStore().getAddressSize());

      connection.close();

      server.stop();

      server.start();

      queueView = (QueueImpl)getProxyToQueue(queue);

      assertEquals(0, queueView.getMessageCount());
      assertEquals(0L, queueView.getPageSubscription().getPagingStore().getAddressSize());
   }


   // I'm adding the core test here to compare semantics between AMQP and core on this test.
   @Test(timeout = 60000)
   public void testPurgeQueueCoreRollback() throws Exception {
      String queue = "purgeQueue";
      SimpleString ssQueue = new SimpleString(queue);
      server.addAddressInfo(new AddressInfo(ssQueue, RoutingType.ANYCAST));
      server.createQueue(new QueueConfiguration(ssQueue).setRoutingType(RoutingType.ANYCAST).setMaxConsumers(1).setPurgeOnNoConsumers(true).setAutoCreateAddress(false));

      ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory("tcp://localhost:5672");
      Connection connection = cf.createConnection();
      Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
      MessageProducer producer = session.createProducer(session.createQueue("purgeQueue"));

      javax.jms.Queue jmsQueue = session.createQueue(queue);
      MessageConsumer consumer = session.createConsumer(jmsQueue);

      for (int i = 0; i < 10; i++) {
         Message message = session.createTextMessage("hello " + i);
         producer.send(message);
      }
      session.commit();

      QueueImpl queueView = (QueueImpl)getProxyToQueue(queue);

      Wait.assertEquals(10, queueView::getMessageCount);

      connection.start();


      for (int i = 0; i < 10; i++) {
         TextMessage txt = (TextMessage)consumer.receive(1000);
         assertNotNull(txt);
         assertEquals("hello " + i, txt.getText());
      }
      consumer.close();
      session.rollback();
      connection.close();

      Wait.assertEquals(0, queueView::getMessageCount);

      server.stop();

      server.start();

      queueView = (QueueImpl)getProxyToQueue(queue);

      assertEquals(0, queueView.getMessageCount());
      assertEquals(0L, queueView.getPageSubscription().getPagingStore().getAddressSize());
   }
}


<|start_filename|>tests/jms-tests/src/test/java/org/apache/activemq/artemis/jms/tests/SecurityTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.jms.tests;

import static org.junit.Assert.fail;

import javax.jms.BytesMessage;
import javax.jms.CompletionListener;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.IllegalStateException;
import javax.jms.JMSContext;
import javax.jms.JMSProducer;
import javax.jms.JMSSecurityException;
import javax.jms.Message;
import javax.jms.MessageProducer;
import javax.jms.Session;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.jms.client.DefaultConnectionProperties;
import org.apache.activemq.artemis.jms.tests.util.ProxyAssertSupport;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

/**
 * Test JMS Security.
 * <br>
 * This test must be run with the Test security config. on the server
 */
public class SecurityTest extends JMSTestCase {
   private String originalAmqUser;
   private String originalAmqPassword;
   private String originalBrokerBindUrl;

   @Before
   public void setupProperty() {
      originalAmqUser = System.getProperty(DefaultConnectionProperties.AMQ_USER);
      originalAmqPassword = System.getProperty(DefaultConnectionProperties.AMQ_PASSWORD);
      originalBrokerBindUrl = System.getProperty(DefaultConnectionProperties.BROKER_BIND_URL);
   }

   @After
   public void clearProperty() {
      if (originalAmqUser == null) {
         System.clearProperty(DefaultConnectionProperties.AMQ_USER);
      } else {
         System.setProperty(DefaultConnectionProperties.AMQ_USER, originalAmqUser);
      }
      if (originalAmqPassword == null) {
         System.clearProperty(DefaultConnectionProperties.AMQ_PASSWORD);
      } else {
         System.setProperty(DefaultConnectionProperties.AMQ_PASSWORD, originalAmqPassword);
      }
      if (originalBrokerBindUrl == null) {
         System.clearProperty(DefaultConnectionProperties.BROKER_BIND_URL);
      } else {
         System.setProperty(DefaultConnectionProperties.BROKER_BIND_URL, originalBrokerBindUrl);
      }
      DefaultConnectionProperties.initialize();
   }


   /**
    * Login with no user, no password Should allow login (equivalent to guest)
    */
   @Test
   public void testLoginNoUserNoPassword() throws Exception {
      createConnection();
      createConnection(null, null);
   }

   /**
    * Login with no user, no password
    * Should allow login (equivalent to guest)
    */
   @Test
   public void testLoginNoUserNoPasswordWithNoGuest() throws Exception {
      createConnection();
      createConnection(null, null);
   }

   /**
    * Login with valid user and password
    * Should allow
    */
   @Test
   public void testLoginValidUserAndPassword() throws Exception {
      createConnection("guest", "guest");
   }

   /**
    * Login with valid user and password
    * Should allow
    */
   @Test
   public void testLoginValidUserAndPasswordSystemProperty() throws Exception {
      System.setProperty(DefaultConnectionProperties.AMQ_USER, "guest");
      System.setProperty(DefaultConnectionProperties.AMQ_PASSWORD, "<PASSWORD>");
      DefaultConnectionProperties.initialize();
      ConnectionFactory cf = new ActiveMQConnectionFactory();
      Connection conn = addConnection(cf.createConnection());
   }

   /**
    * Login with valid user and password
    * Should allow
    */
   @Test
   public void testLoginValidUserAndPasswordSystemPropertyWithAdditionalProperties() throws Exception {
      System.setProperty(DefaultConnectionProperties.AMQ_USER, "guest");
      System.setProperty(DefaultConnectionProperties.AMQ_PASSWORD, "<PASSWORD>");
      System.setProperty(DefaultConnectionProperties.BROKER_BIND_URL, "tcp://localhost:61616?compressLargeMessage=true");
      DefaultConnectionProperties.initialize();
      ConnectionFactory cf = new ActiveMQConnectionFactory();
      Connection conn = addConnection(cf.createConnection());
      Assert.assertTrue(((ActiveMQConnectionFactory) cf).isCompressLargeMessage());
   }

   /**
    * Login with valid user and invalid password
    * Should allow
    */
   @Test
   public void testLoginValidUserInvalidPassword() throws Exception {
      try {
         Connection conn1 = createConnection("guest", "<PASSWORD>");
         ProxyAssertSupport.fail();
      } catch (JMSSecurityException e) {
         // Expected
      }
   }

   /**
    * Login with valid user and invalid password
    * Should allow
    */
   @Test
   public void testLoginValidUserInvalidPasswordSystemProperty() throws Exception {
      System.setProperty(DefaultConnectionProperties.AMQ_USER, "guest");
      System.setProperty(DefaultConnectionProperties.AMQ_PASSWORD, "<PASSWORD>");
      DefaultConnectionProperties.initialize();
      try {
         ConnectionFactory cf = new ActiveMQConnectionFactory();
         Connection conn1 = addConnection(cf.createConnection());
         ProxyAssertSupport.fail();
      } catch (JMSSecurityException e) {
         // Expected
      }
   }

   /**
    * Login with invalid user and invalid password
    * Should allow
    */
   @Test
   public void testLoginInvalidUserInvalidPassword() throws Exception {
      try {
         Connection conn1 = createConnection("not.the.valid.user", "<PASSWORD>");
         ProxyAssertSupport.fail();
      } catch (JMSSecurityException e) {
         // Expected
      }
   }

   /**
    * Login with valid user and password
    * But try send to address not authorised - Persistent
    * Should not allow and should throw exception
    */
   @Test
   public void testLoginValidUserAndPasswordButNotAuthorisedToSend() throws Exception {
      SimpleString queueName = SimpleString.toSimpleString("guest.cannot.send");
      if (getJmsServer().locateQueue(queueName) == null) {
         getJmsServer().createQueue(new QueueConfiguration(queueName).setRoutingType(RoutingType.ANYCAST));
      }
      ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
      Connection connection = connectionFactory.createConnection("guest", "guest");
      Session session = connection.createSession();
      Destination destination = session.createQueue(queueName.toString());
      MessageProducer messageProducer = session.createProducer(destination);
      try {
         messageProducer.send(session.createTextMessage("hello"));
         fail("JMSSecurityException expected as guest is not allowed to send");
      } catch (JMSSecurityException activeMQSecurityException) {
         //pass
      }
      connection.close();
   }

   /**
    * Login with valid user and password
    * But try send to address not authorised - Non Persistent.
    * Should have same behaviour as Persistent with exception on send.
    */
   @Test
   public void testLoginValidUserAndPasswordButNotAuthorisedToSendNonPersistent() throws Exception {
      SimpleString queueName = SimpleString.toSimpleString("guest.cannot.send");
      if (getJmsServer().locateQueue(queueName) == null) {
         getJmsServer().createQueue(new QueueConfiguration(queueName).setRoutingType(RoutingType.ANYCAST));
      }
      ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
      connectionFactory.setConfirmationWindowSize(100);
      connectionFactory.setBlockOnDurableSend(false);
      connectionFactory.setBlockOnNonDurableSend(false);
      Connection connection = connectionFactory.createConnection("guest", "guest");
      Session session = connection.createSession();
      Destination destination = session.createQueue(queueName.toString());
      MessageProducer messageProducer = session.createProducer(destination);
      messageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
      try {
         AtomicReference<Exception> e = new AtomicReference<>();

         CountDownLatch countDownLatch = new CountDownLatch(1);
         messageProducer.send(session.createTextMessage("hello"), new CompletionListener() {
            @Override
            public void onCompletion(Message message) {
               countDownLatch.countDown();
            }

            @Override
            public void onException(Message message, Exception exception) {
               e.set(exception);
               countDownLatch.countDown();
            }
         });
         countDownLatch.await(10, TimeUnit.SECONDS);
         if (e.get() != null) {
            throw e.get();
         }
         fail("JMSSecurityException expected as guest is not allowed to send");
      } catch (JMSSecurityException activeMQSecurityException) {
         activeMQSecurityException.printStackTrace();
      } finally {
         connection.close();
      }
   }

   /**
    * Same as testLoginValidUserAndPasswordButNotAuthorisedToSendNonPersistent, but using JMS 2 API.
    */
   @Test
   public void testLoginValidUserAndPasswordButNotAuthorisedToSendNonPersistentJMS2() throws Exception {
      SimpleString queueName = SimpleString.toSimpleString("guest.cannot.send");
      if (getJmsServer().locateQueue(queueName) == null) {
         getJmsServer().createQueue(new QueueConfiguration(queueName).setRoutingType(RoutingType.ANYCAST));
      }
      ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
      connectionFactory.setConfirmationWindowSize(100);
      connectionFactory.setBlockOnDurableSend(false);
      connectionFactory.setBlockOnNonDurableSend(false);
      JMSContext context = connectionFactory.createContext("guest", "guest");
      Destination destination = context.createQueue(queueName.toString());
      JMSProducer messageProducer = context.createProducer();
      messageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
      try {
         AtomicReference<Exception> e = new AtomicReference<>();

         CountDownLatch countDownLatch = new CountDownLatch(1);
         messageProducer.setAsync(new CompletionListener() {
            @Override
            public void onCompletion(Message message) {
               countDownLatch.countDown();
            }

            @Override
            public void onException(Message message, Exception exception) {
               e.set(exception);
               countDownLatch.countDown();
            }
         });
         messageProducer.send(destination, context.createTextMessage("hello"));
         countDownLatch.await(10, TimeUnit.SECONDS);
         if (e.get() != null) {
            throw e.get();
         }
         fail("JMSSecurityException expected as guest is not allowed to send");
      } catch (JMSSecurityException activeMQSecurityException) {
         activeMQSecurityException.printStackTrace();
      } finally {
         context.close();
      }
   }

   /**
    * Same as testLoginValidUserAndPasswordButNotAuthorisedToSendNonPersistent, but using a large message.
    */
   @Test
   public void testLoginValidUserAndPasswordButNotAuthorisedToSendLargeNonPersistent() throws Exception {
      SimpleString queueName = SimpleString.toSimpleString("guest.cannot.send");
      if (getJmsServer().locateQueue(queueName) == null) {
         getJmsServer().createQueue(new QueueConfiguration(queueName).setRoutingType(RoutingType.ANYCAST));
      }
      ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://localhost:61616");
      connectionFactory.setConfirmationWindowSize(100);
      connectionFactory.setBlockOnDurableSend(false);
      connectionFactory.setBlockOnNonDurableSend(false);
      connectionFactory.setMinLargeMessageSize(1024);
      Connection connection = connectionFactory.createConnection("guest", "guest");
      Session session = connection.createSession();
      Destination destination = session.createQueue(queueName.toString());
      MessageProducer messageProducer = session.createProducer(destination);
      messageProducer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);
      try {
         AtomicReference<Exception> e = new AtomicReference<>();

         CountDownLatch countDownLatch = new CountDownLatch(1);
         BytesMessage message = session.createBytesMessage();
         message.writeBytes(new byte[10 * 1024]);
         messageProducer.send(message, new CompletionListener() {
            @Override
            public void onCompletion(Message message) {
               countDownLatch.countDown();
            }

            @Override
            public void onException(Message message, Exception exception) {
               e.set(exception);
               countDownLatch.countDown();
            }
         });
         countDownLatch.await(10, TimeUnit.SECONDS);
         if (e.get() != null) {
            throw e.get();
         }
         fail("JMSSecurityException expected as guest is not allowed to send");
      } catch (JMSSecurityException activeMQSecurityException) {
         activeMQSecurityException.printStackTrace();
      }
      connection.close();
   }

   /* Now some client id tests */

   /**
    * user/pwd with preconfigured clientID, should return preconf
    */
   @Test
   public void testPreConfClientID() throws Exception {
      Connection conn = null;
      try {
         ActiveMQServerTestCase.deployConnectionFactory("dilbert-id", "preConfcf", "preConfcf");
         ConnectionFactory cf = (ConnectionFactory) getInitialContext().lookup("preConfcf");
         conn = cf.createConnection("guest", "guest");
         String clientID = conn.getClientID();
         ProxyAssertSupport.assertEquals("Invalid ClientID", "dilbert-id", clientID);
      } finally {
         if (conn != null) {
            conn.close();
         }
         ActiveMQServerTestCase.undeployConnectionFactory("preConfcf");
      }
   }

   /**
    * Try setting client ID
    */
   @Test
   public void testSetClientID() throws Exception {
      Connection conn = createConnection();
      conn.setClientID("myID");
      String clientID = conn.getClientID();
      ProxyAssertSupport.assertEquals("Invalid ClientID", "myID", clientID);
   }

   /**
    * Try setting client ID on preconfigured connection - should throw exception
    */
   @Test
   public void testSetClientIDPreConf() throws Exception {
      Connection conn = null;
      try {
         ActiveMQServerTestCase.deployConnectionFactory("dilbert-id", "preConfcf", "preConfcf");
         ConnectionFactory cf = (ConnectionFactory) getInitialContext().lookup("preConfcf");
         conn = cf.createConnection("guest", "guest");
         conn.setClientID("myID");
         ProxyAssertSupport.fail();
      } catch (IllegalStateException e) {
         // Expected
      } finally {
         if (conn != null) {
            conn.close();
         }
         ActiveMQServerTestCase.undeployConnectionFactory("preConfcf");
      }
   }

   /*
    * Try setting client ID after an operation has been performed on the connection
    */
   @Test
   public void testSetClientIDAfterOp() throws Exception {
      Connection conn = createConnection();
      conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
      try {
         conn.setClientID("myID");
         ProxyAssertSupport.fail();
      } catch (IllegalStateException e) {
         // Expected
      }
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/openwire/OpenWireTestBase.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.openwire;

import javax.jms.ConnectionFactory;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.security.Role;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
import org.apache.activemq.artemis.tests.unit.util.InVMNamingContext;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.junit.After;
import org.junit.Before;

public class OpenWireTestBase extends ActiveMQTestBase {

   public static final String OWHOST = "localhost";
   public static final int OWPORT = 61616;

   protected static final String urlString = "tcp://" + OWHOST + ":" + OWPORT + "?wireFormat.cacheEnabled=true";
   protected static final String urlStringLoose = "tcp://" + OWHOST + ":" + OWPORT + "?wireFormat.tightEncodingEnabled=false";

   protected ActiveMQServer server;

   protected boolean realStore = false;
   protected boolean enableSecurity = false;

   protected ConnectionFactory coreCf;
   protected InVMNamingContext namingContext;

   protected MBeanServer mbeanServer;

   @Override
   @Before
   public void setUp() throws Exception {
      super.setUp();
      server = this.createServer(realStore, true);

      Configuration serverConfig = server.getConfiguration();

      Map<String, AddressSettings> addressSettingsMap = serverConfig.getAddressesSettings();

      configureAddressSettings(addressSettingsMap);

      serverConfig.setSecurityEnabled(enableSecurity);

      extraServerConfig(serverConfig);

      if (enableSecurity) {
         ActiveMQJAASSecurityManager securityManager = (ActiveMQJAASSecurityManager) server.getSecurityManager();
         securityManager.getConfiguration().addRole("openwireSender", "sender");
         securityManager.getConfiguration().addUser("openwireSender", "SeNdEr");
         //sender cannot receive
         Role senderRole = new Role("sender", true, false, false, false, true, true, false, false, true, true);

         securityManager.getConfiguration().addRole("openwireReceiver", "receiver");
         securityManager.getConfiguration().addUser("openwireReceiver", "ReCeIvEr");
         //receiver cannot send
         Role receiverRole = new Role("receiver", false, true, false, false, true, true, false, true, false, false);

         securityManager.getConfiguration().addRole("openwireGuest", "guest");
         securityManager.getConfiguration().addUser("openwireGuest", "GuEsT");

         //guest cannot do anything
         Role guestRole = new Role("guest", false, false, false, false, false, false, false, false, false, false);

         securityManager.getConfiguration().addRole("openwireDestinationManager", "manager");
         securityManager.getConfiguration().addUser("openwireDestinationManager", "DeStInAtIoN");

         Role destRole = new Role("manager", false, false, false, false, true, true, false, false, true, false);

         Set<Role> roles = new HashSet<>();
         roles.add(senderRole);
         roles.add(receiverRole);
         roles.add(guestRole);
         roles.add(destRole);

         server.getConfiguration().putSecurityRoles("#", roles);

         // advisory addresses, anyone can create/consume
         // broker can produce
         Role advisoryReceiverRole = new Role("advisoryReceiver", false, true, false, false, true, true, false, true, true, false);

         roles = new HashSet<>();
         roles.add(advisoryReceiverRole);
         server.getConfiguration().putSecurityRoles("ActiveMQ.Advisory.#", roles);

         securityManager.getConfiguration().addRole("openwireReceiver", "advisoryReceiver");
         securityManager.getConfiguration().addRole("openwireSender", "advisoryReceiver");
         securityManager.getConfiguration().addRole("openwireGuest", "advisoryReceiver");
         securityManager.getConfiguration().addRole("openwireDestinationManager", "advisoryReceiver");
      }

      mbeanServer = MBeanServerFactory.createMBeanServer();
      server.setMBeanServer(mbeanServer);
      addServer(server);
      server.start();

      coreCf = ActiveMQJMSClient.createConnectionFactory("vm://0?reconnectAttempts=-1","cf");
   }

   protected void configureAddressSettings(Map<String, AddressSettings> addressSettingsMap) {
      addressSettingsMap.put("#", new AddressSettings().setAutoCreateQueues(false).setAutoCreateAddresses(false).setDeadLetterAddress(new SimpleString("ActiveMQ.DLQ")).setAutoCreateAddresses(true));
   }

   //override this to add extra server configs
   protected void extraServerConfig(Configuration serverConfig) {
   }

   @Override
   @After
   public void tearDown() throws Exception {
      MBeanServerFactory.releaseMBeanServer(mbeanServer);
      mbeanServer = null;
      server.stop();
      super.tearDown();
   }

}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/addressing/SendDLQNoRouteTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.addressing;

import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.junit.Before;
import org.junit.Test;

public class SendDLQNoRouteTest extends ActiveMQTestBase {

   private ActiveMQServer server;

   private ClientSessionFactory sessionFactory;

   @Before
   public void setup() throws Exception {
      server = createServer(true);
      server.start();
   }


   @Test(timeout = 20_000)
   public void testDLQNoRoute() throws Exception {
      AddressSettings addressSettings = new AddressSettings().setSendToDLAOnNoRoute(true);
      addressSettings.setDeadLetterAddress(SimpleString.toSimpleString("DLA"));
      server.getAddressSettingsRepository().addMatch("#", addressSettings);

      AddressInfo info = new AddressInfo(SimpleString.toSimpleString("info")).addRoutingType(RoutingType.MULTICAST);
      server.addAddressInfo(info);

      AddressInfo dla = new AddressInfo(SimpleString.toSimpleString("DLA")).addRoutingType(RoutingType.MULTICAST);
      server.addAddressInfo(dla);


      ServerLocator locator = createNonHALocator(false);

      ClientSessionFactory factory = locator.createSessionFactory();
      ClientSession session = factory.createSession(true, true);
      ClientProducer producer = session.createProducer("info");

      producer.send(session.createMessage(true));

      session.commit();


   }
}


<|start_filename|>tests/smoke-tests/src/test/java/org/apache/activemq/artemis/tests/smoke/paging/SmokePagingTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.tests.smoke.paging;

import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.commands.messages.Consumer;
import org.apache.activemq.artemis.cli.commands.messages.Producer;
import org.apache.activemq.artemis.tests.smoke.common.SmokeTestBase;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class SmokePagingTest extends SmokeTestBase {

   public static final String SERVER_NAME_0 = "paging";

   @Before
   public void before() throws Exception {
      cleanupData(SERVER_NAME_0);
      startServer(SERVER_NAME_0, 0, 30000);
   }


   @Test
   public void testAMQPOnCLI() throws Exception {

      String protocol = "amqp";
      int NUMBER_OF_MESSAGES = 5000;

      internalReceive(protocol, NUMBER_OF_MESSAGES);

   }

   @Test
   public void testCoreOnCLI() throws Exception {

      String protocol = "core";
      int NUMBER_OF_MESSAGES = 5000;

      internalReceive(protocol, NUMBER_OF_MESSAGES);

   }

   private void internalReceive(String protocol, int NUMBER_OF_MESSAGES) throws Exception {
      Producer producer = (Producer)new Producer().setMessageSize(1000).setMessageCount(NUMBER_OF_MESSAGES).setTxBatchSize(1000);
      producer.setProtocol(protocol);
      producer.setSilentInput(true);
      producer.execute(new ActionContext());

      Consumer consumer = new Consumer();
      consumer.setMessageCount(NUMBER_OF_MESSAGES);
      consumer.setProtocol(protocol);
      consumer.setSilentInput(true);
      consumer.setReceiveTimeout(2000);
      consumer.setBreakOnNull(true);
      int consumed = (int)consumer.execute(new ActionContext());

      Assert.assertEquals(NUMBER_OF_MESSAGES, consumed);
   }

}


<|start_filename|>tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/postoffice/impl/AddressMapUnitTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.unit.core.postoffice.impl;

import java.util.concurrent.atomic.AtomicInteger;

import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.postoffice.Address;
import org.apache.activemq.artemis.core.postoffice.impl.AddressImpl;
import org.apache.activemq.artemis.core.postoffice.impl.AddressMap;
import org.apache.activemq.artemis.core.postoffice.impl.AddressMapVisitor;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

public class AddressMapUnitTest {

   AddressMap<SimpleString> underTest = new AddressMap<>("#", "*", '.');

   @Test
   public void testAddGetRemove() throws Exception {

      SimpleString a = new SimpleString("a.b.c");

      assertTrue(isEmpty(a));

      underTest.put(a, a);

      assertFalse(isEmpty(a));

      assertEquals(1, countMatchingWildcards(a));

      underTest.remove(a, a);

      assertTrue(isEmpty(a));
   }

   private boolean isEmpty(SimpleString match) throws Exception {
      return countMatchingWildcards(match) == 0;
   }

   @Test
   public void testWildcardAddGet() throws Exception {

      SimpleString a = new SimpleString("a.*.c");

      assertTrue(isEmpty(a));

      underTest.put(a, a);

      assertFalse(isEmpty(a));

      assertEquals(1, countMatchingWildcards(a));

      underTest.remove(a, a);

      assertTrue(isEmpty(a));
   }

   @Test
   public void testWildcardAllAddGet() throws Exception {

      SimpleString a = new SimpleString("a.b.#");

      assertTrue(isEmpty(a));

      underTest.put(a, a);

      assertFalse(isEmpty(a));

      assertEquals(1, countMatchingWildcards(a));

      underTest.remove(a, a);

      assertTrue(isEmpty(a));
   }

   @Test
   public void testNoDots() throws Exception {
      SimpleString s1 = new SimpleString("abcde");
      SimpleString s2 = new SimpleString("abcde");

      underTest.put(s1, s1);
      assertEquals(1, countMatchingWildcards(s2));
   }

   @Test
   public void testDotsSameLength2() throws Exception {
      SimpleString s1 = new SimpleString("a.b");
      SimpleString s2 = new SimpleString("a.b");

      underTest.put(s1, s1);
      assertEquals(1, countMatchingWildcards(s2));
   }

   @Test
   public void testA() throws Exception {
      SimpleString s1 = new SimpleString("a.b.c");
      SimpleString s2 = new SimpleString("a.b.c.d.e.f.g.h.i.j.k.l.m.n.*");

      underTest.put(s1, s1);
      assertEquals(0, countMatchingWildcards(s2));
   }

   @Test
   public void testB() throws Exception {
      SimpleString s1 = new SimpleString("a.b.c.d");
      SimpleString s2 = new SimpleString("a.b.x.e");
      SimpleString s3 = new SimpleString("a.b.c.*");

      underTest.put(s1, s1);
      underTest.put(s2, s2);

      assertEquals(1, countNonWildcardMatching(s3));
   }

   @Test
   public void testC() throws Exception {
      SimpleString s1 = new SimpleString("a.b.c.d");
      SimpleString s2 = new SimpleString("a.b.c.x");
      SimpleString s3 = new SimpleString("a.b.*.d");

      underTest.put(s1, s1);
      underTest.put(s2, s2);

      assertEquals(1, countNonWildcardMatching(s3));
   }

   @Test
   public void testD() throws Exception {
      SimpleString s1 = new SimpleString("a.b.c.d.e");
      SimpleString s2 = new SimpleString("a.b.c.x.e");
      SimpleString s3 = new SimpleString("a.b.*.d.*");
      Address a1 = new AddressImpl(s1);
      Address a2 = new AddressImpl(s2);
      Address w = new AddressImpl(s3);
      assertTrue(a1.matches(w));
      assertFalse(a2.matches(w));

      underTest.put(s1, s1);
      underTest.put(s2, s2);

      assertEquals(1, countNonWildcardMatching(s3));
   }

   @Test
   public void testE() throws Exception {
      SimpleString s1 = new SimpleString("a.b.c.d.e.f");
      SimpleString s2 = new SimpleString("a.b.c.x.e.f");
      SimpleString s3 = new SimpleString("a.b.*.d.*.f");
      Address a1 = new AddressImpl(s1);
      Address a2 = new AddressImpl(s2);
      Address w = new AddressImpl(s3);
      assertTrue(a1.matches(w));
      assertFalse(a2.matches(w));

      underTest.put(s1, s1);
      underTest.put(s2, s2);

      assertEquals(1, countNonWildcardMatching(s3));

   }

   @Test
   public void testF() throws Exception {
      SimpleString s1 = new SimpleString("a.b.c.d.e.f");
      SimpleString s2 = new SimpleString("a.b.c.x.e.f");
      SimpleString s3 = new SimpleString("#");
      Address a1 = new AddressImpl(s1);
      Address a2 = new AddressImpl(s2);
      Address w = new AddressImpl(s3);
      assertTrue(a1.matches(w));
      assertTrue(a2.matches(w));

      underTest.put(s1, s1);
      underTest.put(s2, s2);

      assertEquals(2, countNonWildcardMatching(s3));

   }

   @Test
   public void testG() throws Exception {
      SimpleString s1 = new SimpleString("a.b.c.d.e.f");
      SimpleString s2 = new SimpleString("a.b.c.x.e.f");
      SimpleString s3 = new SimpleString("a.#");
      Address a1 = new AddressImpl(s1);
      Address a2 = new AddressImpl(s2);
      Address w = new AddressImpl(s3);
      assertTrue(a1.matches(w));
      assertTrue(a2.matches(w));

      underTest.put(s1, s1);
      underTest.put(s2, s2);

      assertEquals(2, countNonWildcardMatching(s3));

   }

   @Test
   public void testH() throws Exception {
      SimpleString s1 = new SimpleString("a.b.c.d.e.f");
      SimpleString s2 = new SimpleString("a.b.c.x.e.f");
      SimpleString s3 = new SimpleString("#.b.#");
      Address a1 = new AddressImpl(s1);
      Address a2 = new AddressImpl(s2);
      Address w = new AddressImpl(s3);
      assertTrue(a1.matches(w));
      assertTrue(a2.matches(w));

      underTest.put(s1, s1);
      underTest.put(s2, s2);

      assertEquals(2, countNonWildcardMatching(s3));
   }

   @Test
   public void testI() throws Exception {
      SimpleString s1 = new SimpleString("a.b.c.d.e.f");
      SimpleString s2 = new SimpleString("a.b.c.x.e.f");
      SimpleString s3 = new SimpleString("a.#.b.#");
      Address a1 = new AddressImpl(s1);
      Address a2 = new AddressImpl(s2);
      Address w = new AddressImpl(s3);
      assertTrue(a1.matches(w));
      assertTrue(a2.matches(w));

      underTest.put(s1, s1);
      underTest.put(s2, s2);

      assertEquals(2, countNonWildcardMatching(s3));

   }

   @Test
   public void testJ() throws Exception {
      SimpleString s1 = new SimpleString("a.b.c.d.e.f");
      SimpleString s2 = new SimpleString("a.b.c.x.e.f");
      SimpleString s3 = new SimpleString("a.#.c.d.e.f");
      Address a1 = new AddressImpl(s1);
      Address a2 = new AddressImpl(s2);
      Address w = new AddressImpl(s3);
      assertTrue(a1.matches(w));
      assertFalse(a2.matches(w));

      underTest.put(s1, s1);
      underTest.put(s2, s2);

      assertEquals(1, countNonWildcardMatching(s3));

   }

   @Test
   public void testK() throws Exception {
      SimpleString s1 = new SimpleString("a.b.c.d.e.f");
      SimpleString s2 = new SimpleString("a.b.c.d.e.x");
      SimpleString s3 = new SimpleString("a.#.c.d.e.*");
      Address a1 = new AddressImpl(s1);
      Address a2 = new AddressImpl(s2);
      Address w = new AddressImpl(s3);
      assertTrue(a1.matches(w));
      assertTrue(a2.matches(w));

      underTest.put(s1, s1);
      underTest.put(s2, s2);

      assertEquals(2, countNonWildcardMatching(s3));

   }

   @Test
   public void testL() throws Exception {
      SimpleString s1 = new SimpleString("a.b.c.d.e.f");
      SimpleString s2 = new SimpleString("a.b.c.d.e.x");
      SimpleString s3 = new SimpleString("a.#.c.d.*.f");
      Address a1 = new AddressImpl(s1);
      Address a2 = new AddressImpl(s2);
      Address w = new AddressImpl(s3);
      assertTrue(a1.matches(w));
      assertFalse(a2.matches(w));

      underTest.put(s1, s1);
      underTest.put(s2, s2);

      assertEquals(1, countNonWildcardMatching(s3));

   }

   @Test
   public void testM() throws Exception {
      SimpleString s1 = new SimpleString("a.b.c");
      SimpleString s2 = new SimpleString("a.b.x.e");
      SimpleString s3 = new SimpleString("a.b.c.#");
      Address a1 = new AddressImpl(s1);
      Address a2 = new AddressImpl(s2);
      Address w = new AddressImpl(s3);
      assertTrue(a1.matches(w));
      assertFalse(a2.matches(w));

      underTest.put(s1, s1);
      underTest.put(s2, s2);

      assertEquals(1, countNonWildcardMatching(s3));

   }

   @Test
   public void testN() throws Exception {
      SimpleString s1 = new SimpleString("usd.stock");
      SimpleString s2 = new SimpleString("a.b.x.e");
      SimpleString s3 = new SimpleString("*.stock.#");
      Address a1 = new AddressImpl(s1);
      Address a2 = new AddressImpl(s2);
      Address w = new AddressImpl(s3);
      assertTrue(a1.matches(w));
      assertFalse(a2.matches(w));

      underTest.put(s1, s1);
      underTest.put(s2, s2);

      assertEquals(1, countNonWildcardMatching(s3));
   }

   @Test
   public void testO() throws Exception {
      SimpleString s1 = new SimpleString("a.b.c.d");
      SimpleString s2 = new SimpleString("a.b.x.e");
      SimpleString s3 = new SimpleString("a.b.c.*");
      Address a1 = new AddressImpl(s1);
      Address a2 = new AddressImpl(s2);
      Address w = new AddressImpl(s3);
      assertTrue(a1.matches(w));
      assertFalse(a2.matches(w));

      underTest.put(s1, s1);
      underTest.put(s2, s2);

      assertEquals(1, countNonWildcardMatching(s3));

   }

   @Test
   public void testP() throws Exception {
      SimpleString s1 = new SimpleString("a.b.c.d");
      SimpleString s3 = new SimpleString("a.b.c#");
      Address a1 = new AddressImpl(s1);
      Address w = new AddressImpl(s3);
      assertFalse(a1.matches(w));

      underTest.put(s1, s1);

      assertEquals(0, countNonWildcardMatching(s3));

   }

   @Test
   public void testQ() throws Exception {
      SimpleString s1 = new SimpleString("a.b.c.d");
      SimpleString s3 = new SimpleString("#a.b.c");
      Address a1 = new AddressImpl(s1);
      Address w = new AddressImpl(s3);
      assertFalse(a1.matches(w));

      underTest.put(s1, s1);
      assertEquals(0, countNonWildcardMatching(s3));

   }

   @Test
   public void testR() throws Exception {
      SimpleString s1 = new SimpleString("a.b.c.d");
      SimpleString s3 = new SimpleString("#*a.b.c");
      Address a1 = new AddressImpl(s1);
      Address w = new AddressImpl(s3);
      assertFalse(a1.matches(w));

      underTest.put(s1, s1);
      assertEquals(0, countNonWildcardMatching(s3));

   }

   @Test
   public void testS() throws Exception {
      SimpleString s1 = new SimpleString("a.b.c.d");
      SimpleString s3 = new SimpleString("a.b.c*");
      Address a1 = new AddressImpl(s1);
      Address w = new AddressImpl(s3);
      assertFalse(a1.matches(w));

      underTest.put(s1, s1);
      assertEquals(0, countNonWildcardMatching(s3));

   }

   @Test
   public void testT() throws Exception {
      SimpleString s1 = new SimpleString("a.b.c.d");
      SimpleString s3 = new SimpleString("*a.b.c");
      Address a1 = new AddressImpl(s1);
      Address w = new AddressImpl(s3);
      assertFalse(a1.matches(w));

      underTest.put(s1, s1);
      assertEquals(0, countNonWildcardMatching(s3));

   }

   @Test
   public void testU() throws Exception {
      SimpleString s1 = new SimpleString("a.b.c.d");
      SimpleString s3 = new SimpleString("*a.b.c");
      Address a1 = new AddressImpl(s1);
      Address w = new AddressImpl(s3);
      assertFalse(a1.matches(w));

      underTest.put(s1, s1);
      assertEquals(0, countNonWildcardMatching(s3));

   }

   @Test
   public void testV() throws Exception {
      final SimpleString s1 = new SimpleString("a.b.d");
      final SimpleString s3 = new SimpleString("a.b.#.d");
      final Address a1 = new AddressImpl(s1);
      final Address w = new AddressImpl(s3);
      assertTrue(a1.matches(w));

      underTest.put(s1, s1);
      assertEquals(1, countNonWildcardMatching(s3));

      final SimpleString s2 = new SimpleString("a.b.b.b.b.d");
      underTest.put(s2, s2);
      assertEquals(2, countNonWildcardMatching(s3));
   }

   @Test
   public void testVReverse() throws Exception {
      final SimpleString s1 = new SimpleString("a.b.d");
      final SimpleString s3 = new SimpleString("a.b.#.d");
      final Address a1 = new AddressImpl(s1);
      final Address w = new AddressImpl(s3);
      assertTrue(a1.matches(w));

      underTest.put(s3, s3);
      assertEquals(1, countMatchingWildcards(s1));

   }

   @Test
   public void testHashNMatch() throws Exception {

      SimpleString addressABCF = new SimpleString("a.b.c.f");
      SimpleString addressACF = new SimpleString("a.c.f");
      SimpleString match = new SimpleString("a.#.f");

      underTest.put(addressABCF, addressABCF);
      underTest.put(addressACF, addressACF);

      assertEquals(2, countNonWildcardMatching(match));
   }

   @Test
   public void testEndHash() throws Exception {

      SimpleString addressAB = new SimpleString("a.b");
      SimpleString addressACF = new SimpleString("a.c.f");
      SimpleString addressABC = new SimpleString("a.b.c");
      SimpleString match = new SimpleString("a.b.#");

      underTest.put(addressAB, addressAB);
      underTest.put(addressACF, addressACF);

      assertEquals(1, countNonWildcardMatching(match));

      underTest.put(addressABC, addressABC);
      assertEquals(2, countNonWildcardMatching(match));
   }

   @Test
   public void testHashEndInMap() throws Exception {

      SimpleString addressABHash = new SimpleString("a.b.#");
      SimpleString addressABC = new SimpleString("a.b.c");
      SimpleString match = new SimpleString("a.b");

      underTest.put(addressABHash, addressABHash);
      underTest.put(addressABC, addressABC);

      assertEquals(1, countMatchingWildcards(match));
   }

   private int countMatchingWildcards(SimpleString plainAddress) throws Exception {

      final AtomicInteger count = new AtomicInteger();
      underTest.visitMatchingWildcards(plainAddress, value -> {
         count.incrementAndGet();
      });

      return count.get();
   }

   private int countNonWildcardMatching(SimpleString canBeWildcardAddress) throws Exception {

      final AtomicInteger count = new AtomicInteger();
      underTest.visitMatching(canBeWildcardAddress, value -> {
         count.incrementAndGet();
      });

      return count.get();
   }

   @Test
   public void testHashEndMatchMap() throws Exception {

      SimpleString match = new SimpleString("a.b.#");
      SimpleString addressABC = new SimpleString("a.b.c");
      SimpleString addressAB = new SimpleString("a.b");

      underTest.put(addressAB, addressAB);
      underTest.put(addressABC, addressABC);

      assertEquals(0, countMatchingWildcards(match));
      assertEquals(2, countNonWildcardMatching(match));

      underTest.put(match, match);
      assertEquals(1, countMatchingWildcards(match));

   }

   @Test
   public void testHashAGet() throws Exception {

      SimpleString hashA = new SimpleString("#.a");
      underTest.put(hashA, hashA);

      SimpleString matchA = new SimpleString("a");
      SimpleString matchAB = new SimpleString("a.b");

      assertEquals(1, countMatchingWildcards(matchA));
      assertEquals(0, countMatchingWildcards(matchAB));

      AddressImpl aStar = new AddressImpl(hashA);
      AddressImpl aA = new AddressImpl(matchA);
      assertTrue(aA.matches(aStar));

      AddressImpl aAB = new AddressImpl(matchAB);
      assertFalse(aAB.matches(aStar));
   }

   @Test
   public void testStarOne() throws Exception {

      SimpleString star = new SimpleString("*");
      underTest.put(star, star);

      SimpleString matchA = new SimpleString("a");
      SimpleString matchAB = new SimpleString("a.b");

      final AtomicInteger count = new AtomicInteger();
      underTest.visitMatchingWildcards(matchA, value -> count.incrementAndGet());
      assertEquals(1, count.get());

      count.set(0);

      underTest.visitMatchingWildcards(matchAB, value -> count.incrementAndGet());

      assertEquals(0, count.get());
   }

   @Test
   public void testHashOne() throws Exception {

      SimpleString hash = new SimpleString("#");
      underTest.put(hash, hash);

      SimpleString matchA = new SimpleString("a");
      SimpleString matchAB = new SimpleString("a.b");
      SimpleString matchABC = new SimpleString("a.b.c");

      final AtomicInteger count = new AtomicInteger();
      AddressMapVisitor<SimpleString> countCollector = value -> count.incrementAndGet();

      count.set(0);
      underTest.visitMatchingWildcards(matchA, countCollector);
      assertEquals(1, count.get());

      count.set(0);
      underTest.visitMatchingWildcards(matchAB, countCollector);
      assertEquals(1, count.get());

      count.set(0);
      underTest.visitMatchingWildcards(matchABC, countCollector);
      assertEquals(1, count.get());
   }

   @Test
   public void testHashAMatch() throws Exception {

      SimpleString a = new SimpleString("a");
      underTest.put(a, a);

      assertEquals(1, countNonWildcardMatching(new SimpleString("#.a")));

      assertEquals(1, countMatchingWildcards(new SimpleString("a")));
   }

   @Test
   public void testHashA() throws Exception {

      SimpleString hashA = new SimpleString("#.a");
      underTest.put(hashA, hashA);

      assertEquals(1, countMatchingWildcards(new SimpleString("a")));

      assertEquals(1, countMatchingWildcards(new SimpleString("d.f.c.a")));

      // has to end in 'a', and not being with 'a'
      SimpleString abcaS = new SimpleString("a.b.c.a");
      AddressImpl aHashA = new AddressImpl(hashA);
      AddressImpl aABCA = new AddressImpl(abcaS);
      assertFalse(aABCA.matches(aHashA));
      assertFalse(aHashA.matches(aABCA));

      assertEquals(1, countMatchingWildcards(abcaS));

      assertEquals(0, countMatchingWildcards(new SimpleString("a.b")));

      assertEquals(0, countMatchingWildcards(new SimpleString("a.b.c")));

      assertEquals(0, countMatchingWildcards(new SimpleString("a.b.c.a.d")));

      // will match a.....a
      SimpleString AHashA = new SimpleString("a.#.a");
      underTest.put(AHashA, AHashA);

      assertEquals(2, countMatchingWildcards(new SimpleString("a.b.c.a")));

      assertEquals(0, countNonWildcardMatching(new SimpleString("a.b.c.a")));

      // only now remove the #.a
      underTest.remove(hashA, hashA);

      assertEquals(1, countMatchingWildcards(new SimpleString("a.b.c.a")));

      assertEquals(1, countMatchingWildcards(new SimpleString("a.a")));

   }

   @Test
   public void testAHashA() throws Exception {

      final AtomicInteger count = new AtomicInteger();
      AddressMapVisitor<SimpleString> countCollector = value -> count.incrementAndGet();

      // will match a.....a
      SimpleString AHashA = new SimpleString("a.#.a");
      underTest.put(AHashA, AHashA);

      count.set(0);
      underTest.visitMatchingWildcards(new SimpleString("a.b.c.a"), countCollector);
      assertEquals(1, count.get());

      count.set(0);
      underTest.visitMatchingWildcards(new SimpleString("a.a"), countCollector);
      assertEquals(1, count.get());

      count.set(0);
      underTest.visitMatchingWildcards(new SimpleString("a"), countCollector);
      assertEquals(0, count.get());
   }

   @Test
   public void testStar() throws Exception {

      SimpleString star = new SimpleString("*");
      SimpleString addressA = new SimpleString("a");
      SimpleString addressAB = new SimpleString("a.b");

      underTest.put(star, star);
      underTest.put(addressAB, addressAB);

      final AtomicInteger count = new AtomicInteger();
      underTest.visitMatchingWildcards(addressA, value -> count.incrementAndGet());

      assertEquals(1, count.get());
   }

   @Test
   public void testSomeAndAny() throws Exception {

      SimpleString star = new SimpleString("test.*.some.#");
      underTest.put(star, star);

      assertEquals(0, countNonWildcardMatching(star));
      assertEquals(1, countMatchingWildcards(star));

      SimpleString addressA = new SimpleString("test.1.some.la");
      underTest.put(addressA, addressA);

      assertEquals(1, countMatchingWildcards(star));
      assertEquals(1, countNonWildcardMatching(star));

      assertEquals(2, countMatchingWildcards(addressA));
      assertEquals(1, countNonWildcardMatching(addressA));

   }

   @Test
   public void testAnyAndSome() throws Exception {

      SimpleString star = new SimpleString("test.#.some.*");
      underTest.put(star, star);

      assertEquals(1, countMatchingWildcards(star));

      // add another match
      SimpleString addressA = new SimpleString("test.1.some.la");
      underTest.put(addressA, addressA);

      assertEquals(1, countMatchingWildcards(star));

      assertEquals(1, countNonWildcardMatching(star));

      assertEquals(1, countNonWildcardMatching(addressA));

      assertEquals(2, countMatchingWildcards(addressA));

   }

   @Test
   public void testAnyAndSomeInMap() throws Exception {

      SimpleString hashHash = new SimpleString("test.#.some.#");
      underTest.put(hashHash, hashHash);

      SimpleString starStar = new SimpleString("test.*.some.*");
      underTest.put(starStar, starStar);

      SimpleString hashStar = new SimpleString("test.#.A.*");
      underTest.put(hashStar, hashStar);

      SimpleString oneHashStar = new SimpleString("test.1.#.T");
      underTest.put(oneHashStar, oneHashStar);

      assertEquals(2, countMatchingWildcards(hashHash));
      assertEquals(0, countNonWildcardMatching(hashHash));

      SimpleString reqular = new SimpleString("test.a.b.some");
      underTest.put(reqular, reqular);
      assertEquals(1, countNonWildcardMatching(hashHash));

      assertEquals(1, countNonWildcardMatching(reqular));

      assertEquals(2, countMatchingWildcards(reqular));
   }

   @Test
   public void testHashAandHashB() throws Exception {

      SimpleString hashAhash = new SimpleString("test.#.aaa.#");
      underTest.put(hashAhash, hashAhash);

      SimpleString hashBhash = new SimpleString("test.#.bbb.#");
      underTest.put(hashBhash, hashBhash);

      assertEquals(2, countMatchingWildcards(SimpleString.toSimpleString("test.aaa.bbb")));
      assertEquals(2, countMatchingWildcards(SimpleString.toSimpleString("test.bbb.aaa")));

      assertEquals(2, countMatchingWildcards(SimpleString.toSimpleString("test.bbb.aaa.ccc")));
      assertEquals(2, countMatchingWildcards(SimpleString.toSimpleString("test.aaa.bbb.ccc")));
   }

   @Test
   public void testHashNoHashNo() throws Exception {

      SimpleString hashAhash = new SimpleString("test.#.0.#.168");
      underTest.put(hashAhash, hashAhash);

      assertEquals(1, countMatchingWildcards(SimpleString.toSimpleString("test.0.168")));
   }

   @Test
   public void testHashNoHashHashNo() throws Exception {

      SimpleString v = new SimpleString("test.#.0.#.168");
      underTest.put(v, v);

      v = new SimpleString("test.#.0.#");
      underTest.put(v, v);

      v = new SimpleString("test.0.#");
      underTest.put(v, v);

      assertEquals(3, countMatchingWildcards(SimpleString.toSimpleString("test.0.168")));
   }

   @Test
   public void testHashNoHashNoWithNMatch() throws Exception {

      for (String s : new String[] {"t.#.0.#", "t.#.1.#", "t.#.2.#", "t.#.3.#", "t.#.1.2.3", "t.0.1.2.3"}) {
         SimpleString v = new SimpleString(s);
         underTest.put(v, v);
      }
      assertEquals(6, countMatchingWildcards(SimpleString.toSimpleString("t.0.1.2.3")));
   }

   @Test
   public void testSomeMoreHashPlacement() throws Exception {

      for (String s : new String[] {"t.#.0.#", "t.0.1.#", "t.0.1.2.#", "t.0.1.#.2.3", "t.*.#.1.2.3"}) {
         SimpleString v = new SimpleString(s);
         underTest.put(v, v);
      }
      assertEquals(5, countMatchingWildcards(SimpleString.toSimpleString("t.0.1.2.3")));
      assertEquals(3, countMatchingWildcards(SimpleString.toSimpleString("t.0.1.2.3.4")));
   }

   @Test
   public void testManyEntries() throws Exception {

      for (int i = 0; i < 10; i++) {
         SimpleString star = new SimpleString("test." + i);
         underTest.put(star, star);
      }

      assertEquals(10, countNonWildcardMatching(new SimpleString("test.*")));

      assertEquals(10, countNonWildcardMatching(new SimpleString("test.#")));

      assertEquals(1, countMatchingWildcards(new SimpleString("test.0")));

      underTest.put(new SimpleString("test.#"), new SimpleString("test.#"));
      underTest.put(new SimpleString("test.*"), new SimpleString("test.*"));

      assertEquals(3, countMatchingWildcards(new SimpleString("test.1")));

      assertEquals(10, countNonWildcardMatching(new SimpleString("test.#")));

      assertEquals(10, countNonWildcardMatching(new SimpleString("test.*")));

      for (int i = 0; i < 10; i++) {
         SimpleString star = new SimpleString("test.a." + i);
         underTest.put(star, star);
      }

      assertEquals(2, countMatchingWildcards(new SimpleString("test.a.0")));
      assertEquals(20, countNonWildcardMatching(new SimpleString("test.#")));

      for (int i = 0; i < 10; i++) {
         SimpleString star = new SimpleString("test.b." + i);
         underTest.put(star, star);
      }

      assertEquals(10, countNonWildcardMatching(new SimpleString("test.b.*")));
      underTest.remove(new SimpleString("test.#"), new SimpleString("test.#"));

      assertEquals(10, countNonWildcardMatching(new SimpleString("test.b.*")));
      assertEquals(1, countMatchingWildcards(new SimpleString("test.a.0")));

      for (int i = 0; i < 10; i++) {
         SimpleString star = new SimpleString("test.c." + i);
         underTest.put(star, star);
      }
      assertEquals(10, countNonWildcardMatching(new SimpleString("test.c.*")));

      SimpleString testStarStar = new SimpleString("test.*.*");
      assertEquals(30, countNonWildcardMatching(testStarStar));

      underTest.put(testStarStar, testStarStar);
      assertEquals(30, countNonWildcardMatching(testStarStar));
      assertEquals(1, countMatchingWildcards(testStarStar));

      assertEquals(1, countMatchingWildcards(new SimpleString("test.b.c")));
   }

   @Test
   public void testReset() throws Exception {
      for (int i = 0; i < 10; i++) {
         SimpleString star = new SimpleString("test." + i);
         underTest.put(star, star);
      }

      assertEquals(0, countMatchingWildcards(new SimpleString("test.*")));

      assertEquals(10, countNonWildcardMatching(new SimpleString("test.*")));
      underTest.reset();
      assertEquals(0, countNonWildcardMatching(new SimpleString("test.*")));
   }

   @Test
   public void testRemove() throws Exception {
      for (int i = 0; i < 10; i++) {
         SimpleString star = new SimpleString("test." + i);
         underTest.put(star, star);
      }

      SimpleString test1 = new SimpleString("test.1");
      assertEquals(1, countMatchingWildcards(test1));

      underTest.remove(test1, test1);
      assertEquals(0, countMatchingWildcards(test1));

      assertEquals(9, countNonWildcardMatching(new SimpleString("test.*")));

      for (int i = 0; i < 10; i++) {
         SimpleString star = new SimpleString("test." + i);
         underTest.remove(star, star);
      }

      assertEquals(0, countNonWildcardMatching(new SimpleString("test.*")));
   }

   @Test
   public void testMax() throws Exception {

      underTest.put(new SimpleString("test.#.a"), new SimpleString("test.#.a"));
      underTest.put(new SimpleString("test.*.a"), new SimpleString("test.*.a"));
      underTest.put(new SimpleString("*.a"), new SimpleString("*.a"));
      underTest.put(new SimpleString("#.a"), new SimpleString("#.a"));

      assertEquals(3, countMatchingWildcards(new SimpleString("test.a")));
      assertEquals(3, countMatchingWildcards(new SimpleString("test.a.a")));
   }

}

<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/AuditLoginModule.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.spi.core.security.jaas;

import org.apache.activemq.artemis.logs.AuditLogger;

import javax.security.auth.Subject;
import javax.security.auth.spi.LoginModule;

/*
* This is only to support auditlogging
* */
public interface AuditLoginModule extends LoginModule {

   /*
   * We need this because if authentication fails at the web layer then there is no way to access the unauthenticated
   * subject as it is removed and the session destroyed and never gets as far as the broker
   * */
   default void registerFailureForAudit(String name) {
      Subject subject = new Subject();
      subject.getPrincipals().add(new UserPrincipal(name));
      AuditLogger.setCurrentCaller(subject);
   }
}


<|start_filename|>artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/ScramClientFunctionality.java<|end_filename|>
/*
 * Copyright 2016 <NAME>
 * <p>
 * All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.protocol.amqp.sasl.scram;

import org.apache.activemq.artemis.spi.core.security.scram.ScramException;

/**
 * Provides building blocks for creating SCRAM authentication client
 */
@SuppressWarnings("unused")
public interface ScramClientFunctionality {
   /**
    * Prepares the first client message
    * @param username Username of the user
    * @return First client message
    * @throws ScramException if username contains prohibited characters
    */
   String prepareFirstMessage(String username) throws ScramException;

   /**
    * Prepares client's final message
    * @param password <PASSWORD>
    * @param serverFirstMessage Server's first message
    * @return Client's final message
    * @throws ScramException if there is an error processing server's message, i.e. it violates the
    *            protocol
    */
   String prepareFinalMessage(String password, String serverFirstMessage) throws ScramException;

   /**
    * Checks if the server's final message is valid
    * @param serverFinalMessage Server's final message
    * @throws ScramException if there is an error processing server's message, i.e. it violates the
    *            protocol
    */
   void checkServerFinalMessage(String serverFinalMessage) throws ScramException;

   /**
    * Checks if authentication is successful. You can call this method only if authentication is
    * completed. Ensure that using {@link #isEnded()}
    * @return true if successful, false otherwise
    */
   boolean isSuccessful();

   /**
    * Checks if authentication is completed, either successfully or not. Authentication is completed
    * if {@link #getState()} returns ENDED.
    * @return true if authentication has ended
    */
   boolean isEnded();

   /**
    * Gets the state of the authentication procedure
    * @return Current state
    */
   State getState();

   /**
    * State of the authentication procedure
    */
   enum State {
               /**
                * Initial state
                */
               INITIAL,
               /**
                * State after first message is prepared
                */
               FIRST_PREPARED,
               /**
                * State after final message is prepared
                */
               FINAL_PREPARED,
               /**
                * Authentication is completes, either successfully or not
                */
               ENDED
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/security/PersistedSecuritySettingTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * <br>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <br>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.tests.integration.security;

import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.ActiveMQBuffers;
import org.apache.activemq.artemis.core.persistence.config.PersistedSecuritySetting;
import org.junit.Test;

public class PersistedSecuritySettingTest {

   @Test
   public void testNPE() {
      PersistedSecuritySetting persistedSecuritySetting = new PersistedSecuritySetting();
      ActiveMQBuffer buffer = ActiveMQBuffers.fixedBuffer(persistedSecuritySetting.getEncodeSize());
      persistedSecuritySetting.encode(buffer);
      persistedSecuritySetting.decode(buffer);
      persistedSecuritySetting.getBrowseRoles();
      persistedSecuritySetting.getConsumeRoles();
      persistedSecuritySetting.getCreateAddressRoles();
      persistedSecuritySetting.getCreateDurableQueueRoles();
      persistedSecuritySetting.getCreateNonDurableQueueRoles();
      persistedSecuritySetting.getDeleteAddressRoles();
      persistedSecuritySetting.getDeleteDurableQueueRoles();
      persistedSecuritySetting.getDeleteNonDurableQueueRoles();
      persistedSecuritySetting.getManageRoles();
      persistedSecuritySetting.getSendRoles();
   }
}


<|start_filename|>artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/messages/Producer.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.cli.commands.messages;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.DeliveryMode;
import javax.jms.Destination;
import javax.jms.Message;
import javax.jms.MessageProducer;
import javax.jms.Session;
import java.io.FileInputStream;
import java.io.InputStream;

import io.airlift.airline.Command;
import io.airlift.airline.Option;
import org.apache.activemq.artemis.cli.commands.ActionContext;
import org.apache.activemq.artemis.cli.factory.serialize.MessageSerializer;

@Command(name = "producer", description = "It will send messages to an instance")
public class Producer extends DestAbstract {

   public static final String DEMO_TEXT = "demo.txt";

   @Option(name = "--non-persistent", description = "It will send messages non persistently")
   boolean nonpersistent = false;

   @Option(name = "--message-size", description = "Size of each byteMessage (The producer will use byte message on this case)")
   int messageSize = 0;

   @Option(name = "--message", description = "Content of each textMessage (The producer will use text message on this case)")
   String message = null;

   @Option(name = "--text-size", description = "Size of each textMessage (The producer will use text message on this case)")
   int textMessageSize;

   @Option(name = "--object-size", description = "Size of each ObjectMessage (The producer will use object message on this case)")
   int objectSize;

   @Option(name = "--msgttl", description = "TTL for each message")
   long msgTTL = 0L;

   @Option(name = "--group", description = "Message Group to be used")
   String msgGroupID = null;

   @Option(name = "--data", description = "Messages will be read form the specified file, other message options will be ignored.")
   String file = null;

   public boolean isNonpersistent() {
      return nonpersistent;
   }

   public Producer setNonpersistent(boolean nonpersistent) {
      this.nonpersistent = nonpersistent;
      return this;
   }

   public int getMessageSize() {
      return messageSize;
   }

   public Producer setMessageSize(int messageSize) {
      this.messageSize = messageSize;
      return this;
   }

   public String getMessage() {
      return message;
   }

   public Producer setMessage(String message) {
      this.message = message;
      return this;
   }

   public int getTextMessageSize() {
      return textMessageSize;
   }

   public Producer setTextMessageSize(int textMessageSize) {
      this.textMessageSize = textMessageSize;
      return this;
   }

   public int getObjectSize() {
      return objectSize;
   }

   public Producer setObjectSize(int objectSize) {
      this.objectSize = objectSize;
      return this;
   }

   public long getMsgTTL() {
      return msgTTL;
   }

   public Producer setMsgTTL(long msgTTL) {
      this.msgTTL = msgTTL;
      return this;
   }

   public String getMsgGroupID() {
      return msgGroupID;
   }

   public Producer setMsgGroupID(String msgGroupID) {
      this.msgGroupID = msgGroupID;
      return this;
   }

   public String getFile() {
      return file;
   }

   public Producer setFile(String file) {
      this.file = file;
      return this;
   }

   @Override
   public Object execute(ActionContext context) throws Exception {
      super.execute(context);

      ConnectionFactory factory = createConnectionFactory();

      try (Connection connection = factory.createConnection()) {

         // If we are reading from file, we process messages sequentially to guarantee ordering.  i.e. no thread creation.
         if (file != null) {
            Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
            Destination dest = getDestination(session);

            MessageProducer producer = session.createProducer(dest);
            producer.setDeliveryMode(DeliveryMode.PERSISTENT);

            int messageCount = 0;
            try {
               MessageSerializer serializer = getMessageSerializer();
               if (serializer == null) {
                  System.err.println("Error. Unable to instantiate serializer class: " + serializer);
                  return null;
               }

               InputStream in;
               try {
                  in = new FileInputStream(file);
               } catch (Exception e) {
                  System.err.println("Error: Unable to open file for reading\n" + e.getMessage());
                  return null;
               }

               serializer.setInput(in, session);
               serializer.start();

               Message message = serializer.read();

               while (message != null) {
                  producer.send(message);
                  message = serializer.read();
                  messageCount++;
               }

               session.commit();
               serializer.stop();
            } catch (Exception e) {
               System.err.println("Error occurred during import.  Rolling back.");
               session.rollback();
               e.printStackTrace();
               return 0;
            }
            System.out.println("Sent " + messageCount + " Messages.");
            return messageCount;
         } else {
            ProducerThread[] threadsArray = new ProducerThread[threads];
            for (int i = 0; i < threads; i++) {
               Session session;
               if (txBatchSize > 0) {
                  session = connection.createSession(true, Session.SESSION_TRANSACTED);
               } else {
                  session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
               }
               Destination dest = getDestination(session);
               threadsArray[i] = new ProducerThread(session, dest, i);

               threadsArray[i]
                  .setVerbose(verbose)
                  .setSleep(sleep)
                  .setPersistent(!nonpersistent)
                  .setMessageSize(messageSize)
                  .setTextMessageSize(textMessageSize)
                  .setMessage(message)
                  .setObjectSize(objectSize)
                  .setMsgTTL(msgTTL)
                  .setMsgGroupID(msgGroupID)
                  .setTransactionBatchSize(txBatchSize)
                  .setMessageCount(messageCount);
            }

            for (ProducerThread thread : threadsArray) {
               thread.start();
            }

            int messagesProduced = 0;
            for (ProducerThread thread : threadsArray) {
               thread.join();
               messagesProduced += thread.getSentCount();
            }
            return messagesProduced;
         }
      }
   }
}


<|start_filename|>artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/ActiveMQConnectionMetaData.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.jms.client;


import java.io.IOException;
import java.io.InputStream;
import javax.jms.ConnectionMetaData;
import javax.jms.JMSException;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;

import org.apache.activemq.artemis.core.version.Version;

/**
 * ActiveMQ Artemis implementation of a JMS ConnectionMetaData.
 */
public class ActiveMQConnectionMetaData implements ConnectionMetaData {
   public static final String DEFAULT_PROP_FILE_NAME = "jms-version.properties";

   private static final String JMS_VERSION_NAME;
   private static final int JMS_MAJOR_VERSION;
   private static final int JMS_MINOR_VERSION;
   static {
      Properties versionProps = new Properties();
      try (InputStream in = ActiveMQConnectionMetaData.class.getClassLoader().getResourceAsStream(DEFAULT_PROP_FILE_NAME)) {
         if (in != null) {
            versionProps.load(in);
         }
      } catch (IOException e) {
      }
      JMS_VERSION_NAME = versionProps.getProperty("activemq.version.implementation.versionName", "2.0");
      JMS_MAJOR_VERSION = Integer.valueOf(versionProps.getProperty("activemq.version.implementation.majorVersion", "2"));
      JMS_MINOR_VERSION = Integer.valueOf(versionProps.getProperty("activemq.version.implementation.minorVersion", "0"));
   }

   // Constants -----------------------------------------------------

   private static final String ACTIVEMQ = "ActiveMQ";

   // Static --------------------------------------------------------

   // Attributes ----------------------------------------------------

   private final Version serverVersion;

   // Constructors --------------------------------------------------

   /**
    * Create a new ActiveMQConnectionMetaData object.
    */
   public ActiveMQConnectionMetaData(final Version serverVersion) {
      this.serverVersion = serverVersion;
   }

   // ConnectionMetaData implementation -----------------------------

   @Override
   public String getJMSVersion() throws JMSException {
      return JMS_VERSION_NAME;
   }

   @Override
   public int getJMSMajorVersion() throws JMSException {
      return JMS_MAJOR_VERSION;
   }

   @Override
   public int getJMSMinorVersion() throws JMSException {
      return JMS_MINOR_VERSION;
   }

   @Override
   public String getJMSProviderName() throws JMSException {
      return ActiveMQConnectionMetaData.ACTIVEMQ;
   }

   @Override
   public String getProviderVersion() throws JMSException {
      return serverVersion.getFullVersion();
   }

   @Override
   public int getProviderMajorVersion() throws JMSException {
      return serverVersion.getMajorVersion();
   }

   @Override
   public int getProviderMinorVersion() throws JMSException {
      return serverVersion.getMinorVersion();
   }

   @Override
   public Enumeration getJMSXPropertyNames() throws JMSException {
      Vector<Object> v = new Vector<>();
      v.add("JMSXGroupID");
      v.add("JMSXGroupSeq");
      v.add("JMSXDeliveryCount");
      return v.elements();
   }
}


<|start_filename|>artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/ssl/CachingSSLContextFactory.java<|end_filename|>
/*
 * Copyright 2020 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.remoting.impl.ssl;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import javax.net.ssl.SSLContext;

import io.netty.handler.ssl.SslContext;
import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants;
import org.apache.activemq.artemis.spi.core.remoting.ssl.SSLContextConfig;
import org.apache.activemq.artemis.spi.core.remoting.ssl.SSLContextFactory;
import org.apache.activemq.artemis.utils.ConfigurationHelper;

/**
 * {@link SSLContextFactory} providing a cache of {@link SSLContext}.
 * Since {@link SSLContext} should be reused instead of recreated and are thread safe.
 * To activate it you need to allow this Service to be discovered by having a
 * <code>META-INF/services/org.apache.activemq.artemis.spi.core.remoting.ssl.SSLContextFactory</code>
 * file with <code>org.apache.activemq.artemis.core.remoting.impl.ssl.CachingSSLContextFactory</code>
 * as value.
 */
public class CachingSSLContextFactory extends DefaultSSLContextFactory {

   private static final ConcurrentMap<Object, SSLContext> sslContextCache = new ConcurrentHashMap<>(2);

   @Override
   public void clearSSLContexts() {
      sslContextCache.clear();
   }

   @Override
   public SSLContext getSSLContext(final SSLContextConfig config, final Map<String, Object> additionalOpts) throws Exception {
      final Object cacheKey = getCacheKey(config, additionalOpts);
      return sslContextCache.computeIfAbsent(cacheKey, key -> {
         try {
            return CachingSSLContextFactory.super.getSSLContext(config, additionalOpts);
         } catch (final Exception ex) {
            throw new RuntimeException("An unexpected exception occured while creating JDK SSLContext with " + config, ex);
         }
      });
   }

   /**
    * Obtains/calculates a cache key for the corresponding {@link SslContext}.
    * <ol>
    * <li>If <code>config</code> contains an entry with key "sslContext", the associated value is returned
    * <li>Otherwise, the provided {@link SSLContextConfig} is used as cache key.
    * </ol>
    *
    * @return the SSL context name to cache/retrieve the {@link SslContext}.
    */
   protected Object getCacheKey(final SSLContextConfig config, final Map<String, Object> additionalOpts) {
      final Object cacheKey = ConfigurationHelper.getStringProperty(TransportConstants.SSL_CONTEXT_PROP_NAME, null, additionalOpts);
      if (cacheKey != null)
         return cacheKey;

      return config;
   }

   @Override
   public int getPriority() {
      return 10;
   }
}


<|start_filename|>tests/activemq5-unit-tests/src/main/java/org/apache/activemq/broker/artemiswrapper/RegionProxy.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.broker.artemiswrapper;

import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.postoffice.QueueBinding;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.broker.ConnectionContext;
import org.apache.activemq.broker.ConsumerBrokerExchange;
import org.apache.activemq.broker.ProducerBrokerExchange;
import org.apache.activemq.broker.region.Destination;
import org.apache.activemq.broker.region.QueueRegion;
import org.apache.activemq.broker.region.Region;
import org.apache.activemq.broker.region.Subscription;
import org.apache.activemq.broker.region.TopicRegion;
import org.apache.activemq.broker.region.policy.DestinationProxy;
import org.apache.activemq.command.ActiveMQDestination;
import org.apache.activemq.command.ActiveMQQueue;
import org.apache.activemq.command.ConsumerControl;
import org.apache.activemq.command.ConsumerInfo;
import org.apache.activemq.command.Message;
import org.apache.activemq.command.MessageAck;
import org.apache.activemq.command.MessageDispatchNotification;
import org.apache.activemq.command.MessagePull;
import org.apache.activemq.command.ProducerInfo;
import org.apache.activemq.command.RemoveSubscriptionInfo;
import org.apache.activemq.command.Response;
import org.mockito.AdditionalAnswers;
import org.mockito.Mockito;

public class RegionProxy implements Region {
   private final ActiveMQServer server;
   private final RoutingType routingType;

   private RegionProxy(ActiveMQServer activeMQServer, RoutingType routingType) {
      this.server = activeMQServer;
      this.routingType = routingType;
   }

   public static Region newQueueRegion(ActiveMQServer activeMQServer) {
      return Mockito.mock(QueueRegion.class, AdditionalAnswers.delegatesTo(new RegionProxy(activeMQServer, RoutingType.ANYCAST)));
   }

   public static Region newTopicRegion(ActiveMQServer activeMQServer) {
      return Mockito.mock(TopicRegion.class, AdditionalAnswers.delegatesTo(new RegionProxy(activeMQServer, RoutingType.MULTICAST)));
   }

   @Override
   public Destination addDestination(ConnectionContext context, ActiveMQDestination destination, boolean createIfTemporary) throws Exception {
      throw new UnsupportedOperationException("Not implemented yet");
   }

   @Override
   public void removeDestination(ConnectionContext context, ActiveMQDestination destination, long timeout) throws Exception {
      throw new UnsupportedOperationException("Not implemented yet");
   }

   @Override
   public Map<ActiveMQDestination, Destination> getDestinationMap() {
      return server.getPostOffice().getAllBindings()
         .filter(QueueBinding.class::isInstance)
         .filter(e -> {
               final SimpleString address = ((QueueBinding) e).getQueue().getAddress();
               return server.getAddressInfo(address).getRoutingType() == routingType;
            }
         )
         .collect(Collectors.toMap(
            e -> {
               final String uniqueName = e.getUniqueName().toString();
               return new ActiveMQQueue(uniqueName);
            },
            e -> {
               final Queue queue = ((QueueBinding) e).getQueue();
               final String address = e.getAddress().toString();
               return new DestinationProxy(queue, address, server);
            }));
   }

   @Override
   public Subscription addConsumer(ConnectionContext context, ConsumerInfo info) throws Exception {
      throw new UnsupportedOperationException("Not implemented yet");
   }

   @Override
   public void removeConsumer(ConnectionContext context, ConsumerInfo info) throws Exception {
      throw new UnsupportedOperationException("Not implemented yet");
   }

   @Override
   public void addProducer(ConnectionContext context, ProducerInfo info) throws Exception {
      throw new UnsupportedOperationException("Not implemented yet");
   }

   @Override
   public void removeProducer(ConnectionContext context, ProducerInfo info) throws Exception {
      throw new UnsupportedOperationException("Not implemented yet");
   }

   @Override
   public void removeSubscription(ConnectionContext context, RemoveSubscriptionInfo info) throws Exception {
      throw new UnsupportedOperationException("Not implemented yet");
   }

   @Override
   public void send(ProducerBrokerExchange producerExchange, Message message) throws Exception {
      throw new UnsupportedOperationException("Not implemented yet");
   }

   @Override
   public void acknowledge(ConsumerBrokerExchange consumerExchange, MessageAck ack) throws Exception {
      throw new UnsupportedOperationException("Not implemented yet");
   }

   @Override
   public Response messagePull(ConnectionContext context, MessagePull pull) throws Exception {
      throw new UnsupportedOperationException("Not implemented yet");
   }

   @Override
   public void processDispatchNotification(MessageDispatchNotification messageDispatchNotification) throws Exception {
      throw new UnsupportedOperationException("Not implemented yet");
   }

   @Override
   public void gc() {
      throw new UnsupportedOperationException("Not implemented yet");
   }

   @Override
   public Set<Destination> getDestinations(ActiveMQDestination destination) {
      throw new UnsupportedOperationException("Not implemented yet");
   }

   @Override
   public void processConsumerControl(ConsumerBrokerExchange consumerExchange, ConsumerControl control) {
      throw new UnsupportedOperationException("Not implemented yet");
   }

   @Override
   public void reapplyInterceptor() {
      throw new UnsupportedOperationException("Not implemented yet");
   }

   @Override
   public void start() throws Exception {
      throw new UnsupportedOperationException("Not implemented yet");
   }

   @Override
   public void stop() throws Exception {
      throw new UnsupportedOperationException("Not implemented yet");
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/stomp/StompWithRejectingInterceptorTest.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.tests.integration.stomp;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.protocol.stomp.Stomp;
import org.apache.activemq.artemis.core.protocol.stomp.StompFrame;
import org.apache.activemq.artemis.core.protocol.stomp.StompFrameInterceptor;
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.tests.integration.stomp.util.ClientStompFrame;
import org.apache.activemq.artemis.tests.integration.stomp.util.StompClientConnection;
import org.apache.activemq.artemis.tests.integration.stomp.util.StompClientConnectionFactory;
import org.apache.activemq.artemis.tests.util.Wait;
import org.junit.Assert;
import org.junit.Test;

public class StompWithRejectingInterceptorTest extends StompTestBase {

   @Override
   public List<String> getIncomingInterceptors() {
      List<String> stompIncomingInterceptor = new ArrayList<>();
      stompIncomingInterceptor.add(IncomingStompFrameRejectInterceptor.class.getName());

      return stompIncomingInterceptor;
   }

   @Test
   public void stompFrameInterceptor() throws Exception {
      IncomingStompFrameRejectInterceptor.interceptedFrames.clear();

      StompClientConnection conn = StompClientConnectionFactory.createClientConnection(uri);
      conn.connect(defUser, defPass);

      ClientStompFrame frame = conn.createFrame("SEND");
      frame.addHeader("destination", getQueuePrefix() + getQueueName());
      frame.setBody("Hello World");
      conn.sendFrame(frame);
      conn.disconnect();

      assertTrue(Wait.waitFor(() -> IncomingStompFrameRejectInterceptor.interceptedFrames.size() == 3, 10000, 50));

      List<String> incomingCommands = new ArrayList<>(4);
      incomingCommands.add("CONNECT");
      incomingCommands.add("SEND");
      incomingCommands.add("DISCONNECT");

      for (int i = 0; i < IncomingStompFrameRejectInterceptor.interceptedFrames.size(); i++) {
         Assert.assertEquals(incomingCommands.get(i), IncomingStompFrameRejectInterceptor.interceptedFrames.get(i).getCommand());
      }

      Wait.assertFalse(() -> server.locateQueue(SimpleString.toSimpleString(getQueuePrefix() + getQueueName())).getMessageCount() > 0, 1000, 100);
   }

   public static class IncomingStompFrameRejectInterceptor implements StompFrameInterceptor {

      static List<StompFrame> interceptedFrames = Collections.synchronizedList(new ArrayList<>());

      @Override
      public boolean intercept(StompFrame stompFrame, RemotingConnection connection) {
         interceptedFrames.add(stompFrame);
         if (stompFrame.getCommand().equals(Stomp.Commands.SEND)) {
            return false;
         }
         return true;
      }
   }
}

<|start_filename|>artemis-core-client/src/main/java/org/apache/activemq/artemis/core/config/federation/FederationTransformerConfiguration.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.config.federation;

import java.io.Serializable;
import java.util.Map;
import java.util.Objects;

import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.core.config.TransformerConfiguration;
import org.apache.activemq.artemis.utils.Preconditions;

public class FederationTransformerConfiguration implements Serializable {

   private String name;

   private TransformerConfiguration transformerConfiguration;

   public FederationTransformerConfiguration() {
   }

   public FederationTransformerConfiguration(String name, TransformerConfiguration transformerConfiguration) {
      this.name = name;
      this.transformerConfiguration = transformerConfiguration;
   }

   public String getName() {
      return name;
   }

   public TransformerConfiguration getTransformerConfiguration() {
      return transformerConfiguration;
   }

   @Override
   public boolean equals(Object o) {
      if (this == o) return true;
      if (!(o instanceof FederationTransformerConfiguration)) return false;
      FederationTransformerConfiguration that = (FederationTransformerConfiguration) o;
      return Objects.equals(name, that.name) &&
            Objects.equals(transformerConfiguration, that.transformerConfiguration);
   }

   @Override
   public int hashCode() {
      return Objects.hash(name, transformerConfiguration);
   }


   public void encode(ActiveMQBuffer buffer) {
      Preconditions.checkArgument(name != null, "name can not be null");
      Preconditions.checkArgument(transformerConfiguration != null, "transformerConfiguration can not be null");
      buffer.writeString(name);

      buffer.writeString(transformerConfiguration.getClassName());
      buffer.writeInt(transformerConfiguration.getProperties() == null ? 0 : transformerConfiguration.getProperties().size());
      if (transformerConfiguration.getProperties() != null) {
         for (Map.Entry<String, String> entry : transformerConfiguration.getProperties().entrySet()) {
            buffer.writeString(entry.getKey());
            buffer.writeString(entry.getValue());
         }
      }
   }

   public void decode(ActiveMQBuffer buffer) {
      name = buffer.readString();
      transformerConfiguration = new TransformerConfiguration(buffer.readString());

      final int propertiesSize = buffer.readInt();
      for (int i = 0; i < propertiesSize; i++) {
         transformerConfiguration.getProperties().put(buffer.readString(), buffer.readString());
      }
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/GlobalDiskFullTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.amqp;

import java.net.URI;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.files.FileStoreMonitor;
import org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl;
import org.apache.activemq.transport.amqp.client.AmqpClient;
import org.apache.activemq.transport.amqp.client.AmqpConnection;
import org.apache.activemq.transport.amqp.client.AmqpMessage;
import org.apache.activemq.transport.amqp.client.AmqpSender;
import org.apache.activemq.transport.amqp.client.AmqpSession;
import org.junit.Assert;
import org.junit.Test;

public class GlobalDiskFullTest extends AmqpClientTestSupport {

   @Override
   protected void addConfiguration(ActiveMQServer server) {
      Configuration serverConfig = server.getConfiguration();
      serverConfig.setDiskScanPeriod(100);
   }

   @Test
   public void testProducerOnDiskFull() throws Exception {
      FileStoreMonitor monitor = ((ActiveMQServerImpl)server).getMonitor().setMaxUsage(0.0);
      final CountDownLatch latch = new CountDownLatch(1);
      monitor.addCallback(new FileStoreMonitor.Callback() {

         @Override
         public void tick(long usableSpace, long totalSpace) {
         }

         @Override
         public void over(long usableSpace, long totalSpace) {
            latch.countDown();
         }
         @Override
         public void under(long usableSpace, long totalSpace) {
         }
      });

      Assert.assertTrue(latch.await(1, TimeUnit.MINUTES));

      AmqpClient client = createAmqpClient(new URI("tcp://localhost:" + AMQP_PORT));
      AmqpConnection connection = addConnection(client.connect());

      try {
         AmqpSession session = connection.createSession();
         AmqpSender sender = session.createSender(getQueueName());
         byte[] payload = new byte[1000];


         AmqpSender anonSender = session.createSender();

         CountDownLatch sentWithName = new CountDownLatch(1);
         CountDownLatch sentAnon = new CountDownLatch(1);

         Thread threadWithName = new Thread() {
            @Override
            public void run() {

               try {
                  final AmqpMessage message = new AmqpMessage();
                  message.setBytes(payload);
                  sender.setSendTimeout(-1);
                  sender.send(message);
               } catch (Exception e) {
                  e.printStackTrace();
               } finally {
                  sentWithName.countDown();
               }
            }
         };

         threadWithName.start();


         Thread threadWithAnon = new Thread() {
            @Override
            public void run() {
               try {
                  final AmqpMessage message = new AmqpMessage();
                  message.setBytes(payload);
                  anonSender.setSendTimeout(-1);
                  message.setAddress(getQueueName());
                  anonSender.send(message);
               } catch (Exception e) {
                  e.printStackTrace();
               } finally {
                  sentAnon.countDown();
               }
            }
         };

         threadWithAnon.start();

         Assert.assertFalse("Thread sender should be blocked", sentWithName.await(500, TimeUnit.MILLISECONDS));
         Assert.assertFalse("Thread sender anonymous should be blocked", sentAnon.await(500, TimeUnit.MILLISECONDS));

         monitor.setMaxUsage(100.0);

         Assert.assertTrue("Thread sender should be released", sentWithName.await(30, TimeUnit.SECONDS));
         Assert.assertTrue("Thread sender anonymous should be released", sentAnon.await(30, TimeUnit.SECONDS));

         threadWithName.join(TimeUnit.SECONDS.toMillis(30));
         threadWithAnon.join(TimeUnit.SECONDS.toMillis(30));
         Assert.assertFalse(threadWithName.isAlive());
         Assert.assertFalse(threadWithAnon.isAlive());
      } finally {
         connection.close();
      }
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/openwire/BasicSecurityTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.openwire;

import javax.jms.BytesMessage;
import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.JMSSecurityException;
import javax.jms.MapMessage;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.MessageProducer;
import javax.jms.ObjectMessage;
import javax.jms.Queue;
import javax.jms.QueueBrowser;
import javax.jms.ServerSession;
import javax.jms.ServerSessionPool;
import javax.jms.Session;
import javax.jms.StreamMessage;
import javax.jms.TemporaryQueue;
import javax.jms.TemporaryTopic;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.TopicSubscriber;

import java.io.Serializable;

import org.apache.activemq.command.ActiveMQQueue;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class BasicSecurityTest extends BasicOpenWireTest {

   @Override
   @Before
   public void setUp() throws Exception {
      this.enableSecurity = true;
      super.setUp();
   }

   @Test
   public void testConnectionWithCredentials() throws Exception {
      Connection newConn = null;

      //correct
      try {
         newConn = factory.createConnection("openwireSender", "SeNdEr");
         newConn.start();
         newConn.close();

         newConn = factory.createConnection("openwireReceiver", "ReCeIvEr");
         newConn.start();
         newConn.close();

         newConn = null;
      } finally {
         if (newConn != null) {
            newConn.close();
         }
      }

      //wrong password
      try {
         newConn = factory.createConnection("openwireSender", "<PASSWORD>");
         newConn.start();
      } catch (JMSSecurityException e) {
         //expected
      } finally {
         if (newConn != null) {
            newConn.close();
         }
      }

      //wrong user
      try {
         newConn = factory.createConnection("wronguser", "SeNdEr");
         newConn.start();
      } catch (JMSSecurityException e) {
         //expected
      } finally {
         if (newConn != null) {
            newConn.close();
         }
      }

      //both wrong
      try {
         newConn = factory.createConnection("wronguser", "wrongpass");
         newConn.start();
      } catch (JMSSecurityException e) {
         //expected
      } finally {
         if (newConn != null) {
            newConn.close();
         }
      }

      //default user
      try {
         newConn = factory.createConnection();
         newConn.start();
      } catch (JMSSecurityException e) {
         //expected
      } finally {
         if (newConn != null) {
            newConn.close();
         }
      }
   }

   @Test
   public void testSendnReceiveAuthorization() throws Exception {
      Connection sendingConn = null;
      Connection receivingConn = null;

      //Sender
      try {
         Destination dest = new ActiveMQQueue(queueName);

         receivingConn = factory.createConnection("openwireReceiver", "ReCeIvEr");
         receivingConn.start();

         sendingConn = factory.createConnection("openwireSender", "SeNdEr");
         sendingConn.start();

         Session sendingSession = sendingConn.createSession(false, Session.AUTO_ACKNOWLEDGE);
         Session receivingSession = receivingConn.createSession(false, Session.AUTO_ACKNOWLEDGE);

         TextMessage message = sendingSession.createTextMessage("Hello World");

         MessageProducer producer = null;

         producer = receivingSession.createProducer(dest);

         try {
            producer.send(message);
         } catch (JMSSecurityException e) {
            //expected
            producer.close();
         }

         producer = sendingSession.createProducer(dest);
         producer.send(message);

         MessageConsumer consumer;
         try {
            consumer = sendingSession.createConsumer(dest);
            Assert.fail("exception expected");
         } catch (JMSSecurityException e) {
            e.printStackTrace();
            //expected
         }

         consumer = receivingSession.createConsumer(dest);
         TextMessage received = (TextMessage) consumer.receive(5000);

         assertNotNull(received);
         assertEquals("Hello World", received.getText());
      } finally {
         if (sendingConn != null) {
            sendingConn.close();
         }

         if (receivingConn != null) {
            receivingConn.close();
         }
      }
   }

   @Test
   public void testCreateTempDestinationAuthorization() throws Exception {
      Connection conn1 = null;
      Connection conn2 = null;

      try {
         conn1 = factory.createConnection("openwireGuest", "GuEsT");
         conn1.start();

         conn2 = factory.createConnection("openwireDestinationManager", "DeStInAtIoN");
         conn2.start();

         Session session1 = conn1.createSession(false, Session.AUTO_ACKNOWLEDGE);

         try {
            session1.createTemporaryQueue();
            fail("user shouldn't be able to create temp queue");
         } catch (JMSSecurityException e) {
            //expected
         }

         Session session2 = conn2.createSession(false, Session.AUTO_ACKNOWLEDGE);

         TemporaryQueue q = session2.createTemporaryQueue();
         assertNotNull(q);
      } finally {
         if (conn1 != null) {
            conn1.close();
         }

         if (conn2 != null) {
            conn2.close();
         }
      }
   }

   @Test
   public void testConnectionConsumer() throws Exception {
      Connection conn1 = null;

      try {

         conn1 = factory.createConnection("openwireGuest", "GuEsT");
         conn1.start();

         try {
            Destination dest = new ActiveMQQueue(queueName);

            conn1.createConnectionConsumer(dest, null, new ServerSessionPool() {
               @Override
               public ServerSession getServerSession() throws JMSException {
                  return new ServerSession() {
                     @Override
                     public Session getSession() throws JMSException {
                        return new Session() {
                           @Override
                           public BytesMessage createBytesMessage() throws JMSException {
                              return null;
                           }

                           @Override
                           public MapMessage createMapMessage() throws JMSException {
                              return null;
                           }

                           @Override
                           public Message createMessage() throws JMSException {
                              return null;
                           }

                           @Override
                           public ObjectMessage createObjectMessage() throws JMSException {
                              return null;
                           }

                           @Override
                           public ObjectMessage createObjectMessage(Serializable object) throws JMSException {
                              return null;
                           }

                           @Override
                           public StreamMessage createStreamMessage() throws JMSException {
                              return null;
                           }

                           @Override
                           public TextMessage createTextMessage() throws JMSException {
                              return null;
                           }

                           @Override
                           public TextMessage createTextMessage(String text) throws JMSException {
                              return null;
                           }

                           @Override
                           public boolean getTransacted() throws JMSException {
                              return false;
                           }

                           @Override
                           public int getAcknowledgeMode() throws JMSException {
                              return 0;
                           }

                           @Override
                           public void commit() throws JMSException {

                           }

                           @Override
                           public void rollback() throws JMSException {

                           }

                           @Override
                           public void close() throws JMSException {

                           }

                           @Override
                           public void recover() throws JMSException {

                           }

                           @Override
                           public MessageListener getMessageListener() throws JMSException {
                              return null;
                           }

                           @Override
                           public void setMessageListener(MessageListener listener) throws JMSException {

                           }

                           @Override
                           public void run() {

                           }

                           @Override
                           public MessageProducer createProducer(Destination destination) throws JMSException {
                              return null;
                           }

                           @Override
                           public MessageConsumer createConsumer(Destination destination) throws JMSException {
                              return null;
                           }

                           @Override
                           public MessageConsumer createConsumer(Destination destination, String messageSelector) throws JMSException {
                              return null;
                           }

                           @Override
                           public MessageConsumer createConsumer(Destination destination,
                                                                 String messageSelector,
                                                                 boolean NoLocal) throws JMSException {
                              return null;
                           }

                           @Override
                           public Queue createQueue(String queueName) throws JMSException {
                              return null;
                           }

                           @Override
                           public Topic createTopic(String topicName) throws JMSException {
                              return null;
                           }

                           @Override
                           public TopicSubscriber createDurableSubscriber(Topic topic, String name) throws JMSException {
                              return null;
                           }

                           @Override
                           public TopicSubscriber createDurableSubscriber(Topic topic,
                                                                          String name,
                                                                          String messageSelector,
                                                                          boolean noLocal) throws JMSException {
                              return null;
                           }

                           @Override
                           public QueueBrowser createBrowser(Queue queue) throws JMSException {
                              return null;
                           }

                           @Override
                           public QueueBrowser createBrowser(Queue queue, String messageSelector) throws JMSException {
                              return null;
                           }

                           @Override
                           public TemporaryQueue createTemporaryQueue() throws JMSException {
                              return null;
                           }

                           @Override
                           public TemporaryTopic createTemporaryTopic() throws JMSException {
                              return null;
                           }

                           @Override
                           public void unsubscribe(String name) throws JMSException {

                           }

                           @Override
                           public MessageConsumer createSharedConsumer(Topic topic, String sharedSubscriptionName) throws JMSException {
                              return null;
                           }

                           @Override
                           public MessageConsumer createSharedConsumer(Topic topic,
                                                                       String sharedSubscriptionName,
                                                                       String messageSelector) throws JMSException {
                              return null;
                           }

                           @Override
                           public MessageConsumer createDurableConsumer(Topic topic, String name) throws JMSException {
                              return null;
                           }

                           @Override
                           public MessageConsumer createDurableConsumer(Topic topic,
                                                                        String name,
                                                                        String messageSelector,
                                                                        boolean noLocal) throws JMSException {
                              return null;
                           }

                           @Override
                           public MessageConsumer createSharedDurableConsumer(Topic topic, String name) throws JMSException {
                              return null;
                           }

                           @Override
                           public MessageConsumer createSharedDurableConsumer(Topic topic, String name, String messageSelector) throws JMSException {
                              return null;
                           }
                        };
                     }

                     @Override
                     public void start() throws JMSException {

                     }
                  };
               }
            }, 100);
         } catch (JMSSecurityException e) {
            //expected
         }

      } finally {
         if (conn1 != null) {
            conn1.close();
         }
      }
   }

}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/AddressPauseTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.client;

import javax.jms.Connection;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import javax.jms.TopicSubscriber;
import org.apache.activemq.artemis.api.core.management.AddressControl;
import org.apache.activemq.artemis.api.core.management.ResourceNames;
import org.apache.activemq.artemis.tests.util.JMSTestBase;
import org.junit.Assert;
import org.junit.Test;

public class AddressPauseTest extends JMSTestBase {


   @Override
   protected boolean usePersistence() {
      return true;
   }

   @Test
   public void testPauseAddress() throws Exception {
      try (Connection connection = cf.createConnection()) {
         connection.setClientID("myClientID");
         connection.start();
         try (Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE)) {
            Topic topic = session.createTopic("jms.topic.MyTopic");
            TopicSubscriber subscriber1 = session.createDurableSubscriber(topic, "my-subscription1");
            AddressControl addressControl = (AddressControl) server.getManagementService().getResource(ResourceNames.ADDRESS + "jms.topic.MyTopic");
            MessageProducer producer = session.createProducer(topic);
            final int numMessages = 100;
            for (int i = 0; i < numMessages; i++) {
               TextMessage mess = session.createTextMessage("msg" + i);
               producer.send(mess);
            }
            session.commit();
            for (int i = 0; i < numMessages; i++) {
               TextMessage m = (TextMessage) subscriber1.receive(5000);
               Assert.assertNotNull(m);
            }
            session.commit();
            //Pausing the subscriptions
            addressControl.pause();
            Assert.assertTrue(addressControl.isPaused());
            //subscriber2 should be paused too
            TopicSubscriber subscriber2 = session.createDurableSubscriber(topic, "my-subscription2");
            for (int i = 0; i < numMessages; i++) {
               TextMessage mess = session.createTextMessage("msg" + i);
               producer.send(mess);
            }
            session.commit();
            TextMessage message = (TextMessage) subscriber1.receiveNoWait();
            Assert.assertNull(message);
            message = (TextMessage) subscriber2.receiveNoWait();
            Assert.assertNull(message);
            //Resuming the subscriptions
            addressControl.resume();
            for (int i = 0; i < numMessages; i++) {
               TextMessage m = (TextMessage) subscriber1.receive(5000);
               Assert.assertNotNull(m);
            }
            session.commit();
            for (int i = 0; i < numMessages; i++) {
               TextMessage m = (TextMessage) subscriber2.receive(5000);
               Assert.assertNotNull(m);
            }
            session.commit();
         }
      }
   }


   @Test
   public void testPauseAddressServerRestart() throws Exception {
      final int numMessages = 100;

      try (Connection connection = cf.createConnection()) {
         connection.setClientID("myClientID");
         connection.start();
         try (Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE)) {
            Topic topic = session.createTopic("jms.topic.MyTopic");
            TopicSubscriber subscriber1 = session.createDurableSubscriber(topic, "my-subscription1");
            AddressControl addressControl = (AddressControl) server.getManagementService().getResource(ResourceNames.ADDRESS + "jms.topic.MyTopic");
            MessageProducer producer = session.createProducer(topic);
            for (int i = 0; i < numMessages; i++) {
               TextMessage mess = session.createTextMessage("msg" + i);
               producer.send(mess);
            }
            session.commit();
            for (int i = 0; i < numMessages; i++) {
               TextMessage m = (TextMessage) subscriber1.receive(5000);
               Assert.assertNotNull(m);
            }
            session.commit();
            //Pausing the subscriptions
            addressControl.pause(true);
         }
      }

      server.stop();

      server.start();

      try (Connection connection = cf.createConnection()) {
         connection.setClientID("myClientID");
         connection.start();
         try (Session session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE)) {
            Topic topic = session.createTopic("jms.topic.MyTopic");
            TopicSubscriber subscriber1 = session.createDurableSubscriber(topic, "my-subscription1");
            AddressControl addressControl = (AddressControl) server.getManagementService().getResource(ResourceNames.ADDRESS + "jms.topic.MyTopic");
            MessageProducer producer = session.createProducer(topic);
            Assert.assertTrue(addressControl.isPaused());
            //subscriber2 should be paused too
            TopicSubscriber subscriber2 = session.createDurableSubscriber(topic, "my-subscription2");
            for (int i = 0; i < numMessages; i++) {
               TextMessage mess = session.createTextMessage("msg" + i);
               producer.send(mess);
            }
            session.commit();
            TextMessage message = (TextMessage) subscriber1.receiveNoWait();
            Assert.assertNull(message);
            message = (TextMessage) subscriber2.receiveNoWait();
            Assert.assertNull(message);
            //Resuming the subscriptions
            addressControl.resume();
            for (int i = 0; i < numMessages; i++) {
               TextMessage m = (TextMessage) subscriber1.receive(5000);
               Assert.assertNotNull(m);
            }
            session.commit();
            for (int i = 0; i < numMessages; i++) {
               TextMessage m = (TextMessage) subscriber2.receive(5000);
               Assert.assertNotNull(m);
            }
            session.commit();
         }
      }
   }
}


<|start_filename|>artemis-server/src/test/java/org/apache/activemq/artemis/spi/core/security/jaas/Krb5LoginModuleTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.spi.core.security.jaas;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.io.IOException;
import java.security.Principal;

import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;

import org.junit.Test;

public class Krb5LoginModuleTest {

   @Test
   public void loginFail() throws Exception {
      Krb5LoginModule underTest = new Krb5LoginModule();

      final Subject subject = new Subject();
      underTest.initialize(subject, new CallbackHandler() {
         @Override
         public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
         }
      }, null, null);

      assertFalse(underTest.login());
   }

   @Test
   public void loginSuccess() throws Exception {
      Krb5LoginModule underTest = new Krb5LoginModule();

      final Subject subject = new Subject();
      underTest.initialize(subject, new CallbackHandler() {
         @Override
         public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
            ((PrincipalsCallback) callbacks[0]).setPeerPrincipals(new Principal[] {new UserPrincipal("A")});
         }
      }, null, null);

      assertTrue(underTest.login());
   }

}


<|start_filename|>artemis-rest/src/test/java/org/apache/activemq/artemis/rest/test/AutoAckQueueTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.rest.test;

import org.apache.activemq.artemis.rest.queue.QueueDeployment;
import org.apache.activemq.artemis.rest.util.Constants;
import org.jboss.logging.Logger;
import org.jboss.resteasy.client.ClientRequest;
import org.jboss.resteasy.client.ClientResponse;
import org.jboss.resteasy.spi.Link;
import org.jboss.resteasy.test.TestPortProvider;
import org.junit.Assert;
import org.junit.Test;

public class AutoAckQueueTest extends MessageTestBase {
   private static final Logger log = Logger.getLogger(AutoAckQueueTest.class);

   @Test
   public void testSuccessFirst() throws Exception {
      String testName = "testSuccessFirst";
      QueueDeployment deployment = new QueueDeployment();
      deployment.setDuplicatesAllowed(true);
      deployment.setDurableSend(false);
      deployment.setName(testName);
      manager.getQueueManager().deploy(deployment);

      ClientRequest request = new ClientRequest(TestPortProvider.generateURL("/queues/" + testName));

      ClientResponse<?> response = request.head();
      response.releaseConnection();
      Assert.assertEquals(200, response.getStatus());
      Link sender = getLinkByTitle(manager.getQueueManager().getLinkStrategy(), response, "create");
      log.debug("create: " + sender);
      Link consumers = getLinkByTitle(manager.getQueueManager().getLinkStrategy(), response, "pull-consumers");
      log.debug("pull: " + consumers);
      log.debug("create-with-id: " + getLinkByTitle(manager.getQueueManager().getLinkStrategy(), response, "create-with-id"));
      response = Util.setAutoAck(consumers, true);
      Link consumeNext = getLinkByTitle(manager.getQueueManager().getLinkStrategy(), response, "consume-next");
      log.debug("poller: " + consumeNext);

      ClientResponse<?> res = sender.request().body("text/plain", Integer.toString(1)).post();
      res.releaseConnection();
      Assert.assertEquals(201, res.getStatus());
      log.debug("create-next: " + getLinkByTitle(manager.getQueueManager().getLinkStrategy(), res, "create-next"));

      res = sender.request().body("text/plain", Integer.toString(2)).post();
      res.releaseConnection();
      Assert.assertEquals(201, res.getStatus());

      res = consumeNext.request().post(String.class);
      Assert.assertEquals(200, res.getStatus());
      Assert.assertEquals("1", res.getEntity(String.class));
      res.releaseConnection();
      Link session = getLinkByTitle(manager.getQueueManager().getLinkStrategy(), res, "consumer");
      log.debug("session: " + session);
      consumeNext = getLinkByTitle(manager.getQueueManager().getLinkStrategy(), res, "consume-next");
      log.debug("consumeNext: " + consumeNext);

      log.debug(consumeNext);
      res = consumeNext.request().header(Constants.WAIT_HEADER, "10").post(String.class);
      Assert.assertEquals(200, res.getStatus());
      Assert.assertEquals("2", res.getEntity(String.class));
      res.releaseConnection();
      session = getLinkByTitle(manager.getQueueManager().getLinkStrategy(), res, "consumer");
      log.debug("session: " + session);
      getLinkByTitle(manager.getQueueManager().getLinkStrategy(), res, "consume-next");
      log.debug("consumeNext: " + consumeNext);

      res = session.request().delete();
      res.releaseConnection();
      Assert.assertEquals(204, res.getStatus());
   }

}

<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/server/plugin/impl/LoggingActiveMQServerPlugin.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.core.server.plugin.impl;

import java.io.Serializable;
import java.util.Map;

import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.config.BridgeConfiguration;
import org.apache.activemq.artemis.core.persistence.OperationContext;
import org.apache.activemq.artemis.core.postoffice.QueueBinding;
import org.apache.activemq.artemis.core.postoffice.RoutingStatus;
import org.apache.activemq.artemis.core.security.SecurityAuth;
import org.apache.activemq.artemis.core.server.MessageReference;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.core.server.RoutingContext;
import org.apache.activemq.artemis.core.server.ServerConsumer;
import org.apache.activemq.artemis.core.server.ServerSession;
import org.apache.activemq.artemis.core.server.cluster.Bridge;
import org.apache.activemq.artemis.core.server.impl.AckReason;
import org.apache.activemq.artemis.core.server.plugin.ActiveMQServerPlugin;
import org.apache.activemq.artemis.core.transaction.Transaction;
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.spi.core.protocol.SessionCallback;
import org.apache.activemq.artemis.utils.critical.CriticalComponent;

/**
 * plugin to log various events within the broker, configured with the following booleans
 *
 * LOG_CONNECTION_EVENTS - connections creation/destroy
 * LOG_SESSION_EVENTS - sessions creation/close
 * LOG_CONSUMER_EVENTS - consumers creation/close
 * LOG_DELIVERING_EVENTS - messages delivered to consumer, acked by consumer
 * LOG_SENDING_EVENTS -  messaged is sent, message is routed
 * LOG_INTERNAL_EVENTS - critical failures, bridge deployments, queue creation/destroyed, message expired
 */

public class LoggingActiveMQServerPlugin implements ActiveMQServerPlugin, Serializable {

   private static final long serialVersionUID = 1L;

   public static final String LOG_ALL_EVENTS = "LOG_ALL_EVENTS";
   public static final String LOG_CONNECTION_EVENTS = "LOG_CONNECTION_EVENTS";
   public static final String LOG_SESSION_EVENTS = "LOG_SESSION_EVENTS";
   public static final String LOG_CONSUMER_EVENTS = "LOG_CONSUMER_EVENTS";
   public static final String LOG_DELIVERING_EVENTS = "LOG_DELIVERING_EVENTS";
   public static final String LOG_SENDING_EVENTS = "LOG_SENDING_EVENTS";
   public static final String LOG_INTERNAL_EVENTS = "LOG_INTERNAL_EVENTS";

   public static final String UNAVAILABLE = "UNAVAILABLE";

   private boolean logAll = false;
   private boolean logConnectionEvents = false;
   private boolean logSessionEvents = false;
   private boolean logConsumerEvents = false;
   private boolean logDeliveringEvents = false;
   private boolean logSendingEvents = false;
   private boolean logInternalEvents = false;

   public boolean isLogAll() {
      return logAll;
   }

   public boolean isLogConnectionEvents() {
      return logConnectionEvents;
   }

   public boolean isLogSessionEvents() {
      return logSessionEvents;
   }

   public boolean isLogConsumerEvents() {
      return logConsumerEvents;
   }

   public boolean isLogDeliveringEvents() {
      return logDeliveringEvents;
   }

   public boolean isLogSendingEvents() {
      return logSendingEvents;
   }

   public boolean isLogInternalEvents() {
      return logInternalEvents;
   }

   /**
    * used to pass configured properties to Plugin
    *
    * @param properties
    */
   @Override
   public void init(Map<String, String> properties) {

      logAll = Boolean.parseBoolean(properties.getOrDefault(LOG_ALL_EVENTS, "false"));
      logConnectionEvents = Boolean.parseBoolean(properties.getOrDefault(LOG_CONNECTION_EVENTS, "false"));
      logSessionEvents = Boolean.parseBoolean(properties.getOrDefault(LOG_SESSION_EVENTS, "false"));
      logConsumerEvents = Boolean.parseBoolean(properties.getOrDefault(LOG_CONSUMER_EVENTS, "false"));
      logDeliveringEvents = Boolean.parseBoolean(properties.getOrDefault(LOG_DELIVERING_EVENTS, "false"));
      logSendingEvents = Boolean.parseBoolean(properties.getOrDefault(LOG_SENDING_EVENTS, "false"));
      logInternalEvents = Boolean.parseBoolean(properties.getOrDefault(LOG_INTERNAL_EVENTS, "false"));

      if (LoggingActiveMQServerPluginLogger.LOGGER.isDebugEnabled()) {
         dumpConfiguration();
      }

   }

   /**
    * A connection has been created.
    *
    * @param connection The newly created connection
    * @throws ActiveMQException
    */
   @Override
   public void afterCreateConnection(RemotingConnection connection) throws ActiveMQException {
      if (logAll || logConnectionEvents) {
         LoggingActiveMQServerPluginLogger.LOGGER.afterCreateConnection(connection);
      }
   }

   /**
    * A connection has been destroyed.
    *
    * @param connection
    * @throws ActiveMQException
    */
   @Override
   public void afterDestroyConnection(RemotingConnection connection) throws ActiveMQException {
      if (logAll || logConnectionEvents) {
         LoggingActiveMQServerPluginLogger.LOGGER.afterDestroyConnection(connection);
      }
   }

   /**
    * Before a session is created.
    *
    * @param name
    * @param username
    * @param minLargeMessageSize
    * @param connection
    * @param autoCommitSends
    * @param autoCommitAcks
    * @param preAcknowledge
    * @param xa
    * @param publicAddress
    * @param callback
    * @param autoCreateQueues
    * @param context
    * @param prefixes
    * @throws ActiveMQException
    */
   @Override
   public void beforeCreateSession(String name,
                                   String username,
                                   int minLargeMessageSize,
                                   RemotingConnection connection,
                                   boolean autoCommitSends,
                                   boolean autoCommitAcks,
                                   boolean preAcknowledge,
                                   boolean xa,
                                   String publicAddress,
                                   SessionCallback callback,
                                   boolean autoCreateQueues,
                                   OperationContext context,
                                   Map<SimpleString, RoutingType> prefixes) throws ActiveMQException {

      if (logAll || logSessionEvents) {
         LoggingActiveMQServerPluginLogger.LOGGER.beforeCreateSession(name, username, minLargeMessageSize, connection,
                                                                      autoCommitSends, autoCommitAcks, preAcknowledge,
                                                                      xa, publicAddress, context);
      }

   }

   /**
    * After a session has been created.
    *
    * @param session The newly created session
    * @throws ActiveMQException
    */
   @Override
   public void afterCreateSession(ServerSession session) throws ActiveMQException {
      if (logAll || logSessionEvents) {
         LoggingActiveMQServerPluginLogger.LOGGER.afterCreateSession((session == null ? UNAVAILABLE : session.getName()),
                                                                     (session == null ? UNAVAILABLE : session.getConnectionID()));
      }

   }

   /**
    * Before a session is closed
    *
    * @param session
    * @param failed
    * @throws ActiveMQException
    */
   @Override
   public void beforeCloseSession(ServerSession session, boolean failed) throws ActiveMQException {
      if (logAll || logSessionEvents) {
         LoggingActiveMQServerPluginLogger.LOGGER.beforeCloseSession((session == null ? UNAVAILABLE : session.getName()),
                                                                     session, failed);
      }
   }

   /**
    * After a session is closed
    *
    * @param session
    * @param failed
    * @throws ActiveMQException
    */
   @Override
   public void afterCloseSession(ServerSession session, boolean failed) throws ActiveMQException {
      if (logAll || logSessionEvents) {
         LoggingActiveMQServerPluginLogger.LOGGER.afterCloseSession((session == null ? UNAVAILABLE : session.getName()),
                                                                    failed);
      }
   }

   /**
    * Before session metadata is added to the session
    *
    * @param session
    * @param key
    * @param data
    * @throws ActiveMQException
    */
   @Override
   public void beforeSessionMetadataAdded(ServerSession session, String key, String data) throws ActiveMQException {
      if (logAll || logSessionEvents) {
         LoggingActiveMQServerPluginLogger.LOGGER.beforeSessionMetadataAdded((session == null ? UNAVAILABLE : session.getName()),
                                                                             session, key, data);
      }
   }

   /**
    * After session metadata is added to the session
    *
    * @param session
    * @param key
    * @param data
    * @throws ActiveMQException
    */
   @Override
   public void afterSessionMetadataAdded(ServerSession session, String key, String data) throws ActiveMQException {
      if (logAll || logSessionEvents) {

         //Details - debug level
         LoggingActiveMQServerPluginLogger.LOGGER.afterSessionMetadataAddedDetails((session == null ? UNAVAILABLE : session.getName()),
                                                                                   session, key, data);

         // info level  log
         LoggingActiveMQServerPluginLogger.LOGGER.afterSessionMetadataAdded((session == null ? UNAVAILABLE : session.getName()),
                                                                            key, data);
      }
   }

   /**
    * Before a consumer is created
    *
    * @param consumerID
    * @param queueBinding
    * @param filterString
    * @param browseOnly
    * @param supportLargeMessage
    * @throws ActiveMQException
    */
   @Override
   public void beforeCreateConsumer(long consumerID,
                                    QueueBinding queueBinding,
                                    SimpleString filterString,
                                    boolean browseOnly,
                                    boolean supportLargeMessage) throws ActiveMQException {

      if (logAll || logConsumerEvents) {
         if (LoggingActiveMQServerPluginLogger.LOGGER.isInfoEnabled()) {
            LoggingActiveMQServerPluginLogger.LOGGER.beforeCreateConsumer(Long.toString(consumerID), queueBinding,
                                                                          filterString, browseOnly, supportLargeMessage);
         }
      }

   }

   /**
    * After a consumer has been created
    *
    * @param consumer the created consumer
    * @throws ActiveMQException
    */
   @Override
   public void afterCreateConsumer(ServerConsumer consumer) throws ActiveMQException {

      if (logAll || logConsumerEvents) {
         if (LoggingActiveMQServerPluginLogger.LOGGER.isInfoEnabled()) {
            LoggingActiveMQServerPluginLogger.LOGGER.afterCreateConsumer((consumer == null ? UNAVAILABLE : Long.toString(consumer.getID())),
                                                                         (consumer == null ? UNAVAILABLE : consumer.getSessionID()));
         }
      }

   }

   /**
    * Before a consumer is closed
    *
    * @param consumer
    * @param failed
    * @throws ActiveMQException
    */
   @Override
   public void beforeCloseConsumer(ServerConsumer consumer, boolean failed) throws ActiveMQException {

      if (logAll || logConsumerEvents) {
         LoggingActiveMQServerPluginLogger.LOGGER.beforeCloseConsumer(consumer, (consumer == null ? UNAVAILABLE : consumer.getSessionID()),
                                                                      failed);
      }
   }

   /**
    * After a consumer is closed
    *
    * @param consumer
    * @param failed
    * @throws ActiveMQException
    */
   @Override
   public void afterCloseConsumer(ServerConsumer consumer, boolean failed) throws ActiveMQException {

      if (logAll || logConsumerEvents) {
         if (LoggingActiveMQServerPluginLogger.LOGGER.isInfoEnabled()) {
            LoggingActiveMQServerPluginLogger.LOGGER.afterCloseConsumer((consumer == null ? UNAVAILABLE : Long.toString(consumer.getID())),
                                                                        (consumer == null ? UNAVAILABLE : consumer.getSessionID()), failed);
         }
      }

   }

   /**
    * Before a queue is created
    *
    * @param queueConfig
    * @throws ActiveMQException
    */
   @Override
   public void beforeCreateQueue(QueueConfiguration queueConfig) throws ActiveMQException {
      if (logAll || logInternalEvents) {
         LoggingActiveMQServerPluginLogger.LOGGER.beforeCreateQueue(queueConfig);
      }
   }

   /**
    * After a queue has been created
    *
    * @param queue The newly created queue
    * @throws ActiveMQException
    */
   @Override
   public void afterCreateQueue(Queue queue) throws ActiveMQException {
      if (logAll || logInternalEvents) {
         LoggingActiveMQServerPluginLogger.LOGGER.afterCreateQueue(queue);
      }
   }

   /**
    * Before a queue is destroyed
    *
    * @param queueName
    * @param session
    * @param checkConsumerCount
    * @param removeConsumers
    * @param autoDeleteAddress
    * @throws ActiveMQException
    */
   @Override
   public void beforeDestroyQueue(SimpleString queueName,
                                  final SecurityAuth session,
                                  boolean checkConsumerCount,
                                  boolean removeConsumers,
                                  boolean autoDeleteAddress) throws ActiveMQException {
      if (logAll || logInternalEvents) {
         LoggingActiveMQServerPluginLogger.LOGGER.beforeDestroyQueue(queueName, session, checkConsumerCount, removeConsumers,
                                                                     autoDeleteAddress);
      }

   }

   /**
    * After a queue has been destroyed
    *
    * @param queue
    * @param address
    * @param session
    * @param checkConsumerCount
    * @param removeConsumers
    * @param autoDeleteAddress
    * @throws ActiveMQException
    */
   @Override
   public void afterDestroyQueue(Queue queue,
                                 SimpleString address,
                                 final SecurityAuth session,
                                 boolean checkConsumerCount,
                                 boolean removeConsumers,
                                 boolean autoDeleteAddress) throws ActiveMQException {

      if (logAll || logInternalEvents) {
         LoggingActiveMQServerPluginLogger.LOGGER.afterDestroyQueue(queue, address, session, checkConsumerCount,
                                                                    removeConsumers, autoDeleteAddress);
      }

   }

   /**
    * Before a message is sent
    *
    * @param session           the session that sends the message
    * @param tx
    * @param message
    * @param direct
    * @param noAutoCreateQueue
    * @throws ActiveMQException
    */
   @Override
   public void beforeSend(ServerSession session,
                          Transaction tx,
                          Message message,
                          boolean direct,
                          boolean noAutoCreateQueue) throws ActiveMQException {

      if (logAll || logSendingEvents) {
         LoggingActiveMQServerPluginLogger.LOGGER.beforeSend(message, tx, session, direct, noAutoCreateQueue);
      }
   }

   /**
    * After a message is sent
    *
    * @param session           the session that sends the message
    * @param tx
    * @param message
    * @param direct
    * @param noAutoCreateQueue
    * @param result
    * @throws ActiveMQException
    */
   @Override
   public void afterSend(ServerSession session,
                         Transaction tx,
                         Message message,
                         boolean direct,
                         boolean noAutoCreateQueue,
                         RoutingStatus result) throws ActiveMQException {

      if (logAll || logSendingEvents) {

         if (LoggingActiveMQServerPluginLogger.LOGGER.isDebugEnabled()) {
            //details - debug level
            LoggingActiveMQServerPluginLogger.LOGGER.afterSendDetails((message == null ? UNAVAILABLE : Long.toString(message.getMessageID())),
                                                                      message, (session == null ? UNAVAILABLE : session.getName()),
                                                                      tx, session, direct, noAutoCreateQueue);
         }

         if (LoggingActiveMQServerPluginLogger.LOGGER.isInfoEnabled()) {
            //info level log
            LoggingActiveMQServerPluginLogger.LOGGER.afterSend((message == null ? UNAVAILABLE : Long.toString(message.getMessageID())),
                                                               (session == null ? UNAVAILABLE : session.getName()),
                                                               (session == null ? UNAVAILABLE : session.getConnectionID().toString()),
                                                               result);
         }
      }
   }

   @Override
   public void onSendException(ServerSession session,
                               Transaction tx,
                               Message message,
                               boolean direct,
                               boolean noAutoCreateQueue,
                               Exception e) throws ActiveMQException {
      if (logAll || logSendingEvents) {

         if (LoggingActiveMQServerPluginLogger.LOGGER.isDebugEnabled()) {
            //details - debug level
            LoggingActiveMQServerPluginLogger.LOGGER.onSendErrorDetails((message == null ? UNAVAILABLE : Long.toString(message.getMessageID())),
                                                                        message, (session == null ? UNAVAILABLE : session.getName()),
                                                                        tx, session, direct, noAutoCreateQueue);
         }

         if (LoggingActiveMQServerPluginLogger.LOGGER.isInfoEnabled()) {
            //info level log
            LoggingActiveMQServerPluginLogger.LOGGER.onSendError((message == null ? UNAVAILABLE : Long.toString(message.getMessageID())),
                                                                 (session == null ? UNAVAILABLE : session.getName()),
                                                                 (session == null ? UNAVAILABLE : session.getConnectionID().toString()),
                                                                 e);
         }
      }
   }

   /**
    * Before a message is routed
    *
    * @param message
    * @param context
    * @param direct
    * @param rejectDuplicates
    * @throws ActiveMQException
    */
   @Override
   public void beforeMessageRoute(Message message,
                                  RoutingContext context,
                                  boolean direct,
                                  boolean rejectDuplicates) throws ActiveMQException {
      if (logAll || logSendingEvents) {
         LoggingActiveMQServerPluginLogger.LOGGER.beforeMessageRoute(message, context, direct, rejectDuplicates);
      }
   }

   /**
    * After a message is routed
    *
    * @param message
    * @param context
    * @param direct
    * @param rejectDuplicates
    * @param result
    * @throws ActiveMQException
    */
   @Override
   public void afterMessageRoute(Message message,
                                 RoutingContext context,
                                 boolean direct,
                                 boolean rejectDuplicates,
                                 RoutingStatus result) throws ActiveMQException {
      if (logAll || logSendingEvents) {

         //details - debug level logging
         LoggingActiveMQServerPluginLogger.LOGGER.afterMessageRouteDetails(message, context, direct, rejectDuplicates);

         if (LoggingActiveMQServerPluginLogger.LOGGER.isInfoEnabled()) {
            //info level log
            LoggingActiveMQServerPluginLogger.LOGGER.afterMessageRoute((message == null ? UNAVAILABLE : Long.toString(message.getMessageID())),
                                                                       result);
         }

      }
   }

   @Override
   public void onMessageRouteException(Message message,
                                       RoutingContext context,
                                       boolean direct,
                                       boolean rejectDuplicates,
                                       Exception e) throws ActiveMQException {
      if (logAll || logSendingEvents) {

         //details - debug level logging
         LoggingActiveMQServerPluginLogger.LOGGER.onMessageRouteErrorDetails(message, context, direct, rejectDuplicates);

         if (LoggingActiveMQServerPluginLogger.LOGGER.isInfoEnabled()) {
            //info level log
            LoggingActiveMQServerPluginLogger.LOGGER.onMessageRouteError((message == null ? UNAVAILABLE : Long.toString(message.getMessageID())),
                                                                         e);
         }

      }
   }

   /**
    * Before a message is delivered to a client consumer
    *
    * @param consumer  the consumer the message will be delivered to
    * @param reference message reference
    * @throws ActiveMQException
    */
   @Override
   public void beforeDeliver(ServerConsumer consumer, MessageReference reference) throws ActiveMQException {

      if (logAll || logDeliveringEvents) {
         LoggingActiveMQServerPluginLogger.LOGGER.beforeDeliver(consumer, reference);
      }
   }

   /**
    * After a message is delivered to a client consumer
    *
    * @param consumer  the consumer the message was delivered to
    * @param reference message reference
    * @throws ActiveMQException
    */
   @Override
   public void afterDeliver(ServerConsumer consumer, MessageReference reference) throws ActiveMQException {

      if (logAll || logDeliveringEvents) {
         Message message = (reference == null ? null : reference.getMessage());

         if (consumer == null) {
            // log at info level and exit
            if (LoggingActiveMQServerPluginLogger.LOGGER.isInfoEnabled()) {
               LoggingActiveMQServerPluginLogger.LOGGER.afterDeliverNoConsumer((message == null ? UNAVAILABLE : Long.toString(message.getMessageID())));
            }
            return;
         }

         if (LoggingActiveMQServerPluginLogger.LOGGER.isDebugEnabled()) {
            //details --- debug level
            LoggingActiveMQServerPluginLogger.LOGGER.afterDeliverDetails((message == null ? UNAVAILABLE : Long.toString(message.getMessageID())),
                                                                         consumer.getQueueAddress(), consumer.getQueueName(),
                                                                         consumer.getSessionID(), consumer.getID(),
                                                                         reference, consumer);
         }

         if (LoggingActiveMQServerPluginLogger.LOGGER.isInfoEnabled()) {
            //info level log
            LoggingActiveMQServerPluginLogger.LOGGER.afterDeliver((message == null ? UNAVAILABLE : Long.toString(message.getMessageID())),
                                                                  consumer.getQueueAddress(),
                                                                  consumer.getQueueName(),
                                                                  consumer.getSessionID(), consumer.getID());
         }

      }
   }

   @Override
   public void messageExpired(MessageReference message,
                              SimpleString messageExpiryAddress,
                              ServerConsumer consumer) {
      if (logAll || logInternalEvents) {
         LoggingActiveMQServerPluginLogger.LOGGER.messageExpired(message, messageExpiryAddress);
      }
   }

   /**
    * A message has been acknowledged
    *
    * @param ref    The acked message
    * @param reason The ack reason
    * @throws ActiveMQException
    */
   @Override
   public void messageAcknowledged(MessageReference ref, AckReason reason, ServerConsumer consumer) throws ActiveMQException {
      if (logAll || logDeliveringEvents) {

         //details - debug logging
         LoggingActiveMQServerPluginLogger.LOGGER.messageAcknowledgedDetails(ref, reason);

         if (LoggingActiveMQServerPluginLogger.LOGGER.isInfoEnabled()) {
            Message message = (ref == null ? null : ref.getMessage());
            Queue queue = (ref == null ? null : ref.getQueue());

            // info level logging
            LoggingActiveMQServerPluginLogger.LOGGER.messageAcknowledged((message == null ? UNAVAILABLE : Long.toString(message.getMessageID())),
                                                                         (consumer == null ? UNAVAILABLE : consumer.getSessionID() != null ? consumer.getSessionID() : null),
                                                                         (consumer == null ? UNAVAILABLE : Long.toString(consumer.getID())),
                                                                         (queue == null ? UNAVAILABLE : queue.getName().toString()),
                                                                         reason);
         }
      }
   }

   /**
    * Before a bridge is deployed
    *
    * @param config The bridge configuration
    * @throws ActiveMQException
    */
   @Override
   public void beforeDeployBridge(BridgeConfiguration config) throws ActiveMQException {
      if (logAll || logInternalEvents) {
         LoggingActiveMQServerPluginLogger.LOGGER.beforeDeployBridge(config);
      }
   }

   /**
    * After a bridge has been deployed
    *
    * @param bridge The newly deployed bridge
    * @throws ActiveMQException
    */
   @Override
   public void afterDeployBridge(Bridge bridge) throws ActiveMQException {
      if (logAll || logInternalEvents) {
         LoggingActiveMQServerPluginLogger.LOGGER.afterDeployBridge(bridge);
      }
   }

   /**
    * A Critical failure has been detected.
    * This will be called before the broker is stopped
    *
    * @param components
    * @throws ActiveMQException
    */
   @Override
   public void criticalFailure(CriticalComponent components) throws ActiveMQException {
      if (logAll || logInternalEvents) {
         LoggingActiveMQServerPluginLogger.LOGGER.criticalFailure(components);
      }
   }

   /**
    * dump the configuration of the logging Plugin
    */
   private void dumpConfiguration() {
      if (LoggingActiveMQServerPluginLogger.LOGGER.isDebugEnabled()) {
         LoggingActiveMQServerPluginLogger.LOGGER.debug("LoggingPlugin logAll=" + logAll);
         LoggingActiveMQServerPluginLogger.LOGGER.debug("LoggingPlugin logConnectionEvents=" + logConnectionEvents);
         LoggingActiveMQServerPluginLogger.LOGGER.debug("LoggingPlugin logSessionEvents=" + logSessionEvents);
         LoggingActiveMQServerPluginLogger.LOGGER.debug("LoggingPlugin logConsumerEvents=" + logConsumerEvents);
         LoggingActiveMQServerPluginLogger.LOGGER.debug("LoggingPlugin logSendingEvents=" + logSendingEvents);
         LoggingActiveMQServerPluginLogger.LOGGER.debug("LoggingPlugin logDeliveringEvents=" + logDeliveringEvents);
         LoggingActiveMQServerPluginLogger.LOGGER.debug("LoggingPlugin logInternalEvents=" + logInternalEvents);
      }

   }

}


<|start_filename|>tests/performance-jmh/src/main/java/org/apache/activemq/artemis/tests/performance/jmh/ConcurrentAppendOnlyChunkListLookupBenchmark.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.performance.jmh;

import org.apache.activemq.artemis.utils.collections.ConcurrentAppendOnlyChunkedList;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;

@State(Scope.Benchmark)
@Fork(2)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 8, time = 1)
public class ConcurrentAppendOnlyChunkListLookupBenchmark {

   private static final Integer MSG = 0;

   @Param({"1000", "10000"})
   int size;

   @Param({"32"})
   int chunkSize;

   private ConcurrentAppendOnlyChunkedList<Integer> list;

   @Setup
   public void init() {
      list = new ConcurrentAppendOnlyChunkedList<>(chunkSize);
      for (int i = 0; i < size; i++) {
         list.add(MSG);
      }
   }

   @State(Scope.Thread)
   public static class Index {

      private int size;
      private int index;

      @Setup
      public void init(ConcurrentAppendOnlyChunkListLookupBenchmark benchmark) {
         index = 0;
         size = benchmark.size;
      }

      public int next() {
         index++;
         if (index == size) {
            index = 0;
            return 0;
         }
         return index;
      }
   }

   @Benchmark
   public Integer lookup(Index index) {
      return list.get(index.next());
   }

}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/paging/AmqpPageTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.amqp.paging;

import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.paging.impl.Page;
import org.apache.activemq.artemis.core.paging.impl.PagedMessageImpl;
import org.apache.activemq.artemis.core.persistence.StorageManager;
import org.apache.activemq.artemis.protocol.amqp.broker.AMQPLargeMessage;
import org.apache.activemq.artemis.protocol.amqp.broker.AMQPStandardMessage;
import org.apache.activemq.artemis.tests.integration.amqp.AmqpTestSupport;
import org.apache.activemq.artemis.tests.unit.core.paging.impl.PageTest;
import org.apache.activemq.transport.amqp.client.AmqpMessage;
import org.apache.qpid.proton.message.impl.MessageImpl;

public class AmqpPageTest extends PageTest {

   private static MessageImpl createProtonMessage(String address, byte[] content) {
      AmqpMessage message = new AmqpMessage();
      message.setBytes(content);
      message.setAddress(address);
      message.setDurable(true);
      MessageImpl protonMessage = (MessageImpl) message.getWrappedMessage();
      return protonMessage;
   }

   private static AMQPStandardMessage createStandardMessage(SimpleString address, long msgId, byte[] content) {
      MessageImpl protonMessage = createProtonMessage(address.toString(), content);
      AMQPStandardMessage amqpMessage = AmqpTestSupport.encodeAndDecodeMessage(0, protonMessage, content.length + 1000);
      amqpMessage.setMessageID(msgId);
      return amqpMessage;
   }

   private static AMQPLargeMessage createLargeMessage(StorageManager storageManager,
                                                      SimpleString address,
                                                      long msgId,
                                                      byte[] content) throws Exception {
      final AMQPLargeMessage amqpMessage = new AMQPLargeMessage(msgId, 0, null, null, storageManager);
      amqpMessage.setAddress(address);
      amqpMessage.setFileDurable(true);
      amqpMessage.addBytes(content);
      amqpMessage.reloadExpiration(0);
      return amqpMessage;
   }

   @Override
   protected void writeMessage(StorageManager storageManager,
                               boolean isLargeMessage,
                               long msgID,
                               SimpleString address,
                               byte[] content,
                               Page page) throws Exception {
      if (!isLargeMessage) {
         final Message message = createStandardMessage(address, msgID, content);
         page.write(new PagedMessageImpl(message, new long[0]));
      } else {
         final AMQPLargeMessage message = createLargeMessage(storageManager, address, msgID, content);
         page.write(new PagedMessageImpl(message, new long[0]));
         message.releaseResources(false, false);
      }
   }
}


<|start_filename|>artemis-commons/src/main/java/org/apache/activemq/artemis/api/core/ObjLongPair.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.api.core;

import java.io.Serializable;
import java.util.Objects;

/**
 * A Pair is a holder for 1 object and 'a' being greater or equal than 0.
 * <p>
 * This is a utility class.
 */
public class ObjLongPair<A> implements Serializable {

   private static final long serialVersionUID = 7749478219139339853L;

   public static final long NIL = -1;

   public ObjLongPair(final A a, final long b) {
      this.a = a;
      this.b = b;
      if (b < 0 && b != NIL) {
         throw new IllegalStateException("b must be >= 0 or == NIL = " + NIL);
      }
   }

   public ObjLongPair(final A a) {
      this.a = a;
      this.b = NIL;
   }

   private A a;
   private long b;

   @Override
   public int hashCode() {
      if (a == null && b == NIL) {
         return super.hashCode();
      }
      // it's ok to use b to compute hashCode although NIL
      return (a == null ? 0 : a.hashCode()) + 37 * Long.hashCode(b);
   }

   @Override
   public boolean equals(final Object other) {
      if (other == this) {
         return true;
      }

      if (other instanceof ObjLongPair == false) {
         return false;
      }

      ObjLongPair<A> pother = (ObjLongPair<A>) other;

      return (Objects.equals(pother.a, a)) && (pother.b == b);
   }

   @Override
   public String toString() {
      return "ObjLongPair[a=" + a + ", b=" + (b == NIL ? "NIL" : b) + "]";
   }

   public void setA(A a) {
      if (this.a == a) {
         return;
      }
      this.a = a;
   }

   public A getA() {
      return a;
   }

   public void setB(long b) {
      if (b < 0 && b != NIL) {
         throw new IllegalStateException("b must be >= 0 or == NIL = " + NIL);
      }
      this.b = b;
   }

   public long getB() {
      return b;
   }
}


<|start_filename|>artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/converter/coreWrapper/CoreMessageWrapper.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.protocol.amqp.converter.coreWrapper;


import java.util.Collections;
import java.util.Enumeration;
import java.util.Map;

import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.ICoreMessage;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.protocol.amqp.converter.AMQPMessageSupport;
import org.apache.activemq.artemis.reader.MessageUtil;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.messaging.AmqpValue;
import org.apache.qpid.proton.amqp.messaging.Properties;
import org.apache.qpid.proton.amqp.messaging.Section;
import org.jboss.logging.Logger;

import static org.apache.activemq.artemis.api.core.FilterConstants.NATIVE_MESSAGE_ID;
import static org.apache.activemq.artemis.api.core.Message.BYTES_TYPE;
import static org.apache.activemq.artemis.api.core.Message.MAP_TYPE;
import static org.apache.activemq.artemis.api.core.Message.OBJECT_TYPE;
import static org.apache.activemq.artemis.api.core.Message.STREAM_TYPE;
import static org.apache.activemq.artemis.api.core.Message.TEXT_TYPE;

import static org.apache.activemq.artemis.protocol.amqp.converter.AMQPMessageSupport.AMQP_UNKNOWN;
import static org.apache.activemq.artemis.protocol.amqp.converter.AMQPMessageSupport.JMS_AMQP_ORIGINAL_ENCODING;
import static org.apache.activemq.artemis.protocol.amqp.converter.AMQPMessageSupport.NON_PERSISTENT;
import static org.apache.activemq.artemis.protocol.amqp.converter.AMQPMessageSupport.PERSISTENT;

public class CoreMessageWrapper {
   private static final Logger logger = Logger.getLogger(CoreMessageWrapper.class);

   protected final ICoreMessage message;
   private ActiveMQBuffer readBodyBuffer;

   public CoreMessageWrapper(ICoreMessage message) {
      this.message = message;
   }

   public static CoreMessageWrapper wrap(ICoreMessage wrapped) {
      switch (wrapped.getType()) {
         case STREAM_TYPE:
            return new CoreStreamMessageWrapper(wrapped);
         case BYTES_TYPE:
            return new CoreBytesMessageWrapper(wrapped);
         case MAP_TYPE:
            return new CoreMapMessageWrapper(wrapped);
         case TEXT_TYPE:
            return new CoreTextMessageWrapper(wrapped);
         case OBJECT_TYPE:
            return new CoreObjectMessageWrapper(wrapped);
         default:
            return new CoreMessageWrapper(wrapped);
      }
   }

   protected short getOrignalEncoding() {
      short orignalEncoding = AMQP_UNKNOWN;

      try {
         orignalEncoding = message.getShortProperty(JMS_AMQP_ORIGINAL_ENCODING);
      } catch (Exception ex) {
         logger.debug(ex.getMessage(), ex);
      // Ignore and stick with UNKNOWN
      }
      return orignalEncoding;
   }


   // returns the AMQP Section for the message type
   public Section createAMQPSection(Map<Symbol, Object> maMap, Properties properties) throws ConversionException {
      maMap.put(AMQPMessageSupport.JMS_MSG_TYPE, AMQPMessageSupport.JMS_MESSAGE);
      // If this is not an AMQP message that was converted then the original encoding
      // will be unknown so we check for special cases of messages with special data
      // encoded into the server message body.
      ICoreMessage internalMessage = this.getInnerMessage();

      // this will represent a readOnly buffer for the message
      ActiveMQBuffer buffer = internalMessage.getDataBuffer();
      try {
         // the buffer may be completely empty (e.g. if the original AMQP message had a null body)
         if (buffer.readableBytes() > 0) {
            Object s = buffer.readNullableSimpleString();
            if (s != null) {
               return new AmqpValue(s.toString());
            }
         }

         return null;
      } catch (Throwable e) {
         logger.debug("Exception ignored during conversion", e.getMessage(), e);
         return new AmqpValue("Conversion to AMQP error: " + e.getMessage());
      }

   }

   public ICoreMessage getInnerMessage() {
      return message;
   }

   /**
    * When reading we use a protected copy so multi-threads can work fine
    */
   protected ActiveMQBuffer getReadBodyBuffer() {
      if (readBodyBuffer == null) {
         // to avoid clashes between multiple threads
         readBodyBuffer = message.getDataBuffer();
      }
      return readBodyBuffer;
   }

   /**
    * When writing on the conversion we use the buffer directly
    */
   protected ActiveMQBuffer getWriteBodyBuffer() {
      readBodyBuffer = null; // it invalidates this buffer if anything is written
      return message.getBodyBuffer();
   }

   public final String getJMSMessageID()  {
      if (message.containsProperty(NATIVE_MESSAGE_ID)) {
         return getStringProperty(NATIVE_MESSAGE_ID);
      }
      return null;
   }

   public final void setJMSMessageID(String id)  {
      if (id != null) {
         message.putStringProperty(NATIVE_MESSAGE_ID, id);
      }
   }

   public final long getJMSTimestamp()  {
      return message.getTimestamp();
   }

   public final void setJMSTimestamp(long timestamp)  {
      message.setTimestamp(timestamp);
   }

   public final byte[] getJMSCorrelationIDAsBytes()  {
      return MessageUtil.getJMSCorrelationIDAsBytes(message);
   }

   public final void setJMSCorrelationIDAsBytes(byte[] correlationID)  {
      message.setCorrelationID(correlationID);
   }

   public final String getJMSCorrelationID()  {

      Object correlationID = message.getCorrelationID();
      if (correlationID instanceof String) {

         return ((String) correlationID);
      } else if (correlationID != null) {
         return String.valueOf(correlationID);
      } else {
         return null;
      }
   }

   public final void setJMSCorrelationID(String correlationID)  {
      message.setCorrelationID(correlationID);
   }

   public final SimpleString getJMSReplyTo()  {
      return MessageUtil.getJMSReplyTo(message);
   }

   public final void setJMSReplyTo(String replyTo)  {
      MessageUtil.setJMSReplyTo(message, SimpleString.toSimpleString(replyTo));
   }

   public SimpleString getDestination()  {
      if (message.getAddress() == null || message.getAddress().isEmpty()) {
         return null;
      }
      return SimpleString.toSimpleString(AMQPMessageSupport.destination(message.getRoutingType(), message.getAddress()));
   }

   public final void setDestination(String destination)  {
      message.setAddress(destination);
   }

   public final int getJMSDeliveryMode()  {
      return message.isDurable() ? PERSISTENT : NON_PERSISTENT;
   }

   public final void setDeliveryMode(int deliveryMode) throws ConversionException {
      switch (deliveryMode) {
         case PERSISTENT:
            message.setDurable(true);
            break;
         case NON_PERSISTENT:
            message.setDurable(false);
            break;
         default:
            // There shouldn't be any other values used
            throw new ConversionException("Invalid mode " + deliveryMode);
      }
   }


   public final String getJMSType()  {
      return MessageUtil.getJMSType(message);
   }

   public final void setJMSType(String type)  {
      MessageUtil.setJMSType(message, type);
   }

   public final long getExpiration()  {
      return message.getExpiration();
   }

   public final void setJMSExpiration(long expiration)  {
      message.setExpiration(expiration);
   }


   public final int getJMSPriority()  {
      return message.getPriority();
   }

   public final void setJMSPriority(int priority)  {
      message.setPriority((byte) priority);
   }

   public final void clearProperties()  {
      MessageUtil.clearProperties(message);

   }

   public final boolean propertyExists(String name)  {
      return MessageUtil.propertyExists(message, name);
   }

   public final boolean getBooleanProperty(String name)  {
      return message.getBooleanProperty(name);
   }

   public final byte getByteProperty(String name)  {
      return message.getByteProperty(name);
   }

   public final short getShortProperty(String name)  {
      return message.getShortProperty(name);
   }

   public final int getIntProperty(String name)  {
      return MessageUtil.getIntProperty(message, name);
   }

   public final long getLongProperty(String name)  {
      return MessageUtil.getLongProperty(message, name);
   }

   public final float getFloatProperty(String name)  {
      return message.getFloatProperty(name);
   }

   public final double getDoubleProperty(String name)  {
      return message.getDoubleProperty(name);
   }

   public final String getStringProperty(String name)  {
      return MessageUtil.getStringProperty(message, name);
   }

   public final Object getObjectProperty(String name)  {
      return MessageUtil.getObjectProperty(message, name);
   }

   public final Enumeration getPropertyNames()  {
      return Collections.enumeration(MessageUtil.getPropertyNames(message));
   }

   public final void setBooleanProperty(String name, boolean value)  {
      message.putBooleanProperty(name, value);
   }

   public final void setByteProperty(String name, byte value)  {
      message.putByteProperty(name, value);
   }

   public final void setShortProperty(String name, short value)  {
      message.putShortProperty(name, value);
   }

   public final void setIntProperty(String name, int value)  {
      MessageUtil.setIntProperty(message, name, value);
   }

   public final void setLongProperty(String name, long value)  {
      MessageUtil.setLongProperty(message, name, value);
   }

   public final void setFloatProperty(String name, float value)  {
      message.putFloatProperty(name, value);
   }

   public final void setDoubleProperty(String name, double value)  {
      message.putDoubleProperty(name, value);
   }

   public final void setStringProperty(String name, String value)  {
      MessageUtil.setStringProperty(message, name, value);
   }

   public final void setObjectProperty(String name, Object value) {
      MessageUtil.setObjectProperty(message, name, value);
   }


   public void clearBody() {
      message.getBodyBuffer().clear();
   }

   /**
    * Encode the body into the internal message
    */
   public void encode() {
      if (!message.isLargeMessage()) {
         message.getBodyBuffer().resetReaderIndex();
      }
   }

   public void decode() {
      if (!message.isLargeMessage()) {
         message.getBodyBuffer().resetReaderIndex();
      }
   }

}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/security/BasicSecurityManagerFailoverTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.security;

import java.util.Arrays;
import java.util.Collection;

import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.core.config.ha.SharedStoreMasterPolicyConfiguration;
import org.apache.activemq.artemis.core.config.ha.SharedStoreSlavePolicyConfiguration;
import org.apache.activemq.artemis.spi.core.security.ActiveMQBasicSecurityManager;
import org.apache.activemq.artemis.tests.integration.cluster.failover.FailoverTestBase;
import org.apache.activemq.artemis.tests.util.ReplicatedBackupUtils;
import org.apache.activemq.artemis.tests.util.TransportConfigurationUtils;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(value = Parameterized.class)
public class BasicSecurityManagerFailoverTest extends FailoverTestBase {

   private boolean replicated;

   @Parameterized.Parameters(name = "replicated={0}")
   public static Collection getParameters() {
      return Arrays.asList(new Object[][]{{true}, {false}});
   }

   public BasicSecurityManagerFailoverTest(boolean replicated) {
      this.replicated = replicated;
   }

   @Override
   protected void createConfigs() throws Exception {
      if (replicated) {
         createReplicatedConfigs();
      } else {
         createSharedStoreConfigs();
      }
   }

   protected void createSharedStoreConfigs() throws Exception {
      nodeManager = createNodeManager();
      TransportConfiguration liveConnector = getConnectorTransportConfiguration(true);
      TransportConfiguration backupConnector = getConnectorTransportConfiguration(false);

      backupConfig = super
         .createDefaultInVMConfig()
         .setSecurityEnabled(true)
         .clearAcceptorConfigurations()
         .addAcceptorConfiguration(getAcceptorTransportConfiguration(false))
         .setHAPolicyConfiguration(new SharedStoreSlavePolicyConfiguration())
         .addConnectorConfiguration(liveConnector.getName(), liveConnector)
         .addConnectorConfiguration(backupConnector.getName(), backupConnector)
         .addClusterConfiguration(createBasicClusterConfig(backupConnector.getName(), liveConnector.getName()));

      backupServer = createTestableServer(backupConfig);

      backupServer.getServer().setSecurityManager(new ActiveMQBasicSecurityManager());

      liveConfig = super
         .createDefaultInVMConfig()
         .setSecurityEnabled(true)
         .clearAcceptorConfigurations()
         .addAcceptorConfiguration(getAcceptorTransportConfiguration(true))
         .setHAPolicyConfiguration(new SharedStoreMasterPolicyConfiguration())
         .addClusterConfiguration(createBasicClusterConfig(liveConnector.getName()))
         .addConnectorConfiguration(liveConnector.getName(), liveConnector);

      liveServer = createTestableServer(liveConfig);

      liveServer.getServer().setSecurityManager(new ActiveMQBasicSecurityManager());
   }

   @Override
   protected void createReplicatedConfigs() throws Exception {
      final TransportConfiguration liveConnector = getConnectorTransportConfiguration(true);
      final TransportConfiguration backupConnector = getConnectorTransportConfiguration(false);
      final TransportConfiguration backupAcceptor = getAcceptorTransportConfiguration(false);

      backupConfig = createDefaultInVMConfig();
      liveConfig = createDefaultInVMConfig();

      ReplicatedBackupUtils.configureReplicationPair(backupConfig, backupConnector, backupAcceptor, liveConfig, liveConnector, null);

      backupConfig
         .setSecurityEnabled(true)
         .setBindingsDirectory(getBindingsDir(0, true))
         .setJournalDirectory(getJournalDir(0, true))
         .setPagingDirectory(getPageDir(0, true))
         .setLargeMessagesDirectory(getLargeMessagesDir(0, true));

      setupHAPolicyConfiguration();
      nodeManager = createReplicatedBackupNodeManager(backupConfig);

      backupServer = createTestableServer(backupConfig);

      backupServer.getServer().setSecurityManager(new ActiveMQBasicSecurityManager());

      liveConfig
         .setSecurityEnabled(true)
         .clearAcceptorConfigurations()
         .addAcceptorConfiguration(getAcceptorTransportConfiguration(true));

      liveServer = createTestableServer(liveConfig);

      liveServer.getServer().setSecurityManager(new ActiveMQBasicSecurityManager());
   }

   @Override
   protected TransportConfiguration getAcceptorTransportConfiguration(final boolean live) {
      return TransportConfigurationUtils.getInVMAcceptor(live);
   }

   @Override
   protected TransportConfiguration getConnectorTransportConfiguration(final boolean live) {
      return TransportConfigurationUtils.getInVMConnector(live);
   }

   @Test
   public void testFailover() throws Exception {

      liveServer.getServer().getActiveMQServerControl().addUser("foo", "bar", "baz", false);

      ClientSessionFactory cf = createSessionFactory(getServerLocator());
      ClientSession session = null;

      try {
         session = cf.createSession("foo", "bar", false, true, true, false, 0);
      } catch (ActiveMQException e) {
         e.printStackTrace();
         Assert.fail("should not throw exception");
      }

      crash(session);
      waitForServerToStart(backupServer.getServer());

      try {
         cf = createSessionFactory(getServerLocator());
         session = cf.createSession("foo", "bar", false, true, true, false, 0);
      } catch (ActiveMQException e) {
         e.printStackTrace();
         Assert.fail("should not throw exception");
      }
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/bridge/BridgeRoutingTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.bridge;

import java.util.Arrays;
import java.util.Collection;

import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.config.BridgeConfiguration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.ComponentConfigurationRoutingType;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.tests.util.Wait;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(value = Parameterized.class)
public class BridgeRoutingTest extends ActiveMQTestBase {

   private ActiveMQServer server0;
   private ActiveMQServer server1;

   private final boolean netty;

   @Parameterized.Parameters(name = "isNetty={0}")
   public static Collection getParameters() {
      return Arrays.asList(new Object[][]{{true}, {false}});
   }

   public BridgeRoutingTest(boolean isNetty) {
      this.netty = isNetty;
   }

   protected boolean isNetty() {
      return netty;
   }

   private String getServer0URL() {
      return isNetty() ? "tcp://localhost:61616" : "vm://0";
   }

   private String getServer1URL() {
      return isNetty() ? "tcp://localhost:61617" : "vm://1";
   }

   @Override
   @Before
   public void setUp() throws Exception {
      super.setUp();
      server0 = createServer(false, createBasicConfig());
      server1 = createServer(false, createBasicConfig());
      server0.getConfiguration().addAcceptorConfiguration("acceptor", getServer0URL());
      server0.getConfiguration().addConnectorConfiguration("connector", getServer1URL());
      server1.getConfiguration().addAcceptorConfiguration("acceptor", getServer1URL());
      server0.start();
      server1.start();
   }

   @Test
   public void testAnycastBridge() throws Exception {
      testBridgeInternal(RoutingType.MULTICAST, RoutingType.ANYCAST, ComponentConfigurationRoutingType.ANYCAST, 0, 1);
   }

   @Test
   public void testAnycastBridgeNegative() throws Exception {
      testBridgeInternal(RoutingType.MULTICAST, RoutingType.ANYCAST, ComponentConfigurationRoutingType.PASS, 500, 0);
   }

   @Test
   public void testMulticastBridge() throws Exception {
      testBridgeInternal(RoutingType.ANYCAST, RoutingType.MULTICAST, ComponentConfigurationRoutingType.MULTICAST, 0, 1);
   }

   @Test
   public void testMulticastBridgeNegative() throws Exception {
      testBridgeInternal(RoutingType.ANYCAST, RoutingType.MULTICAST, ComponentConfigurationRoutingType.PASS, 500, 0);
   }

   @Test
   public void testPassBridge() throws Exception {
      testBridgeInternal(RoutingType.MULTICAST, RoutingType.MULTICAST, ComponentConfigurationRoutingType.PASS, 0, 1);
   }

   @Test
   public void testPassBridge2() throws Exception {
      testBridgeInternal(RoutingType.ANYCAST, RoutingType.ANYCAST, ComponentConfigurationRoutingType.PASS, 0, 1);
   }

   @Test
   public void testPassBridgeNegative() throws Exception {
      testBridgeInternal(RoutingType.ANYCAST, RoutingType.MULTICAST, ComponentConfigurationRoutingType.PASS, 500, 0);
   }

   @Test
   public void testStripBridge() throws Exception {
      testBridgeInternal(RoutingType.MULTICAST, RoutingType.ANYCAST, ComponentConfigurationRoutingType.STRIP, 0, 1);
   }

   @Test
   public void testStripBridge2() throws Exception {
      testBridgeInternal(RoutingType.ANYCAST, RoutingType.MULTICAST, ComponentConfigurationRoutingType.STRIP, 0, 1);
   }

   private void testBridgeInternal(RoutingType sourceRoutingType,
                                   RoutingType destinationRoutingType,
                                   ComponentConfigurationRoutingType bridgeRoutingType,
                                   long sleepTime,
                                   int destinationMessageCount) throws Exception {
      SimpleString source = SimpleString.toSimpleString("source");
      SimpleString destination = SimpleString.toSimpleString("destination");
      int concurrency = 2;

      server0.createQueue(new QueueConfiguration(source).setRoutingType(sourceRoutingType));
      server1.createQueue(new QueueConfiguration(destination).setRoutingType(destinationRoutingType));

      server0.deployBridge(new BridgeConfiguration()
                              .setRoutingType(bridgeRoutingType)
                              .setName("bridge")
                              .setForwardingAddress(destination.toString())
                              .setQueueName(source.toString())
                              .setConfirmationWindowSize(10)
                              .setConcurrency(concurrency)
                              .setStaticConnectors(Arrays.asList("connector")));

      try (ServerLocator locator = ActiveMQClient.createServerLocator(getServer0URL());
           ClientSessionFactory sessionFactory = locator.createSessionFactory();
           ClientSession session = sessionFactory.createSession();
           ClientProducer producer = session.createProducer(source)) {
         producer.send(session.createMessage(true).setRoutingType(sourceRoutingType));
      }
      Wait.waitFor(() -> server0.locateQueue(source).getMessageCount() == 0, 2000, 100);
      Wait.waitFor(() -> server0.getClusterManager().getBridges().get("bridge-0").getMetrics().getMessagesAcknowledged() == 1,2000, 100);
      Thread.sleep(sleepTime);
      assertTrue(Wait.waitFor(() -> server1.locateQueue(destination).getMessageCount() == destinationMessageCount, 2000, 100));
      assertTrue(Wait.waitFor(() -> server0.locateQueue(source).getConsumerCount() == concurrency, 2000, 100));
   }
}

<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/SharedStoreLiveActivation.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.server.impl;

import java.io.IOException;
import java.nio.channels.ClosedChannelException;

import org.apache.activemq.artemis.core.io.IOCriticalErrorListener;
import org.apache.activemq.artemis.core.server.ActivateCallback;
import org.apache.activemq.artemis.core.server.ActiveMQLockAcquisitionTimeoutException;
import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
import org.apache.activemq.artemis.core.server.NodeManager;
import org.apache.activemq.artemis.core.server.NodeManager.LockListener;
import org.apache.activemq.artemis.core.server.NodeManager.NodeManagerException;
import org.apache.activemq.artemis.core.server.cluster.ha.SharedStoreMasterPolicy;
import org.jboss.logging.Logger;

public final class SharedStoreLiveActivation extends LiveActivation {

   private static final Logger logger = Logger.getLogger(SharedStoreLiveActivation.class);

   // this is how we act when we initially start as live
   private final SharedStoreMasterPolicy sharedStoreMasterPolicy;

   private final ActiveMQServerImpl activeMQServer;

   private volatile LockListener activeLockListener;

   private volatile ActivateCallback nodeManagerActivateCallback;

   private final IOCriticalErrorListener ioCriticalErrorListener;

   public SharedStoreLiveActivation(ActiveMQServerImpl server,
                                    SharedStoreMasterPolicy sharedStoreMasterPolicy,
                                    IOCriticalErrorListener ioCriticalErrorListener) {
      this.activeMQServer = server;
      this.sharedStoreMasterPolicy = sharedStoreMasterPolicy;
      this.ioCriticalErrorListener = ioCriticalErrorListener;
   }

   @Override
   public void run() {
      try {
         ActiveMQServerLogger.LOGGER.awaitingLiveLock();

         activeMQServer.checkJournalDirectory();

         if (logger.isDebugEnabled()) {
            logger.debug("First part initialization on " + this);
         }

         if (!activeMQServer.initialisePart1(false))
            return;

         if (activeMQServer.getNodeManager().isBackupLive()) {
            /*
             * looks like we've failed over at some point need to inform that we are the
             * backup so when the current live goes down they failover to us
             */
            if (logger.isDebugEnabled()) {
               logger.debug("announcing backup to the former live" + this);
            }
            activeMQServer.getBackupManager().start();

            if (!sharedStoreMasterPolicy.isWaitForActivation())
               activeMQServer.setState(ActiveMQServerImpl.SERVER_STATE.STARTED);

            activeMQServer.getBackupManager().announceBackup();
         }

         registerActiveLockListener(activeMQServer.getNodeManager());
         nodeManagerActivateCallback = activeMQServer.getNodeManager().startLiveNode();
         activeMQServer.registerActivateCallback(nodeManagerActivateCallback);

         if (activeMQServer.getState() == ActiveMQServerImpl.SERVER_STATE.STOPPED
               || activeMQServer.getState() == ActiveMQServerImpl.SERVER_STATE.STOPPING) {
            return;
         }

         activeMQServer.initialisePart2(false);

         activeMQServer.completeActivation(false);

         ActiveMQServerLogger.LOGGER.serverIsLive();
      } catch (NodeManagerException nodeManagerException) {
         if (nodeManagerException.getCause() instanceof ClosedChannelException) {
            // this is ok, we are being stopped
            return;
         }
         if (nodeManagerException.getCause() instanceof ActiveMQLockAcquisitionTimeoutException) {
            onActivationFailure((ActiveMQLockAcquisitionTimeoutException) nodeManagerException.getCause());
            return;
         }
         unregisterActiveLockListener(activeMQServer.getNodeManager());
         ioCriticalErrorListener.onIOException(nodeManagerException, nodeManagerException.getMessage(), null);
      } catch (Exception e) {
         onActivationFailure(e);
      }
   }

   private void onActivationFailure(Exception e) {
      unregisterActiveLockListener(activeMQServer.getNodeManager());
      ActiveMQServerLogger.LOGGER.initializationError(e);
      activeMQServer.callActivationFailureListeners(e);
   }

   private void registerActiveLockListener(NodeManager nodeManager) {
      LockListener lockListener = () ->
         ioCriticalErrorListener.onIOException(new IOException("lost lock"), "Lost NodeManager lock", null);
      activeLockListener = lockListener;
      nodeManager.registerLockListener(lockListener);
   }

   private void unregisterActiveLockListener(NodeManager nodeManager) {
      LockListener activeLockListener = this.activeLockListener;
      if (activeLockListener != null) {
         nodeManager.unregisterLockListener(activeLockListener);
         this.activeLockListener = null;
      }
   }

   @Override
   public void close(boolean permanently, boolean restarting) throws Exception {
      // TO avoid a NPE from stop
      NodeManager nodeManagerInUse = activeMQServer.getNodeManager();

      if (nodeManagerInUse != null) {
         unregisterActiveLockListener(nodeManagerInUse);
         ActivateCallback activateCallback = nodeManagerActivateCallback;
         if (activateCallback != null) {
            activeMQServer.unregisterActivateCallback(activateCallback);
         }
         if (sharedStoreMasterPolicy.isFailoverOnServerShutdown() || permanently) {
            try {
               nodeManagerInUse.crashLiveServer();
            } catch (Throwable t) {
               if (!permanently) {
                  throw t;
               }
               logger.warn("Errored while closing activation: can be ignored because of permanent close", t);
            }
         } else {
            nodeManagerInUse.pauseLiveServer();
         }

      }
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jdbc/store/journal/ShutdownServerTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.jdbc.store.journal;

import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.persistence.impl.journal.JournalStorageManager;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.jdbc.store.journal.JDBCJournalImpl;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.tests.util.Wait;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class ShutdownServerTest extends ActiveMQTestBase {

   private ActiveMQServer server;

   private final SimpleString QUEUE = new SimpleString("ConsumerTestQueue");

   private ServerLocator locator;

   @Before
   @Override
   public void setUp() throws Exception {
      super.setUp();

      server = createServer(true, createDefaultJDBCConfig(false), AddressSettings.DEFAULT_PAGE_SIZE, AddressSettings.DEFAULT_MAX_SIZE_BYTES);
      server.start();

      locator = createFactory(false);
   }

   @Test
   public void testShutdownServer() throws Throwable {
      ClientSessionFactory sf = createSessionFactory(locator);

      ClientSession session = sf.createSession(false, true, true, false);

      session.createQueue(new QueueConfiguration(QUEUE));

      ClientConsumer consumer = session.createConsumer(QUEUE);

      ClientProducer producer = session.createProducer(QUEUE);
      ClientMessage message = session.createMessage(Message.TEXT_TYPE, true, 0, System.currentTimeMillis(), (byte) 4);
      message.getBodyBuffer().writeString("hi");
      message.putStringProperty("hello", "elo");
      producer.send(message);

      ActiveMQServerImpl impl = (ActiveMQServerImpl) server;
      JournalStorageManager journal = (JournalStorageManager) impl.getStorageManager();
      JDBCJournalImpl journalimpl = (JDBCJournalImpl) journal.getMessageJournal();
      journalimpl.handleException(null, new Exception("failure"));

      Wait.waitFor(() -> !server.isStarted());

      Assert.assertFalse(server.isStarted());

   }

}


<|start_filename|>artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/components/tree.js<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 /// <reference path="tree.component.ts"/>
var Artemis;
(function (Artemis) {
    Artemis._module.component('artemisTreeHeader', {
            template:
                `<div class="tree-nav-sidebar-header">
                  <form role="form" class="search-pf has-button">
                    <div class="form-group has-clear">
                      <div class="search-pf-input-group">
                        <label for="input-search" class="sr-only">Search Tree:</label>
                        <input id="input-search" type="search" class="form-control" placeholder="Search tree:"
                          ng-model="$ctrl.filter">
                        <button type="button" class="clear" aria-hidden="true"
                          ng-hide="$ctrl.filter.length === 0"
                          ng-click="$ctrl.filter = ''">
                          <span class="pficon pficon-close"></span>
                        </button>
                      </div>
                    </div>
                    <div class="form-group tree-nav-buttons">
                      <span class="badge" ng-class="{positive: $ctrl.result.length > 0}"
                        ng-show="$ctrl.filter.length > 0">
                        {{$ctrl.result.length}}
                      </span>
                      <i class="fa fa-plus-square-o" title="Expand All" ng-click="$ctrl.expandAll()"></i>
                      <i class="fa fa-minus-square-o" title="Collapse All" ng-click="$ctrl.contractAll()"></i>
                    </div>
                  </form>
                </div>
            `,
            controller: TreeHeaderController
        })
        .component('artemisTree', {
              template:
              `<div class="tree-nav-sidebar-content">
                  <div id="artemistree" class="treeview-pf-hover treeview-pf-select"></div>
              </div>
              `,
              controller: TreeController
        })
        .name;
    treeElementId = '#artemistree';
    Artemis.log.debug("loaded tree" + Artemis.treeModule);


    function TreeHeaderController($scope, $element) {
        'ngInject';
        Artemis.log.debug("TreeHeaderController ");
        this.$scope = $scope;
        this.$element = $element;
        this.filter = '';
        this.result = [];
        // it's not possible to declare classes to the component host tag in AngularJS
        $element.addClass('tree-nav-sidebar-header');

        TreeHeaderController.prototype.$onInit = function () {
        Artemis.log.debug("TreeHeaderController init");
            var _this = this;
            this.$scope.$watch(angular.bind(this, function () { return _this.filter; }), function (filter, previous) {
                if (filter !== previous) {
                    _this.search(filter);
                }
            });
        };

        TreeHeaderController.prototype.search = function (filter) {
                Artemis.log.debug("TreeHeaderController search");
            var _this = this;
            var doSearch = function (filter) {
                var result = _this.tree().search(filter, {
                    ignoreCase: true,
                    exactMatch: false,
                    revealResults: true
                });
                _this.result.length = 0;
                (_a = _this.result).push.apply(_a, result);
                Core.$apply(_this.$scope);
                var _a;
            };
            _.debounce(doSearch, 300, { leading: false, trailing: true })(filter);
        };

        TreeHeaderController.prototype.tree = function () {
                Artemis.log.debug("TreeHeaderController tree");
            return $(treeElementId).treeview(true);
        };

        TreeHeaderController.prototype.expandAll = function () {
                Artemis.log.debug("TreeHeaderController expand");
            return this.tree()
                .expandNode(this.tree().getNodes(), { levels: HawtioTree.getMaxTreeLevel(this.tree()), silent: true });
        };

        TreeHeaderController.prototype.contractAll = function () {
                Artemis.log.debug("TreeHeaderController contract");
            return this.tree()
                .collapseNode(this.tree().getNodes(), { ignoreChildren: true, silent: true });
        };
    }
    TreeHeaderController.$inject = ['$scope', '$element'];

    function TreeController($scope, $location, workspace, $element) {
        'ngInject';
        this.$scope = $scope;
        this.$location = $location;
        this.workspace = workspace;
        this.$element = $element;
        // it's not possible to declare classes to the component host tag in AngularJS
        $element.addClass('tree-nav-sidebar-content');
        Artemis.log.debug("TreeController ");
        var artemisJmxDomain = localStorage['artemisJmxDomain'] || "org.apache.activemq.artemis";
        TreeController.prototype.$onInit = function () {
        Artemis.log.debug("TreeController onInit");
            var _this = this;
            this.$scope.$on('$destroy', function () { return _this.removeTree(); });
            this.$scope.$on('$routeChangeStart', function () { return Jmx.updateTreeSelectionFromURL(_this.$location, $(treeElementId)); });
            this.$scope.$on('jmxTreeUpdated', function () { return _this.populateTree(); });
            this.populateTree();
        };
        TreeController.prototype.updateSelectionFromURL = function () {
            Jmx.updateTreeSelectionFromURLAndAutoSelect(this.$location, $(treeElementId), function (first) {
                if (first.children == null) {
                    return null;
                }
                // use function to auto select the queue folder on the 1st broker
                var queues = first.children[0];
                if (queues && queues.text === 'Queue') {
                    return queues;
                }
                return null;
            }, true);
        };
        TreeController.prototype.populateTree = function () {
            var _this = this;
            var children = [];
            var tree = this.workspace.tree;
            Artemis.log.debug("tree= "+tree);
            if (tree) {
                var domainName = artemisJmxDomain;
                var folder = tree.get(domainName);

                if (folder) {
                    children = folder.children;
                }
                angular.forEach(children,  function(child) {
                    Artemis.log.debug("child=" + child.text + " " + child.id);
                });
                var treeElement = $("#artemistree");
                this.removeTree();
                Jmx.enableTree(this.$scope, this.$location, this.workspace, $(treeElementId), children);
                this.updateSelectionFromURL();
            }
        };
        TreeController.prototype.removeTree = function () {
            var tree = $(treeElementId).treeview(true);
            // There is no exposed API to check whether the tree has already been initialized,
            // so let's just check if the methods are presents
            if (tree.clearSearch) {
                tree.clearSearch();
                // Bootstrap tree view leaks the node elements into the data structure
                // so let's clean this up when the user leaves the view
                var cleanTreeFolder_1 = function (node) {
                    delete node['$el'];
                    if (node.nodes)
                        node.nodes.forEach(cleanTreeFolder_1);
                };
                cleanTreeFolder_1(this.workspace.tree);
                // Then call the tree clean-up method
                tree.remove();
            }
        }
    }
    TreeController.$inject = ['$scope', '$location', 'workspace', '$element'];

})(Artemis || (Artemis = {}));


<|start_filename|>artemis-protocols/artemis-amqp-protocol/src/test/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPConnectionCallbackTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.protocol.amqp.broker;

import org.apache.activemq.artemis.core.remoting.impl.invm.InVMConnection;
import org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl;
import org.apache.activemq.artemis.protocol.amqp.sasl.AnonymousServerSASL;
import org.apache.activemq.artemis.protocol.amqp.sasl.GSSAPIServerSASL;
import org.apache.activemq.artemis.protocol.amqp.sasl.PlainSASL;
import org.junit.Test;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;

public class AMQPConnectionCallbackTest {

   @Test
   public void getServerSASLOnlyAllowedMechs() throws Exception {
      ProtonProtocolManager protonProtocolManager = new ProtonProtocolManager(new ProtonProtocolManagerFactory(), null, null, null);
      protonProtocolManager.setSaslMechanisms(new String[]{PlainSASL.NAME});
      AMQPConnectionCallback connectionCallback = new AMQPConnectionCallback(protonProtocolManager, new InVMConnection(1, null, null, null), null, new ActiveMQServerImpl());
      assertEquals(1, connectionCallback.getSaslMechanisms().length);
      for (String mech: connectionCallback.getSaslMechanisms()) {
         assertNotNull(connectionCallback.getServerSASL(mech));
      }
      assertNull("can't get mechanism not in the list", connectionCallback.getServerSASL(GSSAPIServerSASL.NAME));
   }

   @Test
   public void getServerSASLAnonDefault() throws Exception {
      ProtonProtocolManager protonProtocolManager = new ProtonProtocolManager(new ProtonProtocolManagerFactory(), null, null, null);
      protonProtocolManager.setSaslMechanisms(new String[]{});
      AMQPConnectionCallback connectionCallback = new AMQPConnectionCallback(protonProtocolManager, null, null, new ActiveMQServerImpl());
      assertNotNull("can get anon with empty list", connectionCallback.getServerSASL(AnonymousServerSASL.NAME));
   }
}

<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/paging/TestDeadlockOnPurgePagingTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.paging;

import javax.jms.Connection;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;

import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.apache.activemq.artemis.core.server.impl.QueueImpl;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.tests.util.Wait;
import org.jboss.logging.Logger;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class TestDeadlockOnPurgePagingTest extends ActiveMQTestBase {

   private static final Logger logger = Logger.getLogger(TestDeadlockOnPurgePagingTest.class);

   protected ServerLocator locator;
   protected ActiveMQServer server;
   protected ClientSessionFactory sf;
   static final int MESSAGE_SIZE = 1024; // 1k
   static final int LARGE_MESSAGE_SIZE = 100 * 1024;

   protected static final int RECEIVE_TIMEOUT = 5000;

   protected static final int PAGE_MAX = 100 * 1024;

   protected static final int PAGE_SIZE = 10 * 1024;

   static final SimpleString ADDRESS = new SimpleString("SimpleAddress");

   @Override
   @Before
   public void setUp() throws Exception {
      super.setUp();
      locator = createInVMNonHALocator();
   }

   @Test
   public void testDeadlockOnPurge() throws Exception {

      int NUMBER_OF_MESSAGES = 5000;
      clearDataRecreateServerDirs();

      Configuration config = createDefaultNettyConfig().setJournalSyncNonTransactional(false);

      server = createServer(true, config, TestDeadlockOnPurgePagingTest.PAGE_SIZE, TestDeadlockOnPurgePagingTest.PAGE_MAX);

      server.start();

      String queue = "purgeQueue";
      SimpleString ssQueue = new SimpleString(queue);
      server.addAddressInfo(new AddressInfo(ssQueue, RoutingType.ANYCAST));
      QueueImpl purgeQueue = (QueueImpl) server.createQueue(new QueueConfiguration(ssQueue).setRoutingType(RoutingType.ANYCAST).setMaxConsumers(1).setPurgeOnNoConsumers(true).setAutoCreateAddress(false));

      ActiveMQConnectionFactory cf = new ActiveMQConnectionFactory();
      Connection connection = cf.createConnection();

      connection.start();

      Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
      javax.jms.Queue jmsQueue = session.createQueue(queue);

      MessageProducer producer = session.createProducer(jmsQueue);

      for (int i = 0; i < 100; i++) {
         producer.send(session.createTextMessage("hello" + i));
      }
      session.commit();

      Wait.assertEquals(0, purgeQueue::getMessageCount);

      Wait.assertEquals(0, purgeQueue.getPageSubscription().getPagingStore()::getAddressSize);

      MessageConsumer consumer = session.createConsumer(jmsQueue);

      for (int i = 0; i < NUMBER_OF_MESSAGES / 5; i++) {
         producer.send(session.createTextMessage("hello" + i));
         if (i == 10) {
            purgeQueue.getPageSubscription().getPagingStore().startPaging();
         }

         if (i > 10 && i % 10 == 0) {
            purgeQueue.getPageSubscription().getPagingStore().forceAnotherPage();
         }
      }
      session.commit();


      for (int i = 0; i < 100; i++) {
         Message message = consumer.receive(5000);
         Assert.assertNotNull(message);
      }
      session.commit();

      consumer.close();

      Wait.assertEquals(0L, purgeQueue::getMessageCount, 5000L, 10L);

      Wait.assertFalse(purgeQueue.getPageSubscription()::isPaging, 5000L, 10L);

      Wait.assertEquals(0L, purgeQueue.getPageSubscription().getPagingStore()::getAddressSize, 5000L, 10L);
   }


}


<|start_filename|>artemis-jms-client/src/main/java/org/apache/activemq/artemis/jms/client/DefaultConnectionProperties.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.jms.client;

import java.security.AccessController;
import java.security.PrivilegedAction;

/**
 * <p>This class will provide default properties for constructors</p>
 *
 * <table border='1'>
 * <caption>Default properties</caption>
 * <tr> <td>Name</td> <td>Default Value</td></tr>
 * <tr> <td>AMQ_HOST or org.apache.activemq.AMQ_HOST</td> <td>localhost</td></tr>
 * <tr><td>AMQ_PORT or org.apache.activemq.AMQ_PORT</td> <td>61616</td></tr>
 * <tr><td>BROKER_BIND_URL or org.apache.activemq.BROKER_BIND_URL</td> <td>tcp://${AMQ_HOST}:${AMQ_PORT}</td></tr>
 * <tr><td>AMQ_USER or org.apache.activemq.AMQ_USER</td> <td>null</td></tr>
 * <tr><td>AMQ_PASSWORD or org.apache.activemq.AMQ_PASSWORD</td> <td>null</td></tr>
 * </table>
 */
public class DefaultConnectionProperties {

   public static final String AMQ_HOST = "AMQ_HOST";
   public static final String AMQ_PORT = "AMQ_PORT";
   public static final String AMQ_USER = "AMQ_USER";
   public static final String AMQ_PASSWORD = "<PASSWORD>";
   public static final String BROKER_BIND_URL = "BROKER_BIND_URL";
   public static final String PREFIX = "org.apache.activemq.";

   public static String DEFAULT_BROKER_HOST;
   public static int DEFAULT_BROKER_PORT;
   public static String DEFAULT_BROKER_BIND_URL;
   public static String DEFAULT_BROKER_URL;
   public static String DEFAULT_USER;
   public static String DEFAULT_PASSWORD;

   static String getProperty(final String defaultValue, final String... propertyNames) {
      return AccessController.doPrivileged(new PrivilegedAction<String>() {
         @Override
         public String run() {
            for (String name : propertyNames) {
               String property = System.getProperty(name);
               if (property != null && !property.isEmpty()) {
                  return property;
               }
            }
            return defaultValue;
         }
      });
   }

   static {
      initialize();
   }

   public static void initialize() {
      String host = getProperty("localhost", AMQ_HOST, PREFIX + AMQ_HOST);
      String port = getProperty("61616", AMQ_PORT, PREFIX + AMQ_PORT);
      DEFAULT_BROKER_HOST = host;
      DEFAULT_BROKER_PORT = Integer.parseInt(port);
      String url = getProperty("tcp://" + host + ":" + port, PREFIX + BROKER_BIND_URL, BROKER_BIND_URL);
      DEFAULT_USER = getProperty(null, AMQ_USER, PREFIX + AMQ_USER);
      DEFAULT_PASSWORD = getProperty(null, AMQ_PASSWORD, PREFIX + AMQ_PASSWORD);

      DEFAULT_BROKER_BIND_URL = url;
      // TODO: improve this once we implement failover:// as ActiveMQ5 does
      DEFAULT_BROKER_URL = DEFAULT_BROKER_BIND_URL;
   }
}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/server/federation/FederationUpstream.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.core.server.federation;

import java.util.Map;
import java.util.Set;

import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.core.config.federation.FederationAddressPolicyConfiguration;
import org.apache.activemq.artemis.core.config.federation.FederationPolicy;
import org.apache.activemq.artemis.core.config.federation.FederationPolicySet;
import org.apache.activemq.artemis.core.config.federation.FederationQueuePolicyConfiguration;
import org.apache.activemq.artemis.core.config.federation.FederationUpstreamConfiguration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;
import org.apache.activemq.artemis.core.server.federation.address.FederatedAddress;
import org.apache.activemq.artemis.core.server.federation.queue.FederatedQueue;

public class FederationUpstream extends AbstractFederationStream {
   private FederationUpstreamConfiguration config;

   public FederationUpstream(ActiveMQServer server, Federation federation, String name, FederationUpstreamConfiguration config) {
      super(server, federation, name, config);
      this.config = config;
   }

   @Override
   public synchronized void start() {
      super.start();

      for (FederatedQueue federatedQueue : federatedQueueMap.values()) {
         federatedQueue.start();
      }
      for (FederatedAddress federatedAddress : federatedAddressMap.values()) {
         federatedAddress.start();
      }

      callFederationStreamStartedPlugins();
   }

   @Override
   public synchronized void stop() {
      for (FederatedAddress federatedAddress : federatedAddressMap.values()) {
         federatedAddress.stop();
      }
      federatedAddressMap.clear();

      for (FederatedQueue federatedQueue : federatedQueueMap.values()) {
         federatedQueue.stop();
      }
      federatedQueueMap.clear();

      super.stop();

      callFederationStreamStoppedPlugins();
   }

   public void deploy(Set<String> policyRefsToDeploy, Map<String, FederationPolicy> policyMap) throws ActiveMQException {
      deployPolicyRefs(policyRefsToDeploy, policyMap, 0);
   }

   private void deployPolicyRefs(Set<String> policyRefsToDeploy, Map<String, FederationPolicy> policyMap, int recursionDepth) throws ActiveMQException {
      for (String policyRef : policyRefsToDeploy) {
         FederationPolicy policy = policyMap.get(policyRef);
         if (policy != null) {
            if (policy instanceof FederationPolicySet) {
               FederationPolicySet federationPolicySet = (FederationPolicySet) policy;
               if (recursionDepth < 10) {
                  deployPolicyRefs(federationPolicySet.getPolicyRefs(), policyMap, ++recursionDepth);
               } else {
                  ActiveMQServerLogger.LOGGER.federationAvoidStackOverflowPolicyRef(name.toString(), policyRef);
               }
            } else if (policy instanceof FederationQueuePolicyConfiguration) {
               deploy((FederationQueuePolicyConfiguration) policy);
            } else if (policy instanceof FederationAddressPolicyConfiguration) {
               deploy((FederationAddressPolicyConfiguration) policy);
            } else {
               ActiveMQServerLogger.LOGGER.federationUnknownPolicyType(name.toString(), policyRef);
            }
         } else {
            ActiveMQServerLogger.LOGGER.federationCantFindPolicyRef(name.toString(), policyRef);
         }
      }
   }

   public synchronized boolean deploy(FederationQueuePolicyConfiguration federatedQueueConfig) throws ActiveMQException {
      String name = federatedQueueConfig.getName();
      FederatedQueue existing = federatedQueueMap.get(name);
      if (existing == null || !existing.getConfig().equals(federatedQueueConfig)) {
         undeployQueue(name);

         FederatedQueue federatedQueue = new FederatedQueue(federation, federatedQueueConfig, server, this);
         federatedQueueMap.put(name, federatedQueue);
         federation.register(federatedQueue);
         if (connection.isStarted()) {
            federatedQueue.start();
         }
         return true;
      }
      return false;

   }

   public synchronized boolean deploy(FederationAddressPolicyConfiguration federatedAddressConfig) throws ActiveMQException {
      String name = federatedAddressConfig.getName();
      FederatedAddress existing = federatedAddressMap.get(name);
      if (existing == null || !existing.getConfig().equals(federatedAddressConfig)) {
         undeployAddress(name);

         FederatedAddress federatedAddress = new FederatedAddress(federation, federatedAddressConfig, server, this);
         federatedAddressMap.put(name, federatedAddress);
         federation.register(federatedAddress);
         if (connection.isStarted()) {
            federatedAddress.start();
         }
         return true;
      }
      return false;
   }

   private void undeployAddress(String name) {
      FederatedAddress federatedAddress = federatedAddressMap.remove(name);
      if (federatedAddress != null) {
         federatedAddress.stop();
         federation.unregister(federatedAddress);
      }
   }

   private void undeployQueue(String name) {
      FederatedQueue federatedQueue = federatedQueueMap.remove(name);
      if (federatedQueue != null) {
         federatedQueue.stop();
         federation.unregister(federatedQueue);
      }
   }

   @Override
   public FederationUpstreamConfiguration getConfig() {
      return config;
   }
}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/server/cluster/ClusterControl.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.server.cluster;

import java.util.Optional;

import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.core.client.impl.ClientSessionFactoryInternal;
import org.apache.activemq.artemis.core.config.ClusterConnectionConfiguration;
import org.apache.activemq.artemis.core.config.ConfigurationUtils;
import org.apache.activemq.artemis.core.protocol.core.Channel;
import org.apache.activemq.artemis.core.protocol.core.CoreRemotingConnection;
import org.apache.activemq.artemis.core.protocol.core.impl.ChannelImpl;
import org.apache.activemq.artemis.core.protocol.core.impl.PacketImpl;
import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.BackupRegistrationMessage;
import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.BackupRequestMessage;
import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.BackupResponseMessage;
import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.ClusterConnectMessage;
import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.ClusterConnectReplyMessage;
import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.NodeAnnounceMessage;
import org.apache.activemq.artemis.core.protocol.core.impl.wireformat.ScaleDownAnnounceMessage;
import org.apache.activemq.artemis.core.server.ActiveMQMessageBundle;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.ActiveMQServerLogger;

/**
 * handles the communication between a cluster node and the cluster, either the whole cluster or a specific node in the
 * cluster such as a replicating node.
 */
public class ClusterControl implements AutoCloseable {

   private Channel clusterChannel;

   private final ClientSessionFactoryInternal sessionFactory;

   private final ActiveMQServer server;

   private final String clusterUser;

   private final String clusterPassword;

   public ClusterControl(ClientSessionFactoryInternal sessionFactory, ActiveMQServer server) {
      this.sessionFactory = sessionFactory;
      this.server = server;
      this.clusterUser = server.getConfiguration().getClusterUser();
      this.clusterPassword = server.getConfiguration().getClusterPassword();
   }

   public Optional<Channel> getClusterChannel() {
      return Optional.ofNullable(clusterChannel);
   }

   /**
    * authorise this cluster control so it can communicate with the cluster, it will set the cluster channel on a successful
    * authentication.
    *
    * @throws ActiveMQException if authorisation wasn't successful.
    */
   public void authorize() throws ActiveMQException {
      CoreRemotingConnection connection = (CoreRemotingConnection) sessionFactory.getConnection();

      clusterChannel = connection.getChannel(ChannelImpl.CHANNEL_ID.CLUSTER.id, -1);

      ClusterConnectReplyMessage packet = (ClusterConnectReplyMessage) clusterChannel.sendBlocking(new ClusterConnectMessage(clusterUser, clusterPassword), PacketImpl.CLUSTER_CONNECT_REPLY);

      if (!packet.isAuthorized()) {
         throw ActiveMQMessageBundle.BUNDLE.unableToValidateClusterUser(clusterUser);
      }
   }

   /**
    * XXX HORNETQ-720
    *
    * @param attemptingFailBack if {@code true} then this server wants to trigger a fail-back when
    *                           up-to-date, that is it wants to take over the role of 'live' from the current 'live'
    *                           server.
    * @throws ActiveMQException
    */
   public void announceReplicatingBackupToLive(final boolean attemptingFailBack,
                                               String replicationClusterName) throws ActiveMQException {

      ClusterConnectionConfiguration config = ConfigurationUtils.getReplicationClusterConfiguration(server.getConfiguration(), replicationClusterName);
      if (config == null) {
         ActiveMQServerLogger.LOGGER.announceBackupNoClusterConnections();
         throw new ActiveMQException("lacking cluster connection");

      }
      TransportConfiguration connector = server.getConfiguration().getConnectorConfigurations().get(config.getConnectorName());

      if (connector == null) {
         ActiveMQServerLogger.LOGGER.announceBackupNoConnector(config.getConnectorName());
         throw new ActiveMQException("lacking cluster connection");
      }

      clusterChannel.send(new BackupRegistrationMessage(connector, clusterUser, clusterPassword, attemptingFailBack));
   }

   /**
    * announce this node to the cluster.
    *
    * @param currentEventID     used if multiple announcements about this node are made.
    * @param nodeID             the node id if the announcing node
    * @param backupGroupName    the backup group name.
    * @param scaleDownGroupName the scaledown group name
    * @param isBackup           are we a backup
    * @param config             the transports config
    * @param backupConfig       the transports backup config
    */
   public void sendNodeAnnounce(final long currentEventID,
                                String nodeID,
                                String backupGroupName,
                                String scaleDownGroupName,
                                boolean isBackup,
                                TransportConfiguration config,
                                TransportConfiguration backupConfig) {
      clusterChannel.send(new NodeAnnounceMessage(currentEventID, nodeID, backupGroupName, scaleDownGroupName, isBackup, config, backupConfig));
   }

   /**
    * create a replication channel
    *
    * @return the replication channel
    */
   public Channel createReplicationChannel() {
      CoreRemotingConnection connection = (CoreRemotingConnection) sessionFactory.getConnection();
      return connection.getChannel(ChannelImpl.CHANNEL_ID.REPLICATION.id, -1);
   }

   /**
    * get the session factory used to connect to the cluster
    *
    * @return the session factory
    */
   public ClientSessionFactoryInternal getSessionFactory() {
      return sessionFactory;
   }

   /**
    * close this cluster control and its resources
    */
   @Override
   public void close() {
      sessionFactory.close();
   }

   public boolean requestReplicatedBackup(int backupSize, SimpleString nodeID) {
      BackupRequestMessage backupRequestMessage = new BackupRequestMessage(backupSize, nodeID);
      return requestBackup(backupRequestMessage);
   }

   private boolean requestBackup(BackupRequestMessage backupRequestMessage) {
      BackupResponseMessage packet;
      try {
         packet = (BackupResponseMessage) clusterChannel.sendBlocking(backupRequestMessage, PacketImpl.BACKUP_REQUEST_RESPONSE);
      } catch (ActiveMQException e) {
         return false;
      }
      return packet.isBackupStarted();
   }

   public boolean requestSharedStoreBackup(int backupSize,
                                           String journalDirectory,
                                           String bindingsDirectory,
                                           String largeMessagesDirectory,
                                           String pagingDirectory) {
      BackupRequestMessage backupRequestMessage = new BackupRequestMessage(backupSize, journalDirectory, bindingsDirectory, largeMessagesDirectory, pagingDirectory);
      return requestBackup(backupRequestMessage);
   }

   public void announceScaleDown(SimpleString targetNodeId, SimpleString scaledDownNodeId) {
      ScaleDownAnnounceMessage announceMessage = new ScaleDownAnnounceMessage(targetNodeId, scaledDownNodeId);
      clusterChannel.send(announceMessage);
   }

   public String getClusterUser() {
      return clusterUser;
   }

   public String getClusterPassword() {
      return clusterPassword;
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/ExtremeCancelsTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.tests.integration.amqp;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.qpid.jms.JmsConnectionFactory;
import org.junit.Assert;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class ExtremeCancelsTest extends JMSClientTestSupport {

   private SimpleString anycastAddress = new SimpleString("theQueue");


   @Override
   protected String getConfiguredProtocols() {
      return "AMQP,OPENWIRE,CORE";
   }

   private boolean isAMQP;

   public ExtremeCancelsTest(boolean isAMQP) {
      this.isAMQP = isAMQP;
   }


   @Parameterized.Parameters(name = "{index}: isAMQP={0}")
   public static Collection<Object[]> parameters() {
      return Arrays.asList(new Object[][] {
         {true}, {false}
      });
   }


   @Test(timeout = 120000)
   public void testLotsOfCloseOpenConsumer() throws Exception {

      server.createQueue(new QueueConfiguration(anycastAddress).setRoutingType(RoutingType.ANYCAST));

      AtomicInteger errors = new AtomicInteger(0);
      AtomicBoolean runnning = new AtomicBoolean(true);
      Runnable runnable = new Runnable() {
         @Override
         public void run() {

            try {
               ConnectionFactory factory = createCF();

               Connection connection = factory.createConnection();
               Session session = connection.createSession();
               connection.start();
               Queue queue = session.createQueue(anycastAddress.toString());

               while (runnning.get()) {
                  MessageConsumer consumer = session.createConsumer(queue);
                  TextMessage message = (TextMessage)consumer.receive(100);
                  if (message != null) {
                     consumer.close();
                  }
               }


               connection.close();

            } catch (Exception e) {
               e.printStackTrace();
               errors.incrementAndGet();
            }
         }
      };

      Thread[] consumers = new Thread[10];

      for (int i = 0; i < consumers.length; i++) {
         consumers[i] = new Thread(runnable);
         consumers[i].start();
      }

      ConnectionFactory factory = createCF();

      Connection connection = factory.createConnection();
      Session session = connection.createSession();
      Queue queue = session.createQueue(anycastAddress.toString());
      MessageProducer producer = session.createProducer(queue);


      final int NUMBER_OF_MESSAGES = 500;


      for (int i = 0; i < NUMBER_OF_MESSAGES; i++) {
         producer.send(session.createTextMessage("Hello guys " + i));
      }

      runnning.set(false);


      for (Thread c : consumers) {
         c.join();
      }

      Assert.assertEquals(0, errors.get());
   }

   private ConnectionFactory createCF() {
      if (isAMQP) {
         return new JmsConnectionFactory(getBrokerQpidJMSConnectionURI());
      } else {
         return new ActiveMQConnectionFactory("tcp://localhost:5672");
      }
   }

}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/persistence/impl/journal/codec/LargeMessagePersister.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.core.persistence.impl.journal.codec;

import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.core.message.impl.CoreMessage;
import org.apache.activemq.artemis.core.persistence.CoreMessageObjectPools;
import org.apache.activemq.artemis.core.persistence.Persister;
import org.apache.activemq.artemis.core.server.LargeServerMessage;

import static org.apache.activemq.artemis.core.persistence.PersisterIDs.CoreLargeMessagePersister_ID;

public class LargeMessagePersister implements Persister<LargeServerMessage> {

   public static final byte ID = CoreLargeMessagePersister_ID;

   private static final LargeMessagePersister theInstance = new LargeMessagePersister();

   @Override
   public byte getID() {
      return ID;
   }

   public static LargeMessagePersister getInstance() {
      return theInstance;
   }

   protected LargeMessagePersister() {
   }

   /* (non-Javadoc)
    * @see org.apache.activemq.artemis.core.journal.EncodingSupport#decode(org.apache.activemq.artemis.spi.core.remoting.ActiveMQBuffer)
    */
   @Override
   public LargeServerMessage decode(final ActiveMQBuffer buffer, LargeServerMessage message, CoreMessageObjectPools objectPools) {
      ((CoreMessage)message).decodeHeadersAndProperties(buffer.byteBuf());
      return message;
   }

   /* (non-Javadoc)
    * @see org.apache.activemq.artemis.core.journal.EncodingSupport#encode(org.apache.activemq.artemis.spi.core.remoting.ActiveMQBuffer)
    */
   @Override
   public void encode(final ActiveMQBuffer buffer, LargeServerMessage message) {
      ((CoreMessage)message).encodeHeadersAndProperties(buffer.byteBuf());
   }

   /* (non-Javadoc)
    * @see org.apache.activemq.artemis.core.journal.EncodingSupport#getEncodeSize()
    */
   @Override
   public int getEncodeSize(LargeServerMessage message) {
      return message.toMessage().getEncodeSize();
   }

}


<|start_filename|>artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/ListUser.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.cli.commands.user;

import javax.json.JsonArray;
import javax.json.JsonObject;

import io.airlift.airline.Command;
import org.apache.activemq.artemis.api.core.JsonUtil;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.management.ManagementHelper;
import org.apache.activemq.artemis.cli.commands.AbstractAction;
import org.apache.activemq.artemis.cli.commands.ActionContext;

/**
 * list existing users, example:
 * ./artemis user list --user guest
 */
@Command(name = "list", description = "List existing user(s)")
public class ListUser extends UserAction {

   @Override
   public Object execute(ActionContext context) throws Exception {
      super.execute(context);

      list();

      return null;
   }

   /**
    * List a single user or all users if username is not specified
    *
    * @throws Exception if communication with the broker fails
    */
   private void list() throws Exception {
      StringBuilder logMessage = new StringBuilder("--- \"user\"(roles) ---\n");
      int userCount = 0;
      final String[] result = new String[1];

      performCoreManagement(new AbstractAction.ManagementCallback<ClientMessage>() {
         @Override
         public void setUpInvocation(ClientMessage message) throws Exception {
            ManagementHelper.putOperationInvocation(message, "broker", "listUser", userCommandUser);
         }

         @Override
         public void requestSuccessful(ClientMessage reply) throws Exception {
            result[0] = (String) ManagementHelper.getResult(reply, String.class);
         }

         @Override
         public void requestFailed(ClientMessage reply) throws Exception {
            String errMsg = (String) ManagementHelper.getResult(reply, String.class);
            context.err.println("Failed to list user " + userCommandUser + ". Reason: " + errMsg);
         }
      });

      // process the JSON results from the broker
      JsonArray array = JsonUtil.readJsonArray(result[0]);
      for (JsonObject object : array.getValuesAs(JsonObject.class)) {
         logMessage.append("\"").append(object.getString("username")).append("\"").append("(");
         JsonArray roles = object.getJsonArray("roles");
         for (int i = 0; i < roles.size(); i++) {
            logMessage.append(roles.getString(i));
            if ((i + 1) < roles.size()) {
               logMessage.append(",");
            }
         }
         logMessage.append(")\n");
         userCount++;
      }
      logMessage.append("\n Total: ").append(userCount);
      context.out.println(logMessage);
   }

}


<|start_filename|>artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/check/CheckTask.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.cli.commands.check;

public class CheckTask {
   public interface Callback {
      void run(CheckContext context) throws Exception;
   }

   private final String assertion;
   private final Callback callback;

   public String getAssertion() {
      return assertion;
   }

   public Callback getCallback() {
      return callback;
   }

   public CheckTask(String assertion, Callback callback) {
      this.assertion = assertion;
      this.callback = callback;
   }
}


<|start_filename|>tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/util/AutomaticLatchTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.unit.util;

import java.util.ArrayList;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.activemq.artemis.utils.AutomaticLatch;
import org.junit.Assert;
import org.junit.Test;

public class AutomaticLatchTest {

   @Test
   public void testWthPending() {
      AtomicInteger value = new AtomicInteger(0);
      AutomaticLatch latch = new AutomaticLatch(1);
      latch.afterCompletion(() -> value.incrementAndGet());
      Assert.assertEquals(0, value.get());

      latch.countDown();

      Assert.assertEquals(1, value.get());
   }

   @Test
   public void testWthoutPending() {
      AtomicInteger value = new AtomicInteger(0);
      AutomaticLatch latch = new AutomaticLatch(0);
      latch.afterCompletion(() -> value.incrementAndGet());
      Assert.assertEquals(1, value.get());
      latch.countUp();
      latch.countDown();

      // the previous latch completion should been cleared by now
      Assert.assertEquals(1, value.get());

      latch.afterCompletion(() -> value.addAndGet(10));
      Assert.assertEquals(11, value.get());

      latch.countUp();
      latch.countDown();

      Assert.assertEquals(11, value.get());
   }

   @Test
   public void testMultipleCallsOrder() {
      ArrayList<Integer> outcome = new ArrayList<>();
      AutomaticLatch latch = new AutomaticLatch(1);
      latch.afterCompletion(() -> outcome.add(0));
      latch.afterCompletion(() -> outcome.add(1));
      latch.afterCompletion(() -> outcome.add(2));

      latch.countDown();

      Assert.assertEquals((Integer)0, outcome.get(0));
      Assert.assertEquals((Integer)1, outcome.get(1));
      Assert.assertEquals((Integer)2, outcome.get(2));

      Assert.assertEquals(3, outcome.size());
   }


}


<|start_filename|>tests/activemq5-unit-tests/src/test/java/org/apache/activemq/transport/failover/FailoverPriorityTest.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.transport.failover;

import javax.jms.Connection;
import javax.jms.JMSException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.jms.server.config.impl.JMSConfigurationImpl;
import org.apache.activemq.artemis.jms.server.embedded.EmbeddedJMS;
import org.apache.activemq.broker.artemiswrapper.OpenwireArtemisBaseTest;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Ignore
public class FailoverPriorityTest extends OpenwireArtemisBaseTest {

   protected final Logger LOG = LoggerFactory.getLogger(getClass());

   private static final String BROKER_A_CLIENT_TC_ADDRESS = "tcp://127.0.0.1:61616";
   private static final String BROKER_B_CLIENT_TC_ADDRESS = "tcp://127.0.0.1:61617";
   private static final String BROKER_C_CLIENT_TC_ADDRESS = "tcp://127.0.0.1:61618";
   private final HashMap<Integer, String> urls = new HashMap<>();

   private final List<ActiveMQConnection> connections = new ArrayList<>();
   private final EmbeddedJMS[] servers = new EmbeddedJMS[3];
   private String clientUrl;
   private final Map<String, String> params = new HashMap<>();

   @Before
   public void setUp() throws Exception {
      urls.put(0, BROKER_A_CLIENT_TC_ADDRESS);
      urls.put(1, BROKER_B_CLIENT_TC_ADDRESS);
      params.clear();
      params.put("rebalanceClusterClients", "true");
      params.put("updateClusterClients", "true");
      params.put("updateClusterClientsOnRemove", "true");
   }

   @After
   public void tearDown() throws Exception {
      shutdownClients();
      for (EmbeddedJMS server : servers) {
         if (server != null) {
            server.stop();
         }
      }
   }

   @Test
   public void testPriorityBackup() throws Exception {
      Configuration config0 = createConfig("127.0.0.1", 0);
      Configuration config1 = createConfig("127.0.0.1", 1);

      deployClusterConfiguration(config0, 1);
      deployClusterConfiguration(config1, 0);

      servers[0] = new EmbeddedJMS().setConfiguration(config0).setJmsConfiguration(new JMSConfigurationImpl());
      servers[1] = new EmbeddedJMS().setConfiguration(config1).setJmsConfiguration(new JMSConfigurationImpl());
      servers[0].start();
      servers[1].start();

      Assert.assertTrue(servers[0].waitClusterForming(100, TimeUnit.MILLISECONDS, 20, 2));
      Assert.assertTrue(servers[1].waitClusterForming(100, TimeUnit.MILLISECONDS, 20, 2));

      Thread.sleep(1000);

      setClientUrl("failover:(" + BROKER_A_CLIENT_TC_ADDRESS + "," + BROKER_B_CLIENT_TC_ADDRESS + ")?randomize=false&priorityBackup=true&initialReconnectDelay=1000&useExponentialBackOff=false");
      createClients(5);

      assertAllConnectedTo(urls.get(0));

      restart(false, 0, 1);

      for (int i = 0; i < 3; i++) {
         restart(true, 0, 1);
      }

      Thread.sleep(5000);

      restart(false, 0, 1);

   }

   @Test
   public void testPriorityBackupList() throws Exception {
      Configuration config0 = createConfig("127.0.0.1", 0);
      Configuration config1 = createConfig("127.0.0.1", 1);

      deployClusterConfiguration(config0, 1);
      deployClusterConfiguration(config1, 0);

      servers[0] = new EmbeddedJMS().setConfiguration(config0).setJmsConfiguration(new JMSConfigurationImpl());
      servers[1] = new EmbeddedJMS().setConfiguration(config1).setJmsConfiguration(new JMSConfigurationImpl());
      servers[0].start();
      servers[1].start();

      Assert.assertTrue(servers[0].waitClusterForming(100, TimeUnit.MILLISECONDS, 20, 2));
      Assert.assertTrue(servers[1].waitClusterForming(100, TimeUnit.MILLISECONDS, 20, 2));
      Thread.sleep(1000);

      setClientUrl("failover:(" + BROKER_A_CLIENT_TC_ADDRESS + "," + BROKER_B_CLIENT_TC_ADDRESS + ")?randomize=false&priorityBackup=true&priorityURIs=tcp://127.0.0.1:61617&initialReconnectDelay=1000&useExponentialBackOff=false");
      createClients(5);

      Thread.sleep(3000);

      assertAllConnectedTo(urls.get(1));

      restart(false, 1, 0);

      for (int i = 0; i < 3; i++) {
         restart(true, 1, 0);
      }

      restart(false, 1, 0);
   }

   @Test
   public void testThreeBrokers() throws Exception {
      setupThreeBrokers();
      Thread.sleep(1000);

      setClientUrl("failover:(" + BROKER_A_CLIENT_TC_ADDRESS + "," + BROKER_B_CLIENT_TC_ADDRESS + "," + BROKER_C_CLIENT_TC_ADDRESS + ")?randomize=false&priorityBackup=true&initialReconnectDelay=1000&useExponentialBackOff=false");

      createClients(5);

      assertAllConnectedTo(urls.get(0));

      restart(true, 0, 1, 3);
   }

   @Test
   public void testPriorityBackupAndUpdateClients() throws Exception {
      Configuration config0 = createConfig("127.0.0.1", 0);
      Configuration config1 = createConfig("127.0.0.1", 1);

      deployClusterConfiguration(config0, 1);
      deployClusterConfiguration(config1, 0);

      servers[0] = new EmbeddedJMS().setConfiguration(config0).setJmsConfiguration(new JMSConfigurationImpl());
      servers[1] = new EmbeddedJMS().setConfiguration(config1).setJmsConfiguration(new JMSConfigurationImpl());
      servers[0].start();
      servers[1].start();

      Assert.assertTrue(servers[0].waitClusterForming(100, TimeUnit.MILLISECONDS, 20, 2));
      Assert.assertTrue(servers[1].waitClusterForming(100, TimeUnit.MILLISECONDS, 20, 2));

      Thread.sleep(1000);

      setClientUrl("failover:(" + BROKER_A_CLIENT_TC_ADDRESS + "," + BROKER_B_CLIENT_TC_ADDRESS + ")?randomize=false&priorityBackup=true&initialReconnectDelay=1000&useExponentialBackOff=false");

      createClients(5);

      // Let's wait a little bit longer just in case it takes a while to realize that the
      // Broker A is the one with higher priority.
      Thread.sleep(5000);

      assertAllConnectedTo(urls.get(0));
   }

   private void restart(boolean primary, int primaryID, int secondaryID) throws Exception {
      restart(primary, primaryID, secondaryID, 2);
   }

   private void restart(boolean primary, int primaryID, int secondaryID, int total) throws Exception {

      Thread.sleep(1000);

      if (primary) {
         LOG.info("Stopping " + primaryID);
         stopBroker(primaryID);
         Assert.assertTrue(servers[secondaryID].waitClusterForming(100, TimeUnit.MILLISECONDS, 20, total - 1));
      } else {
         LOG.info("Stopping " + secondaryID);
         stopBroker(secondaryID);
         Assert.assertTrue(servers[primaryID].waitClusterForming(100, TimeUnit.MILLISECONDS, 20, total - 1));
      }
      Thread.sleep(5000);

      if (primary) {
         assertAllConnectedTo(urls.get(secondaryID));
      } else {
         assertAllConnectedTo(urls.get(primaryID));
      }

      if (primary) {
         Configuration config = createConfig("127.0.0.1", primaryID);

         deployClusterConfiguration(config, secondaryID);

         servers[primaryID] = new EmbeddedJMS().setConfiguration(config).setJmsConfiguration(new JMSConfigurationImpl());
         servers[primaryID].start();

         Assert.assertTrue(servers[primaryID].waitClusterForming(100, TimeUnit.MILLISECONDS, 20, total));
         Assert.assertTrue(servers[secondaryID].waitClusterForming(100, TimeUnit.MILLISECONDS, 20, total));
      } else {
         Configuration config = createConfig("127.0.0.1", secondaryID);

         deployClusterConfiguration(config, primaryID);

         servers[secondaryID] = new EmbeddedJMS().setConfiguration(config).setJmsConfiguration(new JMSConfigurationImpl());
         servers[secondaryID].start();

         Assert.assertTrue(servers[primaryID].waitClusterForming(100, TimeUnit.MILLISECONDS, 20, total));
         Assert.assertTrue(servers[secondaryID].waitClusterForming(100, TimeUnit.MILLISECONDS, 20, total));
      }

      Thread.sleep(5000);

      assertAllConnectedTo(urls.get(primaryID));

   }

   private void stopBroker(int serverID) throws Exception {
      servers[serverID].stop();
   }

   public void setClientUrl(String clientUrl) {
      this.clientUrl = clientUrl;
   }

   protected void createClients(int numOfClients) throws Exception {
      ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory(clientUrl);
      for (int i = 0; i < numOfClients; i++) {
         ActiveMQConnection c = (ActiveMQConnection) factory.createConnection();
         c.start();
         connections.add(c);
      }
   }

   protected void shutdownClients() throws JMSException {
      for (Connection c : connections) {
         c.close();
      }
   }

   protected void assertAllConnectedTo(String url) throws Exception {
      for (ActiveMQConnection c : connections) {
         Assert.assertEquals(url, c.getTransportChannel().getRemoteAddress());
      }
   }

   private void setupThreeBrokers() throws Exception {

      params.put("rebalanceClusterClients", "false");
      params.put("updateClusterClients", "false");
      params.put("updateClusterClientsOnRemove", "false");

      Configuration config0 = createConfig("127.0.0.1", 0, params);
      Configuration config1 = createConfig("127.0.0.1", 1, params);
      Configuration config2 = createConfig("127.0.0.1", 2, params);

      deployClusterConfiguration(config0, 1, 2);
      deployClusterConfiguration(config1, 0, 2);
      deployClusterConfiguration(config2, 0, 1);

      servers[0] = new EmbeddedJMS().setConfiguration(config0).setJmsConfiguration(new JMSConfigurationImpl());
      servers[1] = new EmbeddedJMS().setConfiguration(config1).setJmsConfiguration(new JMSConfigurationImpl());
      servers[2] = new EmbeddedJMS().setConfiguration(config2).setJmsConfiguration(new JMSConfigurationImpl());

      servers[0].start();
      servers[1].start();
      servers[2].start();

      Assert.assertTrue(servers[0].waitClusterForming(100, TimeUnit.MILLISECONDS, 20, 3));
      Assert.assertTrue(servers[1].waitClusterForming(100, TimeUnit.MILLISECONDS, 20, 3));
      Assert.assertTrue(servers[2].waitClusterForming(100, TimeUnit.MILLISECONDS, 20, 3));
   }

}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/JMSLVQTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.amqp;


import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.junit.Test;

public class JMSLVQTest extends JMSClientTestSupport {

   private static final String NORMAL_QUEUE_NAME = "NORMAL";
   private static final String LVQ_QUEUE_NAME = "LVQ";
   private static final String LVQ_CUSTOM_KEY_QUEUE_NAME = "LVQ_CUSTOM_KEY_QUEUE";
   private static final String CUSTOM_KEY = "KEY";

   private ConnectionSupplier AMQPConnection = () -> createConnection();
   private ConnectionSupplier CoreConnection = () -> createCoreConnection();
   private ConnectionSupplier OpenWireConnection = () -> createOpenWireConnection();

   @Override
   protected String getConfiguredProtocols() {
      return "AMQP,OPENWIRE,CORE";
   }

   @Override
   protected void addConfiguration(ActiveMQServer server) {
      server.getConfiguration().setPersistenceEnabled(false);
      server.getConfiguration().setMessageExpiryScanPeriod(1000);
      server.getAddressSettingsRepository().addMatch(NORMAL_QUEUE_NAME, new AddressSettings());
      server.getAddressSettingsRepository().addMatch(LVQ_QUEUE_NAME, new AddressSettings().setDefaultLastValueQueue(true));
      server.getAddressSettingsRepository().addMatch(LVQ_CUSTOM_KEY_QUEUE_NAME, new AddressSettings().setDefaultLastValueQueue(true).setDefaultLastValueKey(SimpleString.toSimpleString(CUSTOM_KEY)));
   }

   @Override
   protected void createAddressAndQueues(ActiveMQServer server) throws Exception {
      super.createAddressAndQueues(server);

      //Add Standard Queue
      server.addAddressInfo(new AddressInfo(SimpleString.toSimpleString(NORMAL_QUEUE_NAME), RoutingType.ANYCAST));
      server.createQueue(new QueueConfiguration(NORMAL_QUEUE_NAME).setRoutingType(RoutingType.ANYCAST));


      //Add LVQ using Default Message.HDR_LAST_VALUE_NAME
      server.addAddressInfo(new AddressInfo(SimpleString.toSimpleString(LVQ_QUEUE_NAME), RoutingType.ANYCAST));
      server.createQueue(new QueueConfiguration(LVQ_QUEUE_NAME).setRoutingType(RoutingType.ANYCAST));

      //Add LVQ using Custom Key
      server.addAddressInfo(new AddressInfo(SimpleString.toSimpleString(LVQ_CUSTOM_KEY_QUEUE_NAME), RoutingType.ANYCAST));
      server.createQueue(new QueueConfiguration(LVQ_CUSTOM_KEY_QUEUE_NAME).setRoutingType(RoutingType.ANYCAST));
   }


   @Test
   public void testLVQAMQPProducerAMQPConsumer() throws Exception {
      testLVQ(AMQPConnection, AMQPConnection);
   }

   @Test
   public void testLVQCoreProducerCoreConsumer() throws Exception {
      testLVQ(CoreConnection, CoreConnection);
   }

   @Test
   public void testLVQCoreProducerAMQPConsumer() throws Exception {
      testLVQ(CoreConnection, AMQPConnection);
   }

   @Test
   public void testLVQAMQPProducerCoreConsumer() throws Exception {
      testLVQ(AMQPConnection, CoreConnection);
   }

   @Test
   public void testLVQOpenWireProducerOpenWireConsumer() throws Exception {
      testLVQ(OpenWireConnection, OpenWireConnection);
   }

   @Test
   public void testLVQCoreProducerOpenWireConsumer() throws Exception {
      testLVQ(CoreConnection, OpenWireConnection);
   }

   @Test
   public void testLVQOpenWireProducerCoreConsumer() throws Exception {
      testLVQ(OpenWireConnection, CoreConnection);
   }

   @Test
   public void testLVQAMQPProducerOpenWireConsumer() throws Exception {
      testLVQ(AMQPConnection, OpenWireConnection);
   }

   @Test
   public void testLVQOpenWireProducerAMQPConsumer() throws Exception {
      testLVQ(OpenWireConnection, AMQPConnection);
   }

   public void testLVQ(ConnectionSupplier producerConnectionSupplier, ConnectionSupplier consumerConnectionSupplier) throws Exception {
      testLVQDefaultKey(producerConnectionSupplier, consumerConnectionSupplier);
      testLVQCustomKey(producerConnectionSupplier, consumerConnectionSupplier);
   }



   public void testLVQDefaultKey(ConnectionSupplier producerConnectionSupplier, ConnectionSupplier consumerConnectionSupplier) throws Exception {
      testLVQ(producerConnectionSupplier, consumerConnectionSupplier, LVQ_QUEUE_NAME, Message.HDR_LAST_VALUE_NAME.toString());
   }

   public void testLVQCustomKey(ConnectionSupplier producerConnectionSupplier, ConnectionSupplier consumerConnectionSupplier) throws Exception {
      testLVQ(producerConnectionSupplier, consumerConnectionSupplier, LVQ_CUSTOM_KEY_QUEUE_NAME, CUSTOM_KEY);
   }

   public void testLVQ(ConnectionSupplier producerConnectionSupplier, ConnectionSupplier consumerConnectionSupplier, String queueName, String lastValueKey) throws Exception {

      sendLVQ(producerConnectionSupplier, queueName, lastValueKey);

      //Simulate a small pause, else both messages could be consumed if consumer is fast enough
      Thread.sleep(10);

      receiveLVQ(consumerConnectionSupplier, queueName, lastValueKey);
   }

   private void receiveLVQ(ConnectionSupplier consumerConnectionSupplier, String queueName, String lastValueKey) throws JMSException {
      try (Connection consumerConnection = consumerConnectionSupplier.createConnection()) {

         Session consumerSession = consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
         Queue consumerQueue = consumerSession.createQueue(queueName);
         MessageConsumer consumer = consumerSession.createConsumer(consumerQueue);
         TextMessage msg = (TextMessage) consumer.receive(1000);
         assertNotNull(msg);
         assertEquals("KEY", msg.getStringProperty(lastValueKey));
         assertEquals("how are you", msg.getText());
         consumer.close();
      }
   }

   private void sendLVQ(ConnectionSupplier producerConnectionSupplier, String queueName, String lastValueKey) throws JMSException {
      try (Connection producerConnection = producerConnectionSupplier.createConnection()) {
         Session producerSession = producerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
         Queue queue1 = producerSession.createQueue(queueName);
         MessageProducer p = producerSession.createProducer(null);

         TextMessage message1 = producerSession.createTextMessage();
         message1.setStringProperty(lastValueKey, "KEY");
         message1.setText("hello");
         p.send(queue1, message1);

         TextMessage message2 = producerSession.createTextMessage();
         message2.setStringProperty(lastValueKey, "KEY");
         message2.setText("how are you");
         p.send(queue1, message2);
      }
   }
}

<|start_filename|>artemis-commons/src/test/java/org/apache/activemq/artemis/utils/HumanReadableByteCountTest.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.utils;

import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.Locale;

import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class HumanReadableByteCountTest {

   @Test
   public void testDefaultLocale() {
      internalTest(Locale.getDefault());
   }

   @Test
   public void testEnglishLocale() {
      internalTest(Locale.ENGLISH);
   }

   @Test
   public void testFrenchLocale() {
      // This locale will use commas instead of periods
      internalTest(Locale.FRENCH);
   }

   private void internalTest(final Locale testLocale) {
      // track the default
      Locale defaultLocale = Locale.getDefault();

      Locale.setDefault(testLocale);
      DecimalFormat decimalFormat = new DecimalFormat("###.0", DecimalFormatSymbols.getInstance(testLocale));

      try {
         String[] suffixes = new String[]{"K", "M", "G", "T", "P", "E"};

         assertEquals("0B", ByteUtil.getHumanReadableByteCount(0));
         assertEquals(decimalFormat.format(999.0) + "B", ByteUtil.getHumanReadableByteCount(999));
         assertEquals(decimalFormat.format(500.0) + "B", ByteUtil.getHumanReadableByteCount(500));

         for (int i = 0, j = 3; i < 6; i++, j += 3) {
            final long magnitude = (long) Math.pow(10, j);
            assertEquals(decimalFormat.format(1.0) + suffixes[i] + "B", ByteUtil.getHumanReadableByteCount(magnitude));
            assertEquals(decimalFormat.format(1.3) + suffixes[i] + "B", ByteUtil.getHumanReadableByteCount(magnitude + (long) (.25 * magnitude)));
            assertEquals(decimalFormat.format(1.5) + suffixes[i] + "B", ByteUtil.getHumanReadableByteCount(magnitude + (long) (.5 * magnitude)));
            assertEquals(decimalFormat.format(1.9) + suffixes[i] + "B", ByteUtil.getHumanReadableByteCount(magnitude + (long) (.9 * magnitude)));
            assertEquals(decimalFormat.format(4.2) + suffixes[i] + "B", ByteUtil.getHumanReadableByteCount(magnitude + (long) (3.2 * magnitude)));
         }
      } finally {
         // reset the default once the test is over
         Locale.setDefault(defaultLocale);
      }
   }
}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/messagecounter/impl/MessageCounterManagerImpl.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.messagecounter.impl;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
import org.apache.activemq.artemis.core.messagecounter.MessageCounter;
import org.apache.activemq.artemis.core.messagecounter.MessageCounterManager;
import org.apache.activemq.artemis.core.server.ActiveMQScheduledComponent;

/**
 * A MessageCounterManager
 */
public class MessageCounterManagerImpl implements MessageCounterManager {

   public static final long DEFAULT_SAMPLE_PERIOD = ActiveMQDefaultConfiguration.getDefaultMessageCounterSamplePeriod();

   public static final long MIN_SAMPLE_PERIOD = 1000;

   public static final int DEFAULT_MAX_DAY_COUNT = ActiveMQDefaultConfiguration.getDefaultMessageCounterMaxDayHistory();

   private final Map<String, MessageCounter> messageCounters;

   private final MessageCountersPinger messageCountersPinger;

   private int maxDayCount = MessageCounterManagerImpl.DEFAULT_MAX_DAY_COUNT;

   public MessageCounterManagerImpl(final ScheduledExecutorService scheduledThreadPool, Executor executor) {
      messageCounters = new HashMap<>();
      messageCountersPinger = new MessageCountersPinger(scheduledThreadPool, executor, MessageCounterManagerImpl.DEFAULT_SAMPLE_PERIOD, TimeUnit.MILLISECONDS, false);
   }

   @Override
   public synchronized void start() {

      messageCountersPinger.start();

   }

   @Override
   public synchronized void stop() {
      messageCountersPinger.stop();
   }

   @Override
   public synchronized void clear() {
      messageCounters.clear();
   }

   @Override
   public synchronized void reschedule(final long newPeriod) {
      messageCountersPinger.setPeriod(newPeriod);
   }

   @Override
   public long getSamplePeriod() {
      return messageCountersPinger.getPeriod();
   }

   @Override
   public int getMaxDayCount() {
      return maxDayCount;
   }

   @Override
   public void setMaxDayCount(final int count) {
      maxDayCount = count;
   }

   @Override
   public void registerMessageCounter(final String name, final MessageCounter counter) {
      synchronized (messageCounters) {
         messageCounters.put(name, counter);
      }
   }

   @Override
   public MessageCounter unregisterMessageCounter(final String name) {
      synchronized (messageCounters) {
         return messageCounters.remove(name);
      }
   }

   public MessageCounter getMessageCounter(String counter) {
      synchronized (messageCounters) {
         return messageCounters.get(counter);
      }
   }

   public Set<MessageCounter> getMessageCounters() {
      synchronized (messageCounters) {
         return new HashSet<>(messageCounters.values());
      }
   }

   @Override
   public void resetAllCounters() {
      synchronized (messageCounters) {
         for (MessageCounter counter : messageCounters.values()) {
            counter.resetCounter();
         }
      }
   }

   @Override
   public void resetAllCounterHistories() {
      synchronized (messageCounters) {
         for (MessageCounter counter : messageCounters.values()) {
            counter.resetHistory();
         }
      }
   }

   private class MessageCountersPinger extends ActiveMQScheduledComponent {

      MessageCountersPinger(ScheduledExecutorService scheduledExecutorService,
                            Executor executor,
                            long checkPeriod,
                            TimeUnit timeUnit,
                            boolean onDemand) {
         super(scheduledExecutorService, executor, checkPeriod, timeUnit, onDemand);
      }

      @Override
      public void run() {

         synchronized (messageCounters) {
            for (MessageCounter counter : messageCounters.values()) {
               counter.onTimer();
            }
         }
      }

   }

}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/openwire/amq/JMSConsumer2Test.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.openwire.amq;

import javax.jms.IllegalStateException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import java.io.IOException;
import java.lang.Thread.UncaughtExceptionHandler;
import java.net.Socket;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.activemq.ActiveMQConnection;
import org.apache.activemq.ActiveMQMessageConsumer;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.tests.integration.openwire.BasicOpenWireTest;
import org.apache.activemq.artemis.utils.ActiveMQThreadFactory;
import org.apache.activemq.artemis.utils.Wait;
import org.apache.activemq.command.ActiveMQDestination;
import org.apache.activemq.command.ActiveMQQueue;
import org.junit.Test;

/**
 * adapted from: org.apache.activemq.JMSConsumerTest
 */
public class JMSConsumer2Test extends BasicOpenWireTest {

   @Test
   public void testMessageListenerWithConsumerCanBeStoppedConcurently() throws Exception {

      final AtomicInteger counter = new AtomicInteger(0);
      final CountDownLatch closeDone = new CountDownLatch(1);

      connection.start();
      Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
      ActiveMQDestination destination = createDestination(session, ActiveMQDestination.QUEUE_TYPE);

      // preload the queue
      sendMessages(session, destination, 2000);

      final ActiveMQMessageConsumer consumer = (ActiveMQMessageConsumer) session.createConsumer(destination);

      final Map<Thread, Throwable> exceptions = Collections.synchronizedMap(new HashMap<Thread, Throwable>());
      Thread.setDefaultUncaughtExceptionHandler(new UncaughtExceptionHandler() {
         @Override
         public void uncaughtException(Thread t, Throwable e) {
            exceptions.put(t, e);
         }
      });

      final class AckAndClose implements Runnable {

         private final Message message;

         AckAndClose(Message m) {
            this.message = m;
         }

         @Override
         public void run() {
            try {
               int count = counter.incrementAndGet();
               if (count == 590) {
                  // close in a separate thread is ok by jms
                  consumer.close();
                  closeDone.countDown();
               }
               if (count % 200 == 0) {
                  // ensure there are some outstanding messages
                  // ack every 200
                  message.acknowledge();
               }
            } catch (Exception e) {
               e.printStackTrace();
               if (!(e instanceof IllegalStateException)) { // The consumer is closed may happen
                  exceptions.put(Thread.currentThread(), e);
               }
            }
         }
      }

      final ExecutorService executor = Executors.newCachedThreadPool(ActiveMQThreadFactory.defaultThreadFactory());
      consumer.setMessageListener(new MessageListener() {
         @Override
         public void onMessage(Message m) {
            // ack and close eventually in separate thread
            executor.execute(new AckAndClose(m));
         }
      });

      assertTrue(closeDone.await(20, TimeUnit.SECONDS));
      // await possible exceptions
      Thread.sleep(1000);
      assertTrue("no exceptions: " + exceptions, exceptions.isEmpty());
      executor.shutdown();
   }

   @Test
   public void testDupsOkConsumer() throws Exception {

      // Receive a message with the JMS API
      connection.start();
      Session session = connection.createSession(false, Session.DUPS_OK_ACKNOWLEDGE);
      ActiveMQDestination destination = createDestination(session, ActiveMQDestination.QUEUE_TYPE);
      MessageConsumer consumer = session.createConsumer(destination);

      // Send the messages
      sendMessages(session, destination, 4);

      // Make sure only 4 message are delivered.
      for (int i = 0; i < 4; i++) {
         Message m = consumer.receive(1000);
         assertNotNull(m);
      }
      assertNull(consumer.receive(1000));

      // Close out the consumer.. no other messages should be left on the queue.
      consumer.close();

      consumer = session.createConsumer(destination);
      assertNull(consumer.receive(1000));
   }

   @Test
   public void testRedispatchOfUncommittedTx() throws Exception {
      connection.start();
      Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
      ActiveMQDestination destination = createDestination(session, ActiveMQDestination.QUEUE_TYPE);

      sendMessages(connection, destination, 2);

      MessageConsumer consumer = session.createConsumer(destination);
      Message m = consumer.receive(1000);
      assertNotNull(m);
      m = consumer.receive(5000);
      assertNotNull(m);
      assertFalse("redelivered flag set", m.getJMSRedelivered());

      // install another consumer while message dispatch is unacked/uncommitted
      Session redispatchSession = connection.createSession(true, Session.SESSION_TRANSACTED);
      MessageConsumer redispatchConsumer = redispatchSession.createConsumer(destination);

      // no commit so will auto rollback and get re-dispatched to
      // redisptachConsumer
      session.close();

      Message msg = redispatchConsumer.receive(3000);
      assertNotNull(msg);

      assertTrue("redelivered flag set", msg.getJMSRedelivered());
      assertEquals(2, msg.getLongProperty("JMSXDeliveryCount"));

      msg = redispatchConsumer.receive(1000);
      assertNotNull(msg);
      assertTrue(msg.getJMSRedelivered());
      assertEquals(2, msg.getLongProperty("JMSXDeliveryCount"));
      redispatchSession.commit();

      assertNull(redispatchConsumer.receive(500));
      redispatchSession.close();
   }

   @Test
   public void testRedispatchOfRolledbackTx() throws Exception {

      connection.start();
      Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
      ActiveMQDestination destination = createDestination(session, ActiveMQDestination.QUEUE_TYPE);

      sendMessages(connection, destination, 2);

      MessageConsumer consumer = session.createConsumer(destination);
      assertNotNull(consumer.receive(1000));
      assertNotNull(consumer.receive(1000));

      // install another consumer while message dispatch is unacked/uncommitted
      Session redispatchSession = connection.createSession(true, Session.SESSION_TRANSACTED);
      MessageConsumer redispatchConsumer = redispatchSession.createConsumer(destination);

      session.rollback();
      session.close();

      Message msg = redispatchConsumer.receive(1000);
      assertNotNull(msg);
      assertTrue(msg.getJMSRedelivered());
      assertEquals(2, msg.getLongProperty("JMSXDeliveryCount"));
      msg = redispatchConsumer.receive(1000);
      assertNotNull(msg);
      assertTrue(msg.getJMSRedelivered());
      assertEquals(2, msg.getLongProperty("JMSXDeliveryCount"));
      redispatchSession.commit();

      assertNull(redispatchConsumer.receive(500));
      redispatchSession.close();
   }

   @Test
   public void testRedeliveryOnServerConnectionFailWithPendingAckInLocalTx() throws Exception {
      // Send a message to the broker.
      connection.start();
      sendMessages(connection, new ActiveMQQueue(queueName), 1);
      connection.close();

      factory.setWatchTopicAdvisories(false);
      factory.setNonBlockingRedelivery(true);
      connection = (ActiveMQConnection) factory.createConnection();
      connection.start();

      Session session = connection.createSession(true, Session.SESSION_TRANSACTED);
      ActiveMQDestination destination = createDestination(session, ActiveMQDestination.QUEUE_TYPE);
      MessageConsumer consumer = session.createConsumer(destination);

      final CountDownLatch gotMessage = new CountDownLatch(1);
      consumer.setMessageListener(message -> gotMessage.countDown());

      assertTrue(gotMessage.await(1, TimeUnit.SECONDS));

      // want to ensure the ack has had a chance to get back to the broker
      final Queue queueInstance = server.locateQueue(new SimpleString(queueName));
      Wait.waitFor(new Wait.Condition() {
         @Override
         public boolean isSatisfied() throws Exception {
            return queueInstance.getAcknowledgeAttempts() > 0;
         }
      });

      // whack the connection so there is no transaction outcome
      try {
         connection.getTransport().narrow(Socket.class).close();
      } catch (IOException e) {
         e.printStackTrace();
      }
      try {
         connection.close();
      } catch (Exception expected) {
      }

      // expect rollback and redelivery on new consumer
      connection = (ActiveMQConnection) factory.createConnection();
      connection.start();

      session = connection.createSession(true, Session.SESSION_TRANSACTED);
      consumer = session.createConsumer(destination);

      assertNotNull(consumer.receive(2000));
      session.commit();

      connection.close();
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/jms/RedeployTempTest.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.tests.integration.jms;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.postoffice.QueueBinding;
import org.apache.activemq.artemis.core.security.Role;
import org.apache.activemq.artemis.core.server.embedded.EmbeddedActiveMQ;
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.utils.ReusableLatch;
import org.junit.Assert;
import org.junit.Test;

public class RedeployTempTest extends ActiveMQTestBase {

   @Test
   public void testRedeployAddressQueueOpenWire() throws Exception {
      Path brokerXML = getTestDirfile().toPath().resolve("broker.xml");
      URL url1 = RedeployTest.class.getClassLoader().getResource("RedeployTempTest-reload-temp.xml");
      URL url2 = RedeployTest.class.getClassLoader().getResource("RedeployTempTest-reload-temp-updated.xml");
      Files.copy(url1.openStream(), brokerXML);

      EmbeddedActiveMQ embeddedActiveMQ = new EmbeddedActiveMQ();
      embeddedActiveMQ.setConfigResourcePath(brokerXML.toUri().toString());
      embeddedActiveMQ.start();

      final ReusableLatch latch = new ReusableLatch(1);

      Runnable tick = latch::countDown;

      embeddedActiveMQ.getActiveMQServer().getReloadManager().setTick(tick);

      ConnectionFactory connectionFactory = new org.apache.activemq.ActiveMQConnectionFactory();
      Connection connection = connectionFactory.createConnection();
      connection.start();
      Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
      Destination destination = session.createQueue("queue");
      MessageProducer messageProducer = session.createProducer(destination);

      Destination replyTo = session.createTemporaryQueue();
      Message message = session.createTextMessage("hello");
      message.setJMSReplyTo(replyTo);
      messageProducer.send(message);

      try {
         latch.await(10, TimeUnit.SECONDS);

         Files.copy(url2.openStream(), brokerXML, StandardCopyOption.REPLACE_EXISTING);
         brokerXML.toFile().setLastModified(System.currentTimeMillis() + 1000);
         latch.setCount(1);
         embeddedActiveMQ.getActiveMQServer().getReloadManager().setTick(tick);
         latch.await(10, TimeUnit.SECONDS);

         try (Connection connectionConsumer = connectionFactory.createConnection()) {
            connectionConsumer.start();
            try (Session sessionConsumer = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) {
               Destination destinationConsumer = session.createQueue("queue");
               MessageConsumer messageConsumer = sessionConsumer.createConsumer(destinationConsumer);

               Message receivedMessage = messageConsumer.receive(1000);
               assertEquals("hello", ((TextMessage) receivedMessage).getText());

               Destination replyToDest = receivedMessage.getJMSReplyTo();
               Message message1 = sessionConsumer.createTextMessage("hi there");

               session.createProducer(replyToDest).send(message1);
            }
         }

         MessageConsumer messageConsumerProducer = session.createConsumer(replyTo);
         Message message2 = messageConsumerProducer.receive(1000);
         Assert.assertNotNull(message2);
         assertEquals("hi there", ((TextMessage) message2).getText());

      } finally {
         connection.close();
         embeddedActiveMQ.stop();
      }
   }

   private AddressSettings getAddressSettings(EmbeddedActiveMQ embeddedActiveMQ, String address) {
      return embeddedActiveMQ.getActiveMQServer().getAddressSettingsRepository().getMatch(address);
   }

   private Set<Role> getSecurityRoles(EmbeddedActiveMQ embeddedActiveMQ, String address) {
      return embeddedActiveMQ.getActiveMQServer().getSecurityRepository().getMatch(address);
   }

   private AddressInfo getAddressInfo(EmbeddedActiveMQ embeddedActiveMQ, String address) {
      return embeddedActiveMQ.getActiveMQServer().getPostOffice().getAddressInfo(SimpleString.toSimpleString(address));
   }

   private org.apache.activemq.artemis.core.server.Queue getQueue(EmbeddedActiveMQ embeddedActiveMQ,
                                                                  String queueName) throws Exception {
      QueueBinding queueBinding = (QueueBinding) embeddedActiveMQ.getActiveMQServer().getPostOffice().getBinding(SimpleString.toSimpleString(queueName));
      return queueBinding == null ? null : queueBinding.getQueue();
   }

   private List<String> listQueuesNamesForAddress(EmbeddedActiveMQ embeddedActiveMQ, String address) throws Exception {
      return embeddedActiveMQ.getActiveMQServer().getPostOffice().listQueuesForAddress(SimpleString.toSimpleString(address)).stream().map(org.apache.activemq.artemis.core.server.Queue::getName).map(SimpleString::toString).collect(Collectors.toList());
   }

}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cluster/topology/NettyHAClientTopologyWithDiscoveryTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.cluster.topology;

import org.apache.activemq.artemis.api.core.DiscoveryGroupConfiguration;
import org.apache.activemq.artemis.api.core.UDPBroadcastEndpointFactory;
import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.core.client.impl.ServerLocatorImpl;
import org.junit.Assert;
import org.junit.Test;

import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.atomic.AtomicInteger;

public class NettyHAClientTopologyWithDiscoveryTest extends HAClientTopologyWithDiscoveryTest {

   @Override
   protected boolean isNetty() {
      return true;
   }



   @Test
   public void testRecoveryBadUDPWithRetry() throws Exception {
      startServers(0);
      ServerLocatorImpl serverLocator = (ServerLocatorImpl) createHAServerLocator();
      serverLocator.setInitialConnectAttempts(10);
      serverLocator.initialize();
      serverLocator.getDiscoveryGroup().stop();


      ClientSessionFactory factory = serverLocator.createSessionFactory();
      ClientSession session = factory.createSession();
      session.close();
   }

   @Test
   public void testRecoveryBadUDPWithoutRetry() throws Exception {
      startServers(0);
      ServerLocatorImpl serverLocator = (ServerLocatorImpl) createHAServerLocator();
      serverLocator.setInitialConnectAttempts(0);
      serverLocator.initialize();
      serverLocator.getDiscoveryGroup().stop();


      boolean failure = false;
      try {
         ClientSessionFactory factory = serverLocator.createSessionFactory();
         ClientSession session = factory.createSession();
         session.close();
         factory.close();
      } catch (Exception e) {
         e.printStackTrace();
         failure = true;
      }

      Assert.assertTrue(failure);

      ClientSessionFactory factory = serverLocator.createSessionFactory();
      ClientSession session = factory.createSession();
      session.close();
      factory.close();

   }

   @Test
   public void testNoServer() {
      final ServerLocatorImpl serverLocator = (ServerLocatorImpl)ActiveMQClient.createServerLocatorWithHA(new DiscoveryGroupConfiguration().
              setBroadcastEndpointFactory(new UDPBroadcastEndpointFactory().setGroupAddress(groupAddress).
                      setGroupPort(groupPort)).setDiscoveryInitialWaitTimeout(10)).setInitialConnectAttempts(0);
      addServerLocator(serverLocator);
      serverLocator.setInitialConnectAttempts(3);

      try {
         serverLocator.createSessionFactory();
         Assert.fail("Exception was expected");
      } catch (Exception e) {
      }
   }


   @Test
   public void testConnectWithMultiThread() throws Exception {
      final AtomicInteger errors = new AtomicInteger(0);
      int NUMBER_OF_THREADS = 100;
      final CyclicBarrier barrier = new CyclicBarrier(NUMBER_OF_THREADS);
      final ServerLocatorImpl serverLocator = (ServerLocatorImpl)ActiveMQClient.createServerLocatorWithHA(new DiscoveryGroupConfiguration().
              setBroadcastEndpointFactory(new UDPBroadcastEndpointFactory().setGroupAddress(groupAddress).
                      setGroupPort(groupPort)).setDiscoveryInitialWaitTimeout(1000)).setInitialConnectAttempts(0);
      serverLocator.setBlockOnNonDurableSend(true).setBlockOnDurableSend(true);
      addServerLocator(serverLocator);

      startServers(0);

      try {

         serverLocator.setInitialConnectAttempts(0);

         Runnable runnable = new Runnable() {
            @Override
            public void run() {
               try {
                  barrier.await();

                  ClientSessionFactory factory = serverLocator.createSessionFactory();
                  ClientSession session = factory.createSession();
                  session.close();
                  factory.close();

               } catch (Exception e) {
                  e.printStackTrace();
                  errors.incrementAndGet();
               }
            }
         };


         Thread[] threads = new Thread[NUMBER_OF_THREADS];

         for (int i = 0; i < threads.length; i++) {
            threads[i] = new Thread(runnable);
            threads[i].start();
         }

         for (Thread t : threads) {
            t.join();
         }


         Assert.assertEquals(0, errors.get());

         serverLocator.close();

         serverLocator.getDiscoveryGroup().stop();
      } finally {
         stopServers(0);
      }
   }





}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/AmqpTestSupport.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.amqp;

import java.net.URI;
import java.util.LinkedList;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import org.apache.activemq.artemis.protocol.amqp.broker.AMQPStandardMessage;
import org.apache.activemq.artemis.protocol.amqp.util.NettyWritable;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.transport.amqp.client.AmqpClient;
import org.apache.activemq.transport.amqp.client.AmqpConnection;
import org.apache.qpid.proton.message.impl.MessageImpl;
import org.junit.After;

/**
 * Base test support class providing client support methods to aid in
 * creating and configuration the AMQP test client.
 */
public class AmqpTestSupport extends ActiveMQTestBase {

   protected static final int AMQP_PORT = 5672;

   protected LinkedList<AmqpConnection> connections = new LinkedList<>();

   protected boolean useSSL;
   protected boolean useWebSockets;

   protected AmqpConnection addConnection(AmqpConnection connection) {
      connections.add(connection);
      return connection;
   }

   @After
   @Override
   public void tearDown() throws Exception {
      for (AmqpConnection conn : connections) {
         try {
            conn.close();
         } catch (Throwable ignored) {
            ignored.printStackTrace();
         }
      }

      super.tearDown();
   }

   public boolean isUseSSL() {
      return useSSL;
   }

   public boolean isUseWebSockets() {
      return useWebSockets;
   }

   public String getAmqpConnectionURIOptions() {
      return "";
   }

   public URI getBrokerAmqpConnectionURI() {
      boolean webSocket = isUseWebSockets();

      try {
         int port = AMQP_PORT;

         String uri = null;

         if (isUseSSL()) {
            if (webSocket) {
               uri = "wss://127.0.0.1:" + port;
            } else {
               uri = "ssl://127.0.0.1:" + port;
            }
         } else {
            if (webSocket) {
               uri = "ws://127.0.0.1:" + port;
            } else {
               uri = "tcp://127.0.0.1:" + port;
            }
         }

         if (!getAmqpConnectionURIOptions().isEmpty()) {
            uri = uri + "?" + getAmqpConnectionURIOptions();
         }

         return new URI(uri);
      } catch (Exception e) {
         throw new RuntimeException();
      }
   }

   public AmqpConnection createAmqpConnection() throws Exception {
      return createAmqpConnection(getBrokerAmqpConnectionURI());
   }

   public AmqpConnection createAmqpConnection(String username, String password) throws Exception {
      return createAmqpConnection(getBrokerAmqpConnectionURI(), username, password);
   }

   public AmqpConnection createAmqpConnection(URI brokerURI) throws Exception {
      return createAmqpConnection(brokerURI, null, null);
   }

   public AmqpConnection createAmqpConnection(URI brokerURI, String username, String password) throws Exception {
      return createAmqpClient(brokerURI, username, password).connect();
   }

   public AmqpClient createAmqpClient() throws Exception {
      return createAmqpClient(getBrokerAmqpConnectionURI(), null, null);
   }

   public AmqpClient createAmqpClient(URI brokerURI) throws Exception {
      return createAmqpClient(brokerURI, null, null);
   }

   public AmqpClient createAmqpClient(String username, String password) throws Exception {
      return createAmqpClient(getBrokerAmqpConnectionURI(), username, password);
   }

   public AmqpClient createAmqpClient(URI brokerURI, String username, String password) throws Exception {
      return new AmqpClient(brokerURI, username, password);
   }

   public static AMQPStandardMessage encodeAndDecodeMessage(int messageFormat, MessageImpl message, int expectedSize) {
      ByteBuf nettyBuffer = Unpooled.buffer(expectedSize);

      message.encode(new NettyWritable(nettyBuffer));
      byte[] bytes = new byte[nettyBuffer.writerIndex()];
      nettyBuffer.readBytes(bytes);

      return new AMQPStandardMessage(messageFormat, bytes, null);
   }


}


<|start_filename|>artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/services/toolbar.js<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
var Artemis;
(function (Artemis) {
    Artemis._module.run(configureToolbar);

       function configureToolbar($templateCache) {
           $templateCache.put('plugin/artemistoolbar.html',
                `
                <div class="row toolbar-pf table-view-pf-toolbar" id="toolbar1">
                    <form class="toolbar-pf-actions">
                        <div class="form-group toolbar-pf-filter">
                            <div class="input-group">
                                <div class="input-group-btn" style="padding-left: 10px">
                                    <button id="filter.values.field" type="button" class="btn btn-default dropdown-toggle" id="filter" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{{$ctrl.filter.text.fieldText}} <span class="caret"></span></button>
                                    <ul class="dropdown-menu">
                                        <li ng-repeat="option in $ctrl.filter.fieldOptions"
                                            id="option.id" ng-click="$ctrl.filter.values.field = option.id;$ctrl.filter.text.fieldText = option.name">{{ option.name }}</ul>
                                    </ul>
                                </div>
                                <div class="input-group-btn">
                                      <button type="button" class="btn btn-default dropdown-toggle" id="filter" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{{$ctrl.filter.text.operationText}}<span class="caret"></span></button>
                                      <ul class="dropdown-menu">
                                        <li ng-repeat="option in $ctrl.filter.operationOptions"
                                              id="option.id" ng-click="$ctrl.filter.values.operation = option.id;$ctrl.filter.text.operationText = option.name">{{ option.name }}</ul>
                                      </ul>
                                </div>
                                <input type="text" class="form-control" ng-model="$ctrl.filter.values.value" placeholder="Value" autocomplete="off" id="filterInput">
                                <div class="input-group-btn" style="padding-left: 10px">
                                      <button type="button" class="btn btn-default dropdown-toggle" id="filter" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{{$ctrl.filter.text.sortOrderText}}<span class="caret"></span></button>
                                      <ul class="dropdown-menu">
                                        <li ng-repeat="option in $ctrl.filter.sortOptions"
                                              id="option.id" ng-click="$ctrl.filter.values.sortOrder = option.id;$ctrl.filter.text.sortOrderText = option.name">{{ option.name }}</ul>
                                      </ul>
                                </div>
                                <div class="input-group-btn">
                                      <button type="button" class="btn btn-default dropdown-toggle" id="filter" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">{{$ctrl.filter.text.sortByText}}<span class="caret"></span></button>
                                      <ul class="dropdown-menu">
                                        <li ng-repeat="option in $ctrl.filter.fieldOptions"
                                              id="option.id" ng-click="$ctrl.filter.values.sortColumn = option.id;$ctrl.filter.text.sortByText = option.name">{{ option.name }}</ul>
                                      </ul>
                                </div>
                                <div class="input-group-btn">
                                    <button class="btn btn-link btn-find" ng-click="$ctrl.refresh()" type="button">
                                        &nbsp;&nbsp;<span class="fa fa-search"></span>&nbsp;&nbsp;
                                    </button>
                                </div>
                                <div class="input-group-btn">
                                    <button class="btn btn-default primary-action ng-binding ng-scope"
                                        type="button"
                                        title=""
                                        ng-click="$ctrl.reset()">Reset
                                    </button>
                                </div>
                                <div class="input-group-btn" style="padding-left: 10px">
                                    <button class="btn btn-default primary-action ng-binding ng-scope"
                                        type="button"
                                        title=""
                                        ng-click="$ctrl.showColumns = true">Columns
                                    </button>
                                </div>
                            </div>
                        </div>
                        <div hawtio-confirm-dialog="$ctrl.showColumns"
                          title="Column Selector"
                          cancel-button-text="Close"
                          on-cancel="$ctrl.updateColumns()"
                          show-ok-button="false">
                            <div class="dialog-body ng-non-bindable" >
                                <table class="table-view-container table table-striped table-bordered table-hover dataTable no-footer">
                                    <tr ng-repeat="col in $ctrl.dtOptions.columns">
                                        <td>{{ col.name }}</td>
                                        <td><input type="checkbox" ng-model="col.visible" placeholder="Name" autocomplete="off" id="name"></td>
                                    </tr>
                                </table>
                            </div>
                        </div>
                    </form>
                 </div>
               `
           )
           $templateCache.put('plugin/artemismessagetoolbar.html',
                `
                <div class="row toolbar-pf table-view-pf-toolbar" id="toolbar1">
                    <div class="col-sm-20">
                        <form class="toolbar-pf-actions">
                            <div class="form-group toolbar-pf-filter">
                                <div class="input-group">
                                    <input type="text" class="form-control" ng-model="$ctrl.filter.values.value" placeholder="Filter..." autocomplete="off" id="filterInput">
                                    <div class="input-group-btn">
                                        <button class="btn btn-link btn-find" ng-click="$ctrl.refresh()" type="button">
                                            &nbsp;&nbsp;<span class="fa fa-search"></span>&nbsp;&nbsp;
                                        </button>
                                    </div>
                                </div>
                            </div>
                            <div class="form-group">
                                    <button class="btn btn-default primary-action ng-binding ng-scope"
                                        type="button"
                                        title=""
                                        ng-click="$ctrl.reset()">Reset
                                    </button>
                                    <button ng-show="$ctrl.dlq" class="btn btn-default primary-action ng-binding ng-scope"
                                        type="button"
                                        title=""
                                        ng-click="$ctrl.retry()">Retry Messages
                                    </button>
                                    <button ng-show="$ctrl.dlq" class="btn btn-default primary-action ng-binding ng-scope"
                                        type="button"
                                        title=""
                                        ng-click="$ctrl.retry()">Move Messages
                                    </button>
                            </div>
                        </form>
                    </div>
                </div>
                `
          )
       }
       configureToolbar.$inject = ['$templateCache'];



})(Artemis || (Artemis = {}));

<|start_filename|>tests/smoke-tests/src/test/java/org/apache/activemq/artemis/tests/smoke/jmxfailback/JmxFailbackTest.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.tests.smoke.jmxfailback;

import javax.management.MBeanServerInvocationHandler;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import java.io.File;

import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
import org.apache.activemq.artemis.api.core.management.ActiveMQServerControl;
import org.apache.activemq.artemis.api.core.management.ObjectNameBuilder;
import org.apache.activemq.artemis.tests.smoke.common.SmokeTestBase;
import org.apache.activemq.artemis.utils.Wait;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class JmxFailbackTest extends SmokeTestBase {

   // This test will use a smoke created by the pom on this project (smoke-tsts)
   private static final String JMX_SERVER_HOSTNAME = "localhost";
   private static final int JMX_SERVER_PORT_0 = 10099;
   private static final int JMX_SERVER_PORT_1 = 10199;

   public static final String SERVER_NAME_0 = "jmx-failback1";
   public static final String SERVER_NAME_1 = "jmx-failback2";

   String urlString_1 = "service:jmx:rmi:///jndi/rmi://" + JMX_SERVER_HOSTNAME + ":" + JMX_SERVER_PORT_0 + "/jmxrmi";
   String urlString_2 = "service:jmx:rmi:///jndi/rmi://" + JMX_SERVER_HOSTNAME + ":" + JMX_SERVER_PORT_1 + "/jmxrmi";

   ObjectNameBuilder objectNameBuilder1 = ObjectNameBuilder.create(ActiveMQDefaultConfiguration.getDefaultJmxDomain(), "live", true);
   ObjectNameBuilder objectNameBuilder2 = ObjectNameBuilder.create(ActiveMQDefaultConfiguration.getDefaultJmxDomain(), "backup", true);

   JMXServiceURL url1 = null;
   JMXServiceURL url2 = null;

   Process server1;
   Process server2;

   @Before
   public void before() throws Exception {
      url1 = new JMXServiceURL(urlString_1);
      url2 = new JMXServiceURL(urlString_2);
      deleteDirectory(new File("shared-jmxfailback"));
      disableCheckThread();
      server1 = startServer(SERVER_NAME_0, 0, 30000);
      Wait.assertTrue(() -> testConnection(url1, objectNameBuilder1));
      server2 = startServer(SERVER_NAME_1, 0, 0);
      Wait.assertTrue(() -> testConnection(url2, objectNameBuilder2));
   }

   boolean isBackup(JMXServiceURL serviceURI, ObjectNameBuilder builder) throws Exception {
      JMXConnector jmx = null;
      try {
         jmx = JMXConnectorFactory.connect(serviceURI);
         builder.getActiveMQServerObjectName();

         ActiveMQServerControl control = MBeanServerInvocationHandler.newProxyInstance(jmx.getMBeanServerConnection(), builder.getActiveMQServerObjectName(), ActiveMQServerControl.class, false);
         return control.isBackup(); // performing any operation to make sure JMX is bound already
      } finally {
         try {
            jmx.close();
         } catch (Exception e) {
         }
      }
   }

   boolean testConnection(JMXServiceURL serviceURI, ObjectNameBuilder builder) {
      try {
         isBackup(serviceURI, builder);
         return true;
      } catch (Exception e) {
         return false;
      }
   }

   @Test
   public void testFailbackOnJMX() throws Exception {
      Assert.assertFalse(isBackup(url1, objectNameBuilder1));
      Assert.assertTrue(isBackup(url2, objectNameBuilder2));

      server1.destroyForcibly();
      Wait.assertFalse(() -> isBackup(url2, objectNameBuilder2));

      server1 = startServer(SERVER_NAME_0, 0, 30000);
      Wait.assertTrue(() -> testConnection(url1, objectNameBuilder1), 5_000, 100);
      Wait.assertTrue(() -> testConnection(url2, objectNameBuilder2), 5_000, 100);

      Wait.assertFalse(() -> isBackup(url1, objectNameBuilder1), 5_000, 100);
      Wait.assertTrue(() -> isBackup(url2, objectNameBuilder2), 5_000, 100);
   }
}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/impl/AddressMap.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.core.postoffice.impl;

import org.apache.activemq.artemis.api.core.SimpleString;

public class AddressMap<T> {

   private final AddressPartNode<T> rootNode;
   private final char DELIMITER;

   public AddressMap(final String any, String single, char delimiter) {
      rootNode = new AddressPartNode<>(any, single);
      this.DELIMITER = delimiter;
   }

   public void put(final SimpleString key, T value) {
      rootNode.add(getPaths(key), 0, value);
   }

   public void remove(final SimpleString key, T value) {
      rootNode.remove(getPaths(key), 0, value);
   }

   public void reset() {
      rootNode.reset();
   }

   public String[] getPaths(final SimpleString address) {
      return address.getPaths(DELIMITER);
   }

   /**
    * @param address - a non wildcard to match against wildcards in the map
    */
   public void visitMatchingWildcards(SimpleString address,
                                      AddressMapVisitor<T> collector) throws Exception {

      final String[] paths = getPaths(address);
      rootNode.visitMatchingWildcards(paths, 0, collector);
   }

   /**
   * @param wildcardAddress - a wildcard address to match against non wildcards in the map
   */
   public void visitMatching(SimpleString wildcardAddress,
                             AddressMapVisitor<T> collector) throws Exception {
      final String[] paths = getPaths(wildcardAddress);
      rootNode.visitNonWildcard(paths, 0, collector);
   }

}



<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/largemessages/AMQPLargeMessageSizeTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.amqp.largemessages;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;

import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.core.io.IOCallback;
import org.apache.activemq.artemis.core.io.SequentialFile;
import org.apache.activemq.artemis.core.io.buffer.TimedBuffer;
import org.apache.activemq.artemis.core.journal.EncodingSupport;
import org.apache.activemq.artemis.core.persistence.impl.journal.LargeBody;
import org.apache.activemq.artemis.core.persistence.impl.journal.LargeServerMessageImpl;
import org.apache.activemq.artemis.core.persistence.impl.nullpm.NullStorageManager;
import org.apache.activemq.artemis.protocol.amqp.broker.AMQPLargeMessage;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.junit.Assert;
import org.junit.Test;

public class AMQPLargeMessageSizeTest extends ActiveMQTestBase {

   @Test
   public void testAMQPMockLargeMessageSize() throws Exception {
      AMQPLargeMessage amqpLargeMessage = new AMQPLargeMessage(1, 0, null, null, null, new MockLargeBody(123456));
      Assert.assertTrue(amqpLargeMessage.getWholeMessageSize() >= 123456);
   }

   @Test
   public void testCoreMockLargeMessageSize() throws Exception {
      LargeServerMessageImpl largeServerMessage = new LargeServerMessageImpl((byte) 0, 1, new MockSM(123456), null);
      Assert.assertTrue(largeServerMessage.getWholeMessageSize() >= 123456);
   }

   private static class MockSM extends NullStorageManager {

      final long size;

      MockSM(long size) {
         this.size = size;
      }

      @Override
      public SequentialFile createFileForLargeMessage(long messageID, boolean durable) {
         return new MockFileSize(size);
      }

      @Override
      public SequentialFile createFileForLargeMessage(long messageID, LargeMessageExtension extension) {
         return new MockFileSize(size);
      }
   }

   private static class MockFileSize implements SequentialFile {

      final long size;

      MockFileSize(long size) {
         this.size = size;
      }

      @Override
      public boolean isOpen() {
         return false;
      }

      @Override
      public boolean exists() {
         return false;
      }

      @Override
      public void open() throws Exception {

      }

      @Override
      public void open(int maxIO, boolean useExecutor) throws Exception {

      }

      @Override
      public ByteBuffer map(int position, long size) throws IOException {
         return null;
      }

      @Override
      public boolean fits(int size) {
         return false;
      }

      @Override
      public int calculateBlockStart(int position) throws Exception {
         return 0;
      }

      @Override
      public String getFileName() {
         return null;
      }

      @Override
      public void fill(int size) throws Exception {

      }

      @Override
      public void delete() throws IOException, InterruptedException, ActiveMQException {

      }

      @Override
      public void write(ActiveMQBuffer bytes, boolean sync, IOCallback callback) throws Exception {

      }

      @Override
      public void write(ActiveMQBuffer bytes, boolean sync) throws Exception {

      }

      @Override
      public void write(EncodingSupport bytes, boolean sync, IOCallback callback) throws Exception {

      }

      @Override
      public void write(EncodingSupport bytes, boolean sync) throws Exception {

      }

      @Override
      public void writeDirect(ByteBuffer bytes, boolean sync, IOCallback callback) {

      }

      @Override
      public void writeDirect(ByteBuffer bytes, boolean sync) throws Exception {

      }

      @Override
      public void blockingWriteDirect(ByteBuffer bytes, boolean sync, boolean releaseBuffer) throws Exception {

      }

      @Override
      public int read(ByteBuffer bytes, IOCallback callback) throws Exception {
         return 0;
      }

      @Override
      public int read(ByteBuffer bytes) throws Exception {
         return 0;
      }

      @Override
      public void position(long pos) throws IOException {

      }

      @Override
      public long position() {
         return 0;
      }

      @Override
      public void close() throws Exception {

      }

      @Override
      public void sync() throws IOException {

      }

      @Override
      public long size() throws Exception {
         return size;
      }

      @Override
      public void renameTo(String newFileName) throws Exception {

      }

      @Override
      public SequentialFile cloneFile() {
         return null;
      }

      @Override
      public void copyTo(SequentialFile newFileName) throws Exception {

      }

      @Override
      public void setTimedBuffer(TimedBuffer buffer) {

      }

      @Override
      public File getJavaFile() {
         return null;
      }
   }

   private static class MockLargeBody extends LargeBody {

      final long size;

      MockLargeBody(long size) {
         super(null, null);
         this.size = size;
      }

      @Override
      public long getBodySize() {
         return size;
      }
   }

}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/server/cluster/ha/ColocatedPolicy.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.server.cluster.ha;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
import org.apache.activemq.artemis.core.io.IOCriticalErrorListener;
import org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl;
import org.apache.activemq.artemis.core.server.impl.ColocatedActivation;
import org.apache.activemq.artemis.core.server.impl.LiveActivation;

public class ColocatedPolicy implements HAPolicy<LiveActivation> {

   /*live stuff*/
   private boolean requestBackup = ActiveMQDefaultConfiguration.isDefaultHapolicyRequestBackup();

   private int backupRequestRetries = ActiveMQDefaultConfiguration.getDefaultHapolicyBackupRequestRetries();

   private long backupRequestRetryInterval = ActiveMQDefaultConfiguration.getDefaultHapolicyBackupRequestRetryInterval();

   private int maxBackups = ActiveMQDefaultConfiguration.getDefaultHapolicyMaxBackups();

   private int backupPortOffset = ActiveMQDefaultConfiguration.getDefaultHapolicyBackupPortOffset();

   /*backup stuff*/
   private List<String> excludedConnectors = new ArrayList<>();

   private BackupPolicy backupPolicy;

   private HAPolicy<LiveActivation> livePolicy;

   public ColocatedPolicy(boolean requestBackup,
                          int backupRequestRetries,
                          long backupRequestRetryInterval,
                          int maxBackups,
                          int backupPortOffset,
                          List<String> excludedConnectors,
                          HAPolicy livePolicy,
                          BackupPolicy backupPolicy) {
      this.requestBackup = requestBackup;
      this.backupRequestRetries = backupRequestRetries;
      this.backupRequestRetryInterval = backupRequestRetryInterval;
      this.maxBackups = maxBackups;
      this.backupPortOffset = backupPortOffset;
      this.excludedConnectors = excludedConnectors;
      this.livePolicy = livePolicy;
      this.backupPolicy = backupPolicy;
   }

   @Override
   public String getBackupGroupName() {
      final HAPolicy<LiveActivation> livePolicy = this.livePolicy;
      if (livePolicy == null) {
         return null;
      }
      return livePolicy.getBackupGroupName();
   }

   @Override
   public String getScaleDownGroupName() {
      return null;
   }

   @Override
   public boolean isSharedStore() {
      return backupPolicy.isSharedStore();
   }

   @Override
   public boolean isBackup() {
      return false;
   }

   @Override
   public LiveActivation createActivation(ActiveMQServerImpl server,
                                          boolean wasLive,
                                          Map<String, Object> activationParams,
                                          IOCriticalErrorListener ioCriticalErrorListener) throws Exception {
      return new ColocatedActivation(server, this, livePolicy.createActivation(server, wasLive, activationParams, ioCriticalErrorListener));
   }

   @Override
   public boolean canScaleDown() {
      return false;
   }

   @Override
   public String getScaleDownClustername() {
      return null;
   }

   public boolean isRequestBackup() {
      return requestBackup;
   }

   public void setRequestBackup(boolean requestBackup) {
      this.requestBackup = requestBackup;
   }

   public int getBackupRequestRetries() {
      return backupRequestRetries;
   }

   public void setBackupRequestRetries(int backupRequestRetries) {
      this.backupRequestRetries = backupRequestRetries;
   }

   public long getBackupRequestRetryInterval() {
      return backupRequestRetryInterval;
   }

   public void setBackupRequestRetryInterval(long backupRequestRetryInterval) {
      this.backupRequestRetryInterval = backupRequestRetryInterval;
   }

   public int getMaxBackups() {
      return maxBackups;
   }

   public void setMaxBackups(int maxBackups) {
      this.maxBackups = maxBackups;
   }

   public int getBackupPortOffset() {
      return backupPortOffset;
   }

   public void setBackupPortOffset(int backupPortOffset) {
      this.backupPortOffset = backupPortOffset;
   }

   public List<String> getExcludedConnectors() {
      return excludedConnectors;
   }

   public void setExcludedConnectors(List<String> excludedConnectors) {
      this.excludedConnectors = excludedConnectors;
   }

   public HAPolicy<LiveActivation> getLivePolicy() {
      return livePolicy;
   }

   public void setLivePolicy(HAPolicy<LiveActivation> livePolicy) {
      this.livePolicy = livePolicy;
   }

   public BackupPolicy getBackupPolicy() {
      return backupPolicy;
   }

   public void setBackupPolicy(BackupPolicy backupPolicy) {
      this.backupPolicy = backupPolicy;
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/openwire/OpenWireLargeMessageTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.openwire;

import javax.jms.BytesMessage;
import javax.jms.Connection;
import javax.jms.DeliveryMode;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import java.util.Map;

import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.paging.PagingStore;
import org.apache.activemq.artemis.core.settings.impl.AddressFullMessagePolicy;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.logs.AssertionLoggerHandler;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class OpenWireLargeMessageTest extends BasicOpenWireTest {

   public OpenWireLargeMessageTest() {
      super();
   }

   public SimpleString lmAddress = new SimpleString("LargeMessageAddress");
   public SimpleString lmDropAddress = new SimpleString("LargeMessageDropAddress");

   @Override
   @Before
   public void setUp() throws Exception {
      this.realStore = true;
      super.setUp();
      server.createQueue(new QueueConfiguration(lmAddress).setRoutingType(RoutingType.ANYCAST));
      server.createQueue(new QueueConfiguration(lmDropAddress).setRoutingType(RoutingType.ANYCAST));
   }

   @Test
   public void testSendLargeMessage() throws Exception {
      try (Connection connection = factory.createConnection()) {
         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
         Queue queue = session.createQueue(lmAddress.toString());
         MessageProducer producer = session.createProducer(queue);
         producer.setDeliveryMode(DeliveryMode.PERSISTENT);

         // Create 1MB Message
         int size = 1024 * 1024;
         byte[] bytes = new byte[size];
         BytesMessage message = session.createBytesMessage();
         message.writeBytes(bytes);
         producer.send(message);
      }
   }

   @Override
   protected void configureAddressSettings(Map<String, AddressSettings> addressSettingsMap) {
      addressSettingsMap.put("#", new AddressSettings().setAutoCreateQueues(false).setAutoCreateAddresses(false).setDeadLetterAddress(new SimpleString("ActiveMQ.DLQ")).setAutoCreateAddresses(true));
      addressSettingsMap.put(lmDropAddress.toString(),
                             new AddressSettings()
                                .setMaxSizeBytes(100 * 1024)
                                .setAddressFullMessagePolicy(AddressFullMessagePolicy.DROP)
                                .setMessageCounterHistoryDayLimit(10)
                                .setRedeliveryDelay(0)
                                .setMaxDeliveryAttempts(0));
   }

   @Test
   public void testSendReceiveLargeMessage() throws Exception {
      // Create 1MB Message
      int size = 1024 * 1024;

      byte[] bytes = new byte[size];

      try (Connection connection = factory.createConnection()) {
         connection.start();

         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
         Queue queue = session.createQueue(lmAddress.toString());
         MessageProducer producer = session.createProducer(queue);
         producer.setDeliveryMode(DeliveryMode.PERSISTENT);

         bytes[0] = 1;

         BytesMessage message = session.createBytesMessage();
         message.writeBytes(bytes);
         producer.send(message);
      }

      server.stop();
      server.start();

      try (Connection connection = factory.createConnection()) {
         connection.start();
         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
         Queue queue = session.createQueue(lmAddress.toString());


         MessageConsumer consumer = session.createConsumer(queue);
         BytesMessage m = (BytesMessage) consumer.receive();
         assertNotNull(m);

         byte[] body = new byte[size];
         m.readBytes(body);

         assertArrayEquals(body, bytes);
      }
   }

   @Test
   public void testFastLargeMessageProducerDropOnPaging() throws Exception {
      AssertionLoggerHandler.startCapture();
      try {
         // Create 100K Message
         int size = 100 * 1024;

         final byte[] bytes = new byte[size];

         try (Connection connection = factory.createConnection()) {
            connection.start();

            try (Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) {
               Queue queue = session.createQueue(lmDropAddress.toString());
               try (MessageProducer producer = session.createProducer(queue)) {
                  producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);

                  bytes[0] = 1;

                  BytesMessage message = session.createBytesMessage();
                  message.writeBytes(bytes);

                  final PagingStore pageStore = server.getPagingManager().getPageStore(lmDropAddress);
                  while (!pageStore.isPaging()) {
                     producer.send(message);
                  }
                  for (int i = 0; i < 10; i++) {
                     producer.send(message);
                  }
                  final long messageCount = server.locateQueue(lmDropAddress).getMessageCount();
                  Assert.assertTrue("The queue cannot be empty", messageCount > 0);
                  try (MessageConsumer messageConsumer = session.createConsumer(queue)) {
                     for (long m = 0; m < messageCount; m++) {
                        if (messageConsumer.receive(2000) == null) {
                           Assert.fail("The messages are not finished yet");
                        }
                     }
                  }
               }
            }
         }
         server.stop();
         Assert.assertFalse(AssertionLoggerHandler.findText("NullPointerException"));
         Assert.assertFalse(AssertionLoggerHandler.findText("It was not possible to delete message"));
      } finally {
         AssertionLoggerHandler.stopCapture();
      }
   }
}


<|start_filename|>artemis-commons/src/main/java/org/apache/activemq/artemis/core/persistence/PersisterIDs.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.core.persistence;



/** this is a list for all the persisters
    The sole purpose of this is to make sure these IDs will not be duplicate
     so we know where to find IDs.
*/

public class PersisterIDs {

   public static final int MAX_PERSISTERS = 5;

   public static final byte CoreLargeMessagePersister_ID = (byte)0;

   public static final byte CoreMessagePersister_ID = (byte)1;

   public static final byte AMQPMessagePersister_ID = (byte)2;

   public static final byte AMQPMessagePersisterV2_ID = (byte)3;

   public static final byte AMQPLargeMessagePersister_ID = (byte)4;

   public static final byte AMQPMessagePersisterV3_ID = (byte)5;

}


<|start_filename|>artemis-core-client/src/main/java/org/apache/activemq/artemis/core/config/federation/FederationPolicySet.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.config.federation;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.utils.Preconditions;

public class FederationPolicySet implements FederationPolicy<FederationPolicySet>, Serializable {

   private String name;
   private Set<String> policyRefs = new HashSet<>();

   @Override
   public String getName() {
      return name;
   }

   @Override
   public FederationPolicySet setName(String name) {
      this.name = name;
      return this;
   }

   public Set<String> getPolicyRefs() {
      return policyRefs;
   }

   public FederationPolicySet addPolicyRef(String name) {
      policyRefs.add(name);
      return this;
   }

   public FederationPolicySet addPolicyRefs(Collection<String> name) {
      policyRefs.addAll(name);
      return this;
   }

   @Override
   public boolean equals(Object o) {
      if (this == o) return true;
      if (!(o instanceof FederationPolicySet)) return false;
      FederationPolicySet that = (FederationPolicySet) o;
      return Objects.equals(name, that.name) &&
            Objects.equals(policyRefs, that.policyRefs);
   }

   @Override
   public int hashCode() {
      return Objects.hash(name, policyRefs);
   }

   @Override
   public void encode(ActiveMQBuffer buffer) {
      Preconditions.checkArgument(name != null, "name can not be null");
      buffer.writeString(name);

      buffer.writeInt(policyRefs == null ? 0 : policyRefs.size());
      if (policyRefs != null) {
         for (String policyRef : policyRefs) {
            buffer.writeString(policyRef);
         }
      }
   }

   @Override
   public void decode(ActiveMQBuffer buffer) {
      name = buffer.readString();

      final int policyRefsSize = buffer.readInt();
      policyRefs = new HashSet<>();

      for (int i = 0; i < policyRefsSize; i++) {
         policyRefs.add(buffer.readString());
      }
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cluster/failover/SharedStoreBackupTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.cluster.failover;

import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.core.config.ScaleDownConfiguration;
import org.apache.activemq.artemis.core.config.ha.SharedStoreMasterPolicyConfiguration;
import org.apache.activemq.artemis.core.config.ha.SharedStoreSlavePolicyConfiguration;
import org.apache.activemq.artemis.core.server.impl.InVMNodeManager;
import org.apache.activemq.artemis.tests.integration.cluster.util.TestableServer;
import org.apache.activemq.artemis.tests.util.TransportConfigurationUtils;
import org.junit.Assert;
import org.junit.Test;

public class SharedStoreBackupTest extends FailoverTestBase {

   @Test
   public void testStartSharedBackupWithScalingDownPolicyDisabled() throws Exception {
      liveServer.stop();
      // wait max 10s for backup to activate
      Assert.assertTrue("Backup did not activate in 10s timeout.", waitForBackupToBecomeActive(backupServer, 10000));
   }

   /**
    * Returns true if backup started in given timeout. False otherwise.
    *
    * @param backupServer backup server
    * @param waitTimeout  timeout in milliseconds
    * @return returns true if backup started in given timeout. False otherwise
    */
   private boolean waitForBackupToBecomeActive(TestableServer backupServer, long waitTimeout) throws Exception {

      long startTime = System.currentTimeMillis();
      boolean isBackupStarted;
      // wait given timeout for backup to activate
      while (!(isBackupStarted = backupServer.isActive()) && System.currentTimeMillis() - startTime < waitTimeout) {
         Thread.sleep(300);
      }
      return isBackupStarted;
   }

   @Override
   protected void createConfigs() throws Exception {
      nodeManager = new InVMNodeManager(false);
      TransportConfiguration liveConnector = getConnectorTransportConfiguration(true);
      TransportConfiguration backupConnector = getConnectorTransportConfiguration(false);
      backupConfig = super.createDefaultConfig(false).clearAcceptorConfigurations().addAcceptorConfiguration(getAcceptorTransportConfiguration(false)).setHAPolicyConfiguration(new SharedStoreSlavePolicyConfiguration().setScaleDownConfiguration(new ScaleDownConfiguration().setEnabled(false)).setRestartBackup(false)).addConnectorConfiguration(liveConnector.getName(), liveConnector).addConnectorConfiguration(backupConnector.getName(), backupConnector).addClusterConfiguration(basicClusterConnectionConfig(backupConnector.getName(), liveConnector.getName()));

      backupServer = createTestableServer(backupConfig);

      liveConfig = super.createDefaultConfig(false).clearAcceptorConfigurations().addAcceptorConfiguration(getAcceptorTransportConfiguration(true)).setHAPolicyConfiguration(new SharedStoreMasterPolicyConfiguration().setFailoverOnServerShutdown(true)).addClusterConfiguration(basicClusterConnectionConfig(liveConnector.getName())).addConnectorConfiguration(liveConnector.getName(), liveConnector);

      liveServer = createTestableServer(liveConfig);
   }

   @Override
   protected TransportConfiguration getAcceptorTransportConfiguration(final boolean live) {
      return TransportConfigurationUtils.getInVMAcceptor(live);
   }

   @Override
   protected TransportConfiguration getConnectorTransportConfiguration(final boolean live) {
      return TransportConfigurationUtils.getInVMConnector(live);
   }

}


<|start_filename|>artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/user/ResetUser.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.cli.commands.user;

import io.airlift.airline.Command;
import io.airlift.airline.Option;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.management.ManagementHelper;
import org.apache.activemq.artemis.cli.commands.AbstractAction;
import org.apache.activemq.artemis.cli.commands.ActionContext;

/**
 * Reset a user's password or roles, example:
 * ./artemis user reset --user guest --role admin --password ***
 */
@Command(name = "reset", description = "Reset user's password or roles")
public class ResetUser extends PasswordAction {

   @Option(name = "--plaintext", description = "store the password in plaintext (Default: false)")
   boolean plaintext = false;

   @Override
   public Object execute(ActionContext context) throws Exception {
      super.execute(context);
      checkInputUser();
      checkInputPassword();
      reset();
      return null;
   }

   private void reset() throws Exception {
      performCoreManagement(new AbstractAction.ManagementCallback<ClientMessage>() {
         @Override
         public void setUpInvocation(ClientMessage message) throws Exception {
            ManagementHelper.putOperationInvocation(message, "broker", "resetUser", userCommandUser, userCommandPassword, role, plaintext);
         }

         @Override
         public void requestSuccessful(ClientMessage reply) throws Exception {
            context.out.println(userCommandUser + " reset successfully.");
         }

         @Override
         public void requestFailed(ClientMessage reply) throws Exception {
            String errMsg = (String) ManagementHelper.getResult(reply, String.class);
            context.err.println("Failed to reset user " + userCommandUser + ". Reason: " + errMsg);
         }
      });
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/JMSNonDestructiveTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.amqp;

import javax.jms.BytesMessage;
import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.management.QueueControl;
import org.apache.activemq.artemis.api.core.management.ResourceNames;
import org.apache.activemq.artemis.core.postoffice.QueueBinding;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.apache.activemq.artemis.core.server.impl.LastValueQueue;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.tests.util.Wait;
import org.apache.activemq.artemis.utils.RetryRule;
import org.jboss.logging.Logger;
import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public class JMSNonDestructiveTest extends JMSClientTestSupport {

   private static final Logger logger = Logger.getLogger(JMSNonDestructiveTest.class);

   @Rule
   public RetryRule retryRule = new RetryRule(2);

   private static final String NON_DESTRUCTIVE_QUEUE_NAME = "NON_DESTRUCTIVE_QUEUE";
   private static final String NON_DESTRUCTIVE_EXPIRY_QUEUE_NAME = "NON_DESTRUCTIVE_EXPIRY_QUEUE";
   private static final String NON_DESTRUCTIVE_LVQ_QUEUE_NAME = "NON_DESTRUCTIVE_LVQ_QUEUE";
   private static final String NON_DESTRUCTIVE_TOMBSTONE_LVQ_QUEUE_NAME = "NON_DESTRUCTIVE_LVQ_TOMBSTONE_QUEUE";

   private ConnectionSupplier AMQPConnection = () -> createConnection();
   private ConnectionSupplier CoreConnection = () -> createCoreConnection();

   protected final boolean persistenceEnabled;
   protected final long scanPeriod;

   public JMSNonDestructiveTest(boolean persistenceEnabled, long scanPeriod) {
      this.persistenceEnabled = persistenceEnabled;
      this.scanPeriod = scanPeriod;
   }

   @Parameterized.Parameters(name = "persistenceEnabled={0}, scanPeriod={1}")
   public static Collection<Object[]> data() {
      Object[][] params = new Object[][]{{false, 100}, {true, 100}, {true, -1}};
      return Arrays.asList(params);
   }

   @Override
   protected String getConfiguredProtocols() {
      return "AMQP,OPENWIRE,CORE";
   }

   @Override
   protected void addConfiguration(ActiveMQServer server) {
      server.getConfiguration().setPersistenceEnabled(persistenceEnabled);
      server.getConfiguration().setMessageExpiryScanPeriod(scanPeriod);
      server.getAddressSettingsRepository().addMatch(NON_DESTRUCTIVE_QUEUE_NAME, new AddressSettings().setDefaultNonDestructive(true));
      server.getAddressSettingsRepository().addMatch(NON_DESTRUCTIVE_EXPIRY_QUEUE_NAME, new AddressSettings().setDefaultNonDestructive(true).setExpiryDelay(100L));
      server.getAddressSettingsRepository().addMatch(NON_DESTRUCTIVE_LVQ_QUEUE_NAME, new AddressSettings().setDefaultLastValueQueue(true).setDefaultNonDestructive(true));
      server.getAddressSettingsRepository().addMatch(NON_DESTRUCTIVE_TOMBSTONE_LVQ_QUEUE_NAME, new AddressSettings().setDefaultLastValueQueue(true).setDefaultNonDestructive(true));
   }
   @Override
   protected void createAddressAndQueues(ActiveMQServer server) throws Exception {
      super.createAddressAndQueues(server);

      //Add Non Destructive Queue
      server.addAddressInfo(new AddressInfo(SimpleString.toSimpleString(NON_DESTRUCTIVE_QUEUE_NAME), RoutingType.ANYCAST));
      server.createQueue(new QueueConfiguration(NON_DESTRUCTIVE_QUEUE_NAME).setRoutingType(RoutingType.ANYCAST));

      //Add Non Destructive Expiry Queue
      server.addAddressInfo(new AddressInfo(SimpleString.toSimpleString(NON_DESTRUCTIVE_EXPIRY_QUEUE_NAME), RoutingType.ANYCAST));
      server.createQueue(new QueueConfiguration(NON_DESTRUCTIVE_EXPIRY_QUEUE_NAME).setRoutingType(RoutingType.ANYCAST));

      //Add Non Destructive Last Value Queue
      server.addAddressInfo(new AddressInfo(SimpleString.toSimpleString(NON_DESTRUCTIVE_LVQ_QUEUE_NAME), RoutingType.ANYCAST));
      server.createQueue(new QueueConfiguration(NON_DESTRUCTIVE_LVQ_QUEUE_NAME).setRoutingType(RoutingType.ANYCAST));

      //Add  Non Destructive Last Value Queue for Tombstone Test
      server.addAddressInfo(new AddressInfo(SimpleString.toSimpleString(NON_DESTRUCTIVE_TOMBSTONE_LVQ_QUEUE_NAME), RoutingType.ANYCAST));
      server.createQueue(new QueueConfiguration(NON_DESTRUCTIVE_TOMBSTONE_LVQ_QUEUE_NAME).setRoutingType(RoutingType.ANYCAST));

   }


   @Test
   public void testNonDestructiveAMQPProducerAMQPConsumer() throws Exception {
      testNonDestructive(AMQPConnection, AMQPConnection);
   }

   @Test
   public void testNonDestructiveCoreProducerCoreConsumer() throws Exception {
      testNonDestructive(CoreConnection, CoreConnection);
   }

   @Test
   public void testNonDestructiveCoreProducerAMQPConsumer() throws Exception {
      testNonDestructive(CoreConnection, AMQPConnection);
   }

   @Test
   public void testNonDestructiveAMQPProducerCoreConsumer() throws Exception {
      testNonDestructive(AMQPConnection, CoreConnection);
   }

   @Test
   public void testNonDestructiveLVQWithConsumerFirstCore() throws Exception {
      testNonDestructiveLVQWithConsumerFirst(CoreConnection);
   }

   @Test
   public void testNonDestructiveLVQWithConsumerFirstAMQP() throws Exception {
      testNonDestructiveLVQWithConsumerFirst(AMQPConnection);
   }

   public void testNonDestructive(ConnectionSupplier producerConnectionSupplier, ConnectionSupplier consumerConnectionSupplier) throws Exception {
      testNonDestructiveSingle(producerConnectionSupplier, consumerConnectionSupplier);
      testNonDestructiveDualConsumer(producerConnectionSupplier, consumerConnectionSupplier);
      testNonDestructiveExpiry(producerConnectionSupplier, consumerConnectionSupplier);
      testNonDestructiveMulitpleMessages(producerConnectionSupplier, consumerConnectionSupplier);
      testNonDestructiveMulitpleMessagesDualConsumer(producerConnectionSupplier, consumerConnectionSupplier);
      testNonDestructiveLVQ(producerConnectionSupplier, consumerConnectionSupplier);
      testNonDestructiveLVQTombstone(producerConnectionSupplier, consumerConnectionSupplier);

   }


   public void testNonDestructiveSingle(ConnectionSupplier producerConnectionSupplier, ConnectionSupplier consumerConnectionSupplier) throws Exception {
      sendMessage(producerConnectionSupplier, NON_DESTRUCTIVE_QUEUE_NAME);

      QueueBinding queueBinding = (QueueBinding) server.getPostOffice().getBinding(SimpleString.toSimpleString(NON_DESTRUCTIVE_QUEUE_NAME));
      assertEquals("Ensure Message count", 1, queueBinding.getQueue().getMessageCount());


      //Consume Once
      receive(consumerConnectionSupplier, NON_DESTRUCTIVE_QUEUE_NAME);
      assertEquals("Ensure Message count", 1, queueBinding.getQueue().getMessageCount());

      //Consume Again as should be non-destructive
      receive(consumerConnectionSupplier, NON_DESTRUCTIVE_QUEUE_NAME);
      assertEquals("Ensure Message count", 1, queueBinding.getQueue().getMessageCount());

      QueueControl control = (QueueControl) server.getManagementService().getResource(ResourceNames.QUEUE + NON_DESTRUCTIVE_QUEUE_NAME);
      control.removeAllMessages();

      assertEquals("Message count after clearing queue via queue control should be 0", 0, queueBinding.getQueue().getMessageCount());
   }

   public void testNonDestructiveDualConsumer(ConnectionSupplier producerConnectionSupplier, ConnectionSupplier consumerConnectionSupplier) throws Exception {
      sendMessage(producerConnectionSupplier, NON_DESTRUCTIVE_QUEUE_NAME);

      QueueBinding queueBinding = (QueueBinding) server.getPostOffice().getBinding(SimpleString.toSimpleString(NON_DESTRUCTIVE_QUEUE_NAME));
      assertEquals("Ensure Message count", 1, queueBinding.getQueue().getMessageCount());


      //Consume Once
      receiveDualConsumer(consumerConnectionSupplier, NON_DESTRUCTIVE_QUEUE_NAME);
      assertEquals("Ensure Message count", 1, queueBinding.getQueue().getMessageCount());

      //Consume Again as should be non-destructive
      receiveDualConsumer(consumerConnectionSupplier, NON_DESTRUCTIVE_QUEUE_NAME);
      assertEquals("Ensure Message count", 1, queueBinding.getQueue().getMessageCount());

      QueueControl control = (QueueControl) server.getManagementService().getResource(ResourceNames.QUEUE + NON_DESTRUCTIVE_QUEUE_NAME);
      control.removeAllMessages();

      assertEquals("Message count after clearing queue via queue control should be 0", 0, queueBinding.getQueue().getMessageCount());
   }

   public void testNonDestructiveExpiry(ConnectionSupplier producerConnectionSupplier, ConnectionSupplier consumerConnectionSupplier) throws Exception {
      sendMessage(producerConnectionSupplier, NON_DESTRUCTIVE_EXPIRY_QUEUE_NAME);

      QueueBinding queueBinding = (QueueBinding) server.getPostOffice().getBinding(SimpleString.toSimpleString(NON_DESTRUCTIVE_EXPIRY_QUEUE_NAME));
      assertEquals("Ensure Message count", 1, queueBinding.getQueue().getMessageCount());


      //Consume Once
      receive(consumerConnectionSupplier, NON_DESTRUCTIVE_EXPIRY_QUEUE_NAME);
      Wait.assertEquals(1, queueBinding.getQueue()::getMessageCount);

      // Wait for expiration
      Wait.waitFor(() -> queueBinding.getQueue().getMessageCount() == 0, 200); // notice the small timeout here is intended,
                  // as it will not suceed if we disable scan as we expect the client to expire destinations

      //Consume Again this time we expect the message to be expired, so nothing delivered
      receiveNull(consumerConnectionSupplier, NON_DESTRUCTIVE_EXPIRY_QUEUE_NAME);
      assertEquals("Ensure Message count", 0, queueBinding.getQueue().getMessageCount());

      QueueControl control = (QueueControl) server.getManagementService().getResource(ResourceNames.QUEUE + NON_DESTRUCTIVE_EXPIRY_QUEUE_NAME);
      control.removeAllMessages();

      assertEquals("Message count after clearing queue via queue control should be 0", 0, queueBinding.getQueue().getMessageCount());
   }

   public void testNonDestructiveMulitpleMessages(ConnectionSupplier producerConnectionSupplier, ConnectionSupplier consumerConnectionSupplier) throws Exception {
      sendMessage(producerConnectionSupplier, NON_DESTRUCTIVE_QUEUE_NAME, 0);
      sendMessage(producerConnectionSupplier, NON_DESTRUCTIVE_QUEUE_NAME, 1);
      sendMessage(producerConnectionSupplier, NON_DESTRUCTIVE_QUEUE_NAME, 2);

      QueueBinding queueBinding = (QueueBinding) server.getPostOffice().getBinding(SimpleString.toSimpleString(NON_DESTRUCTIVE_QUEUE_NAME));
      assertEquals("Ensure Message count", 3, queueBinding.getQueue().getMessageCount());


      //Consume Once
      receive(consumerConnectionSupplier, NON_DESTRUCTIVE_QUEUE_NAME, 3);

      //Consume Again as should be non-destructive
      receive(consumerConnectionSupplier, NON_DESTRUCTIVE_QUEUE_NAME, 3);

      QueueControl control = (QueueControl) server.getManagementService().getResource(ResourceNames.QUEUE + NON_DESTRUCTIVE_QUEUE_NAME);
      control.removeAllMessages();

      assertEquals("Message count after clearing queue via queue control should be 0", 0, queueBinding.getQueue().getMessageCount());
   }

   public void testNonDestructiveMulitpleMessagesDualConsumer(ConnectionSupplier producerConnectionSupplier, ConnectionSupplier consumerConnectionSupplier) throws Exception {
      sendMessage(producerConnectionSupplier, NON_DESTRUCTIVE_QUEUE_NAME, 0);
      sendMessage(producerConnectionSupplier, NON_DESTRUCTIVE_QUEUE_NAME, 1);
      sendMessage(producerConnectionSupplier, NON_DESTRUCTIVE_QUEUE_NAME, 2);

      QueueBinding queueBinding = (QueueBinding) server.getPostOffice().getBinding(SimpleString.toSimpleString(NON_DESTRUCTIVE_QUEUE_NAME));
      assertEquals("Ensure Message count", 3, queueBinding.getQueue().getMessageCount());


      //Consume Once
      receiveDualConsumer(consumerConnectionSupplier, NON_DESTRUCTIVE_QUEUE_NAME, 3);

      //Consume Again as should be non-destructive
      receiveDualConsumer(consumerConnectionSupplier, NON_DESTRUCTIVE_QUEUE_NAME, 3);

      QueueControl control = (QueueControl) server.getManagementService().getResource(ResourceNames.QUEUE + NON_DESTRUCTIVE_QUEUE_NAME);
      control.removeAllMessages();

      assertEquals("Message count after clearing queue via queue control should be 0", 0, queueBinding.getQueue().getMessageCount());
   }

   public void testNonDestructiveLVQ(ConnectionSupplier producerConnectionSupplier, ConnectionSupplier consumerConnectionSupplier) throws Exception {
      sendLVQ(producerConnectionSupplier, NON_DESTRUCTIVE_LVQ_QUEUE_NAME, Message.HDR_LAST_VALUE_NAME.toString());

      QueueBinding queueBinding = (QueueBinding) server.getPostOffice().getBinding(SimpleString.toSimpleString(NON_DESTRUCTIVE_LVQ_QUEUE_NAME));
      assertEquals("Ensure Message count", 1, queueBinding.getQueue().getMessageCount());

      //Simulate a small pause, else both messages could be consumed if consumer is fast enough
      Thread.sleep(10);

      //Consume Once
      receiveLVQ(consumerConnectionSupplier, NON_DESTRUCTIVE_LVQ_QUEUE_NAME, Message.HDR_LAST_VALUE_NAME.toString());
      assertEquals("Ensure Message count", 1, queueBinding.getQueue().getMessageCount());

      //Consume Again as should be non-destructive
      receiveLVQ(consumerConnectionSupplier, NON_DESTRUCTIVE_LVQ_QUEUE_NAME, Message.HDR_LAST_VALUE_NAME.toString());
      assertEquals("Ensure Message count", 1, queueBinding.getQueue().getMessageCount());

      //Send again
      sendLVQ(producerConnectionSupplier, NON_DESTRUCTIVE_LVQ_QUEUE_NAME, Message.HDR_LAST_VALUE_NAME.toString());

      assertEquals("Ensure Message count", 1, queueBinding.getQueue().getMessageCount());

      //Simulate a small pause, else both messages could be consumed if consumer is fast enough
      Thread.sleep(10);

      //Consume Once More
      receiveLVQ(consumerConnectionSupplier, NON_DESTRUCTIVE_LVQ_QUEUE_NAME, Message.HDR_LAST_VALUE_NAME.toString());

      assertEquals("Ensure Message count", 1, queueBinding.getQueue().getMessageCount());

      QueueControl control = (QueueControl) server.getManagementService().getResource(ResourceNames.QUEUE + NON_DESTRUCTIVE_LVQ_QUEUE_NAME);
      control.removeAllMessages();

      assertEquals("Message count after clearing queue via queue control should be 0", 0, queueBinding.getQueue().getMessageCount());
   }

   public void testNonDestructiveLVQWithConsumerFirst(ConnectionSupplier connectionSupplier) throws Exception {
      ExecutorService executor = Executors.newFixedThreadPool(1);
      CountDownLatch consumerSetup = new CountDownLatch(1);
      CountDownLatch consumerComplete = new CountDownLatch(1);

      /*
       * Create the consumer before any messages are sent and keep it there so that the first message which arrives
       * on the queue triggers direct delivery. Without the fix in this commit this essentially "poisons" the queue
       * so that consumers can't get messages later.
       */
      executor.submit(() -> {
         try (Connection connection = connectionSupplier.createConnection();
              Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
              MessageConsumer messageConsumer = session.createConsumer(session.createQueue(NON_DESTRUCTIVE_LVQ_QUEUE_NAME))) {
            connection.start();
            consumerSetup.countDown();
            BytesMessage messageReceived = (BytesMessage) messageConsumer.receive(5000);
            assertNotNull(messageReceived);
            consumerComplete.countDown();
         } catch (Exception e) {
            fail(e.getMessage());
         }

         consumerComplete.countDown();
      });

      // wait for the consumer thread to start and get everything setup
      consumerSetup.await(5, TimeUnit.SECONDS);

      try (Connection connection = connectionSupplier.createConnection();
           Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE)) {
         MessageProducer producer = session.createProducer(session.createQueue(NON_DESTRUCTIVE_LVQ_QUEUE_NAME));
         BytesMessage message = session.createBytesMessage();
         message.writeUTF("mills " + System.currentTimeMillis());
         message.setStringProperty("_AMQ_LVQ_NAME", "STOCK_NAME");
         producer.send(message);

         // wait for the consumer to close then send another message
         consumerComplete.await(5, TimeUnit.SECONDS);

         message = session.createBytesMessage();
         message.writeUTF("mills " + System.currentTimeMillis());
         message.setStringProperty("_AMQ_LVQ_NAME", "STOCK_NAME");
         producer.send(message);
      }

      try (Connection connection = connectionSupplier.createConnection();
           Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
           MessageConsumer messageConsumer = session.createConsumer(session.createQueue(NON_DESTRUCTIVE_LVQ_QUEUE_NAME))) {
         connection.start();
         BytesMessage messageReceived = (BytesMessage) messageConsumer.receive(5000);
         assertNotNull(messageReceived);
      }

      executor.shutdownNow();
   }

   public void testNonDestructiveLVQTombstone(ConnectionSupplier producerConnectionSupplier, ConnectionSupplier consumerConnectionSupplier) throws Exception {
      int tombstoneTimeToLive = 500;

      QueueBinding queueBinding = (QueueBinding) server.getPostOffice().getBinding(SimpleString.toSimpleString(NON_DESTRUCTIVE_TOMBSTONE_LVQ_QUEUE_NAME));
      LastValueQueue lastValueQueue = (LastValueQueue)queueBinding.getQueue();
      //Send again
      sendLVQ(producerConnectionSupplier, NON_DESTRUCTIVE_TOMBSTONE_LVQ_QUEUE_NAME, Message.HDR_LAST_VALUE_NAME.toString());

      assertEquals("Ensure Message count", 1, lastValueQueue.getMessageCount());

      //Simulate a small pause, else both messages could be consumed if consumer is fast enough
      Thread.sleep(10);

      //Consume Once More
      receiveLVQ(consumerConnectionSupplier, NON_DESTRUCTIVE_TOMBSTONE_LVQ_QUEUE_NAME, Message.HDR_LAST_VALUE_NAME.toString());

      //Send Tombstone
      sendLVQTombstone(producerConnectionSupplier, NON_DESTRUCTIVE_TOMBSTONE_LVQ_QUEUE_NAME, Message.HDR_LAST_VALUE_NAME.toString(), tombstoneTimeToLive);

      assertEquals("Ensure Message count", 1, lastValueQueue.getMessageCount());

      //Simulate a small pause, else both messages could be consumed if consumer is fast enough
      Thread.sleep(10);

      //Consume Tombstone ensuring Tombstone exists
      receiveLVQTombstone(consumerConnectionSupplier, NON_DESTRUCTIVE_TOMBSTONE_LVQ_QUEUE_NAME, Message.HDR_LAST_VALUE_NAME.toString());

      //Consume Again ensuring Tombstone exists as should not have expired
      receiveLVQTombstone(consumerConnectionSupplier, NON_DESTRUCTIVE_TOMBSTONE_LVQ_QUEUE_NAME, Message.HDR_LAST_VALUE_NAME.toString());

      assertEquals("Ensure Message count", 1, lastValueQueue.getLastValueKeys().size());

      //Ensure enough time elapsed for expiration and expiry thread to have run.
      Thread.sleep(tombstoneTimeToLive * 3);

      // Consume again testing tombstone has been removed
      receiveLVQAssertEmpty(consumerConnectionSupplier, NON_DESTRUCTIVE_TOMBSTONE_LVQ_QUEUE_NAME);
      assertEquals("Ensure Message count", 0, lastValueQueue.getMessageCount());
      assertEquals("Ensure Message count", 0, lastValueQueue.getLastValueKeys().size());

   }

   @Test
   public void testMessageCount() throws Exception {
      sendMessage(CoreConnection, NON_DESTRUCTIVE_QUEUE_NAME);

      QueueBinding queueBinding = (QueueBinding) server.getPostOffice().getBinding(SimpleString.toSimpleString(NON_DESTRUCTIVE_QUEUE_NAME));
      assertEquals("Ensure Message count", 1, queueBinding.getQueue().getMessageCount());

      //Consume Once
      receive(CoreConnection, NON_DESTRUCTIVE_QUEUE_NAME);
      assertEquals("Ensure Message count", 1, queueBinding.getQueue().getMessageCount());

      sendMessage(CoreConnection, NON_DESTRUCTIVE_QUEUE_NAME);
      assertEquals("Ensure Message count", 2, queueBinding.getQueue().getMessageCount());

      //Consume Again as should be non-destructive
      receive(CoreConnection, NON_DESTRUCTIVE_QUEUE_NAME);
      assertEquals("Ensure Message count", 2, queueBinding.getQueue().getMessageCount());

      QueueControl control = (QueueControl) server.getManagementService().getResource(ResourceNames.QUEUE + NON_DESTRUCTIVE_QUEUE_NAME);
      control.removeAllMessages();

      assertEquals("Message count after clearing queue via queue control should be 0", 0, queueBinding.getQueue().getMessageCount());
   }


   private void receive(ConnectionSupplier consumerConnectionSupplier, String queueName, int i) throws JMSException {
      try (Connection consumerConnection = consumerConnectionSupplier.createConnection()) {

         Session consumerSession = consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
         Queue consumerQueue = consumerSession.createQueue(queueName);
         MessageConsumer consumer = consumerSession.createConsumer(consumerQueue);
         for (int j = 0; j < i; j++) {
            TextMessage msg = (TextMessage) consumer.receive(200);
            assertNotNull(msg);
            assertEquals(Integer.toString(j), msg.getText());
         }
         TextMessage msg = (TextMessage) consumer.receiveNoWait();
         assertNull(msg);
         consumer.close();
      }
   }

   private void receive(ConnectionSupplier consumerConnectionSupplier, String queueName) throws JMSException {
      try (Connection consumerConnection = consumerConnectionSupplier.createConnection()) {

         Session consumerSession = consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
         Queue consumerQueue = consumerSession.createQueue(queueName);
         MessageConsumer consumer = consumerSession.createConsumer(consumerQueue);
         TextMessage msg = (TextMessage) consumer.receive(2000);
         assertNotNull(msg);
         consumer.close();
      }
   }

   private void receiveNull(ConnectionSupplier consumerConnectionSupplier, String queueName) throws JMSException {
      try (Connection consumerConnection = consumerConnectionSupplier.createConnection()) {

         Session consumerSession = consumerConnection.createSession(false, Session.AUTO_ACKNOWLEDGE);
         Queue consumerQueue = consumerSession.createQueue(queueName);
         MessageConsumer consumer = consumerSession.createConsumer(consumerQueue);
         TextMessage msg = (TextMessage) consumer.receiveNoWait();
         assertNull(msg);
         consumer.close();
      }
   }

   private void receiveDualConsumer(ConnectionSupplier consumerConnectionSupplier, String queueName) throws JMSException {
      try (Connection consumerConnection = consumerConnectionSupplier.createConnection();
           Connection consumerConnection2 = consumerConnectionSupplier.createConnection()) {

         MessageConsumer consumer = createConsumer(consumerConnection, queueName);
         MessageConsumer consumer2 = createConsumer(consumerConnection2, queueName);

         TextMessage msg = (TextMessage) consumer.receive(2000);
         TextMessage msg2 = (TextMessage) consumer2.receive(2000);

         assertNotNull(msg);
         assertNotNull(msg2);
         consumer.close();
         consumer2.close();
      }
   }

   private void receiveDualConsumer(ConnectionSupplier consumerConnectionSupplier, String queueName, int i) throws JMSException {
      try (Connection consumerConnection = consumerConnectionSupplier.createConnection();
           Connection consumerConnection2 = consumerConnectionSupplier.createConnection()) {

         MessageConsumer consumer = createConsumer(consumerConnection, queueName);
         MessageConsumer consumer2 = createConsumer(consumerConnection2, queueName);


         for (int j = 0; j < i; j++) {
            TextMessage msg = (TextMessage) consumer.receive(200);
            TextMessage msg2 = (TextMessage) consumer2.receive(200);
            assertNotNull(msg);
            assertNotNull(msg2);
            assertEquals(Integer.toString(j), msg.getText());
            assertEquals(Integer.toString(j), msg2.getText());
         }
         TextMessage msg = (TextMessage) consumer.receiveNoWait();
         assertNull(msg);
         TextMessage msg2 = (TextMessage) consumer2.receiveNoWait();
         assertNull(msg2);
         consumer.close();
         consumer2.close();
      }
   }

   private MessageConsumer createConsumer(Connection connection, String queueName) throws JMSException {
      connection.start();
      Session consumerSession = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
      Queue consumerQueue = consumerSession.createQueue(queueName);
      return consumerSession.createConsumer(consumerQueue);
   }

   private void sendMessage(ConnectionSupplier producerConnectionSupplier, String queueName) throws JMSException {
      sendMessage(producerConnectionSupplier, queueName, 0);
   }

   private void sendMessage(ConnectionSupplier producerConnectionSupplier, String queueName, int i) throws JMSException {
      try (Connection connection = producerConnectionSupplier.createConnection();
           Session session = connection.createSession();
           MessageProducer producer = session.createProducer(session.createQueue(queueName))) {
         TextMessage message1 = session.createTextMessage();
         message1.setText(Integer.toString(i));
         producer.send(message1);
      }
   }

   private void receiveLVQ(ConnectionSupplier consumerConnectionSupplier, String queueName, String lastValueKey) throws JMSException {
      try (Connection connection = consumerConnectionSupplier.createConnection();
           Session session = connection.createSession();
           MessageConsumer consumer = session.createConsumer(session.createQueue(queueName))) {
         TextMessage msg = (TextMessage) consumer.receive(1000);
         assertNotNull(msg);
         assertEquals("KEY", msg.getStringProperty(lastValueKey));
         assertEquals("how are you", msg.getText());
      }
   }

   private void sendLVQ(ConnectionSupplier producerConnectionSupplier, String queueName, String lastValueKey) throws JMSException {
      try (Connection connection = producerConnectionSupplier.createConnection();
           Session session = connection.createSession();
           MessageProducer producer = session.createProducer(session.createQueue(queueName))) {

         TextMessage message1 = session.createTextMessage();
         message1.setStringProperty(lastValueKey, "KEY");
         message1.setText("hello");
         producer.send(message1);

         TextMessage message2 = session.createTextMessage();
         message2.setStringProperty(lastValueKey, "KEY");
         message2.setText("how are you");
         producer.send(message2);
      }
   }

   private void receiveLVQTombstone(ConnectionSupplier consumerConnectionSupplier, String queueName, String lastValueKey) throws JMSException {
      try (Connection connection = consumerConnectionSupplier.createConnection();
           Session session = connection.createSession();
           MessageConsumer consumer = session.createConsumer(session.createQueue(queueName))) {
         TextMessage msg = (TextMessage) consumer.receive(1000);
         assertNotNull(msg);
         assertEquals("KEY", msg.getStringProperty(lastValueKey));
         assertEquals("tombstone", msg.getText());
      }
   }

   private void receiveLVQAssertEmpty(ConnectionSupplier consumerConnectionSupplier, String queueName) throws JMSException {
      try (Connection connection = consumerConnectionSupplier.createConnection();
           Session session = connection.createSession();
           MessageConsumer consumer = session.createConsumer(session.createQueue(queueName))) {
         TextMessage msg = (TextMessage) consumer.receiveNoWait();
         assertNull(msg);
      }
   }


   private void sendLVQTombstone(ConnectionSupplier producerConnectionSupplier, String queueName, String lastValueKey, int tombstoneTimeToLive) throws JMSException {
      try (Connection connection = producerConnectionSupplier.createConnection();
           Session session = connection.createSession();
           MessageProducer producer = session.createProducer(session.createQueue(queueName))) {
         TextMessage message1 = session.createTextMessage();
         message1.setStringProperty(lastValueKey, "KEY");
         message1.setText("tombstone");
         producer.send(message1, javax.jms.Message.DEFAULT_DELIVERY_MODE, javax.jms.Message.DEFAULT_PRIORITY, tombstoneTimeToLive);
      }
   }

   @Test
   public void testMultipleLastValuesCore() throws Exception {
      testMultipleLastValues(CoreConnection);
   }

   @Test
   public void testMultipleLastValuesAMQP() throws Exception {
      testMultipleLastValues(AMQPConnection);
   }

   private void testMultipleLastValues(ConnectionSupplier connectionSupplier) throws Exception {
      final int GROUP_COUNT = 5;
      final int MESSAGE_COUNT_PER_GROUP = 25;
      final int PRODUCER_COUNT = 5;

      HashMap<String, List<String>> results = new HashMap<>();
      for (int i = 0; i < GROUP_COUNT; i++) {
         results.put(i + "", new ArrayList<>());
      }

      HashMap<String, Integer> dups = new HashMap<>();
      List<Producer> producers = new ArrayList<>();

      try (Connection connection = connectionSupplier.createConnection()) {
         Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
         Queue queue = session.createQueue(NON_DESTRUCTIVE_LVQ_QUEUE_NAME);

         MessageConsumer consumer = session.createConsumer(queue);
         connection.start();

         for (int i = 0; i < PRODUCER_COUNT; i++) {
            producers.add(new Producer(connectionSupplier, MESSAGE_COUNT_PER_GROUP, GROUP_COUNT, i));
         }

         for (Producer producer : producers) {
            new Thread(producer).start();
         }

         while (true) {
            TextMessage tm = (TextMessage) consumer.receive(500);
            if (tm == null) {
               break;
            }
            results.get(tm.getStringProperty("lastval")).add(tm.getText());
            tm.acknowledge();
         }

         for (Producer producer : producers) {
            assertFalse("Producer failed!", producer.failed);
         }
      }
      for (Map.Entry<String, List<String>> entry : results.entrySet()) {
         StringBuilder logMessage = new StringBuilder();
         logMessage.append("Messages received with lastval=" + entry.getKey() + " (");
         for (String s : entry.getValue()) {
            int occurrences = Collections.frequency(entry.getValue(), s);
            if (occurrences > 1 && !dups.containsValue(Integer.parseInt(s))) {
               dups.put(s, occurrences);
            }
            logMessage.append(s + ",");
         }
         logger.info(logMessage + ")");
      }
      if (dups.size() > 0) {
         StringBuffer sb = new StringBuffer();
         for (Map.Entry<String, Integer> stringIntegerEntry : dups.entrySet()) {
            sb.append(stringIntegerEntry.getKey() + "(" + stringIntegerEntry.getValue() + "),");
         }
         Assert.fail("Duplicate messages received " + sb);
      }

      Wait.assertEquals((long) GROUP_COUNT, () -> server.locateQueue(NON_DESTRUCTIVE_LVQ_QUEUE_NAME).getMessageCount(), 2000, 100, false);
   }

   private class Producer implements Runnable {
      private final ConnectionSupplier connectionSupplier;
      private final int messageCount;
      private final int groupCount;
      private final int offset;

      public boolean failed = false;

      Producer(ConnectionSupplier connectionSupplier, int messageCount, int groupCount, int offset) {
         this.connectionSupplier = connectionSupplier;
         this.messageCount = messageCount;
         this.groupCount = groupCount;
         this.offset = offset;
      }

      @Override
      public void run() {
         try (Connection connection = connectionSupplier.createConnection()) {
            Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
            Queue queue = session.createQueue(NON_DESTRUCTIVE_LVQ_QUEUE_NAME);
            MessageProducer producer = session.createProducer(queue);

            int startingPoint = offset * (messageCount * groupCount);
            int messagesToSend = messageCount * groupCount;

            for (int i = startingPoint; i < messagesToSend + startingPoint; i++) {
               String lastval = "" + (i % groupCount);
               TextMessage message = session.createTextMessage();
               message.setText("" + i);
               message.setStringProperty("data", "" + i);
               message.setStringProperty("lastval", lastval);
               message.setStringProperty(Message.HDR_LAST_VALUE_NAME.toString(), lastval);
               producer.send(message);
            }
         } catch (JMSException e) {
            e.printStackTrace();
            failed = true;
            return;
         }
      }
   }
}

<|start_filename|>tests/compatibility-tests/src/main/java/org/apache/activemq/artemis/tests/compatibility/GroovyRun.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.tests.compatibility;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;

import groovy.lang.Binding;
import groovy.lang.GroovyShell;

public class GroovyRun {

   public static final String SNAPSHOT = "ARTEMIS-SNAPSHOT";
   public static final String JAKARTAEE = "ARTEMIS-JAKARTAEE";
   public static final String ONE_FIVE = "ARTEMIS-155";
   public static final String ONE_FOUR = "ARTEMIS-140";
   public static final String TWO_ZERO = "ARTEMIS-200";
   public static final String TWO_ONE = "ARTEMIS-210";
   public static final String TWO_FOUR = "ARTEMIS-240";
   public static final String TWO_SIX_THREE = "ARTEMIS-263";
   public static final String TWO_SEVEN_ZERO = "ARTEMIS-270";
   public static final String TWO_TEN_ZERO = "ARTEMIS-2_10_0";
   public static final String HORNETQ_235 = "HORNETQ-235";
   public static final String HORNETQ_247 = "HORNETQ-247";

   public static Binding binding = new Binding();
   public static GroovyShell shell = new GroovyShell(binding);

   public static void clear() {
      binding = new Binding();
      shell = new GroovyShell(binding);
   }

   /**
    * This can be called from the scripts as well.
    *  The scripts will use this method instead of its own groovy method.
    *  As a classloader operation needs to be done here.
    */
   public static Object evaluate(String script,
                                 String[] arg) throws URISyntaxException, IOException {
      return evaluate(script, "arg", arg);
   }

      /**
       * This can be called from the scripts as well.
       *  The scripts will use this method instead of its own groovy method.
       *  As a classloader operation needs to be done here.
       */
   public static Object evaluate(String script,
                               String argVariableName,
                               String[] arg) throws URISyntaxException, IOException {
      URL scriptURL = GroovyRun.class.getClassLoader().getResource(script);
      if (scriptURL == null) {
         throw new RuntimeException("cannot find " + script);
      }
      URI scriptURI = scriptURL.toURI();

      setVariable(argVariableName, arg);

      return shell.evaluate(scriptURI);
   }


   public static void setVariable(String name, Object arg) {
      binding.setVariable(name, arg);
   }

   public static Object getVariable(String name) {
      return binding.getVariable(name);
   }

   // Called with reflection
   public static Object execute(String script) throws Throwable {
      return shell.evaluate(script);
   }

   public static void assertNotNull(Object value) {
      if (value == null) {
         throw new RuntimeException("Null value");
      }
   }

   public static void assertNull(Object value) {
      if (value != null) {
         throw new RuntimeException("Expected Null value");
      }
   }

   public static void assertTrue(boolean  value) {
      if (!value) {
         throw new RuntimeException("Expected true");
      }
   }


   public static void assertFalse(boolean  value) {
      if (value) {
         throw new RuntimeException("Expected false");
      }
   }

   public static void assertEquals(Object value1, Object value2) {
      if ((value1 == null && value2 == null) || !value1.equals(value2)) {
         throw new RuntimeException(value1 + "!=" + value2);
      }
   }

   public static void assertEquals(int value1, int value2) {
      if (value1 != value2) {
         throw new RuntimeException(value1 + "!=" + value2);
      }
   }

   public static void assertEquals(byte[] value1, byte[] value2) {

      assertEquals(value1.length, value2.length);

      for (int i = 0; i < value1.length; i++) {
         assertEquals(value1[i], value2[i]);
      }
   }


   public static byte getSamplebyte(final long position) {
      return (byte) ('a' + position % ('z' - 'a' + 1));
   }
}



<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/SessionStopStartTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.client;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.MessageHandler;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.jboss.logging.Logger;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class SessionStopStartTest extends ActiveMQTestBase {

   private static final Logger log = Logger.getLogger(SessionStopStartTest.class);

   private ActiveMQServer server;

   private final SimpleString QUEUE = new SimpleString("ConsumerTestQueue");

   private ServerLocator locator;

   @Override
   @Before
   public void setUp() throws Exception {
      super.setUp();

      server = createServer(false);
      server.start();
      locator = createInVMNonHALocator();
   }

   @Test
   public void testStopStartConsumerSyncReceiveImmediate() throws Exception {
      ClientSessionFactory sf = createSessionFactory(locator);

      final ClientSession session = sf.createSession(false, true, true);

      session.createQueue(new QueueConfiguration(QUEUE).setDurable(false));

      ClientProducer producer = session.createProducer(QUEUE);

      final int numMessages = 100;

      for (int i = 0; i < numMessages; i++) {
         ClientMessage message = createTextMessage(session, "m" + i);
         message.putIntProperty(new SimpleString("i"), i);
         producer.send(message);
      }

      final ClientConsumer consumer = session.createConsumer(QUEUE);

      session.start();

      for (int i = 0; i < numMessages / 2; i++) {
         ClientMessage cm = consumer.receive(5000);
         Assert.assertNotNull(cm);
         cm.acknowledge();
      }
      session.stop();
      ClientMessage cm = consumer.receiveImmediate();
      Assert.assertNull(cm);

      session.start();
      for (int i = 0; i < numMessages / 2; i++) {
         cm = consumer.receive(5000);
         Assert.assertNotNull(cm);
         cm.acknowledge();
      }

      session.close();
   }

   @Test
   public void testStopStartConsumerSyncReceive() throws Exception {
      ClientSessionFactory sf = createSessionFactory(locator);

      final ClientSession session = sf.createSession(false, true, true);

      session.createQueue(new QueueConfiguration(QUEUE).setDurable(false));

      ClientProducer producer = session.createProducer(QUEUE);

      final int numMessages = 100;

      for (int i = 0; i < numMessages; i++) {
         ClientMessage message = createTextMessage(session, "m" + i);
         message.putIntProperty(new SimpleString("i"), i);
         producer.send(message);
      }

      final ClientConsumer consumer = session.createConsumer(QUEUE);

      session.start();

      for (int i = 0; i < numMessages / 2; i++) {
         ClientMessage cm = consumer.receive(5000);
         Assert.assertNotNull(cm);
         cm.acknowledge();
      }
      session.stop();
      long time = System.currentTimeMillis();
      ClientMessage cm = consumer.receive(1000);
      long taken = System.currentTimeMillis() - time;
      Assert.assertTrue(taken >= 1000);
      Assert.assertNull(cm);

      session.start();
      for (int i = 0; i < numMessages / 2; i++) {
         cm = consumer.receive(5000);
         Assert.assertNotNull(cm);
         cm.acknowledge();
      }

      session.close();
   }

   @Test
   public void testStopStartConsumerAsyncSyncStoppedByHandler() throws Exception {
      ClientSessionFactory sf = createSessionFactory(locator);

      final ClientSession session = sf.createSession(false, true, true);

      session.createQueue(new QueueConfiguration(QUEUE).setDurable(false));

      ClientProducer producer = session.createProducer(QUEUE);

      final int numMessages = 100;

      for (int i = 0; i < numMessages; i++) {
         ClientMessage message = createTextMessage(session, "m" + i);
         message.putIntProperty(new SimpleString("i"), i);
         producer.send(message);
      }

      final ClientConsumer consumer = session.createConsumer(QUEUE);

      session.start();

      final CountDownLatch latch = new CountDownLatch(10);

      // Message should be in consumer

      class MyHandler implements MessageHandler {

         boolean failed;

         boolean started = true;

         int count = 0;

         @Override
         public void onMessage(final ClientMessage message) {

            try {
               if (!started) {
                  failed = true;
               }

               count++;

               if (count == 10) {
                  message.acknowledge();
                  session.stop();
                  started = false;
               }

               latch.countDown();
            } catch (Exception e) {
            }
         }
      }

      MyHandler handler = new MyHandler();

      consumer.setMessageHandler(handler);

      waitForLatch(latch);

      Assert.assertFalse(handler.failed);

      // Make sure no exceptions were thrown from onMessage
      Assert.assertNull(consumer.getLastException());
      consumer.setMessageHandler(null);
      session.start();
      for (int i = 0; i < 90; i++) {
         ClientMessage msg = consumer.receive(1000);
         Assert.assertNotNull("message " + i, msg);
         msg.acknowledge();
      }

      Assert.assertNull(consumer.receiveImmediate());

      session.close();
   }

   @Test
   public void testStopStartConsumerAsyncSync() throws Exception {
      ClientSessionFactory sf = createSessionFactory(locator);

      final ClientSession session = sf.createSession(false, true, true);

      session.createQueue(new QueueConfiguration(QUEUE).setDurable(false));

      ClientProducer producer = session.createProducer(QUEUE);

      final int numMessages = 100;

      for (int i = 0; i < numMessages; i++) {
         ClientMessage message = createTextMessage(session, "m" + i);
         message.putIntProperty(new SimpleString("i"), i);
         producer.send(message);
      }

      final ClientConsumer consumer = session.createConsumer(QUEUE);

      session.start();

      final CountDownLatch latch = new CountDownLatch(10);

      // Message should be in consumer

      class MyHandler implements MessageHandler {

         boolean failed;

         boolean started = true;

         @Override
         public void onMessage(final ClientMessage message) {

            try {
               if (!started) {
                  failed = true;
               }

               latch.countDown();

               if (latch.getCount() == 0) {

                  message.acknowledge();
                  started = false;
                  consumer.setMessageHandler(null);
               }

            } catch (Exception e) {
            }
         }
      }

      MyHandler handler = new MyHandler();

      consumer.setMessageHandler(handler);

      waitForLatch(latch);

      try {
         session.stop();
      } catch (Exception e) {
         SessionStopStartTest.log.warn(e.getMessage(), e);
         throw e;
      }

      Assert.assertFalse(handler.failed);

      // Make sure no exceptions were thrown from onMessage
      Assert.assertNull(consumer.getLastException());
      consumer.setMessageHandler(null);
      session.start();
      for (int i = 0; i < 90; i++) {
         ClientMessage msg = consumer.receive(1000);
         Assert.assertNotNull("message " + i, msg);
         msg.acknowledge();
      }

      Assert.assertNull(consumer.receiveImmediate());

      session.close();
   }

   @Test
   public void testStopStartConsumerAsyncASyncStoppeeByHandler() throws Exception {
      ClientSessionFactory sf = createSessionFactory(locator);

      final ClientSession session = sf.createSession(false, true, true);

      session.createQueue(new QueueConfiguration(QUEUE).setDurable(false));

      ClientProducer producer = session.createProducer(QUEUE);

      final int numMessages = 100;

      for (int i = 0; i < numMessages; i++) {
         ClientMessage message = createTextMessage(session, "m" + i);
         message.putIntProperty(new SimpleString("i"), i);
         producer.send(message);
      }

      final ClientConsumer consumer = session.createConsumer(QUEUE);

      session.start();

      CountDownLatch latch = new CountDownLatch(10);

      // Message should be in consumer

      class MyHandler implements MessageHandler {

         int messageReceived = 0;

         boolean failed;

         boolean started = true;

         private final CountDownLatch latch;

         private boolean stop = true;

         MyHandler(final CountDownLatch latch) {
            this.latch = latch;
         }

         MyHandler(final CountDownLatch latch, final boolean stop) {
            this(latch);
            this.stop = stop;
         }

         @Override
         public void onMessage(final ClientMessage message) {

            try {
               if (!started) {
                  failed = true;
               }
               messageReceived++;
               latch.countDown();

               if (stop && latch.getCount() == 0) {

                  message.acknowledge();
                  session.stop();
                  started = false;
               }

            } catch (Exception e) {
            }
         }
      }

      MyHandler handler = new MyHandler(latch);

      consumer.setMessageHandler(handler);

      waitForLatch(latch);

      Thread.sleep(100);

      Assert.assertFalse(handler.failed);

      // Make sure no exceptions were thrown from onMessage
      Assert.assertNull(consumer.getLastException());
      latch = new CountDownLatch(90);
      handler = new MyHandler(latch, false);
      consumer.setMessageHandler(handler);
      session.start();
      Assert.assertTrue("message received " + handler.messageReceived, latch.await(5, TimeUnit.SECONDS));

      Thread.sleep(100);

      Assert.assertFalse(handler.failed);
      Assert.assertNull(consumer.getLastException());
      session.close();
   }

   @Test
   public void testStopStartConsumerAsyncASync() throws Exception {
      ClientSessionFactory sf = createSessionFactory(locator);

      final ClientSession session = sf.createSession(false, true, true);

      session.createQueue(new QueueConfiguration(QUEUE).setDurable(false));

      ClientProducer producer = session.createProducer(QUEUE);

      final int numMessages = 100;

      for (int i = 0; i < numMessages; i++) {
         ClientMessage message = createTextMessage(session, "m" + i);
         message.putIntProperty(new SimpleString("i"), i);
         producer.send(message);
      }

      final ClientConsumer consumer = session.createConsumer(QUEUE);

      session.start();

      CountDownLatch latch = new CountDownLatch(10);

      // Message should be in consumer

      class MyHandler implements MessageHandler {

         int messageReceived = 0;

         boolean failed;

         boolean started = true;

         private final CountDownLatch latch;

         private boolean stop = true;

         MyHandler(final CountDownLatch latch) {
            this.latch = latch;
         }

         MyHandler(final CountDownLatch latch, final boolean stop) {
            this(latch);
            this.stop = stop;
         }

         @Override
         public void onMessage(final ClientMessage message) {

            try {
               if (!started) {
                  failed = true;
               }
               messageReceived++;
               latch.countDown();

               if (stop && latch.getCount() == 0) {

                  message.acknowledge();
                  consumer.setMessageHandler(null);
                  started = false;
               }

            } catch (Exception e) {
            }
         }
      }

      MyHandler handler = new MyHandler(latch);

      consumer.setMessageHandler(handler);

      waitForLatch(latch);

      Thread.sleep(100);

      Assert.assertFalse(handler.failed);

      // Make sure no exceptions were thrown from onMessage
      Assert.assertNull(consumer.getLastException());
      latch = new CountDownLatch(90);
      handler = new MyHandler(latch, false);
      consumer.setMessageHandler(handler);
      session.start();
      Assert.assertTrue("message received " + handler.messageReceived, latch.await(5, TimeUnit.SECONDS));

      Thread.sleep(100);

      Assert.assertFalse(handler.failed);
      Assert.assertNull(consumer.getLastException());
      session.close();
   }

   private int getMessageEncodeSize(final SimpleString address) throws Exception {
      ServerLocator locator = createInVMNonHALocator();
      ClientSessionFactory cf = createSessionFactory(locator);
      ClientSession session = cf.createSession(false, true, true);
      ClientMessage message = session.createMessage(false);
      // we need to set the destination so we can calculate the encodesize correctly
      message.setAddress(address);
      int encodeSize = message.getEncodeSize();
      session.close();
      cf.close();
      return encodeSize;
   }

   @Test
   public void testStopStartMultipleConsumers() throws Exception {
      locator.setConsumerWindowSize(getMessageEncodeSize(QUEUE) * 33);
      ClientSessionFactory sf = createSessionFactory(locator);

      final ClientSession session = sf.createSession(false, true, true);

      session.createQueue(new QueueConfiguration(QUEUE).setDurable(false));

      ClientProducer producer = session.createProducer(QUEUE);

      final int numMessages = 100;

      for (int i = 0; i < numMessages; i++) {
         ClientMessage message = createTextMessage(session, "m" + i);
         message.putIntProperty(new SimpleString("i"), i);
         producer.send(message);
      }

      ClientConsumer consumer = session.createConsumer(QUEUE);
      ClientConsumer consumer2 = session.createConsumer(QUEUE);
      ClientConsumer consumer3 = session.createConsumer(QUEUE);

      session.start();

      ClientMessage cm = consumer.receive(5000);
      Assert.assertNotNull(cm);
      cm.acknowledge();
      cm = consumer2.receive(5000);
      Assert.assertNotNull(cm);
      cm.acknowledge();
      cm = consumer3.receive(5000);
      Assert.assertNotNull(cm);
      cm.acknowledge();

      session.stop();
      cm = consumer.receiveImmediate();
      Assert.assertNull(cm);
      cm = consumer2.receiveImmediate();
      Assert.assertNull(cm);
      cm = consumer3.receiveImmediate();
      Assert.assertNull(cm);

      session.start();
      cm = consumer.receive(5000);
      Assert.assertNotNull(cm);
      cm = consumer2.receive(5000);
      Assert.assertNotNull(cm);
      cm = consumer3.receive(5000);
      Assert.assertNotNull(cm);
      session.close();
   }

   @Test
   public void testStopStartAlreadyStartedSession() throws Exception {
      ClientSessionFactory sf = createSessionFactory(locator);

      final ClientSession session = sf.createSession(false, true, true);

      session.createQueue(new QueueConfiguration(QUEUE).setDurable(false));

      ClientProducer producer = session.createProducer(QUEUE);

      final int numMessages = 100;

      for (int i = 0; i < numMessages; i++) {
         ClientMessage message = createTextMessage(session, "m" + i);
         message.putIntProperty(new SimpleString("i"), i);
         producer.send(message);
      }

      final ClientConsumer consumer = session.createConsumer(QUEUE);

      session.start();

      for (int i = 0; i < numMessages / 2; i++) {
         ClientMessage cm = consumer.receive(5000);
         Assert.assertNotNull(cm);
         cm.acknowledge();
      }

      session.start();
      for (int i = 0; i < numMessages / 2; i++) {
         ClientMessage cm = consumer.receive(5000);
         Assert.assertNotNull(cm);
         cm.acknowledge();
      }

      session.close();
   }

   @Test
   public void testStopAlreadyStoppedSession() throws Exception {
      ClientSessionFactory sf = createSessionFactory(locator);

      final ClientSession session = sf.createSession(false, true, true);

      session.createQueue(new QueueConfiguration(QUEUE).setDurable(false));

      ClientProducer producer = session.createProducer(QUEUE);

      final int numMessages = 100;

      for (int i = 0; i < numMessages; i++) {
         ClientMessage message = createTextMessage(session, "m" + i);
         message.putIntProperty(new SimpleString("i"), i);
         producer.send(message);
      }

      final ClientConsumer consumer = session.createConsumer(QUEUE);

      session.start();

      for (int i = 0; i < numMessages / 2; i++) {
         ClientMessage cm = consumer.receive(5000);
         Assert.assertNotNull(cm);
         cm.acknowledge();
      }
      session.stop();
      ClientMessage cm = consumer.receiveImmediate();
      Assert.assertNull(cm);

      session.stop();
      cm = consumer.receiveImmediate();
      Assert.assertNull(cm);

      session.start();
      for (int i = 0; i < numMessages / 2; i++) {
         cm = consumer.receive(5000);
         Assert.assertNotNull(cm);
         cm.acknowledge();
      }

      session.close();
   }

}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/federation/FederatedTestBase.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.federation;

import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import java.util.ArrayList;
import java.util.List;

import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.ActiveMQServers;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.junit.Before;

/**
 * Federation Test Base
 */
public class FederatedTestBase extends ActiveMQTestBase {

   protected List<MBeanServer> mBeanServers = new ArrayList<>();
   protected List<ActiveMQServer> servers = new ArrayList<>();


   @Override
   @Before
   public void setUp() throws Exception {
      super.setUp();
      for (int i = 0; i < numberOfServers(); i++) {
         MBeanServer mBeanServer = MBeanServerFactory.createMBeanServer();
         mBeanServers.add(mBeanServer);
         Configuration config = createDefaultConfig(i, false).setSecurityEnabled(false);
         for (int j = 0; j < numberOfServers(); j++) {
            config.addConnectorConfiguration("server" + j, "vm://" + j);
         }
         ActiveMQServer server = addServer(ActiveMQServers.newActiveMQServer(config, mBeanServer, false));

         servers.add(server);
         server.start();

         configureQueues(server);
      }
   }

   protected void configureQueues(ActiveMQServer server) throws Exception {
   }

   protected void createSimpleQueue(ActiveMQServer server, String queueName) throws Exception {
      SimpleString simpleStringQueueName = SimpleString.toSimpleString(queueName);
      try {
         server.createQueue(new QueueConfiguration(simpleStringQueueName).setRoutingType(RoutingType.ANYCAST).setAutoCreateAddress(true));
      } catch (Exception ignored) {
      }

   }

   protected int numberOfServers() {
      return 3;
   }

   public ActiveMQServer getServer(int i) {
      return servers.get(i);
   }


}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/server/cluster/ha/SharedStoreSlavePolicy.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.server.cluster.ha;

import java.util.Map;

import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
import org.apache.activemq.artemis.core.io.IOCriticalErrorListener;
import org.apache.activemq.artemis.core.server.impl.Activation;
import org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl;
import org.apache.activemq.artemis.core.server.impl.SharedStoreBackupActivation;

public class SharedStoreSlavePolicy extends BackupPolicy {

   private boolean failoverOnServerShutdown = ActiveMQDefaultConfiguration.isDefaultFailoverOnServerShutdown();

   private boolean allowAutoFailBack = ActiveMQDefaultConfiguration.isDefaultAllowAutoFailback();

   private boolean isWaitForActivation = ActiveMQDefaultConfiguration.isDefaultWaitForActivation();

   //this is how we act once we have failed over
   private SharedStoreMasterPolicy sharedStoreMasterPolicy;

   public SharedStoreSlavePolicy() {
   }

   public SharedStoreSlavePolicy(boolean failoverOnServerShutdown,
                                 boolean restartBackup,
                                 boolean allowAutoFailBack,
                                 ScaleDownPolicy scaleDownPolicy) {
      this.failoverOnServerShutdown = failoverOnServerShutdown;
      this.restartBackup = restartBackup;
      this.allowAutoFailBack = allowAutoFailBack;
      this.scaleDownPolicy = scaleDownPolicy;
   }

   @Deprecated
   public long getFailbackDelay() {
      return -1;
   }

   @Deprecated
   public void setFailbackDelay(long failbackDelay) {
   }

   public boolean isFailoverOnServerShutdown() {
      return failoverOnServerShutdown;
   }

   public void setFailoverOnServerShutdown(boolean failoverOnServerShutdown) {
      this.failoverOnServerShutdown = failoverOnServerShutdown;
   }

   public SharedStoreMasterPolicy getSharedStoreMasterPolicy() {
      if (sharedStoreMasterPolicy == null) {
         sharedStoreMasterPolicy = new SharedStoreMasterPolicy(failoverOnServerShutdown, isWaitForActivation);
      }
      return sharedStoreMasterPolicy;
   }

   public void setSharedStoreMasterPolicy(SharedStoreMasterPolicy sharedStoreMasterPolicy) {
      this.sharedStoreMasterPolicy = sharedStoreMasterPolicy;
   }

   @Override
   public boolean isSharedStore() {
      return true;
   }

   @Override
   public boolean canScaleDown() {
      return scaleDownPolicy != null;
   }

   public boolean isAllowAutoFailBack() {
      return allowAutoFailBack;
   }

   public void setAllowAutoFailBack(boolean allowAutoFailBack) {
      this.allowAutoFailBack = allowAutoFailBack;
   }

   public void setIsWaitForActivation(boolean isWaitForActivation) {
      this.isWaitForActivation = isWaitForActivation;
   }

   @Override
   public Activation createActivation(ActiveMQServerImpl server,
                                      boolean wasLive,
                                      Map<String, Object> activationParams,
                                      IOCriticalErrorListener ioCriticalErrorListener) {
      return new SharedStoreBackupActivation(server, this, ioCriticalErrorListener);
   }

   @Override
   public String getBackupGroupName() {
      return null;
   }
}


<|start_filename|>artemis-journal/src/main/java/org/apache/activemq/artemis/core/journal/impl/ObjIntIntArrayList.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.journal.impl;

import java.util.Arrays;
import java.util.Objects;

/**
 * Ordered collection of (T, int, int) tuples with positive integers and not null T.<br>
 * This isn't supposed to be a generic collection, but with some effort can became one and
 * could be moved into commons utils.
 */
final class ObjIntIntArrayList<T> {

   private static final Object[] EMPTY_OBJECTS = new Object[0];
   private static final long[] EMPTY_INTS = new long[0];
   private Object[] objects;
   private long[] ints;
   private int size;

   ObjIntIntArrayList(int initialCapacity) {
      objects = initialCapacity == 0 ? EMPTY_OBJECTS : new Object[initialCapacity];
      ints = initialCapacity == 0 ? EMPTY_INTS : new long[initialCapacity];
      size = 0;
   }

   private static long packInts(int a, int b) {
      if (a < 0 || b < 0) {
         throw new IllegalArgumentException("a and b must be >= 0");
      }
      return (((long) a) << 32) | (b & 0xFFFFFFFFL);
   }

   private static int unpackA(long ints) {
      return (int) (ints >> 32);
   }

   private static int unpackB(long ints) {
      return (int) ints;
   }

   private void ensureCapacity() {
      final int currentCapacity = objects.length;
      final int expectedCapacity = size + 1;
      if (expectedCapacity - currentCapacity <= 0) {
         return;
      }
      grow(expectedCapacity, currentCapacity);
   }

   private void grow(int expectedCapacity, int currentCapacity) {
      assert expectedCapacity - currentCapacity > 0;
      int newCapacity = currentCapacity + (currentCapacity >> 1);
      // to cover the 0,1 cases
      if (newCapacity - expectedCapacity < 0) {
         newCapacity = expectedCapacity;
      }
      if (newCapacity - 2147483639 > 0) {
         newCapacity = hugeCapacity(expectedCapacity);
      }
      final Object[] oldObjects = objects;
      final long[] oldInts = ints;
      try {
         final Object[] newObjects = Arrays.copyOf(oldObjects, newCapacity);
         final long[] newInts = Arrays.copyOf(oldInts, newCapacity);
         objects = newObjects;
         ints = newInts;
      } catch (OutOfMemoryError outOfMemoryError) {
         // restore previous ones
         objects = oldObjects;
         ints = oldInts;
         throw outOfMemoryError;
      }
   }

   private static int hugeCapacity(int minCapacity) {
      if (minCapacity < 0) {
         throw new OutOfMemoryError();
      } else {
         return minCapacity > 2147483639 ? 2147483647 : 2147483639;
      }
   }

   public int size() {
      return size;
   }

   public boolean addToIntsIfMatch(int index, T e, int deltaA, int deltaB) {
      Objects.requireNonNull(e, "e must be not null");
      if (deltaA < 0) {
         throw new IllegalArgumentException("deltaA must be >= 0");
      }
      if (deltaB < 0) {
         throw new IllegalArgumentException("deltaB must be >= 0");
      }
      if (index < 0 || index >= size) {
         throw new IndexOutOfBoundsException("index must be >=0 and <" + size);
      }
      final Object elm = objects[index];
      if (!Objects.equals(elm, e)) {
         return false;
      }
      final long packedInts = ints[index];
      final int oldA = unpackA(packedInts);
      final long newA = oldA + deltaA;
      // overflow check
      if (newA < oldA) {
         return false;
      }
      final int oldB = unpackB(packedInts);
      final long newB = oldB + deltaB;
      // overflow check
      if (newB < oldB) {
         return false;
      }
      ints[index] = packInts((int) newA, (int) newB);
      return true;
   }

   public void add(final T e, final int a, int b) {
      Objects.requireNonNull(e, "e must be not null");
      final long packedInts = packInts(a, b);
      ensureCapacity();
      objects[size] = e;
      ints[size] = packedInts;
      size++;
   }

   public void clear() {
      Arrays.fill(objects, 0, size, null);
      size = 0;
   }

   @FunctionalInterface
   public interface ObjIntIntConsumerOneArg<T, A> {

      void accept(T e, int a, int b, A arg);
   }

   public <A> void forEach(ObjIntIntConsumerOneArg<? super T, ? super A> onFile, A arg) {
      for (int i = 0, size = this.size; i < size; i++) {
         final T e = (T) objects[i];
         final long packedInts = ints[i];
         onFile.accept(e, unpackA(packedInts), unpackB(packedInts), arg);
      }
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/federation/FederatedTestUtil.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.tests.integration.federation;

import java.util.Collections;

import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.core.config.FederationConfiguration;
import org.apache.activemq.artemis.core.config.TransformerConfiguration;
import org.apache.activemq.artemis.core.config.federation.FederationAddressPolicyConfiguration;
import org.apache.activemq.artemis.core.config.federation.FederationDownstreamConfiguration;
import org.apache.activemq.artemis.core.config.federation.FederationQueuePolicyConfiguration;
import org.apache.activemq.artemis.core.config.federation.FederationTransformerConfiguration;
import org.apache.activemq.artemis.core.config.federation.FederationUpstreamConfiguration;

public class FederatedTestUtil {

   public static FederationConfiguration createAddressFederationConfiguration(String address, int hops) {
      FederationAddressPolicyConfiguration addressPolicyConfiguration = new FederationAddressPolicyConfiguration();
      addressPolicyConfiguration.setName( "AddressPolicy" + address);
      addressPolicyConfiguration.addInclude(new FederationAddressPolicyConfiguration.Matcher().setAddressMatch(address));
      addressPolicyConfiguration.setMaxHops(hops);

      FederationConfiguration federationConfiguration = new FederationConfiguration();
      federationConfiguration.setName("default");
      federationConfiguration.addFederationPolicy(addressPolicyConfiguration);

      return federationConfiguration;
   }

   public static FederationConfiguration createAddressUpstreamFederationConfiguration(String connector, String address, int hops) {
      FederationUpstreamConfiguration upstreamConfiguration = new FederationUpstreamConfiguration();
      upstreamConfiguration.setName(connector);
      upstreamConfiguration.getConnectionConfiguration().setStaticConnectors(Collections.singletonList(connector));
      upstreamConfiguration.getConnectionConfiguration().setCircuitBreakerTimeout(-1);
      upstreamConfiguration.addPolicyRef("AddressPolicy" + address);

      FederationConfiguration federationConfiguration = createAddressFederationConfiguration(address, hops);
      federationConfiguration.addUpstreamConfiguration(upstreamConfiguration);

      return federationConfiguration;
   }

   public static FederationConfiguration createAddressUpstreamFederationConfiguration(String connector, String address) {
      return createAddressUpstreamFederationConfiguration(connector, address, 1);
   }

   public static FederationConfiguration createAddressDownstreamFederationConfiguration(String connector, String address, TransportConfiguration transportConfiguration) {
      return createAddressDownstreamFederationConfiguration(connector, address, transportConfiguration, 1);
   }

   public static FederationConfiguration createAddressDownstreamFederationConfiguration(String connector, String address, TransportConfiguration transportConfiguration,
                                                                           int hops) {
      FederationDownstreamConfiguration downstreamConfiguration = new FederationDownstreamConfiguration();
      downstreamConfiguration.setName(connector);
      downstreamConfiguration.getConnectionConfiguration().setStaticConnectors(Collections.singletonList(connector));
      downstreamConfiguration.getConnectionConfiguration().setCircuitBreakerTimeout(-1);
      downstreamConfiguration.addPolicyRef("AddressPolicy" + address);
      downstreamConfiguration.setUpstreamConfiguration(transportConfiguration);

      FederationConfiguration federationConfiguration = createAddressFederationConfiguration(address, hops);
      federationConfiguration.addDownstreamConfiguration(downstreamConfiguration);

      return federationConfiguration;
   }

   public static FederationConfiguration createAddressDownstreamFederationConfiguration(String connector, String address, String transportConfigurationRef,
                                                                           int hops) {
      FederationDownstreamConfiguration downstreamConfiguration = new FederationDownstreamConfiguration();
      downstreamConfiguration.setName(connector);
      downstreamConfiguration.getConnectionConfiguration().setStaticConnectors(Collections.singletonList(connector));
      downstreamConfiguration.getConnectionConfiguration().setCircuitBreakerTimeout(-1);
      downstreamConfiguration.addPolicyRef("AddressPolicy" + address);
      downstreamConfiguration.setUpstreamConfigurationRef(transportConfigurationRef);

      FederationConfiguration federationConfiguration = createAddressFederationConfiguration(address, hops);
      federationConfiguration.addDownstreamConfiguration(downstreamConfiguration);

      return federationConfiguration;
   }

   public static FederationConfiguration createAddressDownstreamFederationConfiguration(String connector, String address, String transportConfigurationRef) {
      return createAddressDownstreamFederationConfiguration(connector, address, transportConfigurationRef, 1);
   }

   public static void addAddressTransformerConfiguration(final FederationConfiguration federationConfiguration, final String address) {
      federationConfiguration.addTransformerConfiguration(
         new FederationTransformerConfiguration("transformer", new TransformerConfiguration(FederatedAddressTest.TestTransformer.class.getName())));
      FederationAddressPolicyConfiguration policy = (FederationAddressPolicyConfiguration) federationConfiguration.getFederationPolicyMap().get("AddressPolicy" + address);
      policy.setTransformerRef("transformer");
   }

   public static FederationConfiguration createDownstreamFederationConfiguration(String connector, String queueName, Boolean includeFederated,
                                                                           String transportConfigurationRef) {
      return createQueueDownstreamFederationConfiguration(null, connector, queueName, includeFederated, false, transportConfigurationRef);
   }

   public static FederationConfiguration createQueueDownstreamFederationConfiguration(String name, String connector, String queueName, Boolean includeFederated,
                                                                           boolean shareConnection, String transportConfigurationRef) {
      FederationDownstreamConfiguration downstreamConfiguration = new FederationDownstreamConfiguration();
      downstreamConfiguration.setName(name != null ? name : connector);
      downstreamConfiguration.getConnectionConfiguration().setStaticConnectors(Collections.singletonList(connector));
      downstreamConfiguration.getConnectionConfiguration().setCircuitBreakerTimeout(-1);
      downstreamConfiguration.getConnectionConfiguration().setShareConnection(shareConnection);
      downstreamConfiguration.addPolicyRef("QueuePolicy" + queueName);
      downstreamConfiguration.setUpstreamConfigurationRef(transportConfigurationRef);

      FederationConfiguration federationConfiguration = createQueueFederationConfiguration(connector, queueName, includeFederated);
      federationConfiguration.addDownstreamConfiguration(downstreamConfiguration);

      return federationConfiguration;
   }

   public static FederationConfiguration createQueueDownstreamFederationConfiguration(String connector, String queueName, String transportConfigurationRef) {
      return createQueueDownstreamFederationConfiguration(null, connector, queueName, null, false, transportConfigurationRef);
   }

   public static FederationConfiguration createQueueUpstreamFederationConfiguration(String connector, String queueName, Boolean includeFederated) {
      FederationUpstreamConfiguration upstreamConfiguration = createQueueFederationUpstream(connector, queueName);

      FederationConfiguration federationConfiguration = createQueueFederationConfiguration(connector, queueName, includeFederated);
      federationConfiguration.addUpstreamConfiguration(upstreamConfiguration);

      return federationConfiguration;
   }

   public static FederationUpstreamConfiguration createQueueFederationUpstream(String connector, String queueName) {

      FederationUpstreamConfiguration upstreamConfiguration = new FederationUpstreamConfiguration();
      upstreamConfiguration.setName("server1-upstream");
      upstreamConfiguration.getConnectionConfiguration().setStaticConnectors(Collections.singletonList(connector));
      upstreamConfiguration.getConnectionConfiguration().setCircuitBreakerTimeout(-1);
      upstreamConfiguration.addPolicyRef("QueuePolicy" + queueName);

      return upstreamConfiguration;
   }

   public static FederationConfiguration createQueueUpstreamFederationConfiguration(String connector, String queueName) {
      return createQueueUpstreamFederationConfiguration(connector, queueName, null);
   }

   public static FederationConfiguration createQueueFederationConfiguration(String connector, String queueName, Boolean includeFederated) {

      FederationQueuePolicyConfiguration queuePolicyConfiguration = new FederationQueuePolicyConfiguration();
      queuePolicyConfiguration.setName( "QueuePolicy" + queueName);
      queuePolicyConfiguration.addInclude(new FederationQueuePolicyConfiguration.Matcher()
                                             .setQueueMatch(queueName).setAddressMatch("#"));
      if (includeFederated != null) {
         queuePolicyConfiguration.setIncludeFederated(includeFederated);
      }

      FederationConfiguration federationConfiguration = new FederationConfiguration();
      federationConfiguration.setName("default");
      federationConfiguration.addFederationPolicy(queuePolicyConfiguration);

      return federationConfiguration;
   }

   public static void addQueueTransformerConfiguration(final FederationConfiguration federationConfiguration, final String queueName) {
      federationConfiguration.addTransformerConfiguration(
         new FederationTransformerConfiguration("transformer", new TransformerConfiguration(FederatedQueueTest.TestTransformer.class.getName())));
      FederationQueuePolicyConfiguration policy = (FederationQueuePolicyConfiguration) federationConfiguration.getFederationPolicyMap().get("QueuePolicy" + queueName);
      policy.setTransformerRef("transformer");
   }

}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/stomp/StompTestBase.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.stomp;

import javax.jms.BytesMessage;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.UUID;

import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.config.CoreAddressConfiguration;
import org.apache.activemq.artemis.core.protocol.stomp.Stomp;
import org.apache.activemq.artemis.core.remoting.impl.invm.InVMAcceptorFactory;
import org.apache.activemq.artemis.core.remoting.impl.invm.InVMConnectorFactory;
import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants;
import org.apache.activemq.artemis.core.security.Role;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.ActiveMQServers;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.jms.client.ActiveMQJMSConnectionFactory;
import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
import org.apache.activemq.artemis.tests.integration.stomp.util.AbstractStompClientConnection;
import org.apache.activemq.artemis.tests.integration.stomp.util.ClientStompFrame;
import org.apache.activemq.artemis.tests.integration.stomp.util.StompClientConnection;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.utils.RetryRule;
import org.jboss.logging.Logger;
import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

@RunWith(Parameterized.class)
public abstract class StompTestBase extends ActiveMQTestBase {

   private static final Logger log = Logger.getLogger(StompTestBase.class);

   @Parameterized.Parameter
   public String scheme;

   @Rule
   public RetryRule retryRule = new RetryRule(2);

   protected URI uri;

   @Parameterized.Parameters(name = "{0}")
   public static Collection<Object[]> data() {
      return Arrays.asList(new Object[][]{{"ws+v10.stomp"}, {"tcp+v10.stomp"}});
   }

   protected String hostname = "127.0.0.1";

   protected final int port = 61613;

   private ConnectionFactory connectionFactory;

   protected Connection connection;

   protected Session session;

   protected Queue queue;

   protected Topic topic;

   protected ActiveMQServer server;

   protected String defUser = "brianm";

   protected String defPass = "<PASSWORD>";

   // Implementation methods
   // -------------------------------------------------------------------------
   public boolean isCompressLargeMessages() {
      return false;
   }

   public boolean isSecurityEnabled() {
      return false;
   }

   public boolean isPersistenceEnabled() {
      return false;
   }

   public boolean isEnableStompMessageId() {
      return false;
   }

   public Integer getStompMinLargeMessageSize() {
      return null;
   }

   public List<String> getIncomingInterceptors() {
      return null;
   }

   public List<String> getOutgoingInterceptors() {
      return null;
   }

   @Override
   @Before
   public void setUp() throws Exception {
      super.setUp();

      uri = new URI(scheme + "://" + hostname + ":" + port);

      server = createServer();
      server.start();

      waitForServerToStart(server);

      connectionFactory = createConnectionFactory();

      ((ActiveMQConnectionFactory)connectionFactory).setCompressLargeMessage(isCompressLargeMessages());

      if (isSecurityEnabled()) {
         connection = connectionFactory.createConnection("brianm", "wombats");
      } else {
         connection = connectionFactory.createConnection();
      }
      session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
      queue = session.createQueue(getQueueName());
      topic = session.createTopic(getTopicName());
      connection.start();
   }

   @Override
   @After
   public void tearDown() throws Exception {
      if (connection != null) {
         connection.close();
      }
      super.tearDown();
   }


   @After
   public void tearDownConnections() {
      AbstractStompClientConnection.tearDownConnections();
   }


   /**
    * @return
    * @throws Exception
    */
   protected ActiveMQServer createServer() throws Exception {
      String stompAcceptorURI = "tcp://" + TransportConstants.DEFAULT_HOST + ":" + TransportConstants.DEFAULT_STOMP_PORT + "?" + TransportConstants.STOMP_CONSUMER_WINDOW_SIZE + "=-1";
      if (isEnableStompMessageId()) {
         stompAcceptorURI += ";" + TransportConstants.STOMP_ENABLE_MESSAGE_ID + "=true";
      }
      if (getStompMinLargeMessageSize() != null) {
         stompAcceptorURI += ";" + TransportConstants.STOMP_MIN_LARGE_MESSAGE_SIZE + "=2048";
      }

      Configuration config = createBasicConfig().setSecurityEnabled(isSecurityEnabled())
                                                .setPersistenceEnabled(isPersistenceEnabled())
                                                .addAcceptorConfiguration("stomp", stompAcceptorURI)
                                                .addAcceptorConfiguration(new TransportConfiguration(InVMAcceptorFactory.class.getName()))
                                                .setConnectionTtlCheckInterval(500)
                                                .addQueueConfiguration(new QueueConfiguration(getQueueName()).setRoutingType(RoutingType.ANYCAST))
                                                .addAddressConfiguration(new CoreAddressConfiguration().setName(getTopicName()).addRoutingType(RoutingType.MULTICAST));

      if (getIncomingInterceptors() != null) {
         config.setIncomingInterceptorClassNames(getIncomingInterceptors());
      }

      if (getOutgoingInterceptors() != null) {
         config.setOutgoingInterceptorClassNames(getOutgoingInterceptors());
      }

      config.setPersistenceEnabled(true);

      ActiveMQServer activeMQServer = addServer(ActiveMQServers.newActiveMQServer(config, defUser, defPass));

      if (isSecurityEnabled()) {
         ActiveMQJAASSecurityManager securityManager = (ActiveMQJAASSecurityManager) activeMQServer.getSecurityManager();

         final String role = "testRole";
         securityManager.getConfiguration().addRole(defUser, role);
         config.getSecurityRoles().put("#", new HashSet<Role>() {
            {
               add(new Role(role, true, true, true, true, true, true, true, true, true, true));
            }
         });
      }

      return activeMQServer;
   }

   protected ConnectionFactory createConnectionFactory() {
      return new ActiveMQJMSConnectionFactory(false, new TransportConfiguration(InVMConnectorFactory.class.getName()));
   }

   protected static String getQueueName() {
      return "testQueue";
   }

   protected static String getQueuePrefix() {
      return "";
   }

   protected static String getTopicName() {
      return "testtopic";
   }

   protected static String getTopicPrefix() {
      return "";
   }

   public void sendJmsMessage(String msg) throws Exception {
      sendJmsMessage(msg, queue);
   }

   public void sendJmsMessage(String msg, Destination destination) throws Exception {
      MessageProducer producer = session.createProducer(destination);
      TextMessage message = session.createTextMessage(msg);
      producer.send(message);
   }

   public void sendJmsMessage(byte[] data, Destination destination) throws Exception {
      sendJmsMessage(data, "foo", "xyz", destination);
   }

   public void sendJmsMessage(String msg, String propertyName, String propertyValue) throws Exception {
      sendJmsMessage(msg.getBytes(StandardCharsets.UTF_8), propertyName, propertyValue, queue);
   }

   public void sendJmsMessage(byte[] data,
                              String propertyName,
                              String propertyValue,
                              Destination destination) throws Exception {
      MessageProducer producer = session.createProducer(destination);
      BytesMessage message = session.createBytesMessage();
      message.setStringProperty(propertyName, propertyValue);
      message.writeBytes(data);
      producer.send(message);
   }

   public static void abortTransaction(StompClientConnection conn, String txID) throws IOException, InterruptedException {
      ClientStompFrame abortFrame = conn.createFrame(Stomp.Commands.ABORT)
                                        .addHeader(Stomp.Headers.TRANSACTION, txID);

      conn.sendFrame(abortFrame);
   }

   public static void beginTransaction(StompClientConnection conn, String txID) throws IOException, InterruptedException {
      ClientStompFrame beginFrame = conn.createFrame(Stomp.Commands.BEGIN)
                                        .addHeader(Stomp.Headers.TRANSACTION, txID);

      conn.sendFrame(beginFrame);
   }

   public static void commitTransaction(StompClientConnection conn, String txID) throws IOException, InterruptedException {
      commitTransaction(conn, txID, false);
   }

   public static void commitTransaction(StompClientConnection conn,
                                 String txID,
                                 boolean receipt) throws IOException, InterruptedException {
      ClientStompFrame beginFrame = conn.createFrame(Stomp.Commands.COMMIT)
                                        .addHeader(Stomp.Headers.TRANSACTION, txID);
      String uuid = UUID.randomUUID().toString();
      if (receipt) {
         beginFrame.addHeader(Stomp.Headers.RECEIPT_REQUESTED, uuid);
      }
      ClientStompFrame resp = conn.sendFrame(beginFrame);
      if (receipt) {
         assertEquals(uuid, resp.getHeader(Stomp.Headers.Response.RECEIPT_ID));
      }
   }

   public static void ack(StompClientConnection conn,
                   String subscriptionId,
                   ClientStompFrame messageIdFrame) throws IOException, InterruptedException {
      String messageID = messageIdFrame.getHeader(Stomp.Headers.Message.MESSAGE_ID);

      ClientStompFrame frame = conn.createFrame(Stomp.Commands.ACK)
                                      .addHeader(Stomp.Headers.Message.MESSAGE_ID, messageID);

      if (subscriptionId != null) {
         frame.addHeader(Stomp.Headers.Ack.SUBSCRIPTION, subscriptionId);
      }

      ClientStompFrame response = conn.sendFrame(frame);
      if (response != null) {
         throw new IOException("failed to ack " + response);
      }
   }

   public static void ack(StompClientConnection conn,
                   String subscriptionId,
                   String mid,
                   String txID) throws IOException, InterruptedException {
      ClientStompFrame frame = conn.createFrame(Stomp.Commands.ACK)
                                      .addHeader(Stomp.Headers.Ack.SUBSCRIPTION, subscriptionId)
                                      .addHeader(Stomp.Headers.Message.MESSAGE_ID, mid);
      if (txID != null) {
         frame.addHeader(Stomp.Headers.TRANSACTION, txID);
      }

      conn.sendFrame(frame);
   }

   public static void nack(StompClientConnection conn, String subscriptionId, String messageId) throws IOException, InterruptedException {
      ClientStompFrame frame = conn.createFrame(Stomp.Commands.NACK)
                                      .addHeader(Stomp.Headers.Ack.SUBSCRIPTION, subscriptionId)
                                      .addHeader(Stomp.Headers.Message.MESSAGE_ID, messageId);

      conn.sendFrame(frame);
   }

   public static ClientStompFrame subscribe(StompClientConnection conn,
                                     String subscriptionId) throws IOException, InterruptedException {
      return subscribe(conn, subscriptionId, Stomp.Headers.Subscribe.AckModeValues.AUTO);
   }

   public static ClientStompFrame subscribe(StompClientConnection conn,
                                     String subscriptionId,
                                     String ack) throws IOException, InterruptedException {
      return subscribe(conn, subscriptionId, ack, null);
   }

   public static ClientStompFrame subscribe(StompClientConnection conn,
                                     String subscriptionId,
                                     String ack,
                                     String durableId) throws IOException, InterruptedException {
      return subscribe(conn, subscriptionId, ack, durableId, true);
   }

   public static ClientStompFrame subscribe(StompClientConnection conn,
                                     String subscriptionId,
                                     String ack,
                                     String durableId,
                                     boolean receipt) throws IOException, InterruptedException {
      return subscribe(conn, subscriptionId, ack, durableId, null, receipt);
   }

   public static ClientStompFrame subscribe(StompClientConnection conn,
                                     String subscriptionId,
                                     String ack,
                                     String durableId,
                                     String selector) throws IOException, InterruptedException {
      return subscribe(conn, subscriptionId, ack, durableId, selector, true);
   }

   public static ClientStompFrame subscribe(StompClientConnection conn,
                                     String subscriptionId,
                                     String ack,
                                     String durableId,
                                     String selector,
                                     boolean receipt) throws IOException, InterruptedException {
      return subscribe(conn, subscriptionId, ack, durableId, selector, getQueuePrefix() + getQueueName(), receipt);
   }

   public static ClientStompFrame subscribeQueue(StompClientConnection conn, String subId, String destination) throws IOException, InterruptedException {
      return subscribe(conn, subId, Stomp.Headers.Subscribe.AckModeValues.AUTO, null, null, destination, true);
   }

   public static ClientStompFrame subscribe(StompClientConnection conn,
                                            String subscriptionId,
                                            String ack,
                                            String durableId,
                                            String selector,
                                            String destination,
                                            boolean receipt) throws IOException, InterruptedException {
      return subscribe(conn, subscriptionId, ack, durableId, selector, destination, receipt, null);
   }

   public static ClientStompFrame subscribe(StompClientConnection conn,
                                            String subscriptionId,
                                            String ack,
                                            String durableId,
                                            String selector,
                                            String destination,
                                            boolean receipt,
                                            Integer consumerWindowSize) throws IOException, InterruptedException {
      return subscribe(conn, subscriptionId, ack, durableId, selector, destination, receipt, consumerWindowSize, Stomp.Headers.Subscribe.CONSUMER_WINDOW_SIZE);
   }

   public static ClientStompFrame subscribe(StompClientConnection conn,
                                            String subscriptionId,
                                            String ack,
                                            String durableId,
                                            String selector,
                                            String destination,
                                            boolean receipt,
                                            Integer consumerWindowSize,
                                            String consumerWindowSizeHeader) throws IOException, InterruptedException {

      ClientStompFrame frame = conn.createFrame(Stomp.Commands.SUBSCRIBE)
                                   .addHeader(Stomp.Headers.Subscribe.SUBSCRIPTION_TYPE, RoutingType.ANYCAST.toString())
                                   .addHeader(Stomp.Headers.Subscribe.DESTINATION, destination);
      if (subscriptionId != null) {
         frame.addHeader(Stomp.Headers.Subscribe.ID, subscriptionId);
      }
      if (ack != null) {
         frame.addHeader(Stomp.Headers.Subscribe.ACK_MODE, ack);
      }
      if (durableId != null) {
         frame.addHeader(Stomp.Headers.Subscribe.DURABLE_SUBSCRIPTION_NAME, durableId);
      }
      if (selector != null) {
         frame.addHeader(Stomp.Headers.Subscribe.SELECTOR, selector);
      }
      if (consumerWindowSize != null) {
         frame.addHeader(consumerWindowSizeHeader, consumerWindowSize.toString());
      }

      String uuid = UUID.randomUUID().toString();
      if (receipt) {
         frame.addHeader(Stomp.Headers.RECEIPT_REQUESTED, uuid);
      }

      frame = conn.sendFrame(frame);

      // Return Error Frame back to the client
      if (frame != null && frame.getCommand().equals("ERROR")) {
         return frame;
      }

      if (receipt) {
         assertEquals(uuid, frame.getHeader(Stomp.Headers.Response.RECEIPT_ID));
      }

      return frame;
   }

   public static ClientStompFrame subscribeTopic(StompClientConnection conn,
                                          String subscriptionId,
                                          String ack,
                                          String durableId) throws IOException, InterruptedException {
      return subscribeTopic(conn, subscriptionId, ack, durableId, true);
   }

   public static ClientStompFrame subscribeTopic(StompClientConnection conn,
                                          String subscriptionId,
                                          String ack,
                                          String durableId,
                                          boolean receipt) throws IOException, InterruptedException {
      return subscribeTopic(conn, subscriptionId, ack, durableId, receipt, false);
   }

   public static ClientStompFrame subscribeTopic(StompClientConnection conn,
         String subscriptionId,
         String ack,
         String durableId,
         boolean receipt,
         boolean noLocal) throws IOException, InterruptedException {
      return subscribeTopic(conn, subscriptionId, ack, durableId, Stomp.Headers.Subscribe.DURABLE_SUBSCRIPTION_NAME, receipt, noLocal);
   }

   public static ClientStompFrame subscribeTopicLegacyActiveMQ(StompClientConnection conn,
         String subscriptionId,
         String ack,
         String durableId,
         boolean receipt,
         boolean noLocal) throws IOException, InterruptedException {
      return subscribeTopic(conn, subscriptionId, ack, durableId, Stomp.Headers.Subscribe.ACTIVEMQ_DURABLE_SUBSCRIPTION_NAME, receipt, noLocal);
   }

   public static ClientStompFrame subscribeTopic(StompClientConnection conn,
                                          String subscriptionId,
                                          String ack,
                                          String durableId,
                                          String durableIdHeader,
                                          boolean receipt,
                                          boolean noLocal) throws IOException, InterruptedException {
      ClientStompFrame frame = conn.createFrame(Stomp.Commands.SUBSCRIBE)
                                   .addHeader(Stomp.Headers.Subscribe.SUBSCRIPTION_TYPE, RoutingType.MULTICAST.toString())
                                   .addHeader(Stomp.Headers.Subscribe.DESTINATION, getTopicPrefix() + getTopicName());
      if (subscriptionId != null) {
         frame.addHeader(Stomp.Headers.Subscribe.ID, subscriptionId);
      }
      if (ack != null) {
         frame.addHeader(Stomp.Headers.Subscribe.ACK_MODE, ack);
      }
      if (durableId != null) {
         frame.addHeader(durableIdHeader, durableId);
      }
      String uuid = UUID.randomUUID().toString();
      if (receipt) {
         frame.addHeader(Stomp.Headers.RECEIPT_REQUESTED, uuid);
      }
      if (noLocal) {
         frame.addHeader(Stomp.Headers.Subscribe.NO_LOCAL, "true");
      }

      frame = conn.sendFrame(frame);

      if (frame.getCommand().equals("ERROR")) {
         return frame;
      }

      if (receipt) {
         assertNotNull("Requested receipt, but response is null", frame);
         assertTrue(frame.getHeader(Stomp.Headers.Response.RECEIPT_ID).equals(uuid));
      }

      return frame;
   }

   public static ClientStompFrame unsubscribe(StompClientConnection conn, String subscriptionId) throws IOException, InterruptedException {
      return unsubscribe(conn, subscriptionId, null, false, false);
   }

   public static ClientStompFrame unsubscribe(StompClientConnection conn,
                                       String subscriptionId,
                                       boolean receipt) throws IOException, InterruptedException {
      return unsubscribe(conn, subscriptionId, null, receipt, false);
   }

   public static ClientStompFrame unsubscribe(StompClientConnection conn,
         String subscriptionId,
         String destination,
         boolean receipt,
         boolean durable) throws IOException, InterruptedException {
      return unsubscribe(conn, subscriptionId, Stomp.Headers.Unsubscribe.DURABLE_SUBSCRIPTION_NAME, destination, receipt, durable);
   }

   public static ClientStompFrame unsubscribeLegacyActiveMQ(StompClientConnection conn,
         String subscriptionId,
         String destination,
         boolean receipt,
         boolean durable) throws IOException, InterruptedException {
      return unsubscribe(conn, subscriptionId, Stomp.Headers.Unsubscribe.ACTIVEMQ_DURABLE_SUBSCRIPTION_NAME, destination, receipt, durable);
   }

   public static ClientStompFrame unsubscribe(StompClientConnection conn,
                                       String subscriptionId,
                                       String subscriptionIdHeader,
                                       String destination,
                                       boolean receipt,
                                       boolean durable) throws IOException, InterruptedException {
      ClientStompFrame frame = conn.createFrame(Stomp.Commands.UNSUBSCRIBE);
      if (durable && subscriptionId != null) {
         frame.addHeader(subscriptionIdHeader, subscriptionId);
      } else if (!durable && subscriptionId != null) {
         frame.addHeader(Stomp.Headers.Unsubscribe.ID, subscriptionId);
      }

      if (destination != null) {
         frame.addHeader(Stomp.Headers.Unsubscribe.DESTINATION, destination);
      }

      String uuid = UUID.randomUUID().toString();

      if (receipt) {
         frame.addHeader(Stomp.Headers.RECEIPT_REQUESTED, uuid);
      }

      frame = conn.sendFrame(frame);

      if (receipt) {
         assertEquals(Stomp.Responses.RECEIPT, frame.getCommand());
         assertEquals(uuid, frame.getHeader(Stomp.Headers.Response.RECEIPT_ID));
      }

      return frame;
   }

   public static ClientStompFrame send(StompClientConnection conn, String destination, String contentType, String body) throws IOException, InterruptedException {
      return send(conn, destination, contentType, body, false);
   }

   public static ClientStompFrame send(StompClientConnection conn, String destination, String contentType, String body, boolean receipt) throws IOException, InterruptedException {
      return send(conn, destination, contentType, body, receipt, null);
   }

   public static ClientStompFrame send(StompClientConnection conn, String destination, String contentType, String body, boolean receipt, RoutingType destinationType) throws IOException, InterruptedException {
      return send(conn, destination, contentType, body, receipt, destinationType, null);
   }

   public static ClientStompFrame send(StompClientConnection conn, String destination, String contentType, String body, boolean receipt, RoutingType destinationType, String txId) throws IOException, InterruptedException {
      ClientStompFrame frame = conn.createFrame(Stomp.Commands.SEND)
                                   .addHeader(Stomp.Headers.Send.DESTINATION, destination)
                                   .setBody(body);

      if (contentType != null) {
         frame.addHeader(Stomp.Headers.CONTENT_TYPE, contentType);
      }

      if (destinationType != null) {
         frame.addHeader(Stomp.Headers.Send.DESTINATION_TYPE, destinationType.toString());
      }

      if (txId != null) {
         frame.addHeader(Stomp.Headers.TRANSACTION, txId);
      }

      String uuid = UUID.randomUUID().toString();

      if (receipt) {
         frame.addHeader(Stomp.Headers.RECEIPT_REQUESTED, uuid);
      }
      frame = conn.sendFrame(frame);

      if (frame != null && frame.getCommand().equals("ERROR")) {
         return frame;
      }

      if (receipt) {
         assertEquals(Stomp.Responses.RECEIPT, frame.getCommand());
         assertEquals(uuid, frame.getHeader(Stomp.Headers.Response.RECEIPT_ID));
      }

      log.debug("Received: " + frame);

      return frame;
   }

   public static URI createStompClientUri(String scheme, String hostname, int port) throws URISyntaxException {
      return new URI(scheme + "://" + hostname + ":" + port);
   }
}


<|start_filename|>artemis-server/src/test/java/org/apache/activemq/artemis/core/security/jaas/JAASSecurityManagerTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.security.jaas;

import javax.security.auth.Subject;

import org.apache.activemq.artemis.core.security.CheckType;
import org.apache.activemq.artemis.core.security.Role;
import org.apache.activemq.artemis.core.security.impl.SecurityStoreImpl;
import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
import org.jboss.logging.Logger;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;

import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

@RunWith(Parameterized.class)
public class JAASSecurityManagerTest {
   private static final Logger log = Logger.getLogger(JAASSecurityManagerTest.class);

   @Parameterized.Parameters(name = "newLoader=({0})")
   public static Collection<Object[]> data() {
      return Arrays.asList(new Object[][] {{true}, {false}});
   }

   static {
      String path = System.getProperty("java.security.auth.login.config");
      if (path == null) {
         URL resource = PropertiesLoginModuleTest.class.getClassLoader().getResource("login.config");
         if (resource != null) {
            try {
               path = URLDecoder.decode(resource.getFile(), StandardCharsets.UTF_8.name());
               System.setProperty("java.security.auth.login.config", path);
            } catch (UnsupportedEncodingException e) {
               throw new RuntimeException(e);
            }
         }
      }
   }

   @Parameterized.Parameter
   public boolean usingNewLoader;

   @Rule
   public TemporaryFolder tmpDir = new TemporaryFolder();

   @Test
   public void testLoginClassloading() throws Exception {
      ClassLoader existingLoader = Thread.currentThread().getContextClassLoader();
      log.debug("loader: " + existingLoader);
      try {
         if (usingNewLoader) {
            URLClassLoader simulatedLoader = new URLClassLoader(new URL[]{tmpDir.getRoot().toURI().toURL()}, null);
            Thread.currentThread().setContextClassLoader(simulatedLoader);
         }
         ActiveMQJAASSecurityManager securityManager = new ActiveMQJAASSecurityManager("PropertiesLogin");

         Subject result = securityManager.authenticate("first", "secret", null, null);

         assertNotNull(result);
         assertEquals("first", SecurityStoreImpl.getUserFromSubject(result));

         Role role = new Role("programmers", true, true, true, true, true, true, true, true, true, true);
         Set<Role> roles = new HashSet<>();
         roles.add(role);
         boolean authorizationResult = securityManager.authorize(result, roles, CheckType.SEND, "someaddress");

         assertTrue(authorizationResult);

      } finally {
         Thread.currentThread().setContextClassLoader(existingLoader);
      }
   }

}


<|start_filename|>artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/components/navigation.js<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 /// <reference path="tree.component.ts"/>
var Artemis;
(function (Artemis) {
    Artemis.log.debug("loading navigation");
    var TAB_CONFIG = {
        attributes: {
            title: 'Attributes',
            route: '/artemis/attributes'
        },
        operations: {
            title: 'Operations',
            route: '/artemis/operations'
        },
        chart: {
            title: 'Chart',
            route: '/artemis/charts'
        },
        createAddress: {
            title: 'Create address',
            route: '/artemis/artemisCreateAddress'
        },
        deleteAddress: {
            title: 'Delete address',
            route: '/artemis/artemisDeleteAddress'
        },
        createQueue: {
            title: 'Create queue',
            route: '/artemis/artemisCreateQueue'
        },
        deleteQueue: {
            title: 'Delete queue',
            route: '/artemis/artemisDeleteQueue'
        },
        sendMessage: {
            title: 'Send message',
            route: '/artemis/artemisSendMessage'
        },
        addressSendMessage: {
            title: 'Send message',
            route: '/artemis/artemisAddressSendMessage'
        },
        browseQueue: {
            title: 'Browse queue',
            route: '/artemis/artemisBrowseQueue'
        },
        brokerDiagram: {
            title: 'Broker diagram',
            route: '/artemis/artemisBrokerDiagram'
        },
        artemisStatus: {
            title: 'Status',
            route: '/artemis/artemisStatus'
        },
        artemisConnections: {
            title: 'Connections',
            route: '/artemis/artemisConnections'
        },
        artemisSessions: {
            title: 'Sessions',
            route: '/artemis/artemisSessions'
        },
        artemisConsumers: {
            title: 'Consumers',
            route: '/artemis/artemisConsumers'
        },
        artemisProducers: {
            title: 'Producers',
            route: '/artemis/artemisProducers'
        },
        artemisAddresses: {
            title: 'Addresses',
            route: '/artemis/artemisAddresses'
        },
        artemisQueues: {
            title: 'Queues',
            route: '/artemis/artemisQueues'
        }
    };
    Artemis._module
    .config(configureRoutes)
    .component('artemisNavigation', {
        template: `<hawtio-tabs tabs="$ctrl.tabs" on-change="$ctrl.goto(tab)"></hawtio-tabs>`,
        controller: ArtemisNavigationController
    })
    .name;
    Artemis.log.debug("loaded navigation " + Artemis.navigationModule);

    function ArtemisNavigationController($scope, $location, workspace, localStorage, jolokia) {
        'ngInject';
        var ctrl = this;
        this.$location = $location;
        artemisJmxDomain = localStorage['artemisJmxDomain'] || "org.apache.activemq.artemis";

        $scope.$on('jmxTreeClicked', function () {
            ctrl.tabs = getTabs();
            var tab = _.find(ctrl.tabs, { path: ctrl.$location.path() });
            if (!tab) {
                tab = ctrl.tabs[0];
            }
            ctrl.$location.path(tab.path);
        });

        ArtemisNavigationController.prototype.$onInit = function () {
            this.tabs = getTabs();
        };

        ArtemisNavigationController.prototype.goto = function (tab) {
            this.$location.path(tab.path);
        };

        ctrl.showCreateAddress = hasInvokeRights(jolokia, Artemis.getBrokerMBean(workspace, jolokia), 'createAddress');
        ctrl.showDeleteAddress = hasInvokeRights(jolokia, Artemis.getBrokerMBean(workspace, jolokia), 'deleteAddress');
        ctrl.showCreateQueue = hasInvokeRights(jolokia, Artemis.getBrokerMBean(workspace, jolokia), 'createQueue');
        ctrl.showDeleteQueue = hasInvokeRights(jolokia, Artemis.getBrokerMBean(workspace, jolokia), 'destroyQueue');

        function getTabs() {

            var tabs = [];
            var enabledRoutes = Object.keys(TAB_CONFIG)
                .map(function (config) { return TAB_CONFIG[config].route; })
                .filter(function (route) { return _.startsWith(route, '/artemis'); });
            if (enabledRoutes.length > 0) {
                tabs.push(new Nav.HawtioTab(TAB_CONFIG.artemisStatus.title, TAB_CONFIG.artemisStatus.route));
                tabs.push(new Nav.HawtioTab(TAB_CONFIG.artemisConnections.title, TAB_CONFIG.artemisConnections.route));
                tabs.push(new Nav.HawtioTab(TAB_CONFIG.artemisSessions.title, TAB_CONFIG.artemisSessions.route));
                tabs.push(new Nav.HawtioTab(TAB_CONFIG.artemisConsumers.title, TAB_CONFIG.artemisConsumers.route));
                tabs.push(new Nav.HawtioTab(TAB_CONFIG.artemisProducers.title, TAB_CONFIG.artemisProducers.route));
                tabs.push(new Nav.HawtioTab(TAB_CONFIG.artemisAddresses.title, TAB_CONFIG.artemisAddresses.route));
                tabs.push(new Nav.HawtioTab(TAB_CONFIG.artemisQueues.title, TAB_CONFIG.artemisQueues.route));
                tabs.push(new Nav.HawtioTab(TAB_CONFIG.attributes.title, TAB_CONFIG.attributes.route));
                tabs.push(new Nav.HawtioTab(TAB_CONFIG.operations.title, TAB_CONFIG.operations.route));
                tabs.push(new Nav.HawtioTab(TAB_CONFIG.chart.title, TAB_CONFIG.chart.route));
                if (shouldShowCreateAddressTab()) {
                    tabs.push(new Nav.HawtioTab(TAB_CONFIG.createAddress.title, TAB_CONFIG.createAddress.route));
                }
                if (shouldShowDeleteAddressTab()) {
                    tabs.push(new Nav.HawtioTab(TAB_CONFIG.deleteAddress.title, TAB_CONFIG.deleteAddress.route));
                }
                if (shouldShowCreateQueueTab()) {
                    tabs.push(new Nav.HawtioTab(TAB_CONFIG.createQueue.title, TAB_CONFIG.createQueue.route));
                }
                if (shouldShowDeleteQueueTab()) {
                    tabs.push(new Nav.HawtioTab(TAB_CONFIG.deleteQueue.title, TAB_CONFIG.deleteQueue.route));
                }
                if (shouldShowSendMessageTab(workspace)) {
                    tabs.push(new Nav.HawtioTab(TAB_CONFIG.sendMessage.title, TAB_CONFIG.sendMessage.route));
                }
                if (shouldShowAddressSendMessageTab(workspace)) {
                    tabs.push(new Nav.HawtioTab(TAB_CONFIG.addressSendMessage.title, TAB_CONFIG.addressSendMessage.route));
                }
                if (shouldShowBrowseMessageTab(workspace)) {
                    tabs.push(new Nav.HawtioTab(TAB_CONFIG.browseQueue.title, TAB_CONFIG.browseQueue.route));
                }
                tabs.push(new Nav.HawtioTab(TAB_CONFIG.brokerDiagram.title, TAB_CONFIG.brokerDiagram.route));
            }
            return tabs;
        }

        function shouldShowCreateAddressTab() {
            return workspace.selectionHasDomainAndLastFolderName(artemisJmxDomain, 'addresses') && ctrl.showCreateAddress;
        }

        function shouldShowDeleteAddressTab() {
            return workspace.hasDomainAndProperties(artemisJmxDomain, {'component': 'addresses'}) && !workspace.hasDomainAndProperties(artemisJmxDomain, {'subcomponent': 'queues'}) && !workspace.hasDomainAndProperties(artemisJmxDomain, {'subcomponent': 'diverts'}) && ctrl.showDeleteAddress;
        }

        function shouldShowCreateQueueTab() {
            return workspace.hasDomainAndProperties(artemisJmxDomain, {'component': 'addresses'}) && !workspace.hasDomainAndProperties(artemisJmxDomain, {'subcomponent': 'queues'}) && !workspace.hasDomainAndProperties(artemisJmxDomain, {'subcomponent': 'diverts'}) && ctrl.showCreateQueue;
        }

        function shouldShowDeleteQueueTab() {
            return workspace.hasDomainAndProperties(artemisJmxDomain, {'subcomponent': 'queues'}) && ctrl.showDeleteQueue;
        }

        function shouldShowSendMessageTab(workspace) {
            return workspace.hasDomainAndProperties(artemisJmxDomain, {'subcomponent': 'queues'}) && hasQueueinvokeRights(workspace, "sendMessage");
        }

        function shouldShowAddressSendMessageTab(workspace) {
            return workspace.hasDomainAndProperties(artemisJmxDomain, {'component': 'addresses'}) && !workspace.hasDomainAndProperties(artemisJmxDomain, {'subcomponent': 'queues'}) && hasQueueinvokeRights(workspace, "sendMessage");
        }

        function shouldShowBrowseMessageTab(workspace) {
            return workspace.hasDomainAndProperties(artemisJmxDomain, {'subcomponent': 'queues'}) && hasQueueinvokeRights(workspace, "browse") && hasQueueinvokeRights(workspace, "countMessages");
        }

        function hasInvokeRights(jolokia, mbean, operation) {
            var response = jolokia.request({
                type: 'exec',
                mbean: 'hawtio:type=security,area=jmx,name=ArtemisJMXSecurity',
                operation: 'canInvoke(java.lang.String, java.lang.String)',
                arguments: [mbean, operation] },
                Core.onSuccess(null));

            Artemis.log.debug(operation + "=" + response.value);
            return response.value;
        }
        function hasQueueinvokeRights(workspace, operation) {
            var selection = workspace.selection;
            if (!selection)
                return false;
            var mbean = selection.objectName;
            if (!mbean)
                return false;
            return hasInvokeRights(jolokia, mbean, operation)
        }
    }
    ArtemisNavigationController.$inject = ['$scope', '$location', 'workspace', 'localStorage', 'jolokia']

    function configureRoutes($routeProvider) {
       $routeProvider.
        when('/artemis/attributes', { templateUrl: 'plugins/jmx/html/attributes/attributes.html' }).
        when('/artemis/operations', { template: '<operations></operations>' }).
        when('/artemis/charts', { templateUrl: 'plugins/jmx/html/charts.html' }).
        when('/artemis/charts/edit', { templateUrl: 'plugins/jmx/html/chartEdit.html' }).
        when('/artemis/artemisCreateAddress', { template: '<artemis-create-address></artemis-create-address>'}).
        when('/artemis/artemisDeleteAddress', { template: '<artemis-delete-address></artemis-delete-address>'}).
        when('/artemis/artemisCreateQueue', { template: '<artemis-create-queue></artemis-create-queue>'}).
        when('/artemis/artemisDeleteQueue', { template: '<artemis-delete-queue></artemis-delete-queue>'}).
        when('/artemis/artemisSendMessage', { template: '<artemis-send-message></artemis-send-message>'}).
        when('/artemis/artemisAddressSendMessage', { template: '<artemis-address-send-message></artemis-address-send-message>'}).
        when('/artemis/artemisBrowseQueue', { template: '<artemis-browse-queue></artemis-browse-queue>'}).
        when('/artemis/artemisBrokerDiagram', { template: '<artemis-broker-diagram></artemis-broker-diagram>'}).
        when('/artemis/artemisStatus', { template: '<artemis-status></artemis-status>'}).
        when('/artemis/artemisConnections', { template: '<artemis-connections></artemis-connections>'}).
        when('/artemis/artemisSessions', { template: '<artemis-sessions></artemis-sessions>'}).
        when('/artemis/artemisConsumers', { template: '<artemis-consumers></artemis-consumers>'}).
        when('/artemis/artemisProducers', { template: '<artemis-producers></artemis-producers>'}).
        when('/artemis/artemisAddresses', { template: '<artemis-addresses></artemis-addresses>'}).
        when('/artemis/artemisQueues', { template: '<artemis-queues></artemis-queues>'});
    }
    configureRoutes.$inject = ['$routeProvider'];

})(Artemis || (Artemis = {}));


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/client/ExpiryLargeMessageTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.client;

import javax.jms.BytesMessage;
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import java.io.File;

import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.core.settings.impl.AddressFullMessagePolicy;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.tests.util.CFUtil;
import org.apache.activemq.artemis.tests.util.Wait;
import org.junit.Test;

/**
 * This test will send large messages in page-mode, DLQ then, expiry then, and they should be received fine
 */
public class ExpiryLargeMessageTest extends ActiveMQTestBase {

   // Constants -----------------------------------------------------
   final SimpleString EXPIRY = new SimpleString("my-expiry");

   final SimpleString DLQ = new SimpleString("my-DLQ");

   final SimpleString MY_QUEUE = new SimpleString("MY-QUEUE");

   final int messageSize = 10 * 1024;

   // it has to be an even number
   final int numberOfMessages = 50;

   // Attributes ----------------------------------------------------

   // Static --------------------------------------------------------

   // Constructors --------------------------------------------------

   // Public --------------------------------------------------------

   @Test
   public void testExpiryMessagesThenDLQ() throws Exception {
      ActiveMQServer server = createServer(true);

      server.getConfiguration().setMessageExpiryScanPeriod(600000);

      AddressSettings setting = new AddressSettings().setAddressFullMessagePolicy(AddressFullMessagePolicy.PAGE).setMaxDeliveryAttempts(5).setMaxSizeBytes(50 * 1024).setPageSizeBytes(10 * 1024).setExpiryAddress(EXPIRY).setDeadLetterAddress(DLQ);
      server.getAddressSettingsRepository().addMatch(MY_QUEUE.toString(), setting);
      server.getAddressSettingsRepository().addMatch(EXPIRY.toString(), setting);

      server.start();

      server.createQueue(new QueueConfiguration(EXPIRY).setRoutingType(RoutingType.ANYCAST));

      server.createQueue(new QueueConfiguration(DLQ).setRoutingType(RoutingType.ANYCAST));

      server.createQueue(new QueueConfiguration(MY_QUEUE).setRoutingType(RoutingType.ANYCAST));

      ServerLocator locator = createInVMNonHALocator();

      ClientSessionFactory sf = addSessionFactory(createSessionFactory(locator));

      ClientSession session = sf.createSession(true, true, 0);

      byte[] bufferSample = new byte[messageSize];

      for (int i = 0; i < bufferSample.length; i++) {
         bufferSample[i] = getSamplebyte(i);
      }

      ClientProducer producer = session.createProducer(MY_QUEUE);

      long timeToExpiry = System.currentTimeMillis() + 1000;
      for (int i = 0; i < numberOfMessages; i++) {
         ClientMessage message = session.createMessage(true);

         message.putIntProperty("count", i);

         // Send a few regular messages first, then all is just large messages
         if (i % 2 == 0) {
            message.putBooleanProperty("tst-large", false);
            message.getBodyBuffer().writeBytes(bufferSample);
         } else {
            message.putBooleanProperty("tst-large", true);
            message.setBodyInputStream(createFakeLargeStream(messageSize));
         }

         message.setExpiration(timeToExpiry);

         producer.send(message);
      }

      session.close();

      server.stop();
      server.start();

      Queue queueExpiry = server.locateQueue(EXPIRY);
      Queue myQueue = server.locateQueue(MY_QUEUE);

      sf = createSessionFactory(locator);

      Thread.sleep(1500);

      Wait.assertEquals(numberOfMessages, () -> {
         myQueue.expireReferences();
         return getMessageCount(queueExpiry);
      });

      session = sf.createSession(false, false);

      ClientConsumer cons = session.createConsumer(EXPIRY);
      session.start();

      // Consume half of the messages to make sure all the messages are paging (on the second try)
      for (int i = 0; i < numberOfMessages / 2; i++) {
         ClientMessage msg = cons.receive(5000);
         assertNotNull(msg);
         msg.acknowledge();
      }

      session.commit();

      cons.close();

      for (int rep = 0; rep < 6; rep++) {
         cons = session.createConsumer(EXPIRY);
         session.start();

         for (int i = 0; i < numberOfMessages / 2; i++) {
            ClientMessage message = cons.receive(5000);
            assertNotNull(message);

            if (i % 10 == 0) {
               instanceLog.debug("Received " + i);
            }

            for (int location = 0; location < messageSize; location++) {
               assertEquals(getSamplebyte(location), message.getBodyBuffer().readByte());
            }
            message.acknowledge();
         }

         session.rollback();

         cons.close();

         session.close();
         sf.close();

         if (rep == 0) {
            // restart the server at the first try
            server.stop();
            server.start();
         }

         sf = createSessionFactory(locator);
         session = sf.createSession(false, false);
         session.start();
      }

      cons = session.createConsumer(EXPIRY);
      session.start();
      assertNull(cons.receiveImmediate());

      cons.close();

      session.close();
      sf.close();

      for (int rep = 0; rep < 2; rep++) {
         sf = createSessionFactory(locator);

         session = sf.createSession(false, false);

         cons = session.createConsumer(DLQ);

         session.start();

         for (int i = 0; i < numberOfMessages / 2; i++) {
            ClientMessage message = cons.receive(5000);
            assertNotNull(message);

            if (i % 10 == 0) {
               instanceLog.debug("Received " + i);
            }

            for (int location = 0; location < messageSize; location++) {
               assertEquals(getSamplebyte(location), message.getBodyBuffer().readByte());
            }
            message.acknowledge();
         }
         if (rep == 0) {
            session.rollback();
            session.close();
            sf.close();
            server.stop();
            server.start();
         }
      }

      session.commit();

      assertNull(cons.receiveImmediate());

      session.close();
      sf.close();
      locator.close();

      validateNoFilesOnLargeDir();
   }


   @Test
   public void testExpiryMessagesAMQP() throws Exception {
      testExpiryMessagesAMQP(false, 300 * 1024);
   }

   @Test
   public void testExpiryMessagesAMQPRestartBeforeExpiry() throws Exception {
      testExpiryMessagesAMQP(true, 300 * 1024);
   }

   // this is just sanity check for the test
   @Test
   public void testExpiryMessagesAMQPRegularMessageStandardMessage() throws Exception {
      testExpiryMessagesAMQP(false, 30);
   }

   // this is just sanity check for the test
   @Test
   public void testExpiryMessagesAMQPRestartBeforeExpiryStandardMessage() throws Exception {
      testExpiryMessagesAMQP(true, 30);
   }

   public void testExpiryMessagesAMQP(boolean restartBefore, int bodySize) throws Exception {
      ActiveMQServer server = createServer(true, true);

      server.getConfiguration().setMessageExpiryScanPeriod(6000);

      AddressSettings setting = new AddressSettings().setAddressFullMessagePolicy(AddressFullMessagePolicy.PAGE).setMaxDeliveryAttempts(5).setMaxSizeBytes(50 * 1024).setPageSizeBytes(10 * 1024).setExpiryAddress(EXPIRY).setDeadLetterAddress(DLQ);
      server.getAddressSettingsRepository().addMatch(MY_QUEUE.toString(), setting);
      server.getAddressSettingsRepository().addMatch(EXPIRY.toString(), setting);

      server.start();

      server.createQueue(new QueueConfiguration(EXPIRY).setRoutingType(RoutingType.ANYCAST));

      server.createQueue(new QueueConfiguration(DLQ).setRoutingType(RoutingType.ANYCAST));

      server.createQueue(new QueueConfiguration(MY_QUEUE).setRoutingType(RoutingType.ANYCAST));

      ConnectionFactory connectionFactory = CFUtil.createConnectionFactory("AMQP", "tcp://localhost:61616");
      Connection connection = connectionFactory.createConnection();
      Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);

      byte[] bufferSample = new byte[bodySize];

      for (int i = 0; i < bufferSample.length; i++) {
         bufferSample[i] = getSamplebyte(i);
      }

      javax.jms.Queue jmsQueue = session.createQueue(MY_QUEUE.toString());

      MessageProducer producer = session.createProducer(jmsQueue);
      producer.setTimeToLive(300);

      for (int i = 0; i < numberOfMessages; i++) {
         BytesMessage message = session.createBytesMessage();
         message.writeBytes(bufferSample);

         message.setIntProperty("count", i);

         producer.send(message);
      }

      session.close();
      connection.close();

      if (restartBefore) {
         server.stop();
         server.start();
      }

      Queue queueExpiry = server.locateQueue(EXPIRY);
      Queue myQueue = server.locateQueue(MY_QUEUE);

      Wait.assertEquals(numberOfMessages, () -> {
         myQueue.expireReferences();
         return getMessageCount(queueExpiry);
      });

      if (!restartBefore) {
         server.stop();
         server.start();
      }


      // validateNoFilesOnLargeDir(getLargeMessagesDir(), numberOfMessages);

      connection = connectionFactory.createConnection();
      session = connection.createSession(true, Session.SESSION_TRANSACTED);

      MessageConsumer cons = session.createConsumer(session.createQueue(EXPIRY.toString()));
      connection.start();

      // Consume half of the messages to make sure all the messages are paging (on the second try)
      for (int i = 0; i < numberOfMessages; i++) {
         javax.jms.Message msg = cons.receive(5000);
         assertNotNull(msg);
         msg.acknowledge();
      }

      session.commit();

      connection.close();

   }

   /**
    * Tests if the system would still couple with old data where the LargeMessage was linked to its previous copy
    *
    * @throws Exception
    */
   @Test
   public void testCompatilityWithLinks() throws Exception {
      ActiveMQServer server = createServer(true);

      server.getConfiguration().setMessageExpiryScanPeriod(600000);

      AddressSettings setting = new AddressSettings().setAddressFullMessagePolicy(AddressFullMessagePolicy.PAGE).setMaxDeliveryAttempts(5).setMaxSizeBytes(-1).setPageSizeBytes(10 * 1024).setExpiryAddress(EXPIRY).setDeadLetterAddress(DLQ);
      server.getAddressSettingsRepository().addMatch(MY_QUEUE.toString(), setting);
      server.getAddressSettingsRepository().addMatch(EXPIRY.toString(), setting);

      server.start();

      server.createQueue(new QueueConfiguration(EXPIRY).setRoutingType(RoutingType.ANYCAST));

      server.createQueue(new QueueConfiguration(DLQ).setRoutingType(RoutingType.ANYCAST));

      server.createQueue(new QueueConfiguration(MY_QUEUE).setRoutingType(RoutingType.ANYCAST));

      ServerLocator locator = createInVMNonHALocator();

      ClientSessionFactory sf = addSessionFactory(createSessionFactory(locator));

      ClientSession session = sf.createSession(true, true, 0);

      byte[] bufferSample = new byte[messageSize];

      for (int i = 0; i < bufferSample.length; i++) {
         bufferSample[i] = getSamplebyte(i);
      }

      ClientProducer producer = session.createProducer(MY_QUEUE);

      long timeToExpiry = System.currentTimeMillis() + 1000;
      for (int i = 0; i < numberOfMessages; i++) {
         ClientMessage message = session.createMessage(true);

         message.putIntProperty("count", i);

         // Everything is going to be a large message
         message.putBooleanProperty("tst-large", true);
         message.setBodyInputStream(createFakeLargeStream(messageSize));

         message.setExpiration(timeToExpiry);

         producer.send(message);
      }

      server.stop();
      server.start();

      sf = createSessionFactory(locator);

      session = sf.createSession(true, true, 0);
      session.start();

      Thread.sleep(1500);

      ClientConsumer cons = session.createConsumer(MY_QUEUE);
      assertNull(cons.receive(1000));

      session.close();

      session = sf.createSession(false, false);

      cons = session.createConsumer(EXPIRY);
      session.start();

      ClientMessage msg = cons.receive(5000);
      assertNotNull(msg);
      msg.acknowledge();
      session.rollback();

      server.stop();

      // rename the file, simulating old behaviour
      long messageID = msg.getMessageID();
      long oldID = msg.getLongProperty(Message.HDR_ORIG_MESSAGE_ID);

      File largeMessagesFileDir = new File(getLargeMessagesDir());
      File oldFile = new File(largeMessagesFileDir, oldID + ".msg");
      File currentFile = new File(largeMessagesFileDir, messageID + ".msg");
      currentFile.renameTo(oldFile);

      server.start();

      sf = createSessionFactory(locator);

      session = sf.createSession(true, true, 0);
      session.start();

      cons = session.createConsumer(EXPIRY);

      for (int i = 0; i < numberOfMessages; i++) {
         ClientMessage message = cons.receive(5000);
         assertNotNull(message);

         if (i % 10 == 0) {
            instanceLog.debug("Received " + i);
         }

         for (int location = 0; location < messageSize; location++) {
            assertEquals(getSamplebyte(location), message.getBodyBuffer().readByte());
         }
         message.acknowledge();
      }

      session.commit();

      session.close();
   }

   // Package protected ---------------------------------------------

   // Protected -----------------------------------------------------

   // Private -------------------------------------------------------

   // Inner classes -------------------------------------------------

}


<|start_filename|>artemis-cli/src/main/java/org/apache/activemq/artemis/cli/commands/tools/xml/XmlDataExporterUtil.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.cli.commands.tools.xml;

import com.google.common.base.Preconditions;
import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.utils.Base64;

/**
 * Common utility methods to help with XML message conversion
 */
public class XmlDataExporterUtil {

   public static String convertProperty(final Object value) {
      if (value instanceof byte[]) {
         return encode((byte[]) value);
      } else {
         return value == null ? XmlDataConstants.NULL : value.toString();
      }
   }

   public static String getPropertyType(final Object value) {
      String stringValue = null;

      // if the value is null then we can't really know what it is so just set
      // the type to the most generic thing
      if (value == null) {
         stringValue = XmlDataConstants.PROPERTY_TYPE_BYTES;
      } else if (value instanceof Boolean) {
         stringValue = XmlDataConstants.PROPERTY_TYPE_BOOLEAN;
      } else if (value instanceof Byte) {
         stringValue = XmlDataConstants.PROPERTY_TYPE_BYTE;
      } else if (value instanceof Short) {
         stringValue = XmlDataConstants.PROPERTY_TYPE_SHORT;
      } else if (value instanceof Integer) {
         stringValue = XmlDataConstants.PROPERTY_TYPE_INTEGER;
      } else if (value instanceof Long) {
         stringValue = XmlDataConstants.PROPERTY_TYPE_LONG;
      } else if (value instanceof Float) {
         stringValue = XmlDataConstants.PROPERTY_TYPE_FLOAT;
      } else if (value instanceof Double) {
         stringValue = XmlDataConstants.PROPERTY_TYPE_DOUBLE;
      } else if (value instanceof String) {
         stringValue = XmlDataConstants.PROPERTY_TYPE_STRING;
      } else if (value instanceof SimpleString) {
         stringValue = XmlDataConstants.PROPERTY_TYPE_SIMPLE_STRING;
      } else if (value instanceof byte[]) {
         stringValue = XmlDataConstants.PROPERTY_TYPE_BYTES;
      }

      return stringValue;
   }

   public static String getMessagePrettyType(byte rawType) {
      String prettyType = XmlDataConstants.DEFAULT_TYPE_PRETTY;

      if (rawType == Message.BYTES_TYPE) {
         prettyType = XmlDataConstants.BYTES_TYPE_PRETTY;
      } else if (rawType == Message.MAP_TYPE) {
         prettyType = XmlDataConstants.MAP_TYPE_PRETTY;
      } else if (rawType == Message.OBJECT_TYPE) {
         prettyType = XmlDataConstants.OBJECT_TYPE_PRETTY;
      } else if (rawType == Message.STREAM_TYPE) {
         prettyType = XmlDataConstants.STREAM_TYPE_PRETTY;
      } else if (rawType == Message.TEXT_TYPE) {
         prettyType = XmlDataConstants.TEXT_TYPE_PRETTY;
      }

      return prettyType;
   }

   /**
    * Base64 encode a ServerMessage body into the proper XML format
    */
   public static String encodeMessageBodyBase64(final Message message) throws Exception {
      Preconditions.checkNotNull(message, "ServerMessage can not be null");

      ActiveMQBuffer byteBuffer = message.toCore().getReadOnlyBodyBuffer();
      byte[] buffer = new byte[byteBuffer.writerIndex()];
      byteBuffer.readBytes(buffer);

      return XmlDataExporterUtil.encode(buffer);
   }

   protected static String encode(final byte[] data) {
      return Base64.encodeBytes(data, 0, data.length, Base64.DONT_BREAK_LINES | Base64.URL_SAFE);
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/plugin/FederationBrokerPluginTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.plugin;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.Topic;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.config.FederationConfiguration;
import org.apache.activemq.artemis.core.server.ServerConsumer;
import org.apache.activemq.artemis.core.server.plugin.ActiveMQServerFederationPlugin;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.tests.integration.federation.FederatedTestBase;
import org.apache.activemq.artemis.tests.integration.federation.FederatedTestUtil;
import org.apache.activemq.artemis.tests.util.Wait;
import org.apache.activemq.artemis.utils.RetryRule;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;

import static org.apache.activemq.artemis.tests.integration.plugin.MethodCalledVerifier.AFTER_CLOSE_FEDERATED_QUEUE_CONSUMER;
import static org.apache.activemq.artemis.tests.integration.plugin.MethodCalledVerifier.AFTER_CREATE_FEDERATED_QUEUE_CONSUMER;
import static org.apache.activemq.artemis.tests.integration.plugin.MethodCalledVerifier.AFTER_FEDERATED_QUEUE_CONSUMER_MESSAGE_HANDLED;
import static org.apache.activemq.artemis.tests.integration.plugin.MethodCalledVerifier.BEFORE_CLOSE_FEDERATED_QUEUE_CONSUMER;
import static org.apache.activemq.artemis.tests.integration.plugin.MethodCalledVerifier.BEFORE_CREATE_FEDERATED_QUEUE_CONSUMER;
import static org.apache.activemq.artemis.tests.integration.plugin.MethodCalledVerifier.BEFORE_FEDERATED_QUEUE_CONSUMER_MESSAGE_HANDLED;
import static org.apache.activemq.artemis.tests.integration.plugin.MethodCalledVerifier.FEDERATED_ADDRESS_CONDITIONAL_CREATE_CONSUMER;
import static org.apache.activemq.artemis.tests.integration.plugin.MethodCalledVerifier.FEDERATED_QUEUE_CONDITIONAL_CREATE_CONSUMER;
import static org.apache.activemq.artemis.tests.integration.plugin.MethodCalledVerifier.FEDERATION_STREAM_STARTED;
import static org.apache.activemq.artemis.tests.integration.plugin.MethodCalledVerifier.FEDERATION_STREAM_STOPPED;

public class FederationBrokerPluginTest extends FederatedTestBase {

   @Rule
   public RetryRule retryRule = new RetryRule(2);

   private final Map<String, AtomicInteger> methodCalls = new ConcurrentHashMap<>();
   private final MethodCalledVerifier verifier0 = new MethodCalledVerifier(methodCalls);

   @Override
   @Before
   public void setUp() throws Exception {
      super.setUp();

      getServer(0).registerBrokerPlugin(verifier0);
   }

   @Test
   public void testFederationStreamStartStop() throws Exception {
      String address = getName();

      FederationConfiguration federationConfiguration = FederatedTestUtil.createAddressUpstreamFederationConfiguration("server1", address);
      getServer(0).getConfiguration().getFederationConfigurations().add(federationConfiguration);
      getServer(0).getFederationManager().deploy();

      verifier0.validatePluginMethodsEquals(1, 5000, 500, FEDERATION_STREAM_STARTED);
      getServer(0).getFederationManager().stop();
      verifier0.validatePluginMethodsEquals(1, 5000, 500, FEDERATION_STREAM_STOPPED);

   }

   @Test
   public void testFederationStreamConsumerAddressUpstream() throws Exception {
      String address = getName();

      FederationConfiguration federationConfiguration = FederatedTestUtil.createAddressUpstreamFederationConfiguration("server1", address);
      getServer(0).getConfiguration().getFederationConfigurations().add(federationConfiguration);
      getServer(0).getFederationManager().deploy();

      testFederationStreamConsumerAddress(address);
   }

   @Test
   public void testFederationStreamConsumerAddressDownstream() throws Exception {
      String address = getName();

      FederationConfiguration federationConfiguration = FederatedTestUtil.createAddressDownstreamFederationConfiguration(
         "server0", address, "server1");
      getServer(1).getConfiguration().getFederationConfigurations().add(federationConfiguration);
      getServer(1).getFederationManager().deploy();

      testFederationStreamConsumerAddress(address);
   }


   private void testFederationStreamConsumerAddress(String address) throws Exception {
      ConnectionFactory cf1 = getCF(1);
      ConnectionFactory cf0 = getCF(0);
      try (Connection connection1 = cf1.createConnection(); Connection connection0 = cf0.createConnection()) {
         connection1.start();
         connection0.start();

         Session session0 = connection0.createSession();
         Session session1 = connection1.createSession();

         Topic topic0 = session0.createTopic(address);
         Topic topic1 = session1.createTopic(address);

         MessageConsumer consumer0 = session0.createConsumer(topic0);
         MessageProducer producer1 = session1.createProducer(topic1);

         assertTrue(Wait.waitFor(() -> getServer(1).getPostOffice().getBindingsForAddress(
            SimpleString.toSimpleString(address)).getBindings().size() == 1, 5000, 500));

         verifier0.validatePluginMethodsEquals(1, 5000, 500, BEFORE_CREATE_FEDERATED_QUEUE_CONSUMER,
                                               AFTER_CREATE_FEDERATED_QUEUE_CONSUMER, FEDERATED_ADDRESS_CONDITIONAL_CREATE_CONSUMER);
         verifier0.validatePluginMethodsEquals(0, 5000, 500, BEFORE_CLOSE_FEDERATED_QUEUE_CONSUMER,
                                               AFTER_CLOSE_FEDERATED_QUEUE_CONSUMER);

         producer1.send(session1.createTextMessage("hello"));
         assertNotNull(consumer0.receive(5000));

         consumer0.close();

         verifier0.validatePluginMethodsEquals(1, 5000, 500, BEFORE_CLOSE_FEDERATED_QUEUE_CONSUMER,
                                               AFTER_CLOSE_FEDERATED_QUEUE_CONSUMER, BEFORE_FEDERATED_QUEUE_CONSUMER_MESSAGE_HANDLED,
                                               AFTER_FEDERATED_QUEUE_CONSUMER_MESSAGE_HANDLED);
      }
   }

   @Test
   public void testFederationStreamConsumerQueueUpstream() throws Exception {
      String queueName = getName();

      FederationConfiguration federationConfiguration = FederatedTestUtil.createQueueUpstreamFederationConfiguration("server1", queueName);
      getServer(0).getConfiguration().getFederationConfigurations().add(federationConfiguration);
      getServer(0).getFederationManager().deploy();

      testFederationStreamConsumerQueue(queueName);
   }

   @Test
   public void testFederationStreamConsumerQueueDownstream() throws Exception {
      String queueName = getName();

      FederationConfiguration federationConfiguration = FederatedTestUtil.createQueueDownstreamFederationConfiguration(
         "server0", queueName, "server1");
      getServer(1).getConfiguration().getFederationConfigurations().add(federationConfiguration);
      getServer(1).getFederationManager().deploy();

      testFederationStreamConsumerQueue(queueName);
   }

   private void testFederationStreamConsumerQueue(String queueName) throws Exception {
      ConnectionFactory cf1 = getCF(1);
      ConnectionFactory cf0 = getCF(0);
      try (Connection connection1 = cf1.createConnection(); Connection connection0 = cf0.createConnection()) {
         connection0.start();
         connection1.start();

         Session session0 = connection0.createSession();
         Session session1 = connection1.createSession();

         Queue queue0 = session0.createQueue(queueName);
         Queue queue1 = session1.createQueue(queueName);

         MessageProducer producer1 = session1.createProducer(queue1);
         producer1.send(session1.createTextMessage("hello"));

         MessageConsumer consumer0 = session0.createConsumer(queue0);
         assertNotNull(consumer0.receive(1000));

         verifier0.validatePluginMethodsEquals(1, 5000, 500, BEFORE_CREATE_FEDERATED_QUEUE_CONSUMER,
                                               AFTER_CREATE_FEDERATED_QUEUE_CONSUMER, FEDERATED_QUEUE_CONDITIONAL_CREATE_CONSUMER);
         verifier0.validatePluginMethodsEquals(0, 5000, 500, BEFORE_CLOSE_FEDERATED_QUEUE_CONSUMER,
                                               AFTER_CLOSE_FEDERATED_QUEUE_CONSUMER);

         consumer0.close();

         verifier0.validatePluginMethodsEquals(1, 5000, 500, BEFORE_CLOSE_FEDERATED_QUEUE_CONSUMER,
                                               AFTER_CLOSE_FEDERATED_QUEUE_CONSUMER, BEFORE_FEDERATED_QUEUE_CONSUMER_MESSAGE_HANDLED,
                                               AFTER_FEDERATED_QUEUE_CONSUMER_MESSAGE_HANDLED);

      }
   }

   @Test
   public void testFederatedAddressConditional() throws Exception {
      String address = getName();

      getServer(0).registerBrokerPlugin(new ActiveMQServerFederationPlugin() {
         @Override
         public boolean federatedAddressConditionalCreateConsumer(org.apache.activemq.artemis.core.server.Queue queue) {
            //always return false for test
            return false;
         }
      });

      FederationConfiguration federationConfiguration = FederatedTestUtil.createAddressUpstreamFederationConfiguration("server1", address);
      getServer(0).getConfiguration().getFederationConfigurations().add(federationConfiguration);
      getServer(0).getFederationManager().deploy();

      ConnectionFactory cf1 = getCF(1);
      ConnectionFactory cf0 = getCF(0);
      try (Connection connection1 = cf1.createConnection(); Connection connection0 = cf0.createConnection()) {
         connection1.start();
         connection0.start();

         Session session0 = connection0.createSession();
         Session session1 = connection1.createSession();

         Topic topic0 = session0.createTopic(address);
         Topic topic1 = session1.createTopic(address);

         MessageConsumer consumer0 = session0.createConsumer(topic0);
         MessageProducer producer1 = session1.createProducer(topic1);

         assertFalse(Wait.waitFor(() -> getServer(1).getPostOffice().getBindingsForAddress(
            SimpleString.toSimpleString(address)).getBindings().size() > 0, 2000, 500));

         verifier0.validatePluginMethodsEquals(1, 5000, 500, FEDERATED_ADDRESS_CONDITIONAL_CREATE_CONSUMER);
         verifier0.validatePluginMethodsEquals(0, 5000, 500, BEFORE_CREATE_FEDERATED_QUEUE_CONSUMER,
                                               AFTER_CREATE_FEDERATED_QUEUE_CONSUMER);

         producer1.send(session1.createTextMessage("hello"));
         assertNull(consumer0.receive(1000));
         consumer0.close();

         verifier0.validatePluginMethodsEquals(0, 5000, 500, BEFORE_CLOSE_FEDERATED_QUEUE_CONSUMER,
                                               AFTER_CLOSE_FEDERATED_QUEUE_CONSUMER);

      }
   }

   @Test
   public void testFederatedQueueConditional() throws Exception {
      String queueName = getName();

      getServer(0).registerBrokerPlugin(new ActiveMQServerFederationPlugin() {
         @Override
         public boolean federatedQueueConditionalCreateConsumer(ServerConsumer consumer) {
            //always return false for test
            return false;
         }
      });

      FederationConfiguration federationConfiguration = FederatedTestUtil.createQueueUpstreamFederationConfiguration("server1", queueName);
      getServer(0).getConfiguration().getFederationConfigurations().add(federationConfiguration);
      getServer(0).getFederationManager().deploy();

      ConnectionFactory cf1 = getCF(1);
      ConnectionFactory cf0 = getCF(0);
      try (Connection connection1 = cf1.createConnection(); Connection connection0 = cf0.createConnection()) {
         connection0.start();
         connection1.start();

         Session session0 = connection0.createSession();
         Session session1 = connection1.createSession();

         Queue queue0 = session0.createQueue(queueName);
         Queue queue1 = session1.createQueue(queueName);

         MessageProducer producer1 = session1.createProducer(queue1);
         producer1.send(session1.createTextMessage("hello"));

         MessageConsumer consumer0 = session0.createConsumer(queue0);
         assertNull(consumer0.receive(1000));

         verifier0.validatePluginMethodsEquals(1, 5000, 500, FEDERATED_QUEUE_CONDITIONAL_CREATE_CONSUMER);
         verifier0.validatePluginMethodsEquals(0, 5000, 500, BEFORE_CREATE_FEDERATED_QUEUE_CONSUMER,
                                               AFTER_CREATE_FEDERATED_QUEUE_CONSUMER);
         consumer0.close();

         verifier0.validatePluginMethodsEquals(0, 5000, 500, BEFORE_CLOSE_FEDERATED_QUEUE_CONSUMER,
                                               AFTER_CLOSE_FEDERATED_QUEUE_CONSUMER);

      }
   }

   protected ConnectionFactory getCF(int i) throws Exception {
      return new ActiveMQConnectionFactory("vm://" + i);
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/persistence/DivertConfigurationStorageTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.persistence;

import org.apache.activemq.artemis.core.config.DivertConfiguration;
import org.apache.activemq.artemis.core.config.StoreConfiguration;
import org.apache.activemq.artemis.core.config.TransformerConfiguration;
import org.apache.activemq.artemis.core.persistence.config.PersistedDivertConfiguration;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.util.List;
import java.util.Map;

public class DivertConfigurationStorageTest  extends StorageManagerTestBase {

   public DivertConfigurationStorageTest(StoreConfiguration.StoreType storeType) {
      super(storeType);
   }

   @Override
   @Before
   public void setUp() throws Exception {
      super.setUp();
   }

   @Test
   public void testStoreDivertConfiguration() throws Exception {
      createStorage();

      DivertConfiguration configuration = new DivertConfiguration();
      configuration.setName("name");
      configuration.setAddress("address");
      configuration.setExclusive(true);
      configuration.setForwardingAddress("forward");
      configuration.setRoutingName("routiingName");
      TransformerConfiguration mytransformer = new TransformerConfiguration("mytransformer");
      mytransformer.getProperties().put("key1", "prop1");
      mytransformer.getProperties().put("key2", "prop2");
      mytransformer.getProperties().put("key3", "prop3");
      configuration.setTransformerConfiguration(mytransformer);

      journal.storeDivertConfiguration(new PersistedDivertConfiguration(configuration));

      journal.stop();

      journal.start();

      List<PersistedDivertConfiguration> divertConfigurations = journal.recoverDivertConfigurations();

      Assert.assertEquals(1, divertConfigurations.size());

      PersistedDivertConfiguration persistedDivertConfiguration = divertConfigurations.get(0);
      Assert.assertEquals(configuration.getName(), persistedDivertConfiguration.getDivertConfiguration().getName());
      Assert.assertEquals(configuration.getAddress(), persistedDivertConfiguration.getDivertConfiguration().getAddress());
      Assert.assertEquals(configuration.isExclusive(), persistedDivertConfiguration.getDivertConfiguration().isExclusive());
      Assert.assertEquals(configuration.getForwardingAddress(), persistedDivertConfiguration.getDivertConfiguration().getForwardingAddress());
      Assert.assertEquals(configuration.getRoutingName(), persistedDivertConfiguration.getDivertConfiguration().getRoutingName());
      Assert.assertNotNull(persistedDivertConfiguration.getDivertConfiguration().getTransformerConfiguration());
      Assert.assertEquals("mytransformer", persistedDivertConfiguration.getDivertConfiguration().getTransformerConfiguration().getClassName());
      Map<String, String> properties = persistedDivertConfiguration.getDivertConfiguration().getTransformerConfiguration().getProperties();
      Assert.assertEquals(3, properties.size());
      Assert.assertEquals("prop1", properties.get("key1"));
      Assert.assertEquals("prop2", properties.get("key2"));
      Assert.assertEquals("prop3", properties.get("key3"));
      journal.stop();

      journal = null;

   }

   @Test
   public void testStoreDivertConfigurationNoTransformer() throws Exception {
      createStorage();

      DivertConfiguration configuration = new DivertConfiguration();
      configuration.setName("name");
      configuration.setAddress("address");
      configuration.setExclusive(true);
      configuration.setForwardingAddress("forward");
      configuration.setRoutingName("routiingName");

      journal.storeDivertConfiguration(new PersistedDivertConfiguration(configuration));

      journal.stop();

      journal.start();

      List<PersistedDivertConfiguration> divertConfigurations = journal.recoverDivertConfigurations();

      Assert.assertEquals(1, divertConfigurations.size());

      PersistedDivertConfiguration persistedDivertConfiguration = divertConfigurations.get(0);
      Assert.assertEquals(configuration.getName(), persistedDivertConfiguration.getDivertConfiguration().getName());
      Assert.assertEquals(configuration.getAddress(), persistedDivertConfiguration.getDivertConfiguration().getAddress());
      Assert.assertEquals(configuration.isExclusive(), persistedDivertConfiguration.getDivertConfiguration().isExclusive());
      Assert.assertEquals(configuration.getForwardingAddress(), persistedDivertConfiguration.getDivertConfiguration().getForwardingAddress());
      Assert.assertEquals(configuration.getRoutingName(), persistedDivertConfiguration.getDivertConfiguration().getRoutingName());
      Assert.assertNull(persistedDivertConfiguration.getDivertConfiguration().getTransformerConfiguration());
      journal.stop();

      journal = null;

   }
}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/impl/WildcardAddressManager.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.postoffice.impl;

import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.config.WildcardConfiguration;
import org.apache.activemq.artemis.core.persistence.StorageManager;
import org.apache.activemq.artemis.core.postoffice.Binding;
import org.apache.activemq.artemis.core.postoffice.Bindings;
import org.apache.activemq.artemis.core.postoffice.BindingsFactory;
import org.apache.activemq.artemis.core.server.metrics.MetricsManager;
import org.apache.activemq.artemis.core.transaction.Transaction;

/**
 * extends the simple manager to allow wildcard addresses to be used.
 */
public class WildcardAddressManager extends SimpleAddressManager {

   private final AddressMap<Bindings> addressMap = new AddressMap<>(wildcardConfiguration.getAnyWordsString(), wildcardConfiguration.getSingleWordString(), wildcardConfiguration.getDelimiter());

   public WildcardAddressManager(final BindingsFactory bindingsFactory,
                                 final WildcardConfiguration wildcardConfiguration,
                                 final StorageManager storageManager,
                                 final MetricsManager metricsManager) {
      super(bindingsFactory, wildcardConfiguration, storageManager, metricsManager);
   }

   public WildcardAddressManager(final BindingsFactory bindingsFactory,
                                 final StorageManager storageManager,
                                 final MetricsManager metricsManager) {
      super(bindingsFactory, storageManager, metricsManager);
   }

   // publish, may be a new address that needs wildcard bindings added
   // won't contain a wildcard because we don't ever route to a wildcards at this time
   @Override
   public Bindings getBindingsForRoutingAddress(final SimpleString address) throws Exception {
      assert !isAWildcardAddress(address);

      Bindings bindings = super.getBindingsForRoutingAddress(address);

      if (bindings == null) {

         final Bindings[] lazyCreateResult = new Bindings[1];

         addressMap.visitMatchingWildcards(address, new AddressMapVisitor<Bindings>() {

            Bindings newBindings = null;
            @Override
            public void visit(Bindings matchingBindings) throws Exception {
               if (newBindings == null) {
                  newBindings = addMappingsInternal(address, matchingBindings.getBindings());
                  lazyCreateResult[0] = newBindings;
               } else {
                  for (Binding binding : matchingBindings.getBindings()) {
                     newBindings.addBinding(binding);
                  }
               }
            }
         });

         bindings = lazyCreateResult[0];
         if (bindings != null) {
            // record such that any new wildcard bindings can join
            addressMap.put(address, bindings);
         }
      }
      return bindings;
   }

   /**
    * If the address to add the binding to contains a wildcard then a copy of the binding (with the same underlying queue)
    * will be added to matching addresses. If the address is non wildcard, then we need to add any existing matching wildcard
    * bindings to this address the first time we see it.
    *
    * @param binding the binding to add
    * @return true if the address was a new mapping
    */
   @Override
   public boolean addBinding(final Binding binding) throws Exception {
      final boolean bindingsForANewAddress = super.addBinding(binding);
      final SimpleString address = binding.getAddress();
      final Bindings bindingsForRoutingAddress = mappings.get(binding.getAddress());

      if (isAWildcardAddress(address)) {

         addressMap.visitMatching(address, bindings -> {
            // this wildcard binding needs to be added to matching addresses
            bindings.addBinding(binding);
         });

      } else if (bindingsForANewAddress) {
         // existing wildcards may match this new simple address
         addressMap.visitMatchingWildcards(address, bindings -> {
            // apply existing bindings from matching wildcards
            for (Binding toAdd : bindings.getBindings()) {
               bindingsForRoutingAddress.addBinding(toAdd);
            }
         });
      }

      if (bindingsForANewAddress) {
         addressMap.put(address, bindingsForRoutingAddress);
      }
      return bindingsForANewAddress;
   }

   @Override
   public Binding removeBinding(final SimpleString uniqueName, Transaction tx) throws Exception {
      Binding binding = super.removeBinding(uniqueName, tx);
      if (binding != null) {
         SimpleString address = binding.getAddress();
         if (isAWildcardAddress(address)) {

            addressMap.visitMatching(address, bindings -> removeBindingInternal(bindings.getName(), uniqueName));

         }
      }
      return binding;
   }

   private boolean isAWildcardAddress(SimpleString address) {
      return address.containsEitherOf(wildcardConfiguration.getAnyWords(), wildcardConfiguration.getSingleWord());
   }

   @Override
   protected void bindingsEmpty(SimpleString realAddress, Bindings bindings) {
      addressMap.remove(realAddress, bindings);
   }

   @Override
   public void clear() {
      super.clear();
      addressMap.reset();
   }

   public AddressMap<Bindings> getAddressMap() {
      return addressMap;
   }
}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/transaction/ResourceManager.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.transaction;

import javax.transaction.xa.Xid;
import java.util.List;
import java.util.Map;

import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.core.server.ActiveMQComponent;
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;

public interface ResourceManager extends ActiveMQComponent {

   boolean putTransaction(Xid xid, Transaction tx, RemotingConnection remotingConnection) throws ActiveMQException;

   Transaction getTransaction(Xid xid);

   Transaction removeTransaction(Xid xid, RemotingConnection remotingConnection) throws ActiveMQException;

   int getTimeoutSeconds();

   List<Xid> getPreparedTransactions();

   Map<Xid, Long> getPreparedTransactionsWithCreationTime();

   void putHeuristicCompletion(long txid, Xid xid, boolean b);

   long removeHeuristicCompletion(Xid xid);

   List<Xid> getHeuristicCommittedTransactions();

   List<Xid> getHeuristicRolledbackTransactions();

   List<Xid> getInDoubtTransactions();

   int size();

}


<|start_filename|>tests/performance-jmh/src/main/java/org/apache/activemq/artemis/tests/performance/jmh/WildcardAddressManagerPerfTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.performance.jmh;

import java.util.concurrent.atomic.AtomicLong;

import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.config.WildcardConfiguration;
import org.apache.activemq.artemis.core.filter.Filter;
import org.apache.activemq.artemis.core.postoffice.Binding;
import org.apache.activemq.artemis.core.postoffice.BindingType;
import org.apache.activemq.artemis.core.postoffice.Bindings;
import org.apache.activemq.artemis.core.postoffice.BindingsFactory;
import org.apache.activemq.artemis.core.postoffice.impl.BindingsImpl;
import org.apache.activemq.artemis.core.postoffice.impl.WildcardAddressManager;
import org.apache.activemq.artemis.core.server.Bindable;
import org.apache.activemq.artemis.core.server.RoutingContext;
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Group;
import org.openjdk.jmh.annotations.GroupThreads;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;

@State(Scope.Benchmark)
@Fork(2)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 8, time = 1)
public class WildcardAddressManagerPerfTest {

   private static class BindingFactoryFake implements BindingsFactory {

      @Override
      public Bindings createBindings(SimpleString address) {
         return new BindingsImpl(address, null);
      }
   }

   private static class BindingFake implements Binding {

      final SimpleString address;
      final SimpleString id;
      final Long idl;

      BindingFake(SimpleString addressParameter, SimpleString id, long idl) {
         this.address = addressParameter;
         this.id = id;
         this.idl = idl;
      }

      @Override
      public void unproposed(SimpleString groupID) {

      }

      @Override
      public SimpleString getAddress() {
         return address;
      }

      @Override
      public Bindable getBindable() {
         return null;
      }

      @Override
      public BindingType getType() {
         return BindingType.LOCAL_QUEUE;
      }

      @Override
      public SimpleString getUniqueName() {
         return id;
      }

      @Override
      public SimpleString getRoutingName() {
         return id;
      }

      @Override
      public SimpleString getClusterName() {
         return null;
      }

      @Override
      public Filter getFilter() {
         return null;
      }

      @Override
      public boolean isHighAcceptPriority(Message message) {
         return false;
      }

      @Override
      public boolean isExclusive() {
         return false;
      }

      @Override
      public Long getID() {
         return idl;
      }

      @Override
      public int getDistance() {
         return 0;
      }

      @Override
      public void route(Message message, RoutingContext context) {
      }

      @Override
      public void close() {
      }

      @Override
      public String toManagementString() {
         return "FakeBiding Address=" + this.address;
      }

      @Override
      public boolean isConnected() {
         return true;
      }

      @Override
      public void routeWithAck(Message message, RoutingContext context) {

      }
   }

   public WildcardAddressManager addressManager;

   @Param({"2", "8", "10"})
   int topicsLog2;
   int topics;
   AtomicLong topicCounter;
   private static final WildcardConfiguration WILDCARD_CONFIGURATION;
   SimpleString[] addresses;

   static {
      WILDCARD_CONFIGURATION = new WildcardConfiguration();
      WILDCARD_CONFIGURATION.setAnyWords('>');
   }

   private static final SimpleString WILDCARD = SimpleString.toSimpleString("Topic1.>");

   @Setup
   public void init() throws Exception {
      addressManager = new WildcardAddressManager(new BindingFactoryFake(), WILDCARD_CONFIGURATION, null, null);

      addressManager.addAddressInfo(new AddressInfo(WILDCARD, RoutingType.MULTICAST));

      topics = 1 << topicsLog2;
      addresses = new SimpleString[topics];
      for (int i = 0; i < topics; i++) {
         Binding binding = new BindingFake(WILDCARD, SimpleString.toSimpleString("" + i), i);
         addressManager.addBinding(binding);
         addresses[i] = SimpleString.toSimpleString("Topic1." + i);
         addressManager.getBindingsForRoutingAddress(addresses[i]);
      }
      topicCounter = new AtomicLong(0);
      topicCounter.set(topics);
   }

   private long nextId() {
      return topicCounter.getAndIncrement();
   }

   @State(value = Scope.Thread)
   public static class ThreadState {

      Binding binding;
      long next;
      SimpleString[] addresses;

      @Setup
      public void init(WildcardAddressManagerPerfTest benchmarkState) {
         final long id = benchmarkState.nextId();
         binding = new BindingFake(WILDCARD, SimpleString.toSimpleString("" + id), id);
         addresses = benchmarkState.addresses;
      }

      public SimpleString nextAddress() {
         final long current = next;
         next = current + 1;
         final int index = (int) (current & (addresses.length - 1));
         return addresses[index];
      }
   }

   @Benchmark
   @Group("both")
   @GroupThreads(2)
   public Bindings testPublishWhileAddRemoveNewBinding(ThreadState state) throws Exception {
      return addressManager.getBindingsForRoutingAddress(state.nextAddress());
   }

   @Benchmark
   @Group("both")
   @GroupThreads(2)
   public Binding testAddRemoveNewBindingWhilePublish(ThreadState state) throws Exception {
      final Binding binding = state.binding;
      addressManager.addBinding(binding);
      return addressManager.removeBinding(binding.getUniqueName(), null);
   }

   @Benchmark
   @GroupThreads(4)
   public Bindings testJustPublish(ThreadState state) throws Exception {
      return addressManager.getBindingsForRoutingAddress(state.nextAddress());
   }

   @Benchmark
   @GroupThreads(4)
   public Binding testJustAddRemoveNewBinding(ThreadState state) throws Exception {
      final Binding binding = state.binding;
      addressManager.addBinding(binding);
      return addressManager.removeBinding(binding.getUniqueName(), null);
   }

}



<|start_filename|>artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/BufferHelper.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.utils;

import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.logs.ActiveMQUtilBundle;

/**
 * Helper methods to read and write from ActiveMQBuffer.
 */
public class BufferHelper {

   /**
    * Size of a String as if it was a Nullable Simple String
    */
   public static int sizeOfNullableSimpleString(String str) {
      if (str == null) {
         return DataConstants.SIZE_BOOLEAN;
      } else {
         return DataConstants.SIZE_BOOLEAN + sizeOfSimpleString(str);
      }
   }

   /**
    * Size of a String as it if was a Simple String
    */
   public static int sizeOfSimpleString(String str) {
      return DataConstants.SIZE_INT + str.length() * 2;
   }

   public static void writeAsNullableSimpleString(ActiveMQBuffer buffer, String str) {
      buffer.writeNullableSimpleString(SimpleString.toSimpleString(str));
   }

   public static String readNullableSimpleStringAsString(ActiveMQBuffer buffer) {
      SimpleString str = buffer.readNullableSimpleString();
      return str != null ? str.toString() : null;
   }

   public static void writeAsSimpleString(ActiveMQBuffer buffer, String str) {
      buffer.writeSimpleString(new SimpleString(str));
   }

   /**
    * @param buffer
    */
   public static void writeNullableBoolean(ActiveMQBuffer buffer, Boolean value) {
      buffer.writeBoolean(value != null);

      if (value != null) {
         buffer.writeBoolean(value.booleanValue());
      }
   }

   public static int sizeOfNullableBoolean(Boolean value) {
      return DataConstants.SIZE_BOOLEAN + (value != null ? DataConstants.SIZE_BOOLEAN : 0);
   }

   public static Boolean readNullableBoolean(ActiveMQBuffer buffer) {
      boolean isNotNull = buffer.readBoolean();

      if (isNotNull) {
         return buffer.readBoolean();
      } else {
         return null;
      }
   }

   /**
    * @param buffer
    */
   public static void writeNullableLong(ActiveMQBuffer buffer, Long value) {
      buffer.writeBoolean(value != null);

      if (value != null) {
         buffer.writeLong(value.longValue());
      }
   }

   /**
    * @param buffer
    */
   public static void writeNullableDouble(ActiveMQBuffer buffer, Double value) {
      buffer.writeBoolean(value != null);

      if (value != null) {
         buffer.writeDouble(value.doubleValue());
      }
   }

   public static int sizeOfNullableLong(Long value) {
      return DataConstants.SIZE_BOOLEAN + (value != null ? DataConstants.SIZE_LONG : 0);
   }

   public static int sizeOfNullableDouble(Double value) {
      return DataConstants.SIZE_BOOLEAN + (value != null ? DataConstants.SIZE_DOUBLE : 0);
   }

   public static Long readNullableLong(ActiveMQBuffer buffer) {
      boolean isNotNull = buffer.readBoolean();

      if (isNotNull) {
         return buffer.readLong();
      } else {
         return null;
      }
   }

   /**
    * @param buffer
    */
   public static void writeNullableInteger(ActiveMQBuffer buffer, Integer value) {
      buffer.writeBoolean(value != null);

      if (value != null) {
         buffer.writeInt(value.intValue());
      }
   }

   public static int sizeOfNullableInteger(Integer value) {
      return DataConstants.SIZE_BOOLEAN + (value != null ? DataConstants.SIZE_INT : 0);
   }

   public static Integer readNullableInteger(ActiveMQBuffer buffer) {
      boolean isNotNull = buffer.readBoolean();

      if (isNotNull) {
         return buffer.readInt();
      } else {
         return null;
      }
   }

   public static Double readNullableDouble(ActiveMQBuffer buffer) {
      boolean isNotNull = buffer.readBoolean();

      if (isNotNull) {
         return buffer.readDouble();
      } else {
         return null;
      }
   }

   public static int sizeOfNullableString(String s) {
      if (s == null) {
         return DataConstants.SIZE_BOOLEAN;
      }
      return DataConstants.SIZE_BOOLEAN + sizeOfString(s);
   }

   public static int sizeOfString(String s) {
      int len = s.length();
      if (len < 9) {
         return DataConstants.SIZE_INT + (len * DataConstants.SIZE_SHORT);
      }
      // 4095 == 0xfff
      if (len < 4095) {
         // beware: this one has O(n) cost: look at UTF8Util::saveUTF
         final int expectedEncodedUTF8Len = UTF8Util.calculateUTFSize(s);
         if (expectedEncodedUTF8Len > 65535) {
            throw ActiveMQUtilBundle.BUNDLE.stringTooLong(len);
         }
         return DataConstants.SIZE_INT + DataConstants.SIZE_SHORT + expectedEncodedUTF8Len;
      }
      // it seems weird but this SIZE_INT is required due to how UTF8Util is encoding UTF strings
      // so this SIZE_INT is required
      // perhaps we could optimize it and remove it, but that would break compatibility with older clients and journal
      return DataConstants.SIZE_INT + sizeOfSimpleString(s);
   }
}



<|start_filename|>tests/smoke-tests/src/test/java/org/apache/activemq/artemis/tests/smoke/console/pages/QueuesPage.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.tests.smoke.console.pages;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

public class QueuesPage extends ArtemisPage {
   private static final int MESSAGES_COUNT_COLUMN = 10;

   public QueuesPage(WebDriver driver) {
      super(driver);
   }

   public QueuePage getQueuePage(String name, int timeout) {
      WebElement messagesCountWebElement = driver.findElement(getQueueLocator(name)).
         findElements(By.tagName("td")).get(MESSAGES_COUNT_COLUMN);

      messagesCountWebElement.findElement(By.tagName("a")).click();

      waitForElementToBeVisible(By.xpath("//h1[contains(text(),'Browse Queue')]"), timeout);

      return new QueuePage(driver);
   }

   public int countQueue(String name) {
      return driver.findElements(getQueueLocator(name)).size();
   }

   public int getMessagesCount(String name) {
      WebElement messagesCountWebElement = driver.findElement(getQueueLocator(name)).
         findElements(By.tagName("td")).get(MESSAGES_COUNT_COLUMN);

      return Integer.parseInt(messagesCountWebElement.findElement(By.tagName("a")).getText());
   }

   private By getQueueLocator(String name) {
      return By.xpath("//tr[td/span/a='" + name + "']");
   }
}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/postoffice/impl/LocalQueueBinding.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.postoffice.impl;

import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.filter.Filter;
import org.apache.activemq.artemis.core.postoffice.BindingType;
import org.apache.activemq.artemis.core.postoffice.QueueBinding;
import org.apache.activemq.artemis.core.server.Bindable;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.core.server.RoutingContext;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.jboss.logging.Logger;

public class LocalQueueBinding implements QueueBinding {

   private static final Logger logger = Logger.getLogger(LocalQueueBinding.class);

   private final SimpleString address;

   private final Queue queue;

   private final SimpleString clusterName;

   private SimpleString name;

   public LocalQueueBinding(final SimpleString address, final Queue queue, final SimpleString nodeID) {
      this.address = address;

      this.queue = queue;

      this.name = queue.getName();

      clusterName = queue.getName().concat(nodeID);
   }

   @Override
   public boolean isLocal() {
      return true;
   }

   @Override
   public Long getID() {
      return queue.getID();
   }

   @Override
   public Filter getFilter() {
      return queue.getFilter();
   }

   @Override
   public SimpleString getAddress() {
      return address;
   }

   @Override
   public Bindable getBindable() {
      return queue;
   }

   @Override
   public Queue getQueue() {
      return queue;
   }

   @Override
   public SimpleString getRoutingName() {
      if (queue.getRoutingType() == RoutingType.ANYCAST) {
         return address;
      }
      return name;
   }

   @Override
   public SimpleString getUniqueName() {
      return queue.getName();
   }

   @Override
   public SimpleString getClusterName() {
      return clusterName;
   }

   @Override
   public boolean isExclusive() {
      return false;
   }

   @Override
   public int getDistance() {
      return 0;
   }

   @Override
   public boolean isHighAcceptPriority(final Message message) {
      // It's a high accept priority if the queue has at least one matching consumer

      return queue.hasMatchingConsumer(message);
   }

   @Override
   public void unproposed(SimpleString groupID) {
      queue.unproposed(groupID);
   }

   @Override
   public void route(final Message message, final RoutingContext context) throws Exception {
      if (isMatchRoutingType(context)) {
         if (logger.isTraceEnabled()) {
            logger.trace("adding routing " + queue.getID() + " on message " + message);
         }
         queue.route(message, context);
      } else {
         if (logger.isTraceEnabled()) {
            logger.trace("routing " + queue.getID() + " is ignored as routing type did not match");
         }
      }
   }

   @Override
   public void routeWithAck(Message message, RoutingContext context) throws Exception {
      if (isMatchRoutingType(context)) {
         if (logger.isTraceEnabled()) {
            logger.trace("Message " + message + " routed with ack on queue " + queue.getID());
         }
         queue.routeWithAck(message, context);
      }
   }

   private boolean isMatchRoutingType(RoutingContext context) {
      return (context.getRoutingType() == null || context.getRoutingType() == queue.getRoutingType());
   }

   public boolean isQueueBinding() {
      return true;
   }

   @Override
   public int consumerCount() {
      return queue.getConsumerCount();
   }

   @Override
   public BindingType getType() {
      return BindingType.LOCAL_QUEUE;
   }

   @Override
   public void close() throws Exception {
      queue.close();
   }

   @Override
   public String toString() {
      return "LocalQueueBinding [address=" + address +
         ", queue=" +
         queue +
         ", filter=" +
         getFilter() +
         ", name=" +
         name +
         ", clusterName=" +
         clusterName +
         "]";
   }

   @Override
   public String toManagementString() {
      return this.getClass().getSimpleName() + " [address=" + address + ", queue=" + queue + "]";
   }

   @Override
   public boolean isConnected() {
      return true;
   }
}


<|start_filename|>artemis-commons/src/main/java/org/apache/activemq/artemis/utils/pools/MpscPool.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.utils.pools;

import java.util.Queue;
import java.util.function.Consumer;
import java.util.function.Supplier;

import io.netty.util.internal.PlatformDependent;


/**
 * A simple encapsulation of Netty MpscQueue to provide a pool of objects.
 * Use this pool only when the borrowing of object (consume) is done on a single thread.
 * This is using a Multi Producer Single Consumer queue (MPSC).
 * If you need other uses you may create different strategies for ObjectPooling.
 * @param <T>
 */
public class MpscPool<T> extends Pool<T> {

   public MpscPool(int maxSize, Consumer<T> cleaner, Supplier<T> supplier) {
      super(maxSize, cleaner, supplier);
   }

   @Override
   protected Queue<T> createQueue(int maxSize) {
      final Queue<T> internalPool;
      if (maxSize > 0) {
         internalPool = PlatformDependent.newFixedMpscQueue(maxSize);
      } else {
         internalPool = null;
      }
      return internalPool;
   }

}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/plugin/ResourceBrokerPluginTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.plugin;

import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.plugin.ActiveMQServerResourcePlugin;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.core.transaction.Transaction;
import org.apache.activemq.artemis.core.transaction.impl.XidImpl;
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.utils.UUIDGenerator;
import org.jboss.logging.Logger;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class ResourceBrokerPluginTest extends ActiveMQTestBase {
   private static final Logger logger = Logger.getLogger(ResourceBrokerPluginTest.class);

   private final Map<String, AddressSettings> addressSettings = new HashMap<>();

   private ActiveMQServer server;

   private ClientSession clientSession;

   private ClientSessionFactory sessionFactory;

   private Configuration configuration;

   private ServerLocator locator;

   @Override
   @Before
   public void setUp() throws Exception {
      super.setUp();

      addressSettings.clear();

      configuration = createDefaultNettyConfig();

      server = createServer(true, configuration, -1, -1, addressSettings);

      // start the server
      server.start();

      locator = createNettyNonHALocator();
      sessionFactory = createSessionFactory(locator);

      clientSession = addClientSession(sessionFactory.createSession(true, false, false));
   }

   @Test
   public void testXATransaction() throws Exception {
      final CountDownLatch latch = new CountDownLatch(4);
      final Xid clientXid = new XidImpl("XA_TEST".getBytes(), 1, UUIDGenerator.getInstance().generateStringUUID().getBytes());

      server.registerBrokerPlugin(new ActiveMQServerResourcePlugin() {
         @Override
         public void beforePutTransaction(Xid xid,
                                          Transaction tx,
                                          RemotingConnection remotingConnection) throws ActiveMQException {
            Assert.assertEquals(clientXid, xid);
            latch.countDown();
         }

         @Override
         public void afterPutTransaction(Xid xid,
                                         Transaction tx,
                                         RemotingConnection remotingConnection) throws ActiveMQException {
            Assert.assertEquals(clientXid, xid);
            latch.countDown();
         }

         @Override
         public void beforeRemoveTransaction(Xid xid, RemotingConnection remotingConnection) throws ActiveMQException {
            Assert.assertEquals(clientXid, xid);
            latch.countDown();
         }

         @Override
         public void afterRemoveTransaction(Xid xid, RemotingConnection remotingConnection) throws ActiveMQException {
            Assert.assertEquals(clientXid, xid);
            latch.countDown();
         }
      });

      clientSession.start(clientXid, XAResource.TMNOFLAGS);
      clientSession.end(clientXid, XAResource.TMSUCCESS);
      clientSession.commit(clientXid, true);
      Assert.assertTrue(latch.await(100, TimeUnit.MILLISECONDS));
   }

   @Test
   public void testXAClientsMisconfiguration() throws Exception {
      // https://github.com/jbosstm/narayana/blob/5.10.5.Final/ArjunaCore/arjuna/classes/com/arjuna/ats/internal/arjuna/FormatConstants.java#L30
      final int JTA_FORMAT_ID = 131077;
      final CountDownLatch latch = new CountDownLatch(1);
      ClientSessionFactory sessionFactoryEx = createSessionFactory(locator);
      ClientSession clientSessionEx = sessionFactoryEx.createSession(true, false, false);

      server.registerBrokerPlugin(new ActiveMQServerResourcePlugin() {
         private final ConcurrentMap<String, String> clients = new ConcurrentHashMap<>();

         @Override
         public void afterPutTransaction(Xid xid,
                                         Transaction tx,
                                         RemotingConnection remotingConnection) throws ActiveMQException {
            if (xid.getFormatId() == JTA_FORMAT_ID) {
               // https://github.com/jbosstm/narayana/blob/5.10.5.Final/ArjunaJTA/jta/classes/com/arjuna/ats/jta/xa/XATxConverter.java#L188
               String nodeName = new String(Arrays.copyOfRange(xid.getGlobalTransactionId(),28, xid.getGlobalTransactionId().length), StandardCharsets.UTF_8);

               String clientAddress = clients.putIfAbsent(nodeName, remotingConnection.getRemoteAddress());

               if (clientAddress != null && !clientAddress.equals(remotingConnection.getRemoteAddress())) {
                  latch.countDown();

                  logger.warn("Possible XA client misconfiguration. Two addresses with the same node name " +
                                 nodeName + ": " + clientAddress + "/" + remotingConnection.getRemoteAddress());
               }
            }
         }
      });

      Xid xid = new XidImpl("XA_TEST".getBytes(), JTA_FORMAT_ID, UUIDGenerator.getInstance().generateStringUUID().getBytes());
      clientSession.start(xid, XAResource.TMNOFLAGS);

      byte[] getGlobalTransactionIdEx = xid.getGlobalTransactionId().clone();
      getGlobalTransactionIdEx[0] = (byte)(getGlobalTransactionIdEx[0] + 1);
      Xid xidEx = new XidImpl(xid.getBranchQualifier(), JTA_FORMAT_ID, getGlobalTransactionIdEx);
      clientSessionEx.start(xidEx, XAResource.TMNOFLAGS);

      Assert.assertTrue(latch.await(100, TimeUnit.MILLISECONDS));
   }
}


<|start_filename|>artemis-web/src/main/java/org/apache/activemq/artemis/component/JolokiaFilter.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.component;

import org.apache.activemq.artemis.logs.AuditLogger;
import org.eclipse.jetty.server.Request;

import javax.security.auth.Subject;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;

/*
* This intercepts all calls made via jolokia
* */
public class JolokiaFilter implements Filter {
   @Override
   public void init(FilterConfig filterConfig) {
   }

   @Override
   public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
      /*
      * this is the only place we can catch the remote address of the calling console client thru Jolokia.
      * We set the address on the calling thread which will end up in JMX audit logging
      * */
      if (AuditLogger.isAnyLoggingEnabled() && servletRequest != null) {
         String remoteHost = servletRequest.getRemoteHost();
         AuditLogger.setRemoteAddress(remoteHost + ":" + servletRequest.getRemotePort());
      }
      filterChain.doFilter(servletRequest, servletResponse);
      /*
      * This is the only place we can get access to the authenticated subject on invocations after the login has happened.
      * we set the subject for audit logging
      * */
      if (AuditLogger.isAnyLoggingEnabled()) {
         try {
            HttpSession session = ((Request) servletRequest).getSession();
            Subject subject = (Subject) session.getAttribute("subject");
            AuditLogger.setCurrentCaller(subject);
         } catch (Throwable e) {
            //best effort
         }
      }
   }

   @Override
   public void destroy() {
   }
}


<|start_filename|>artemis-core-client/src/main/java/org/apache/activemq/artemis/reader/MessageUtil.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.reader;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.ActiveMQPropertyConversionException;
import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.api.core.SimpleString;

/**
 * static methods intended for import static on JMS like messages.
 *
 * This provides a helper for core message to act some of the JMS functions used by the JMS wrapper
 */
public class MessageUtil {

   public static final String CORRELATIONID_HEADER_NAME_STRING = "JMSCorrelationID";

   public static final SimpleString CORRELATIONID_HEADER_NAME = new SimpleString(CORRELATIONID_HEADER_NAME_STRING);

   public static final SimpleString REPLYTO_HEADER_NAME = new SimpleString("JMSReplyTo");

   public static final String TYPE_HEADER_NAME_STRING = "JMSType";

   public static final SimpleString TYPE_HEADER_NAME = new SimpleString(TYPE_HEADER_NAME_STRING);

   public static final SimpleString JMS = new SimpleString("JMS");

   public static final SimpleString JMSX = new SimpleString("JMSX");

   public static final SimpleString JMS_ = new SimpleString("JMS_");

   public static final String JMSXDELIVERYCOUNT = "JMSXDeliveryCount";

   public static final String JMSXGROUPID = "JMSXGroupID";

   public static final String JMSXGROUPSEQ = "JMSXGroupSeq";

   public static final String JMSXUSERID = "JMSXUserID";

   public static final String CONNECTION_ID_PROPERTY_NAME_STRING = "__AMQ_CID";

   public static final SimpleString CONNECTION_ID_PROPERTY_NAME = new SimpleString(CONNECTION_ID_PROPERTY_NAME_STRING);

   //   public static ActiveMQBuffer getBodyBuffer(Message message) {
   //      return message.getBodyBuffer();
   //   }

   public static byte[] getJMSCorrelationIDAsBytes(Message message) {
      Object obj = message.getObjectProperty(CORRELATIONID_HEADER_NAME);

      if (obj instanceof byte[]) {
         return (byte[]) obj;
      } else {
         return null;
      }
   }

   public static void setJMSType(Message message, String type) {
      message.putStringProperty(TYPE_HEADER_NAME, new SimpleString(type));
   }

   public static String getJMSType(Message message) {
      SimpleString ss = message.getSimpleStringProperty(TYPE_HEADER_NAME);

      if (ss != null) {
         return ss.toString();
      } else {
         return null;
      }
   }

   public static final void setJMSCorrelationIDAsBytes(Message message,
                                                       final byte[] correlationID) throws ActiveMQException {
      if (correlationID == null || correlationID.length == 0) {
         throw new ActiveMQException("Please specify a non-zero length byte[]");
      }
      message.putBytesProperty(CORRELATIONID_HEADER_NAME, correlationID);
   }

   public static void setJMSCorrelationID(Message message, final String correlationID) {
      if (correlationID == null) {
         message.removeProperty(CORRELATIONID_HEADER_NAME);
      } else {
         message.putStringProperty(CORRELATIONID_HEADER_NAME, new SimpleString(correlationID));
      }
   }

   public static String getJMSCorrelationID(Message message) {
      try {
         return message.getStringProperty(CORRELATIONID_HEADER_NAME);
      } catch (ActiveMQPropertyConversionException e) {
         return null;
      }
   }

   public static SimpleString getJMSReplyTo(Message message) {
      return message.getSimpleStringProperty(REPLYTO_HEADER_NAME);
   }

   public static void setJMSReplyTo(Message message, final String dest) {
      if (dest == null) {
         message.removeProperty(REPLYTO_HEADER_NAME);
      } else {
         message.putStringProperty(REPLYTO_HEADER_NAME, dest);
      }
   }

   public static void setJMSReplyTo(Message message, final SimpleString dest) {
      if (dest == null) {
         message.removeProperty(REPLYTO_HEADER_NAME);
      } else {
         message.putStringProperty(REPLYTO_HEADER_NAME, dest);
      }
   }

   public static void clearProperties(Message message) {
      /**
       * JavaDoc for this method states:
       *    Clears a message's properties.
       *    The message's header fields and body are not cleared.
       *
       * Since the {@code Message.HDR_ROUTING_TYPE} is used for the JMSDestination header it isn't cleared
       */

      List<SimpleString> toRemove = new ArrayList<>();

      for (SimpleString propName : message.getPropertyNames()) {
         if ((!propName.startsWith(JMS) || propName.startsWith(JMSX) ||
            propName.startsWith(JMS_)) && !propName.equals(Message.HDR_ROUTING_TYPE)) {
            toRemove.add(propName);
         }
      }

      for (SimpleString propName : toRemove) {
         message.removeProperty(propName);
      }
   }

   public static Set<String> getPropertyNames(Message message) {
      HashSet<String> set = new HashSet<>();

      for (SimpleString propName : message.getPropertyNames()) {
         if (propName.equals(Message.HDR_GROUP_ID)) {
            set.add(MessageUtil.JMSXGROUPID);
         } else if (propName.equals(Message.HDR_GROUP_SEQUENCE)) {
            set.add(MessageUtil.JMSXGROUPSEQ);
         } else if (propName.equals(Message.HDR_VALIDATED_USER)) {
            set.add(MessageUtil.JMSXUSERID);
         } else if ((!propName.startsWith(JMS) || propName.startsWith(JMSX) || propName.startsWith(JMS_)) && !propName.startsWith(CONNECTION_ID_PROPERTY_NAME) && !propName.equals(Message.HDR_ROUTING_TYPE) && !propName.startsWith(Message.HDR_ROUTE_TO_IDS)) {
            set.add(propName.toString());
         }
      }

      set.add(JMSXDELIVERYCOUNT);

      return set;
   }

   public static boolean propertyExists(Message message, String name) {
      return message.containsProperty(new SimpleString(name)) || name.equals(MessageUtil.JMSXDELIVERYCOUNT) ||
         (MessageUtil.JMSXGROUPID.equals(name) && message.containsProperty(Message.HDR_GROUP_ID)) ||
         (MessageUtil.JMSXGROUPSEQ.equals(name) && message.containsProperty(Message.HDR_GROUP_SEQUENCE)) ||
         (MessageUtil.JMSXUSERID.equals(name) && message.containsProperty(Message.HDR_VALIDATED_USER));
   }


   public static String getStringProperty(final Message message, final String name) {
      if (MessageUtil.JMSXGROUPID.equals(name)) {
         return Objects.toString(message.getGroupID(), null);
      } else if (MessageUtil.JMSXGROUPSEQ.equals(name)) {
         return Integer.toString(message.getGroupSequence());
      } else if (MessageUtil.JMSXUSERID.equals(name)) {
         return message.getValidatedUserID();
      } else {
         return message.getStringProperty(name);
      }
   }

   public static Object getObjectProperty(final Message message, final String name) {
      final Object val;
      if (MessageUtil.JMSXGROUPID.equals(name)) {
         val = message.getGroupID();
      } else if (MessageUtil.JMSXGROUPSEQ.equals(name)) {
         val = message.getGroupSequence();
      } else if (MessageUtil.JMSXUSERID.equals(name)) {
         val = message.getValidatedUserID();
      } else {
         val = message.getObjectProperty(name);
      }
      if (val instanceof SimpleString) {
         return val.toString();
      }
      return val;
   }

   public static long getLongProperty(final Message message, final String name) {
      if (MessageUtil.JMSXGROUPSEQ.equals(name)) {
         return message.getGroupSequence();
      } else {
         return message.getLongProperty(name);
      }
   }

   public static int getIntProperty(final Message message, final String name) {
      if (MessageUtil.JMSXGROUPSEQ.equals(name)) {
         return message.getGroupSequence();
      } else {
         return message.getIntProperty(name);
      }
   }

   public static void setIntProperty(final Message message, final String name, final int value) {
      if (MessageUtil.JMSXGROUPSEQ.equals(name)) {
         message.setGroupSequence(value);
      } else {
         message.putIntProperty(name, value);
      }
   }

   public static void setLongProperty(final Message message, final String name, final long value) {
      if (MessageUtil.JMSXGROUPSEQ.equals(name)) {
         message.setGroupSequence((int) value);
      } else {
         message.putLongProperty(name, value);
      }
   }

   public static void setStringProperty(final Message message, final String name, final String value) {
      if (MessageUtil.JMSXGROUPID.equals(name)) {
         message.setGroupID(value);
      } else if (MessageUtil.JMSXGROUPSEQ.equals(name)) {
         message.setGroupSequence(getInteger(value));
      } else if (MessageUtil.JMSXUSERID.equals(name)) {
         message.setValidatedUserID(value);
      } else {
         message.putStringProperty(name, value);
      }
   }

   public static void setObjectProperty(final Message message,  final String name, final Object value) {
      if (MessageUtil.JMSXGROUPID.equals(name)) {
         message.setGroupID(value == null ? null : value.toString());
      } else if (MessageUtil.JMSXGROUPSEQ.equals(name)) {
         message.setGroupSequence(getInteger(value));
      } else if (MessageUtil.JMSXUSERID.equals(name)) {
         message.setValidatedUserID(value == null ? null : value.toString());
      } else {
         message.putObjectProperty(name, value);
      }
   }

   private static int getInteger(final Object value) {
      Objects.requireNonNull(value);
      final int integer;
      if (value instanceof Integer) {
         integer = (Integer) value;
      } else if (value instanceof Number) {
         integer = ((Number) value).intValue();
      } else {
         integer = Integer.parseInt(value.toString());
      }
      return integer;
   }
}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/config/FileDeploymentManager.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.config;

import javax.management.MBeanServer;
import java.net.URL;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.activemq.artemis.core.deployers.Deployable;
import org.apache.activemq.artemis.core.server.ActivateCallback;
import org.apache.activemq.artemis.core.server.ActiveMQComponent;
import org.apache.activemq.artemis.spi.core.security.ActiveMQSecurityManager;
import org.apache.activemq.artemis.utils.XMLUtil;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * ised to build a set of ActiveMQComponents from a set of Deployables pulled out of the configuration file
 */
public class FileDeploymentManager {

   private static final String DEFAULT_CONFIGURATION_URL = "broker.xml";

   private final String configurationUrl;

   LinkedHashMap<String, Deployable> deployables = new LinkedHashMap<>();

   public FileDeploymentManager() {
      this.configurationUrl = DEFAULT_CONFIGURATION_URL;
   }

   public FileDeploymentManager(String configurationUrl) {
      this.configurationUrl = configurationUrl;
   }

   /*
   * parse a set of configuration with the Deployables that were given.
   */
   public void readConfiguration() throws Exception {
      URL url;

      url = Thread.currentThread().getContextClassLoader().getResource(configurationUrl);

      if (url == null) {
         // trying a different classloader now
         url = getClass().getClassLoader().getResource(configurationUrl);
      }

      if (url == null) {
         // The URL is outside of the classloader. Trying a pure url now
         url = new URL(configurationUrl);
      }

      Element e = XMLUtil.urlToElement(url);

      //iterate around all the deployables
      for (Deployable deployable : deployables.values()) {
         String root = deployable.getRootElement();
         NodeList children = e.getElementsByTagName(root);
         //if the root element exists then parse it
         if (root != null && children.getLength() > 0) {
            Node item = children.item(0);
            XMLUtil.validate(item, deployable.getSchema());
            deployable.parse((Element) item, url);
         }
      }
   }

   /*
   * Build a set of ActiveMQComponents from the Deployables configured
   */
   public Map<String, ActiveMQComponent> buildService(ActiveMQSecurityManager securityManager,
                                                      MBeanServer mBeanServer, ActivateCallback activateCallback) throws Exception {
      Map<String, ActiveMQComponent> components = new HashMap<>();
      for (Deployable deployable : deployables.values()) {
         // if the deployable was parsed then build the service
         if (deployable.isParsed()) {
            deployable.buildService(securityManager, mBeanServer, deployables, components, activateCallback);
         }
      }
      return components;
   }

   /*
   * add a Deployable to be configured
   */
   public FileDeploymentManager addDeployable(Deployable deployable) {
      deployables.put(deployable.getRootElement(), deployable);
      return this;
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cluster/bridge/BridgeTestBase.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.cluster.bridge;

import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.config.ha.SharedStoreMasterPolicyConfiguration;
import org.apache.activemq.artemis.core.config.ha.SharedStoreSlavePolicyConfiguration;
import org.apache.activemq.artemis.core.remoting.impl.invm.InVMConnector;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.ActiveMQServers;
import org.apache.activemq.artemis.core.server.NodeManager;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.tests.util.InVMNodeManagerServer;
import org.apache.activemq.artemis.utils.RetryRule;
import org.junit.After;
import org.junit.Rule;

public abstract class BridgeTestBase extends ActiveMQTestBase {


   @Rule
   public RetryRule retryRule = new RetryRule(2);

   @Override
   @After
   public void tearDown() throws Exception {
      InVMConnector.failOnCreateConnection = false;

      super.tearDown();
   }

   protected ActiveMQServer createActiveMQServer(final int id,
                                                 final boolean netty,
                                                 final Map<String, Object> params) throws Exception {
      return createActiveMQServer(id, params, netty, null);
   }

   protected ActiveMQServer createActiveMQServer(final int id,
                                                 final Map<String, Object> params,
                                                 final boolean netty,
                                                 final NodeManager nodeManager) throws Exception {
      TransportConfiguration tc = new TransportConfiguration();

      if (netty) {
         params.put(org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.PORT_PROP_NAME, org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.DEFAULT_PORT + id);
         tc = new TransportConfiguration(NETTY_ACCEPTOR_FACTORY, params);

      } else {
         params.put(org.apache.activemq.artemis.core.remoting.impl.invm.TransportConstants.SERVER_ID_PROP_NAME, id);
         tc = new TransportConfiguration(INVM_ACCEPTOR_FACTORY, params);
      }
      Configuration serviceConf = createBasicConfig().setJournalType(getDefaultJournalType()).setBindingsDirectory(getBindingsDir(id, false)).setJournalMinFiles(2).setJournalDirectory(getJournalDir(id, false)).setPagingDirectory(getPageDir(id, false)).setLargeMessagesDirectory(getLargeMessagesDir(id, false))
         // these tests don't need any big storage so limiting the size of the journal files to speed up the test
         .setJournalFileSize(100 * 1024).addAcceptorConfiguration(tc).setHAPolicyConfiguration(new SharedStoreMasterPolicyConfiguration());

      ActiveMQServer server;
      if (nodeManager == null) {
         server = ActiveMQServers.newActiveMQServer(serviceConf, true);
      } else {
         server = new InVMNodeManagerServer(serviceConf, nodeManager);
      }

      return addServer(server);
   }

   protected ActiveMQServer createBackupActiveMQServer(final int id,
                                                       final Map<String, Object> params,
                                                       final boolean netty,
                                                       final int liveId,
                                                       final NodeManager nodeManager) throws Exception {
      TransportConfiguration tc = new TransportConfiguration();

      if (netty) {
         params.put(org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.PORT_PROP_NAME, org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants.DEFAULT_PORT + id);
         tc = new TransportConfiguration(NETTY_ACCEPTOR_FACTORY, params);

      } else {
         params.put(org.apache.activemq.artemis.core.remoting.impl.invm.TransportConstants.SERVER_ID_PROP_NAME, id);
         tc = new TransportConfiguration(INVM_ACCEPTOR_FACTORY, params);
      }

      Configuration serviceConf = createBasicConfig().setJournalType(getDefaultJournalType()).setBindingsDirectory(getBindingsDir(liveId, false)).setJournalMinFiles(2).setJournalDirectory(getJournalDir(liveId, false)).setPagingDirectory(getPageDir(liveId, false)).setLargeMessagesDirectory(getLargeMessagesDir(liveId, false))
         // these tests don't need any big storage so limiting the size of the journal files to speed up the test
         .setJournalFileSize(100 * 1024).addAcceptorConfiguration(tc).setHAPolicyConfiguration(new SharedStoreSlavePolicyConfiguration());

      ActiveMQServer server;
      if (nodeManager == null) {
         server = ActiveMQServers.newActiveMQServer(serviceConf, true);
      } else {
         server = new InVMNodeManagerServer(serviceConf, nodeManager);
      }
      return addServer(server);
   }

   protected void waitForServerStart(ActiveMQServer server) throws Exception {
      if (!server.waitForActivation(5000L, TimeUnit.MILLISECONDS))
         throw new IllegalStateException("Timed out waiting for server starting = " + server);
   }
}


<|start_filename|>artemis-jms-server/src/main/java/org/apache/activemq/artemis/jms/bridge/QualityOfServiceMode.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.jms.bridge;

/**
 * <h2>Quality of server (QoS) levels</h2>
 *
 * <h3>QOS_AT_MOST_ONCE</h3>
 *
 * With this QoS mode messages will reach the destination from the source at
 * most once. The messages are consumed from the source and acknowledged before
 * sending to the destination. Therefore there is a possibility that if failure
 * occurs between removing them from the source and them arriving at the
 * destination they could be lost. Hence delivery will occur at most once. This
 * mode is available for both persistent and non persistent messages.
 *
 * <h3>QOS_DUPLICATES_OK</h3>
 *
 * With this QoS mode, the messages are consumed from the source and then
 * acknowledged after they have been successfully sent to the destination.
 * Therefore there is a possibility that if failure occurs after sending to the
 * destination but before acknowledging them, they could be sent again when the
 * system recovers. I.e. the destination might receive duplicates after a
 * failure. This mode is available for both persistent and non persistent
 * messages.
 *
 * <h3>QOS_ONCE_AND_ONLY_ONCE</h3>
 *
 * This QoS mode ensures messages will reach the destination from the source
 * once and only once. (Sometimes this mode is known as "exactly once"). If both
 * the source and the destination are on the same ActiveMQ Artemis server
 * instance then this can be achieved by sending and acknowledging the messages
 * in the same local transaction. If the source and destination are on different
 * servers this is achieved by enlisting the sending and consuming sessions in a
 * JTA transaction. The JTA transaction is controlled by JBoss Transactions JTA
 * implementation which is a fully recovering transaction manager, thus
 * providing a very high degree of durability. If JTA is required then both
 * supplied connection factories need to be XAConnectionFactory implementations.
 * This mode is only available for persistent messages. This is likely to be the
 * slowest mode since it requires extra persistence for the transaction logging.
 *
 * Note: For a specific application it may possible to provide once and only
 * once semantics without using the QOS_ONCE_AND_ONLY_ONCE QoS level. This can
 * be done by using the QOS_DUPLICATES_OK mode and then checking for duplicates
 * at the destination and discarding them. Some JMS servers provide automatic
 * duplicate message detection functionality, or this may be possible to
 * implement on the application level by maintaining a cache of received message
 * ids on disk and comparing received messages to them. The cache would only be
 * valid for a certain period of time so this approach is not as watertight as
 * using QOS_ONCE_AND_ONLY_ONCE but may be a good choice depending on your
 * specific application.
 */
public enum QualityOfServiceMode {
   AT_MOST_ONCE(0), DUPLICATES_OK(1), ONCE_AND_ONLY_ONCE(2);

   private final int value;

   QualityOfServiceMode(final int value) {
      this.value = value;
   }

   public int intValue() {
      return value;
   }

   public static QualityOfServiceMode valueOf(final int value) {
      if (value == AT_MOST_ONCE.value) {
         return AT_MOST_ONCE;
      }
      if (value == DUPLICATES_OK.value) {
         return DUPLICATES_OK;
      }
      if (value == ONCE_AND_ONLY_ONCE.value) {
         return ONCE_AND_ONLY_ONCE;
      }
      throw new IllegalArgumentException("invalid QualityOfServiceMode value: " + value);
   }

}


<|start_filename|>examples/features/federation/federated-address-divert/src/main/java/org/apache/activemq/artemis/jms/example/FederatedAddressDivertExample.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.jms.example;

import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.jms.Topic;
import org.apache.activemq.artemis.api.jms.ActiveMQJMSClient;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;

/**
 * A simple example that demonstrates multicast address replication between remote servers,
 * using Address Federation feature and diverts.
 */
public class FederatedAddressDivertExample {

   public static void main(final String[] args) throws Exception {
      Connection connectionEUWest = null;

      Connection connectionEUEast = null;


      try {
         // Step 1. Instantiate the Topic (multicast) for the producers
         Topic topic = ActiveMQJMSClient.createTopic("exampleTopic");

         //Create a topic for the consumers
         Topic topic2 = ActiveMQJMSClient.createTopic("divertExampleTopic");

         // Step 2. Instantiate connection towards server EU West
         ConnectionFactory cfEUWest = new ActiveMQConnectionFactory("tcp://localhost:61616");

         // Step 3. Instantiate connection towards server EU East
         ConnectionFactory cfEUEast = new ActiveMQConnectionFactory("tcp://localhost:61617");


         // Step 5. We create a JMS Connection connectionEUWest which is a connection to server EU West
         connectionEUWest = cfEUWest.createConnection();

         // Step 6. We create a JMS Connection connectionEUEast which is a connection to server EU East
         connectionEUEast = cfEUEast.createConnection();

         // Step 8. We create a JMS Session on server EU West
         Session sessionEUWest = connectionEUWest.createSession(false, Session.AUTO_ACKNOWLEDGE);

         // Step 9. We create a JMS Session on server EU East
         Session sessionEUEast = connectionEUEast.createSession(false, Session.AUTO_ACKNOWLEDGE);

         // Step 11. We start the connections to ensure delivery occurs on them
         connectionEUWest.start();

         connectionEUEast.start();

         // Step 12. We create a JMS MessageProducer object on each server
         MessageProducer producerEUEast = sessionEUEast.createProducer(topic);

         // Step 13. We create JMS MessageConsumer objects on each server - Messages will be diverted to this topic
         MessageConsumer consumerEUWest = sessionEUWest.createSharedDurableConsumer(topic2, "exampleSubscription");


         // Step 14. Let a little time for everything to start and form.

         Thread.sleep(5000);

         // Step 13. We send some messages to server EU West
         final int numMessages = 10;

         // Step 15. Repeat same test one last time, this time sending on EU East

         for (int i = 0; i < numMessages; i++) {
            TextMessage message = sessionEUEast.createTextMessage("This is text sent from EU East, message " + i);

            producerEUEast.send(message);

            System.out.println("EU East   :: Sent message: " + message.getText());
         }

         // Step 14. We now consume those messages on *all* servers .
         // We note that every consumer, receives a message even so on seperate servers

         for (int i = 0; i < numMessages; i++) {
            TextMessage messageEUWest = (TextMessage) consumerEUWest.receive(5000);

            System.out.println("EU West   :: Got message: " + messageEUWest.getText());
         }
      } finally {
         // Step 16. Be sure to close our resources!
         if (connectionEUWest != null) {
            connectionEUWest.stop();
            connectionEUWest.close();
         }

         if (connectionEUEast != null) {
            connectionEUEast.stop();
            connectionEUEast.close();
         }
      }
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cluster/failover/LiveCrashOnBackupSyncTest.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.cluster.failover;

import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.client.impl.ServerLocatorImpl;
import org.apache.activemq.artemis.core.config.ClusterConnectionConfiguration;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.config.ha.ReplicaPolicyConfiguration;
import org.apache.activemq.artemis.core.config.ha.ReplicatedPolicyConfiguration;
import org.apache.activemq.artemis.core.config.impl.ConfigurationImpl;
import org.apache.activemq.artemis.core.config.impl.SecurityConfiguration;
import org.apache.activemq.artemis.core.io.SequentialFileFactory;
import org.apache.activemq.artemis.core.paging.PagingManager;
import org.apache.activemq.artemis.core.paging.PagingStore;
import org.apache.activemq.artemis.core.paging.PagingStoreFactory;
import org.apache.activemq.artemis.core.paging.impl.PagingStoreFactoryNIO;
import org.apache.activemq.artemis.core.paging.impl.PagingStoreImpl;
import org.apache.activemq.artemis.core.persistence.StorageManager;
import org.apache.activemq.artemis.core.replication.ReplicationManager;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.ActiveMQServers;
import org.apache.activemq.artemis.core.server.JournalType;
import org.apache.activemq.artemis.core.server.impl.ActiveMQServerImpl;
import org.apache.activemq.artemis.core.settings.impl.AddressSettings;
import org.apache.activemq.artemis.tests.util.Wait;
import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
import org.apache.activemq.artemis.spi.core.security.jaas.InVMLoginModule;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.utils.SpawnedVMSupport;
import org.apache.activemq.artemis.utils.actors.ArtemisExecutor;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.io.File;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class LiveCrashOnBackupSyncTest extends ActiveMQTestBase {

   static int OK = 2;

   public File liveDir;
   public File backupDir;

   @Before
   public void setupDirectories() throws Exception {

      liveDir = temporaryFolder.newFolder("live");
      backupDir = temporaryFolder.newFolder("backup");
      liveDir.mkdirs();
      backupDir.mkdirs();
   }

   @Test
   public void liveCrashOnBackupSyncLargeMessageTest() throws Exception {
      Process process = SpawnedVMSupport.spawnVM(LiveCrashOnBackupSyncTest.class.getCanonicalName(), backupDir.getAbsolutePath(), liveDir.getAbsolutePath());
      try {
         Assert.assertEquals(OK, process.waitFor());

         Configuration liveConfiguration = createLiveConfiguration();
         ActiveMQServer liveServer = ActiveMQServers.newActiveMQServer(liveConfiguration);
         liveServer.start();
         Wait.waitFor(() -> liveServer.isStarted());

         File liveLMDir = liveServer.getConfiguration().getLargeMessagesLocation();
         Wait.assertTrue(() -> getAllMessageFileIds(liveLMDir).size() == 0, 5000, 100);
         Set<Long> liveLM = getAllMessageFileIds(liveLMDir);
         Assert.assertEquals("we really ought to delete these after delivery", 0, liveLM.size());
         liveServer.stop();
      } finally {
         process.destroy();
         Assert.assertTrue(process.waitFor(5, TimeUnit.SECONDS));
         Assert.assertFalse(process.isAlive());
      }
   }

   private Configuration createLiveConfiguration() throws Exception {
      Configuration conf = new ConfigurationImpl();
      conf.setName("localhost::live");
      conf.setBrokerInstance(liveDir);
      conf.addAcceptorConfiguration("live", "tcp://localhost:61616");
      conf.addConnectorConfiguration("backup", "tcp://localhost:61617");
      conf.addConnectorConfiguration("live", "tcp://localhost:61616");
      conf.setClusterUser("mycluster");
      conf.setClusterPassword("<PASSWORD>");
      ReplicatedPolicyConfiguration haPolicy = new ReplicatedPolicyConfiguration();
      haPolicy.setVoteOnReplicationFailure(false);
      haPolicy.setCheckForLiveServer(false);
      conf.setHAPolicyConfiguration(haPolicy);
      ClusterConnectionConfiguration ccconf = new ClusterConnectionConfiguration();
      ccconf.setStaticConnectors(new ArrayList<>()).getStaticConnectors().add("backup");
      ccconf.setName("cluster");
      ccconf.setConnectorName("live");
      conf.addClusterConfiguration(ccconf);

      conf.setSecurityEnabled(false).setJMXManagementEnabled(false).setJournalType(JournalType.MAPPED).setJournalFileSize(1024 * 512).setConnectionTTLOverride(60_000L);
      return conf;
   }

   private Configuration createBackupConfiguration() throws Exception {
      Configuration conf = new ConfigurationImpl();
      conf.setName("localhost::backup");
      conf.setBrokerInstance(backupDir);
      ReplicaPolicyConfiguration haPolicy = new ReplicaPolicyConfiguration();
      haPolicy.setClusterName("cluster");
      conf.setHAPolicyConfiguration(haPolicy);
      conf.addAcceptorConfiguration("backup", "tcp://localhost:61617");
      conf.addConnectorConfiguration("live", "tcp://localhost:61616");
      conf.addConnectorConfiguration("backup", "tcp://localhost:61617");
      conf.setClusterUser("mycluster");
      conf.setClusterPassword("<PASSWORD>");
      ClusterConnectionConfiguration ccconf = new ClusterConnectionConfiguration();
      ccconf.setStaticConnectors(new ArrayList<>()).getStaticConnectors().add("live");
      ccconf.setName("cluster");
      ccconf.setConnectorName("backup");
      conf.addClusterConfiguration(ccconf);

      conf.setSecurityEnabled(false).setJMXManagementEnabled(false).setJournalType(JournalType.MAPPED).setJournalFileSize(1024 * 512).setConnectionTTLOverride(60_000L);
      return conf;
   }

   private void createProducerSendSomeLargeMessages(int msgCount) throws Exception {
      byte[] buffer = new byte[100 * 1024];
      ServerLocator locator = ServerLocatorImpl.newLocator("tcp://localhost:61616");
      locator.setCallTimeout(60_000L);
      locator.setConnectionTTL(60_000L);
      final ClientSessionFactory csf = locator.createSessionFactory();
      ClientSession session = csf.createSession();
      session.createQueue(new QueueConfiguration("LiveCrashTestQueue").setRoutingType(RoutingType.ANYCAST));
      ClientProducer producer = session.createProducer("LiveCrashTestQueue");
      ClientMessage msgs = session.createMessage(true);
      msgs.getBodyBuffer().writeBytes(buffer);
      for (int i = 0; i < msgCount; i++) {
         producer.send(msgs);
      }
      producer.close();
      session.close();
   }

   private void receiveMsgs(int msgCount) throws Exception {
      ServerLocator locator = ServerLocatorImpl.newLocator("tcp://localhost:61616");
      locator.setCallTimeout(60_000L);
      locator.setConnectionTTL(60_000L);
      final ClientSessionFactory csf = locator.createSessionFactory();
      ClientSession session = csf.createSession();
      session.start();
      ClientConsumer consumer = session.createConsumer("LiveCrashTestQueue");
      for (int i = 0; i < msgCount; i++) {
         ClientMessage message = consumer.receive(1000);
         Assert.assertNotNull("Expecting a message " + i, message);
         message.acknowledge();
      }
      session.commit();
      consumer.close();
      session.close();
   }

   private Set<Long> getAllMessageFileIds(File dir) {
      Set<Long> idsOnBkp = new TreeSet<>();
      String[] fileList = dir.list();
      if (fileList != null) {
         for (String filename : fileList) {
            if (filename.endsWith(".msg")) {
               idsOnBkp.add(Long.valueOf(filename.split("\\.")[0]));
            }
         }
      }
      return idsOnBkp;
   }

   public static void main(String[] arg) {
      try {
         if (arg.length < 2) {
            System.err.println("Expected backup and live as parameters");
            System.exit(-1);
         }
         LiveCrashOnBackupSyncTest stop = new LiveCrashOnBackupSyncTest();
         stop.backupDir = new File(arg[0]);
         stop.liveDir = new File(arg[1]);
         Configuration liveConfiguration = stop.createLiveConfiguration();
         ActiveMQServer liveServer = new ActiveMQServerImpl(liveConfiguration, ManagementFactory.getPlatformMBeanServer(), new ActiveMQJAASSecurityManager(InVMLoginModule.class.getName(), new SecurityConfiguration())) {
            @Override
            protected PagingStoreFactoryNIO getPagingStoreFactory() {
               return new PagingStoreFactoryNIO(this.getStorageManager(), this.getConfiguration().getPagingLocation(), this.getConfiguration().getJournalBufferTimeout_NIO(), this.getScheduledPool(), this.getExecutorFactory(), this.getConfiguration().isJournalSyncNonTransactional(), null) {
                  @Override
                  public synchronized PagingStore newStore(SimpleString address, AddressSettings settings) {
                     return new DelayPagingStoreImpl(address, this.getScheduledExecutor(), liveConfiguration.getJournalBufferTimeout_NIO(), getPagingManager(), getStorageManager(), null, this, address, settings, getExecutorFactory().getExecutor(), this.isSyncNonTransactional());
                  }
               };
            }
         };
         liveServer.start();
         Wait.waitFor(() -> liveServer.isStarted());

         Configuration backupConfiguration = stop.createBackupConfiguration();
         ActiveMQServer backupServer = ActiveMQServers.newActiveMQServer(backupConfiguration);
         backupServer.start();
         Wait.waitFor(() -> backupServer.isStarted());

         stop.createProducerSendSomeLargeMessages(100);
         stop.receiveMsgs(100);

         //flush
         liveServer.getStorageManager().getMessageJournal().stop();

         System.exit(OK);
      } catch (Exception e) {
         e.printStackTrace();
      } catch (Throwable throwable) {
         throwable.printStackTrace();
      }
   }
}

class DelayPagingStoreImpl extends PagingStoreImpl {

   DelayPagingStoreImpl(SimpleString address,
                               ScheduledExecutorService scheduledExecutor,
                               long syncTimeout,
                               PagingManager pagingManager,
                               StorageManager storageManager,
                               SequentialFileFactory fileFactory,
                               PagingStoreFactory storeFactory,
                               SimpleString storeName,
                               AddressSettings addressSettings,
                               ArtemisExecutor executor,
                               boolean syncNonTransactional) {
      super(address, scheduledExecutor, syncTimeout, pagingManager, storageManager, fileFactory, storeFactory, storeName, addressSettings, executor, syncNonTransactional);
   }

   @Override
   public void sendPages(ReplicationManager replicator, Collection<Integer> pageIds) throws Exception {
      //in order to extend the synchronization time
      Thread.sleep(20 * 1000);
      super.sendPages(replicator, pageIds);
   }
}

<|start_filename|>tests/performance-jmh/src/main/java/org/apache/activemq/artemis/tests/performance/jmh/ByteArrayHashCodeBenchamark.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.performance.jmh;

import java.util.Arrays;
import java.util.SplittableRandom;
import java.util.concurrent.TimeUnit;

import org.apache.activemq.artemis.utils.ByteUtil;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;

@State(Scope.Benchmark)
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@Fork(2)
@Warmup(iterations = 5, time = 200, timeUnit = TimeUnit.MILLISECONDS)
@Measurement(iterations = 8, time = 200, timeUnit = TimeUnit.MILLISECONDS)
public class ByteArrayHashCodeBenchamark {

   @Param({"7", "8", "36"})
   private int length;

   @Param("0")
   private int seed;

   /**
    * The higher the less predictable for the CPU branch predictor.
    */
   @Param({"4", "10"})
   private int logPermutations;

   @Param({"true"})
   private boolean unsafe;

   private long seq;
   private int inputMask;
   private byte[][] inputs;

   @Setup
   public void init() {
      System.setProperty("io.netty.noUnsafe", Boolean.valueOf(!unsafe).toString());
      int inputSize = 1 << logPermutations;
      inputs = new byte[inputSize][];
      inputMask = inputs.length - 1;
      // splittable random can create repeatable sequence of inputs
      SplittableRandom random = new SplittableRandom(seed);
      for (int i = 0; i < inputs.length; i++) {
         final byte[] bytes = new byte[length];
         for (int b = 0; b < length; b++) {
            bytes[b] = (byte) random.nextInt(Byte.MIN_VALUE, Byte.MAX_VALUE + 1);
         }
         inputs[i] = bytes;
      }
   }

   private byte[] nextInput() {
      final long seq = this.seq;
      final int index = (int) (seq & inputMask);
      this.seq = seq + 1;
      return inputs[index];
   }

   @Benchmark
   public int artemisHashCode() {
      return ByteUtil.hashCode(nextInput());
   }

   @Benchmark
   public int arraysHashCode() {
      return Arrays.hashCode(nextInput());
   }

}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/openwire/VirtualTopicToFQQNOpenWireTest.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.openwire;

import javax.jms.Connection;
import javax.jms.Destination;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import java.util.Set;

import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.core.management.QueueControl;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.tests.integration.management.ManagementControlHelper;
import org.apache.activemq.artemis.utils.Wait;
import org.junit.Test;

public class VirtualTopicToFQQNOpenWireTest extends OpenWireTestBase {

   @Override
   protected void extraServerConfig(Configuration serverConfig) {
      Set<TransportConfiguration> acceptors = serverConfig.getAcceptorConfigurations();
      for (TransportConfiguration tc : acceptors) {
         if (tc.getName().equals("netty")) {
            tc.getExtraParams().put("virtualTopicConsumerWildcards", "Consumer.*.>;2,C.*.>;2;selectorAware=true");
            tc.getExtraParams().put("virtualTopicConsumerLruCacheMax", "10000");
         }
      }
      serverConfig.setJMXManagementEnabled(true);
   }

   @Test
   public void testAutoVirtualTopicFQQN() throws Exception {
      Connection connection = null;

      SimpleString topic = new SimpleString("VirtualTopic.Orders");
      this.server.getAddressSettingsRepository().getMatch("VirtualTopic.#").setAutoCreateQueues(true);
      this.server.getAddressSettingsRepository().getMatch("VirtualTopic.#").setAutoCreateAddresses(true);
      this.server.getAddressSettingsRepository().getMatch("VirtualTopic.#").setAutoDeleteQueues(false);

      try {
         ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(urlString);
         activeMQConnectionFactory.setWatchTopicAdvisories(false);
         connection = activeMQConnectionFactory.createConnection();
         connection.start();

         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
         Destination destination = session.createTopic(topic.toString());

         MessageConsumer messageConsumerA = session.createConsumer(session.createQueue("Consumer.A." + topic.toString()));
         MessageConsumer messageConsumerB = session.createConsumer(session.createQueue("Consumer.B." + topic.toString()));

         MessageProducer producer = session.createProducer(destination);
         TextMessage message = session.createTextMessage("This is a text message");
         producer.send(message);

         TextMessage messageReceivedA = (TextMessage) messageConsumerA.receive(2000);
         TextMessage messageReceivedB = (TextMessage) messageConsumerB.receive(2000);

         assertTrue((messageReceivedA != null && messageReceivedB != null));
         String text = messageReceivedA.getText();
         assertEquals("This is a text message", text);

         messageConsumerA.close();
         messageConsumerB.close();

      } finally {
         if (connection != null) {
            connection.close();
         }
      }
   }

   @Test
   public void testTwoTopicSubsSameNameAutoVirtualTopicFQQN() throws Exception {
      Connection connection = null;

      SimpleString topic1 = new SimpleString("VirtualTopic.Orders1");
      SimpleString topic2 = new SimpleString("VirtualTopic.Orders2");

      this.server.getAddressSettingsRepository().getMatch("VirtualTopic.#").setAutoCreateQueues(true);
      this.server.getAddressSettingsRepository().getMatch("VirtualTopic.#").setAutoCreateAddresses(true);

      try {
         ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(urlString);
         activeMQConnectionFactory.setWatchTopicAdvisories(false);
         connection = activeMQConnectionFactory.createConnection();
         connection.start();

         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
         Destination destination1 = session.createTopic(topic1.toString());
         Destination destination2 = session.createTopic(topic2.toString());

         MessageConsumer messageConsumer1 = session.createConsumer(session.createQueue("Consumer.A." + topic1.toString()));
         MessageConsumer messageConsumer2 = session.createConsumer(session.createQueue("Consumer.A." + topic2.toString()));

         MessageProducer producer = session.createProducer(null);
         TextMessage message = session.createTextMessage("This is a text message to 1");
         producer.send(destination1, message);
         message = session.createTextMessage("This is a text message to 2");
         producer.send(destination2, message);


         TextMessage messageReceived1 = (TextMessage) messageConsumer1.receive(2000);
         TextMessage messageReceived2 = (TextMessage) messageConsumer2.receive(2000);

         assertNotNull(messageReceived1);
         assertNotNull(messageReceived2);

         String text = messageReceived1.getText();
         assertEquals("This is a text message to 1", text);

         text = messageReceived2.getText();
         assertEquals("This is a text message to 2", text);

         messageConsumer1.close();
         messageConsumer2.close();

      } finally {
         if (connection != null) {
            connection.close();
         }
      }
   }


   @Test
   public void testAutoVirtualTopicWildcardFQQN() throws Exception {
      Connection connection = null;

      SimpleString topicA = new SimpleString("VirtualTopic.Orders.A");
      SimpleString topicB = new SimpleString("VirtualTopic.Orders.B");
      SimpleString topic = new SimpleString("VirtualTopic.Orders.>");

      this.server.getAddressSettingsRepository().getMatch("VirtualTopic.#").setAutoCreateQueues(true);
      this.server.getAddressSettingsRepository().getMatch("VirtualTopic.#").setAutoCreateAddresses(true);

      try {
         ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(urlString);
         activeMQConnectionFactory.setWatchTopicAdvisories(false);
         connection = activeMQConnectionFactory.createConnection();
         connection.start();

         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
         Destination destination = session.createTopic(topicA.toString() + "," + topicB.toString());

         MessageConsumer messageConsumerA = session.createConsumer(session.createQueue("Consumer.A." + topic.toString()));
        // MessageConsumer messageConsumerB = session.createConsumer(session.createQueue("Consumer.B." + topic.toString()));

         MessageProducer producer = session.createProducer(destination);
         TextMessage message = session.createTextMessage("This is a text message");
         producer.send(message);

         TextMessage messageReceivedA = (TextMessage) messageConsumerA.receive(2000);
         TextMessage messageReceivedB = (TextMessage) messageConsumerA.receive(2000);

         assertTrue((messageReceivedA != null && messageReceivedB != null));
         String text = messageReceivedA.getText();
         assertEquals("This is a text message", text);

         messageConsumerA.close();

      } finally {
         if (connection != null) {
            connection.close();
         }
      }
   }

   @Test
   public void testAutoVirtualTopicWildcardStarFQQN() throws Exception {
      Connection connection = null;

      SimpleString topicA = new SimpleString("VirtualTopic.Orders.A");
      SimpleString topicB = new SimpleString("VirtualTopic.Orders.B");
      SimpleString topic = new SimpleString("VirtualTopic.Orders.*");

      this.server.getAddressSettingsRepository().getMatch("VirtualTopic.#").setAutoCreateQueues(true);
      this.server.getAddressSettingsRepository().getMatch("VirtualTopic.#").setAutoCreateAddresses(true);

      try {
         ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(urlString);
         activeMQConnectionFactory.setWatchTopicAdvisories(false);
         connection = activeMQConnectionFactory.createConnection();
         connection.start();

         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
         Destination destination = session.createTopic(topicA.toString() + "," + topicB.toString());

         MessageConsumer messageConsumerA = session.createConsumer(session.createQueue("Consumer.A." + topic.toString()));

         MessageProducer producer = session.createProducer(destination);
         TextMessage message = session.createTextMessage("This is a text message");
         producer.send(message);

         TextMessage messageReceivedA = (TextMessage) messageConsumerA.receive(2000);
         TextMessage messageReceivedB = (TextMessage) messageConsumerA.receive(2000);

         assertTrue((messageReceivedA != null && messageReceivedB != null));
         String text = messageReceivedA.getText();
         assertEquals("This is a text message", text);

         messageConsumerA.close();

      } finally {
         if (connection != null) {
            connection.close();
         }
      }
   }


   @Test
   public void testSelectorAwareVT() throws Exception {
      Connection connection = null;

      SimpleString topic = new SimpleString("SVT.Orders.A");

      this.server.getAddressSettingsRepository().getMatch("SVT.#").setAutoCreateQueues(true);
      this.server.getAddressSettingsRepository().getMatch("SVT.#").setAutoCreateAddresses(true);

      try {
         ActiveMQConnectionFactory activeMQConnectionFactory = new ActiveMQConnectionFactory(urlString);
         activeMQConnectionFactory.setWatchTopicAdvisories(false);
         connection = activeMQConnectionFactory.createConnection();
         connection.start();

         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
         Destination destination = session.createTopic(topic.toString());

         MessageConsumer messageConsumerA = session.createConsumer(session.createQueue("C.A." + topic.toString()), "stuff = 'A'");
         MessageConsumer messageConsumerB = session.createConsumer(session.createQueue("C.B." + topic.toString()), "stuff = 'B'");

         MessageProducer producer = session.createProducer(destination);
         TextMessage message = session.createTextMessage("This is a text message");
         for (String stuffValue : new String[] {"A", "B", "C"}) {
            message.setStringProperty("stuff", stuffValue);
            producer.send(message);
         }

         TextMessage messageReceivedA = (TextMessage) messageConsumerA.receive(2000);
         TextMessage messageReceivedB = (TextMessage) messageConsumerB.receive(2000);

         assertTrue((messageReceivedA != null && messageReceivedB != null));
         String text = messageReceivedA.getText();
         assertEquals("This is a text message", text);

         assertEquals("A", messageReceivedA.getStringProperty("stuff"));
         assertEquals("B", messageReceivedB.getStringProperty("stuff"));

         // verify C message got dropped

         final QueueControl queueControlA = ManagementControlHelper.createQueueControl(topic, SimpleString.toSimpleString("C.A." + topic.toString()), RoutingType.MULTICAST, mbeanServer);
         Wait.assertEquals(0, () -> queueControlA.countMessages());

         final QueueControl queueControlB = ManagementControlHelper.createQueueControl(topic, SimpleString.toSimpleString("C.B." + topic.toString()), RoutingType.MULTICAST, mbeanServer);
         Wait.assertEquals(0, () -> queueControlB.countMessages());

      } finally {
         if (connection != null) {
            connection.close();
         }
      }
   }

}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/SimpleTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * <br>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <br>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.tests.integration;

import java.util.UUID;

import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.junit.Before;
import org.junit.Test;

/**
 * A simple test-case used for documentation purposes.
 */
public class SimpleTest extends ActiveMQTestBase {

   protected ActiveMQServer server;

   protected ClientSession session;

   protected ClientSessionFactory sf;

   protected ServerLocator locator;

   @Override
   @Before
   public void setUp() throws Exception {
      /**
       * Invoke org.apache.activemq.artemis.tests.util.ActiveMQTestBase's setUp() to bootstrap everything properly.
       */
      super.setUp();

      /**
       * Create a configuration for an in-vm server.
       * Use that configuration to instantiate a new server that doesn't use persistence, and then start it.
       * Note that creating the server instance using this method ensures that the server will be cleaned up properly
       * when the test is torn down.
       */
      server = createServer(false, createDefaultInVMConfig());
      server.start();

      /**
       * Create a ServerLocator for the in-vm server. Using this method instead of using, e.g. ActiveMQClient.createServerLocatorWithHA(..),
       * ensures that the locator will be cleaned up properly when the test is torn down.
       */
      locator = createInVMNonHALocator();

      /**
       * Create a session factory from the server locator. Using this method instead of using, e.g. ServerLocator.createSessionFactory(),
       * ensures that the factory will be cleaned up properly when the test is torn down.
       */
      sf = createSessionFactory(locator);

      /**
       * Create a session from the factory. The call to create the session is surrounded with addClientSession to
       * ensure the session will be cleaned up properly when the test is torn down.
       */
      session = addClientSession(sf.createSession(false, true, true));
   }

   @Test
   public void simpleTest() throws Exception {
      final String data = "Simple Text " + UUID.randomUUID().toString();
      final String queueName = "simpleQueue";
      final String addressName = "simpleAddress";

      // Create a queue bound to a particular address where the test will send to & consume from.
      session.createQueue(new QueueConfiguration(queueName).setAddress(addressName).setRoutingType(RoutingType.ANYCAST));

      // Create a producer to send a message to the previously created address.
      ClientProducer producer = session.createProducer(addressName);

      // Create a non-durable message.
      ClientMessage message = session.createMessage(false);

      // Put some data into the message.
      message.getBodyBuffer().writeString(data);

      // Send the message. This send will be auto-committed based on the way the session was created in setUp()
      producer.send(message);

      // Close the producer.
      producer.close();

      // Create a consumer on the queue bound to the address where the message was sent.
      ClientConsumer consumer = session.createConsumer(queueName);

      // Start the session to allow messages to be consumed.
      session.start();

      // Receive the message we sent previously.
      message = consumer.receive(1000);

      // Ensure the message was received.
      assertNotNull(message);

      // Acknowledge the message.
      message.acknowledge();

      // Ensure the data in the message received matches the data in the message sent.
      assertEquals(data, message.getBodyBuffer().readString());
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/paging/AmqpPageReaderTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.tests.integration.amqp.paging;

import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.ActiveMQBuffers;
import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.paging.cursor.impl.PageReaderTest;
import org.apache.activemq.artemis.protocol.amqp.broker.AMQPStandardMessage;
import org.apache.activemq.artemis.spi.core.protocol.MessagePersister;
import org.apache.activemq.artemis.tests.integration.amqp.AmqpTestSupport;
import org.apache.activemq.transport.amqp.client.AmqpMessage;
import org.apache.qpid.proton.message.impl.MessageImpl;
import org.junit.Assert;
import org.junit.Test;

public class AmqpPageReaderTest extends PageReaderTest {

   public MessageImpl createProtonMessage(String address) {
      AmqpMessage message = new AmqpMessage();
      final StringBuilder builder = new StringBuilder();
      for (int i = 0; i < 1000; i++) {
         builder.append('0');
      }
      final String data = builder.toString();
      message.setText(data);
      message.setAddress(address);
      message.setDurable(true);

      MessageImpl protonMessage = (MessageImpl) message.getWrappedMessage();

      return protonMessage;
   }

   @Override
   protected Message createMessage(SimpleString address, int msgId, byte[] content) {
      MessageImpl protonMessage = createProtonMessage(address.toString());
      AMQPStandardMessage amqpStandardMessage =  AmqpTestSupport.encodeAndDecodeMessage(0, protonMessage, 2 * 1024);
      amqpStandardMessage.setMessageID(msgId);

      return amqpStandardMessage;
   }


   @Test
   public void testEncodeSize() throws Exception {

      Message message = createMessage(SimpleString.toSimpleString("Test"), 1, new byte[10]);

      MessagePersister persister = (MessagePersister)message.getPersister();

      ActiveMQBuffer buffer = ActiveMQBuffers.dynamicBuffer(1024);
      persister.encode(buffer, message);

      Assert.assertEquals(persister.getEncodeSize(message), buffer.writerIndex());

      // the very first byte is the persisterID, we skip that since we are calling the Persister directly
      buffer.readerIndex(1);
      Message messageRead = persister.decode(buffer, null, null);

      // The current persister does not guarantee the same encode size after loading
      /// if this ever changes we can uncomment the next line.
      // Assert.assertEquals(persister.getEncodeSize(message), persister.getEncodeSize(messageRead));


   }
}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/config/amqpBrokerConnectivity/AMQPBrokerConnectConfiguration.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.config.amqpBrokerConnectivity;

import java.net.URI;
import java.util.ArrayList;
import java.util.List;

import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.core.config.brokerConnectivity.BrokerConnectConfiguration;
import org.apache.activemq.artemis.uri.ConnectorTransportConfigurationParser;

/**
 * This is a specific AMQP Broker Connection Configuration
 * */
public class AMQPBrokerConnectConfiguration extends BrokerConnectConfiguration {

   List<TransportConfiguration> transportConfigurations;

   List<AMQPBrokerConnectionElement> connectionElements;

   public AMQPBrokerConnectConfiguration(String name, String uri) {
      super(name, uri);
   }

   public AMQPBrokerConnectConfiguration addElement(AMQPBrokerConnectionElement amqpBrokerConnectionElement) {
      if (connectionElements == null) {
         connectionElements = new ArrayList<>();
      }
      amqpBrokerConnectionElement.setParent(this);


      if (amqpBrokerConnectionElement.getType() == AMQPBrokerConnectionAddressType.MIRROR && !(amqpBrokerConnectionElement instanceof AMQPMirrorBrokerConnectionElement)) {
         throw new IllegalArgumentException("must be an AMQPMirrorConnectionElement");
      }

      connectionElements.add(amqpBrokerConnectionElement);

      return this;
   }

   public List<AMQPBrokerConnectionElement> getConnectionElements() {
      return connectionElements;
   }

   @Override
   public void parseURI() throws Exception {
      ConnectorTransportConfigurationParser parser = new ConnectorTransportConfigurationParser(false);
      URI transportURI = parser.expandURI(getUri());
      this.transportConfigurations = parser.newObject(transportURI, getName());
   }

   public List<TransportConfiguration> getTransportConfigurations() throws Exception {
      if (transportConfigurations == null) {
         parseURI();
      }
      return transportConfigurations;
   }

   @Override
   public AMQPBrokerConnectConfiguration setReconnectAttempts(int reconnectAttempts) {
      super.setReconnectAttempts(reconnectAttempts);
      return this;
   }

   @Override
   public AMQPBrokerConnectConfiguration setUser(String user) {
      super.setUser(user);
      return this;
   }

   @Override
   public AMQPBrokerConnectConfiguration setRetryInterval(int retryInterval) {
      super.setRetryInterval(retryInterval);
      return this;
   }

   @Override
   public AMQPBrokerConnectConfiguration setPassword(String password) {
      super.setPassword(password);
      return this;
   }

   @Override
   public AMQPBrokerConnectConfiguration setUri(String uri) {
      super.setUri(uri);
      return this;
   }

   @Override
   public AMQPBrokerConnectConfiguration setName(String name) {
      super.setName(name);
      return this;
   }

   @Override
   public AMQPBrokerConnectConfiguration setAutostart(boolean autostart) {
      super.setAutostart(autostart);
      return this;
   }

}


<|start_filename|>artemis-server/src/test/java/org/apache/activemq/artemis/core/remoting/impl/netty/HttpAcceptorHandlerTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.remoting.impl.netty;

import io.netty.channel.embedded.EmbeddedChannel;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;

import static org.mockito.Mockito.spy;

/**
 * HttpAcceptorHandlerTest
 */
@RunWith(MockitoJUnitRunner.class)
public class HttpAcceptorHandlerTest {

   private static final String HTTP_HANDLER = "http-handler";

   private HttpKeepAliveRunnable spy;

   @Before
   public void setUp() throws Exception {
      spy = spy(new HttpKeepAliveRunnable());
   }

   @Test
   public void testUnregisterIsCalledTwiceWhenChannelIsInactive() {
      EmbeddedChannel channel = new EmbeddedChannel();

      HttpAcceptorHandler httpHandler = new HttpAcceptorHandler(spy, 1000, channel);
      channel.pipeline().addLast(HTTP_HANDLER, httpHandler);

      channel.close();

      Mockito.verify(spy, Mockito.times(2)).unregisterKeepAliveHandler(httpHandler);
   }

   @Test
   public void testUnregisterIsCalledWhenHandlerIsRemovedFromPipeline() {
      EmbeddedChannel channel = new EmbeddedChannel();

      HttpAcceptorHandler httpHandler = new HttpAcceptorHandler(spy, 1000, channel);
      channel.pipeline().addLast(HTTP_HANDLER, httpHandler);

      channel.pipeline().remove(HTTP_HANDLER);

      Mockito.verify(spy).unregisterKeepAliveHandler(httpHandler);
   }
}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/server/plugin/impl/BrokerMessageAuthorizationPlugin.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.core.server.plugin.impl;

import javax.security.auth.Subject;

import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.core.security.SecurityStore;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.ConsumerInfo;
import org.apache.activemq.artemis.core.server.MessageReference;
import org.apache.activemq.artemis.core.server.ServerConsumer;
import org.apache.activemq.artemis.core.server.ServerSession;
import org.apache.activemq.artemis.core.server.plugin.ActiveMQServerPlugin;
import org.apache.activemq.artemis.spi.core.security.jaas.RolePrincipal;
import org.jboss.logging.Logger;

public class BrokerMessageAuthorizationPlugin implements ActiveMQServerPlugin {

   private static final Logger logger = Logger.getLogger(BrokerMessageAuthorizationPlugin.class);

   private static final String ROLE_PROPERTY = "ROLE_PROPERTY";
   private final AtomicReference<ActiveMQServer> server = new AtomicReference<>();
   private String roleProperty = "requiredRole";

   @Override
   public void init(Map<String, String> properties) {
      roleProperty = properties.getOrDefault(ROLE_PROPERTY, "requiredRole");
   }

   @Override
   public void registered(ActiveMQServer server) {
      this.server.set(server);
   }

   @Override
   public void unregistered(ActiveMQServer server) {
      this.server.set(null);
   }

   @Override
   public boolean canAccept(ServerConsumer consumer, MessageReference reference) throws ActiveMQException {

      String requiredRole = reference.getMessage().getStringProperty(roleProperty);
      if (requiredRole == null) {
         return true;
      }

      Subject subject = getSubject(consumer);
      if (subject == null) {
         if (logger.isDebugEnabled()) {
            logger.debug("Subject not found for consumer: " + consumer.getID());
         }
         return false;
      }
      boolean permitted = new RolePrincipal(requiredRole).implies(subject);
      if (!permitted && logger.isDebugEnabled()) {
         logger.debug("Message consumer: " + consumer.getID() + " does not have required role `" + requiredRole + "` needed to receive message: " + reference.getMessageID());
      }
      return permitted;
   }

   private Subject getSubject(ConsumerInfo consumer) {
      final ActiveMQServer activeMQServer = server.get();
      final SecurityStore securityStore = activeMQServer.getSecurityStore();
      ServerSession session = activeMQServer.getSessionByID(consumer.getSessionName());
      return securityStore.getSessionSubject(session);
   }

}


<|start_filename|>artemis-core-client/src/main/java/org/apache/activemq/artemis/core/remoting/impl/ssl/DefaultSSLContextFactory.java<|end_filename|>
/*
 * Copyright 2020 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.remoting.impl.ssl;

import java.util.Map;
import javax.net.ssl.SSLContext;
import org.apache.activemq.artemis.core.remoting.impl.netty.TransportConstants;
import org.apache.activemq.artemis.spi.core.remoting.ssl.SSLContextConfig;
import org.apache.activemq.artemis.spi.core.remoting.ssl.SSLContextFactory;
import org.apache.activemq.artemis.utils.ConfigurationHelper;

/**
 * Simple SSLContextFactory for use in NettyConnector and NettyAcceptor.
 */
public class DefaultSSLContextFactory implements SSLContextFactory {

   @Override
   public SSLContext getSSLContext(final SSLContextConfig config, final Map<String, Object> additionalOpts) throws Exception {
      final boolean useDefaultSslContext = ConfigurationHelper.getBooleanProperty(
         TransportConstants.USE_DEFAULT_SSL_CONTEXT_PROP_NAME,
         TransportConstants.DEFAULT_USE_DEFAULT_SSL_CONTEXT,
         additionalOpts
      );

      if (useDefaultSslContext) {
         log.debug("Using the Default JDK SSLContext.");
         return SSLContext.getDefault();
      }

      log.debugf("Creating JDK SSLContext with %s", config);
      return new SSLSupport(config).createContext();
   }

   @Override
   public int getPriority() {
      return 5;
   }
}


<|start_filename|>artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/components/status.js<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 /// <reference path="tree.component.ts"/>
var Artemis;
(function (Artemis) {
    Artemis.log.debug("loading status");
    Artemis._module.component('artemisStatus', {
        template:
               `<h1>Current Status
                <button type="button" class="btn btn-link jvm-title-popover"
                          uib-popover-template="'status-instructions.html'" popover-placement="bottom-left"
                          popover-title="Instructions" popover-trigger="'outsideClick'">
                    <span class="pficon pficon-help"></span>
                </button>
                </h1>
                <div class="container-fluid">
                     <div class="row">
                        <div class="col-md-3 text-center">
                            <label>Address Memory Used</label>
                            <p class="text-left">
                            <pf-donut-pct-chart config="$ctrl.addressMemoryConfig" data="$ctrl.addressMemoryData" center-label="$ctrl.addressMemoryLabel"></pf-donut-pct-chart>
                            </p>
                        </div>
                     </div>
                     <div class="row">
                         <div class="col-xs-12 col-sm-6 col-md-6 col-lg-4">
                               <pf-info-status-card status="$ctrl.infoStatus" show-top-border="true"></pf-info-status-card>
                         </div>
                     </div>
                     <div class="row">
                         <div class="col-xs-12 col-sm-6 col-md-6 col-lg-4">
                               <pf-info-status-card status="$ctrl.clusterInfoStatus" show-top-border="true"></pf-info-status-card>
                         </div>
                     </div>
                </div>
                <script type="text/ng-template" id="status-instructions.html">
                  <div>
                    <p>
                      This page allows you to view the current status of the broker as well as the status of the cluster it belongs to.
                    </p>
                    <p>
                    It also shows the current address memory usage in relationship to the <code>global-max-size</code>
                    </p>
                    <p>Note these metrics update every 5 seconds</p>
                  </div>
                </script>
        `,
        controller: StatusController
    })
    .name;
    Artemis.log.debug("loaded address " + Artemis.addressModule);

    function StatusController($scope, workspace, jolokia, localStorage, $interval) {
        var ctrl = this;
        var mbean = Artemis.getBrokerMBean(workspace, jolokia);

        StatusController.prototype.$onInit = function () {
            jolokia.request({ type: 'read', mbean: mbean, attribute: 'Version'}, Core.onSuccess(function(response) {
                ctrl.infoStatus.info[0] = "version: " + response.value;
            }));
            jolokia.request({ type: 'read', mbean: mbean, attribute: 'HAPolicy'}, Core.onSuccess(function(response) {
                ctrl.clusterInfoStatus.info[2] = "HA Policy: " + response.value;
            }));
            loadStatus();
            ctrl.promise = $interval(function () { return loadStatus(); }, 5000);
        };
        StatusController.prototype.$onDestroy = function () {
            $interval.cancel(this.promise);
        };

        ctrl.infoStatus = {
          "title":"Broker Info",
          "href":"#",
          "iconClass": "pficon pficon-ok",
          "info":[
            "version",
            "uptime:",
            "started:"
          ]
        };
        ctrl.clusterInfoStatus = {
          "title":"Cluster Info",
          "href":"#",
          "iconClass": "pficon pficon-ok",
          "info":[
            "Lives:",
            "Backups:",
            "HA Policy: :"
          ]
        };
        ctrl.addressMemoryConfig = {
            'chartId': 'addressMemoryChart',
            'units': 'MB',
            'thresholds':{'warning':'75','error':'90'}
        };

        ctrl.addressMemoryData = {
            'used': '0',
            'total': '1000'
        };
        ctrl.addressMemoryLabel = "used";

        function loadStatus() {
            jolokia.request({ type: 'read', mbean: mbean, attribute: 'GlobalMaxSize'}, Core.onSuccess(function(response) { ctrl.addressMemoryData.total = (response.value / 1048576).toFixed(2); }));
            jolokia.request({ type: 'read', mbean: mbean, attribute: 'AddressMemoryUsage'}, Core.onSuccess(function(response) { ctrl.addressMemoryData.used = (response.value / 1048576).toFixed(2); }));
            jolokia.request({ type: 'read', mbean: mbean, attribute: 'Uptime'}, Core.onSuccess(function(response) {
                ctrl.infoStatus.info[1] = "uptime: " + response.value;
            }));
            jolokia.request({ type: 'read', mbean: mbean, attribute: 'Started'}, Core.onSuccess(function(response) {
                ctrl.infoStatus.info[2] = "started: " + response.value;
                if(response.value == false) {
                    ctrl.infoStatus.iconClass = "pficon pficon-error-circle-o";
                } else {
                    ctrl.infoStatus.iconClass = "pficon pficon-ok";
                }
            }));
            var lives = 0;
            var backups = 0;
            var response = jolokia.request({ type: 'exec', mbean: mbean, operation: 'listNetworkTopology()' }, Core.onSuccess(null));
            var responseValue = response.value;
            var brokers = angular.fromJson(responseValue);
            angular.forEach(brokers, function (broker) {
                if (broker.live) {
                    lives++;
                }
                if (broker.backup) {
                    backups++;
                }
            })
            ctrl.clusterInfoStatus.info[0] = "Lives: " + lives;
            ctrl.clusterInfoStatus.info[1] = "Backups: " + backups;
            if (ctrl.clusterInfoStatus.info[2] == "HA Policy: Replicated") {
                jolokia.request({ type: 'read', mbean: mbean, attribute: 'ReplicaSync'}, Core.onSuccess(function(response) {
                    ctrl.clusterInfoStatus.info[3] = "replicating: " + response.value;
                    if (response.value == false) {
                        ctrl.clusterInfoStatus.iconClass = "pficon pficon-error-circle-o";
                    } else {
                        ctrl.clusterInfoStatus.iconClass = "pficon pficon-ok";
                    }
                }));
            }
        }
    }
    StatusController.$inject = ['$scope', 'workspace', 'jolokia', 'localStorage', '$interval'];

})(Artemis || (Artemis = {}));

<|start_filename|>artemis-core-client/src/test/java/org/apache/activemq/artemis/ClientThreadPoolsTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Properties;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.activemq.artemis.api.core.client.ActiveMQClient;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.client.impl.ServerLocatorImpl;
import org.apache.activemq.artemis.utils.ActiveMQThreadFactory;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

import static org.junit.Assert.assertEquals;

public class ClientThreadPoolsTest {

   private static Properties systemProperties;

   @BeforeClass
   public static void setup() {
      systemProperties = System.getProperties();
   }

   @AfterClass
   public static void tearDown() {
      System.clearProperty(ActiveMQClient.THREAD_POOL_MAX_SIZE_PROPERTY_KEY);
      System.clearProperty(ActiveMQClient.SCHEDULED_THREAD_POOL_SIZE_PROPERTY_KEY);
      ActiveMQClient.initializeGlobalThreadPoolProperties();
      ActiveMQClient.clearThreadPools();
      Assert.assertEquals(ActiveMQClient.DEFAULT_GLOBAL_THREAD_POOL_MAX_SIZE, ActiveMQClient.getGlobalThreadPoolSize());
   }

   @Test
   public void testSystemPropertyThreadPoolSettings() throws Exception {
      int threadPoolMaxSize = 100;
      int scheduledThreadPoolSize = 10;

      System.setProperty(ActiveMQClient.THREAD_POOL_MAX_SIZE_PROPERTY_KEY, "" + threadPoolMaxSize);
      System.setProperty(ActiveMQClient.SCHEDULED_THREAD_POOL_SIZE_PROPERTY_KEY, "" + scheduledThreadPoolSize);
      ActiveMQClient.initializeGlobalThreadPoolProperties();
      ActiveMQClient.clearThreadPools();

      testSystemPropertiesThreadPoolSettings(threadPoolMaxSize, scheduledThreadPoolSize);
   }

   @Test
   public void testShutdownPoolInUse() throws Exception {
      ActiveMQClient.setGlobalThreadPoolProperties(10, 1);
      ActiveMQClient.clearThreadPools();

      final CountDownLatch inUse = new CountDownLatch(1);
      final CountDownLatch neverLeave = new CountDownLatch(1);

      ActiveMQClient.getGlobalThreadPool().execute(new Runnable() {
         @Override
         public void run() {
            try {
               inUse.countDown();
               neverLeave.await();
            } catch (Exception e) {
               e.printStackTrace();
               neverLeave.countDown();
            }
         }
      });

      Assert.assertTrue(inUse.await(10, TimeUnit.SECONDS));
      ActiveMQClient.clearThreadPools(100, TimeUnit.MILLISECONDS);
      Assert.assertTrue(neverLeave.await(10, TimeUnit.SECONDS));
   }

   @Test
   public void testInjectPools() throws Exception {
      ActiveMQClient.clearThreadPools();

      ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());

      ScheduledThreadPoolExecutor scheduledThreadPoolExecutor = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(1, ActiveMQThreadFactory.defaultThreadFactory());

      ActiveMQClient.injectPools(poolExecutor, scheduledThreadPoolExecutor);

      final CountDownLatch inUse = new CountDownLatch(1);
      final CountDownLatch neverLeave = new CountDownLatch(1);

      ActiveMQClient.getGlobalThreadPool().execute(new Runnable() {
         @Override
         public void run() {
            try {
               inUse.countDown();
               neverLeave.await();
            } catch (Exception e) {
               e.printStackTrace();
               neverLeave.countDown();
            }
         }
      });

      Assert.assertTrue(inUse.await(10, TimeUnit.SECONDS));
      poolExecutor.shutdownNow();
      scheduledThreadPoolExecutor.shutdownNow();
      Assert.assertTrue(neverLeave.await(10, TimeUnit.SECONDS));

      Assert.assertTrue(inUse.await(10, TimeUnit.SECONDS));
      Assert.assertTrue(neverLeave.await(10, TimeUnit.SECONDS));

      ActiveMQClient.clearThreadPools(100, TimeUnit.MILLISECONDS);
   }

   @Test
   public void testStaticPropertiesThreadPoolSettings() throws Exception {

      int testMaxSize = 999;
      int testScheduleSize = 9;

      ActiveMQClient.setGlobalThreadPoolProperties(testMaxSize, testScheduleSize);
      ActiveMQClient.clearThreadPools();
      testSystemPropertiesThreadPoolSettings(testMaxSize, testScheduleSize);
   }

   @Test
   public void testSmallPool() throws Exception {

      int testMaxSize = 2;
      int testScheduleSize = 9;

      ActiveMQClient.setGlobalThreadPoolProperties(testMaxSize, testScheduleSize);
      ActiveMQClient.clearThreadPools();
      testSystemPropertiesThreadPoolSettings(testMaxSize, testScheduleSize);
   }

   private void testSystemPropertiesThreadPoolSettings(int expectedMax, int expectedScheduled) throws Exception {
      ServerLocatorImpl serverLocator = new ServerLocatorImpl(false);
      serverLocator.isUseGlobalPools();

      Method setThreadPools = ServerLocatorImpl.class.getDeclaredMethod("setThreadPools");
      setThreadPools.setAccessible(true);
      setThreadPools.invoke(serverLocator);

      // TODO: I would get this from the ActiveMQClient
      Field threadPoolField = ServerLocatorImpl.class.getDeclaredField("threadPool");
      Field scheduledThreadPoolField = ServerLocatorImpl.class.getDeclaredField("scheduledThreadPool");

      threadPoolField.setAccessible(true);
      scheduledThreadPoolField.setAccessible(true);

      ThreadPoolExecutor threadPool = (ThreadPoolExecutor) ActiveMQClient.getGlobalThreadPool();

      final CountDownLatch doneMax = new CountDownLatch(expectedMax);
      final CountDownLatch latch = new CountDownLatch(1);
      final CountDownLatch latchTotal = new CountDownLatch(expectedMax * 3); // we will schedule 3 * max, so all runnables should execute
      final AtomicInteger errors = new AtomicInteger(0);

      // Set this to true if you need to debug why executions are not being performed.
      final boolean debugExecutions = false;

      for (int i = 0; i < expectedMax * 3; i++) {
         final int localI = i;
         threadPool.execute(new Runnable() {
            @Override
            public void run() {
               try {

                  if (debugExecutions) {
                     System.out.println("runnable " + localI);
                  }
                  doneMax.countDown();
                  latch.await();
                  latchTotal.countDown();
               } catch (Exception e) {
                  errors.incrementAndGet();
               } finally {
                  if (debugExecutions) {
                     System.out.println("done " + localI);
                  }
               }
            }
         });
      }

      Assert.assertTrue(doneMax.await(5, TimeUnit.SECONDS));
      latch.countDown();
      Assert.assertTrue(latchTotal.await(5, TimeUnit.SECONDS));

      ScheduledThreadPoolExecutor scheduledThreadPool = (ScheduledThreadPoolExecutor) scheduledThreadPoolField.get(serverLocator);

      assertEquals(expectedMax, threadPool.getMaximumPoolSize());
      assertEquals(expectedScheduled, scheduledThreadPool.getCorePoolSize());
   }

   @Test
   public void testThreadPoolInjection() throws Exception {

      ServerLocator serverLocator = new ServerLocatorImpl(false);

      ThreadPoolExecutor threadPool = new ThreadPoolExecutor(1, 1, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>());
      ScheduledThreadPoolExecutor scheduledThreadPool = new ScheduledThreadPoolExecutor(1);
      serverLocator.setThreadPools(threadPool, scheduledThreadPool);

      Field threadPoolField = ServerLocatorImpl.class.getDeclaredField("threadPool");
      Field scheduledThreadPoolField = ServerLocatorImpl.class.getDeclaredField("scheduledThreadPool");

      serverLocator.initialize();

      threadPoolField.setAccessible(true);
      scheduledThreadPoolField.setAccessible(true);

      ThreadPoolExecutor tpe = (ThreadPoolExecutor) threadPoolField.get(serverLocator);
      ScheduledThreadPoolExecutor stpe = (ScheduledThreadPoolExecutor) scheduledThreadPoolField.get(serverLocator);

      assertEquals(threadPool, tpe);
      assertEquals(scheduledThreadPool, stpe);
   }

   @After
   public void cleanup() {
      // Resets the global thread pool properties back to default.
      System.setProperties(systemProperties);
      ActiveMQClient.initializeGlobalThreadPoolProperties();
      ActiveMQClient.clearThreadPools();
   }

}


<|start_filename|>artemis-ra/src/main/java/org/apache/activemq/artemis/ra/ActiveMQRAConnectionMetaData.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.ra;

import java.io.IOException;
import java.io.InputStream;
import javax.jms.ConnectionMetaData;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;

/**
 * This class implements javax.jms.ConnectionMetaData
 */
public class ActiveMQRAConnectionMetaData implements ConnectionMetaData {

   public static final String DEFAULT_PROP_FILE_NAME = "jms-version.properties";

   private static final String JMS_VERSION_NAME;
   private static final int JMS_MAJOR_VERSION;
   private static final int JMS_MINOR_VERSION;
   static {
      Properties versionProps = new Properties();
      try (InputStream in = ActiveMQRAConnectionMetaData.class.getClassLoader().getResourceAsStream(DEFAULT_PROP_FILE_NAME)) {
         if (in != null) {
            versionProps.load(in);
         }
      } catch (IOException e) {
      }
      JMS_VERSION_NAME = versionProps.getProperty("activemq.version.implementation.versionName", "2.0");
      JMS_MAJOR_VERSION = Integer.valueOf(versionProps.getProperty("activemq.version.implementation.majorVersion", "2"));
      JMS_MINOR_VERSION = Integer.valueOf(versionProps.getProperty("activemq.version.implementation.minorVersion", "0"));
   }

   /**
    * Constructor
    */
   public ActiveMQRAConnectionMetaData() {
      if (ActiveMQRALogger.LOGGER.isTraceEnabled()) {
         ActiveMQRALogger.LOGGER.trace("constructor()");
      }
   }

   /**
    * Get the JMS version
    *
    * @return The version
    */
   @Override
   public String getJMSVersion() {
      if (ActiveMQRALogger.LOGGER.isTraceEnabled()) {
         ActiveMQRALogger.LOGGER.trace("getJMSVersion()");
      }
      return JMS_VERSION_NAME;
   }

   /**
    * Get the JMS major version
    *
    * @return The major version
    */
   @Override
   public int getJMSMajorVersion() {
      if (ActiveMQRALogger.LOGGER.isTraceEnabled()) {
         ActiveMQRALogger.LOGGER.trace("getJMSMajorVersion()");
      }
      return JMS_MAJOR_VERSION;
   }

   /**
    * Get the JMS minor version
    *
    * @return The minor version
    */
   @Override
   public int getJMSMinorVersion() {
      if (ActiveMQRALogger.LOGGER.isTraceEnabled()) {
         ActiveMQRALogger.LOGGER.trace("getJMSMinorVersion()");
      }
      return JMS_MINOR_VERSION;
   }

   /**
    * Get the JMS provider name
    *
    * @return The name
    */
   @Override
   public String getJMSProviderName() {
      if (ActiveMQRALogger.LOGGER.isTraceEnabled()) {
         ActiveMQRALogger.LOGGER.trace("getJMSProviderName()");
      }

      return "ActiveMQ Artemis";
   }

   /**
    * Get the provider version
    *
    * @return The version
    */
   @Override
   public String getProviderVersion() {
      if (ActiveMQRALogger.LOGGER.isTraceEnabled()) {
         ActiveMQRALogger.LOGGER.trace("getJMSProviderName()");
      }

      return "2.4";
   }

   /**
    * Get the provider major version
    *
    * @return The version
    */
   @Override
   public int getProviderMajorVersion() {
      if (ActiveMQRALogger.LOGGER.isTraceEnabled()) {
         ActiveMQRALogger.LOGGER.trace("getProviderMajorVersion()");
      }

      return 2;
   }

   /**
    * Get the provider minor version
    *
    * @return The version
    */
   @Override
   public int getProviderMinorVersion() {
      if (ActiveMQRALogger.LOGGER.isTraceEnabled()) {
         ActiveMQRALogger.LOGGER.trace("getProviderMinorVersion()");
      }

      return 4;
   }

   /**
    * Get the JMS XPropertyNames
    *
    * @return The names
    */
   @Override
   public Enumeration<Object> getJMSXPropertyNames() {
      Vector<Object> v = new Vector<>();
      v.add("JMSXGroupID");
      v.add("JMSXGroupSeq");
      v.add("JMSXDeliveryCount");
      return v.elements();
   }
}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/spi/core/security/jaas/PrincipalsCallback.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.spi.core.security.jaas;

import java.security.Principal;

import javax.security.auth.callback.Callback;

/**
 * A Callback for getting the peer principals.
 */
public class PrincipalsCallback implements Callback {

   Principal[] peerPrincipals;

   /**
    * Setter for peer Principals.
    * @param principal The certificates to be returned.
    */
   public void setPeerPrincipals(Principal[] principal) {
      peerPrincipals = principal;
   }

   /**
    * Getter for peer Principals.
    * @return The principal being carried.
    */
   public Principal[] getPeerPrincipals() {
      return peerPrincipals;
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/persistence/DeleteQueueRestartTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.persistence;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientProducer;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.jms.client.ActiveMQBytesMessage;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.junit.Assert;
import org.junit.Test;

public class DeleteQueueRestartTest extends ActiveMQTestBase {

   // Constants -----------------------------------------------------

   private static final String ADDRESS = "ADDRESS";

   // Attributes ----------------------------------------------------

   // Static --------------------------------------------------------

   // Constructors --------------------------------------------------

   // Public --------------------------------------------------------

   @Test
   public void testDeleteQueueAndRestart() throws Exception {
      // This test could eventually pass, even when the queue was being deleted in the wrong order,
      // however it failed in 90% of the runs with 5 iterations.
      for (int i = 0; i < 5; i++) {
         setUp();
         internalDeleteQueueAndRestart();
         tearDown();
      }
   }

   private void internalDeleteQueueAndRestart() throws Exception {
      ActiveMQServer server = createServer(true);

      server.start();

      ServerLocator locator = createInVMNonHALocator().setBlockOnDurableSend(true).setBlockOnNonDurableSend(true).setMinLargeMessageSize(1024 * 1024);

      ClientSessionFactory factory = createSessionFactory(locator);

      final ClientSession session = factory.createSession(false, true, true);

      session.createQueue(new QueueConfiguration(DeleteQueueRestartTest.ADDRESS));

      ClientProducer prod = session.createProducer(DeleteQueueRestartTest.ADDRESS);

      for (int i = 0; i < 100; i++) {
         ClientMessage msg = createBytesMessage(session, ActiveMQBytesMessage.TYPE, new byte[0], true);
         prod.send(msg);
      }

      final CountDownLatch count = new CountDownLatch(1);

      // Using another thread, as the deleteQueue is a blocked call
      new Thread() {
         @Override
         public void run() {
            try {
               session.deleteQueue(DeleteQueueRestartTest.ADDRESS);
               session.close();
               count.countDown();
            } catch (ActiveMQException e) {
            }
         }
      }.start();

      Assert.assertTrue(count.await(5, TimeUnit.SECONDS));

      server.stop();

      server.start();

      server.stop();

   }
   // Package protected ---------------------------------------------

   // Protected -----------------------------------------------------

   // Private -------------------------------------------------------

   // Inner classes -------------------------------------------------

}


<|start_filename|>artemis-commons/src/test/java/org/apache/activemq/artemis/utils/actors/OrderedExecutorSanityTest.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.utils.actors;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import org.jboss.logging.Logger;
import org.junit.Assert;
import org.junit.Test;

public class OrderedExecutorSanityTest {
   private static final Logger log = Logger.getLogger(OrderedExecutorSanityTest.class);

   @Test
   public void shouldExecuteTasksInOrder() throws InterruptedException {
      final int threads = 3;
      final int tasks = 100;
      final long timeoutMillis = TimeUnit.SECONDS.toMillis(10);
      final ExecutorService executorService = Executors.newFixedThreadPool(threads);
      try {
         final ArtemisExecutor executor = new OrderedExecutor(executorService);
         //it can be not thread safe too
         final List<Integer> results = new ArrayList<>(tasks);
         final List<Integer> expectedResults = new ArrayList<>(tasks);
         final CountDownLatch executed = new CountDownLatch(tasks);
         for (int i = 0; i < tasks; i++) {
            final int value = i;
            executor.execute(() -> {
               results.add(value);
               executed.countDown();
            });
            expectedResults.add(value);
         }
         Assert.assertTrue("The tasks must be executed in " + timeoutMillis + " ms", executed.await(timeoutMillis, TimeUnit.MILLISECONDS));
         Assert.assertArrayEquals("The processing of tasks must be ordered", expectedResults.toArray(), results.toArray());
      } finally {
         executorService.shutdown();
      }
   }

   @Test
   public void shouldShutdownNowDoNotExecuteFurtherTasks() throws InterruptedException {
      final long timeoutMillis = TimeUnit.SECONDS.toMillis(10);
      final ExecutorService executorService = Executors.newSingleThreadExecutor();
      try {
         final OrderedExecutor executor = new OrderedExecutor(executorService);
         final CountDownLatch executed = new CountDownLatch(1);
         executor.execute(executed::countDown);
         Assert.assertTrue("The task must be executed in " + timeoutMillis + " ms", executed.await(timeoutMillis, TimeUnit.MILLISECONDS));
         executor.shutdownNow();
         Assert.assertEquals("There are no remaining tasks to be executed", 0, executor.remaining());
         //from now on new tasks won't be executed
         executor.execute(() -> System.out.println("this will never happen"));
         //to avoid memory leaks the executor must take care of the new submitted tasks immediatly
         Assert.assertEquals("Any new task submitted after death must be collected", 0, executor.remaining());
      } finally {
         executorService.shutdown();
      }
   }



   @Test
   public void shutdownNowOnDelegateExecutor() throws Exception {
      final ExecutorService executorService = Executors.newSingleThreadExecutor();
      try {
         final OrderedExecutor executor = new OrderedExecutor(executorService);
         final CyclicBarrier latch = new CyclicBarrier(2);
         final AtomicInteger numberOfTasks = new AtomicInteger(0);
         final CountDownLatch ran = new CountDownLatch(1);

         executor.execute(() -> {
            try {
               latch.await(1, TimeUnit.MINUTES);
               numberOfTasks.set(executor.shutdownNow());
               ran.countDown();
            } catch (Exception e) {
               e.printStackTrace();
            }
         });


         for (int i = 0; i < 100; i++) {
            executor.execute(() -> System.out.println("Dont worry, this will never happen"));
         }

         latch.await();
         ran.await(1, TimeUnit.SECONDS);
         Assert.assertEquals(100, numberOfTasks.get());

         Assert.assertEquals(ProcessorBase.STATE_FORCED_SHUTDOWN, executor.status());
         Assert.assertEquals(0, executor.remaining());
      } finally {
         executorService.shutdown();
      }
   }

   @Test
   public void shutdownNowWithBlocked() throws Exception {
      final ExecutorService executorService = Executors.newSingleThreadExecutor();
      try {
         final OrderedExecutor executor = new OrderedExecutor(executorService);
         final CyclicBarrier latch = new CyclicBarrier(2);
         final CyclicBarrier secondlatch = new CyclicBarrier(2);
         final CountDownLatch ran = new CountDownLatch(1);

         executor.execute(() -> {
            try {
               latch.await(1, TimeUnit.MINUTES);
               secondlatch.await(1, TimeUnit.MINUTES);
               ran.countDown();
            } catch (Exception e) {
               e.printStackTrace();
            }
         });


         for (int i = 0; i < 100; i++) {
            executor.execute(() -> System.out.println("Dont worry, this will never happen"));
         }

         latch.await();
         try {
            Assert.assertEquals(100, executor.shutdownNow());
         } finally {
            secondlatch.await();
         }

         Assert.assertEquals(ProcessorBase.STATE_FORCED_SHUTDOWN, executor.status());
         Assert.assertEquals(0, executor.remaining());
      } finally {
         executorService.shutdown();
      }
   }


   @Test
   public void testMeasure() throws InterruptedException {
      final ExecutorService executorService = Executors.newSingleThreadExecutor();
      try {
         final OrderedExecutor executor = new OrderedExecutor(executorService);
         int MAX_LOOP = 1_000_000;

         // extend the number for longer numbers
         int runs = 10;

         for (int i = 0; i < runs; i++) {
            long start = System.nanoTime();
            final CountDownLatch executed = new CountDownLatch(MAX_LOOP);
            for (int l = 0; l < MAX_LOOP; l++) {
               executor.execute(executed::countDown);
            }
            Assert.assertTrue(executed.await(1, TimeUnit.MINUTES));
            long end = System.nanoTime();

            long elapsed = (end - start);

            log.info("execution " + i + " in " + TimeUnit.NANOSECONDS.toMillis(elapsed) + " milliseconds");
         }
      } finally {
         executorService.shutdown();
      }
   }

}


<|start_filename|>artemis-rest/src/main/java/org/apache/activemq/artemis/rest/HttpHeaderProperty.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.rest;

public class HttpHeaderProperty {

   public static final String CONTENT_TYPE = "http_content$type";
   public static final String MESSAGE_PROPERTY_DISCRIMINATOR = "message.property.";

   /**
    * Either strips the prefix "message.property." and returns the rest of the name or (if not starting with aforementioned prefix)
    * converts an HTTP header name to a selector compatible property name.  '-' character is converted to
    * '$'. The return property name will also be all lower case with an "http_" prepended.  For example
    * "Content-Type" would be converted to "http_content$type";
    *
    * @param httpHeader
    * @return
    */
   public static String toPropertyName(String httpHeader) {
      if (httpHeader.startsWith( MESSAGE_PROPERTY_DISCRIMINATOR )) {
         return httpHeader.replaceAll( MESSAGE_PROPERTY_DISCRIMINATOR, "" );
      } else {
         httpHeader = httpHeader.replace( '-', '$' );
         return "http_" + httpHeader.toLowerCase();
      }
   }

   /**
    * Converts a JMS property name to an HTTP header name.
    *
    * @param name
    * @return null if property name isn't an HTTP header name.
    */
   public static String fromPropertyName(String name) {
      if (!name.startsWith("http_"))
         return null;
      return name.substring("http_".length()).replace('$', '-');
   }
}

<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/JMSTemporaryDestinationTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.amqp;

import java.util.concurrent.TimeUnit;

import javax.jms.Connection;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TemporaryQueue;
import javax.jms.TemporaryTopic;
import javax.jms.TextMessage;

import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.tests.util.Wait;
import org.junit.Test;

public class JMSTemporaryDestinationTest extends JMSClientTestSupport {

   @Test(timeout = 60000)
   public void testCreateTemporaryQueue() throws Throwable {
      Connection connection = createConnection();

      try {
         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
         TemporaryQueue queue = session.createTemporaryQueue();
         instanceLog.debug("queue:" + queue.getQueueName());
         MessageProducer producer = session.createProducer(queue);

         TextMessage message = session.createTextMessage();
         message.setText("Message temporary");
         producer.send(message);

         MessageConsumer consumer = session.createConsumer(queue);
         connection.start();

         message = (TextMessage) consumer.receive(5000);

         assertNotNull(message);
      } finally {
         connection.close();
      }
   }

   @Test(timeout = 30000)
   public void testDeleteTemporaryQueue() throws Exception {
      Connection connection = createConnection();

      try {
         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
         final javax.jms.Queue queue = session.createTemporaryQueue();
         assertNotNull(queue);
         assertTrue(queue instanceof TemporaryQueue);

         Queue queueView = getProxyToQueue(queue.getQueueName());
         assertNotNull(queueView);

         TemporaryQueue tempQueue = (TemporaryQueue) queue;
         tempQueue.delete();

         assertTrue("Temp Queue should be deleted.", Wait.waitFor(new Wait.Condition() {

            @Override
            public boolean isSatisfied() throws Exception {
               return getProxyToQueue(queue.getQueueName()) == null;
            }
         }, TimeUnit.SECONDS.toMillis(30), TimeUnit.MILLISECONDS.toMillis(50)));
      } finally {
         connection.close();
      }
   }

   @Test(timeout = 60000)
   public void testCreateTemporaryTopic() throws Throwable {
      Connection connection = createConnection();

      Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
      TemporaryTopic topic = session.createTemporaryTopic();

      instanceLog.debug("topic:" + topic.getTopicName());
      MessageConsumer consumer = session.createConsumer(topic);
      MessageProducer producer = session.createProducer(topic);

      TextMessage message = session.createTextMessage();
      message.setText("Message temporary");
      producer.send(message);

      connection.start();

      message = (TextMessage) consumer.receive(5000);

      assertNotNull(message);
   }

   @Test(timeout = 30000)
   public void testDeleteTemporaryTopic() throws Exception {
      Connection connection = createConnection();

      try {
         Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
         final javax.jms.Topic topic = session.createTemporaryTopic();
         assertNotNull(topic);
         assertTrue(topic instanceof TemporaryTopic);

         Queue queueView = getProxyToQueue(topic.getTopicName());
         assertNotNull(queueView);

         TemporaryTopic tempTopic = (TemporaryTopic) topic;
         tempTopic.delete();

         assertTrue("Temp Queue should be deleted.", Wait.waitFor(new Wait.Condition() {

            @Override
            public boolean isSatisfied() throws Exception {
               return getProxyToQueue(topic.getTopicName()) == null;
            }
         }, TimeUnit.SECONDS.toMillis(30), TimeUnit.MILLISECONDS.toMillis(50)));
      } finally {
         connection.close();
      }
   }
}


<|start_filename|>artemis-cli/src/test/java/org/apache/activemq/cli/test/TransferTest.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.cli.test;

import org.apache.activemq.artemis.api.core.Pair;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.cli.commands.messages.Transfer;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.core.server.management.ManagementContext;
import org.apache.activemq.artemis.jms.client.ActiveMQConnectionFactory;
import org.apache.activemq.artemis.utils.Wait;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import javax.jms.Connection;
import javax.jms.Session;

public class TransferTest extends CliTestBase {
   private Connection connection;
   private ActiveMQConnectionFactory cf;
   private ActiveMQServer server;
   private static final int TEST_MESSAGE_COUNT = 10;

   @Before
   @Override
   public void setup() throws Exception {
      setupAuth();
      super.setup();
      server = ((Pair<ManagementContext, ActiveMQServer>)startServer()).getB();
      cf = getConnectionFactory(61616);
      connection = cf.createConnection("admin", "admin");
   }

   @After
   @Override
   public void tearDown() throws Exception {
      closeConnection(cf, connection);
      super.tearDown();
   }

   @Test
   public void testTransferMessages() throws Exception {
      testTransferMessages(TEST_MESSAGE_COUNT, 0);
   }

   @Test
   public void testTransferMessagesWithMessageCount() throws Exception {
      testTransferMessages(TEST_MESSAGE_COUNT, 5);
   }

   private void testTransferMessages(int messages, int limit) throws Exception {
      String sourceQueueName = "SOURCE_QUEUE";
      String targetQueueName = "TARGET_QUEUE";

      server.createQueue(new QueueConfiguration(sourceQueueName).setRoutingType(RoutingType.ANYCAST));
      server.createQueue(new QueueConfiguration(targetQueueName).setRoutingType(RoutingType.ANYCAST));

      Session session = createSession(connection);
      produceMessages(session, sourceQueueName, messages, false);

      Queue sourceQueue = server.locateQueue(sourceQueueName);

      Wait.assertEquals(messages, sourceQueue::getMessageCount);

      Transfer transfer = new Transfer()
         .setSourceUser("admin")
         .setSourcePassword("<PASSWORD>")
         .setSourceQueue(sourceQueueName)
         .setTargetUser("admin")
         .setTargetPassword("<PASSWORD>")
         .setTargetQueue(targetQueueName)
         .setReceiveTimeout(100);

      if (limit > 0) {
         transfer.setMessageCount(limit);

         Assert.assertEquals(limit, transfer.execute(new TestActionContext()));

         Queue targetQueue = server.locateQueue(targetQueueName);
         Wait.assertEquals(messages - limit, sourceQueue::getMessageCount);
         Wait.assertEquals(limit, targetQueue::getMessageCount);
      } else {
         Assert.assertEquals(messages, transfer.execute(new TestActionContext()));

         Queue targetQueue = server.locateQueue(targetQueueName);
         Wait.assertEquals(0, sourceQueue::getMessageCount);
         Wait.assertEquals(messages, targetQueue::getMessageCount);
      }
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/cluster/distribution/ClusterConnectionConfigTest.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.cluster.distribution;

import org.apache.activemq.artemis.core.client.impl.ServerLocatorInternal;
import org.apache.activemq.artemis.core.config.ClusterConnectionConfiguration;
import org.apache.activemq.artemis.core.server.cluster.MessageFlowRecord;
import org.apache.activemq.artemis.core.server.cluster.impl.ClusterConnectionImpl;
import org.apache.activemq.artemis.core.server.cluster.impl.MessageLoadBalancingType;
import org.junit.Before;
import org.junit.Test;

import java.lang.reflect.Field;
import java.util.Map;
import java.util.Random;

public class ClusterConnectionConfigTest extends ClusterTestBase {

   @Override
   @Before
   public void setUp() throws Exception {
      super.setUp();
      start();
   }

   private void start() throws Exception {
      setupServers();
   }

   protected boolean isNetty() {
      return true;
   }

   protected void setupServers() throws Exception {
      setupServer(0, isFileStorage(), isNetty());
      setupServer(1, isFileStorage(), isNetty());
   }

   protected void setupCluster(final MessageLoadBalancingType messageLoadBalancingType, final ClusterConfigCallback cb) throws Exception {
      setupClusterConnection("cluster0", "queues", messageLoadBalancingType, 1, isNetty(), cb, 0, 1, 2);
      setupClusterConnection("cluster1", "queues", messageLoadBalancingType, 1, isNetty(), cb, 1, 0, 2);
   }

   @Test
   public void testRedistributionFlowControl() throws Exception {
      final int producerWindow = new Random().nextInt(Integer.MAX_VALUE);
      setupCluster(MessageLoadBalancingType.ON_DEMAND, (ClusterConnectionConfiguration cfg) -> {
         cfg.setProducerWindowSize(producerWindow);
      });
      startServers(0, 1);

      setupSessionFactory(0, isNetty());
      setupSessionFactory(1, isNetty());

      createQueue(0, "queues.testaddress", "queue0", null, false);
      createQueue(1, "queues.testaddress", "queue0", null, false);

      addConsumer(1, 1, "queue0", null);

      waitForBindings(0, "queues.testaddress", 1, 0, true);
      waitForBindings(1, "queues.testaddress", 1, 1, true);

      waitForBindings(0, "queues.testaddress", 1, 1, false);
      waitForBindings(1, "queues.testaddress", 1, 0, false);

      send(0, "queues.testaddress", 1, false, null);

      //receiveMessages(consumers[1].consumer, 0, 1, true);
      Thread.sleep(5000);
      makeSureForwardingFlowControl(producerWindow, 0, 1);


      removeConsumer(1);
   }

   private void makeSureForwardingFlowControl(int producerWindow, int... indices) throws NoSuchFieldException, IllegalAccessException {
      for (int i : indices) {
         ClusterConnectionImpl cc = (ClusterConnectionImpl) servers[i].getClusterManager().getClusterConnection("cluster" + i);
         Map<String, MessageFlowRecord> map = cc.getRecords();
         assertEquals(1, map.size());
         MessageFlowRecord record = map.entrySet().iterator().next().getValue();

         Field f = record.getClass().getDeclaredField("targetLocator"); //NoSuchFieldException
         f.setAccessible(true);
         ServerLocatorInternal targetLocator = (ServerLocatorInternal) f.get(record);
         assertEquals(producerWindow, targetLocator.getProducerWindowSize());
      }
   }

}


<|start_filename|>tests/smoke-tests/src/test/java/org/apache/activemq/artemis/tests/smoke/console/LoginTest.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.tests.smoke.console;

import org.apache.activemq.artemis.tests.smoke.console.pages.LoginPage;
import org.apache.activemq.artemis.tests.smoke.console.pages.StatusPage;
import org.junit.Test;
import org.openqa.selenium.MutableCapabilities;

public class LoginTest extends ConsoleTest {

   public LoginTest(MutableCapabilities browserOptions) {
      super(browserOptions);
   }

   @Test
   public void testLogin() {
      LoginPage loginPage = new LoginPage(driver);
      StatusPage statusPage = loginPage.loginValidUser(
         SERVER_ADMIN_USERNAME, SERVER_ADMIN_PASSWORD, DEFAULT_TIMEOUT);

      assertEquals(SERVER_ADMIN_USERNAME, statusPage.getUser());
   }

   @Test
   public void testLoginBrand() {
      String expectedBrandImage = serverUrl + System.getProperty(
         "artemis.console.brand.image", DEFAULT_CONSOLE_BRAND_IMAGE);

      LoginPage loginPage = new LoginPage(driver);
      assertEquals(expectedBrandImage, loginPage.getBrandImage(DEFAULT_TIMEOUT));
   }
}


<|start_filename|>tests/unit-tests/src/test/java/org/apache/activemq/artemis/tests/unit/core/postoffice/impl/DuplicateDetectionUnitTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.unit.core.postoffice.impl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;

import org.apache.activemq.artemis.api.config.ActiveMQDefaultConfiguration;
import org.apache.activemq.artemis.api.core.Pair;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.persistence.AddressBindingInfo;
import org.apache.activemq.artemis.core.persistence.GroupingInfo;
import org.apache.activemq.artemis.core.persistence.QueueBindingInfo;
import org.apache.activemq.artemis.core.persistence.impl.journal.JournalStorageManager;
import org.apache.activemq.artemis.core.postoffice.DuplicateIDCache;
import org.apache.activemq.artemis.core.postoffice.PostOffice;
import org.apache.activemq.artemis.core.postoffice.impl.DuplicateIDCaches;
import org.apache.activemq.artemis.core.server.impl.PostOfficeJournalLoader;
import org.apache.activemq.artemis.core.transaction.impl.ResourceManagerImpl;
import org.apache.activemq.artemis.tests.unit.core.server.impl.fakes.FakePostOffice;
import org.apache.activemq.artemis.tests.unit.util.FakePagingManager;
import org.apache.activemq.artemis.tests.util.ActiveMQTestBase;
import org.apache.activemq.artemis.utils.ActiveMQThreadFactory;
import org.apache.activemq.artemis.utils.ExecutorFactory;
import org.apache.activemq.artemis.utils.RandomUtil;
import org.apache.activemq.artemis.utils.actors.OrderedExecutorFactory;
import org.apache.activemq.artemis.utils.critical.EmptyCriticalAnalyzer;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

public class DuplicateDetectionUnitTest extends ActiveMQTestBase {
   // Constants -----------------------------------------------------

   // Attributes ----------------------------------------------------

   // Static --------------------------------------------------------

   // Constructors --------------------------------------------------

   ExecutorService executor;

   ExecutorFactory factory;

   @Override
   @After
   public void tearDown() throws Exception {
      executor.shutdown();
      super.tearDown();
   }

   @Override
   @Before
   public void setUp() throws Exception {
      super.setUp();
      executor = Executors.newFixedThreadPool(10, ActiveMQThreadFactory.defaultThreadFactory());
      factory = new OrderedExecutorFactory(executor);
   }

   // Public --------------------------------------------------------

   @Test
   public void testReloadDuplication() throws Exception {

      JournalStorageManager journal = null;

      try {
         clearDataRecreateServerDirs();

         SimpleString ADDRESS = new SimpleString("address");

         Configuration configuration = createDefaultInVMConfig();

         PostOffice postOffice = new FakePostOffice();

         ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(ActiveMQDefaultConfiguration.getDefaultScheduledThreadPoolMaxSize(), ActiveMQThreadFactory.defaultThreadFactory());

         journal = new JournalStorageManager(configuration, EmptyCriticalAnalyzer.getInstance(), factory, factory);

         journal.start();
         journal.loadBindingJournal(new ArrayList<QueueBindingInfo>(), new ArrayList<GroupingInfo>(), new ArrayList<AddressBindingInfo>());

         HashMap<SimpleString, List<Pair<byte[], Long>>> mapDups = new HashMap<>();

         FakePagingManager pagingManager = new FakePagingManager();
         journal.loadMessageJournal(postOffice, pagingManager, new ResourceManagerImpl(null, 0, 0, scheduledThreadPool), null, mapDups, null, null, new PostOfficeJournalLoader(postOffice, pagingManager, null, null, null, null, null, null));

         Assert.assertEquals(0, mapDups.size());

         DuplicateIDCache cacheID = DuplicateIDCaches.persistent(ADDRESS, 10, journal);

         for (int i = 0; i < 100; i++) {
            cacheID.addToCache(RandomUtil.randomBytes());
         }

         journal.stop();

         journal = new JournalStorageManager(configuration, EmptyCriticalAnalyzer.getInstance(), factory, factory);
         journal.start();
         journal.loadBindingJournal(new ArrayList<QueueBindingInfo>(), new ArrayList<GroupingInfo>(), new ArrayList<AddressBindingInfo>());

         journal.loadMessageJournal(postOffice, pagingManager, new ResourceManagerImpl(null, 0, 0, scheduledThreadPool), null, mapDups, null, null, new PostOfficeJournalLoader(postOffice, pagingManager, null, null, null, null, null, null));

         Assert.assertEquals(1, mapDups.size());

         List<Pair<byte[], Long>> values = mapDups.get(ADDRESS);

         Assert.assertEquals(10, values.size());

         cacheID = DuplicateIDCaches.persistent(ADDRESS, 10, journal);
         cacheID.load(values);

         for (int i = 0; i < 100; i++) {
            cacheID.addToCache(RandomUtil.randomBytes(), null);
         }

         journal.stop();

         mapDups.clear();

         journal = new JournalStorageManager(configuration, EmptyCriticalAnalyzer.getInstance(), factory, factory);
         journal.start();
         journal.loadBindingJournal(new ArrayList<QueueBindingInfo>(), new ArrayList<GroupingInfo>(), new ArrayList<AddressBindingInfo>());

         journal.loadMessageJournal(postOffice, pagingManager, new ResourceManagerImpl(null, 0, 0, scheduledThreadPool), null, mapDups, null, null, new PostOfficeJournalLoader(postOffice, pagingManager, null, null, null, null, null, null));

         Assert.assertEquals(1, mapDups.size());

         values = mapDups.get(ADDRESS);

         Assert.assertEquals(10, values.size());

         scheduledThreadPool.shutdown();
      } finally {
         if (journal != null) {
            try {
               journal.stop();
            } catch (Throwable ignored) {
            }
         }
      }

   }
}


<|start_filename|>artemis-commons/src/main/java/org/apache/activemq/artemis/utils/uri/URISchema.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.utils.uri;

import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;

public abstract class URISchema<T, P> {

   public abstract String getSchemaName();

   public T newObject(URI uri, P param) throws Exception {
      return newObject(uri, null, param);
   }

   public void populateObject(URI uri, T bean) throws Exception {
      internalPopulateObject(uri, parseQuery(uri.getQuery(), null), bean);
   }

   public URI newURI(T bean) throws Exception {
      return internalNewURI(bean);
   }

   private URIFactory<T, P> parentFactory;

   void setFactory(URIFactory<T, P> factory) {
      this.parentFactory = factory;
   }

   protected URIFactory<T, P> getFactory() {
      return parentFactory;
   }

   protected String getHost(URI uri) {
      URI defaultFactory = getDefaultURI();
      if (defaultFactory != null && uri.getHost() == null && defaultFactory.getScheme().equals(uri.getScheme())) {
         uri = defaultFactory;
      }
      return uri.getHost();
   }

   protected URI getDefaultURI() {
      URIFactory<T, P> factory = getFactory();
      if (factory == null) {
         return null;
      } else {
         return factory.getDefaultURI();
      }
   }

   protected int getPort(URI uri) {
      URI defaultFactory = getDefaultURI();
      if (defaultFactory != null && uri.getPort() < 0 && defaultFactory.getScheme().equals(uri.getScheme())) {
         uri = defaultFactory;
      }
      return uri.getPort();
   }

   /**
    * It will create a new Object for the URI selected schema.
    * the propertyOverrides is used to replace whatever was defined on the URL string
    *
    * @param uri               The URI
    * @param propertyOverrides used to replace whatever was defined on the URL string
    * @return new Object
    * @throws Exception On error
    */
   public T newObject(URI uri, Map<String, String> propertyOverrides, P param) throws Exception {
      return internalNewObject(uri, parseQuery(uri.getQuery(), propertyOverrides), param);
   }

   protected abstract T internalNewObject(URI uri, Map<String, String> query, P param) throws Exception;

   /**
    * This is the default implementation.
    * Sub classes are should provide a proper implementation for their schemas.
    */
   protected URI internalNewURI(T bean) throws Exception {
      String query = BeanSupport.getData(null, bean);

      return new URI(getSchemaName(), null, "//", query, null);

   }

   protected void internalPopulateObject(URI uri, Map<String, String> query, T bean) throws Exception {
      BeanSupport.setData(uri, bean, query);
   }

   public static Map<String, String> parseQuery(String uri,
                                                Map<String, String> propertyOverrides) throws URISyntaxException {
      try {
         Map<String, String> rc = new HashMap<>();
         if (uri != null && !uri.isEmpty()) {
            String[] parameters = uri.split("&");
            for (String parameter : parameters) {
               int p = parameter.indexOf("=");
               if (p >= 0) {
                  String name = BeanSupport.decodeURI(parameter.substring(0, p));
                  String value = BeanSupport.decodeURI(parameter.substring(p + 1));
                  rc.put(name, value);
               } else {
                  if (!parameter.trim().isEmpty()) {
                     rc.put(parameter, null);
                  }
               }
            }
         }

         if (propertyOverrides != null) {
            for (Map.Entry<String, String> entry : propertyOverrides.entrySet()) {
               rc.put(entry.getKey(), entry.getValue());
            }
         }
         return rc;
      } catch (UnsupportedEncodingException e) {
         throw (URISyntaxException) new URISyntaxException(e.toString(), "Invalid encoding").initCause(e);
      }
   }

   protected String printQuery(Map<String, String> query) {
      StringBuffer buffer = new StringBuffer();
      for (Map.Entry<String, String> entry : query.entrySet()) {
         buffer.append(entry.getKey() + "=" + entry.getValue());
         buffer.append("\n");
      }

      return buffer.toString();
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/LargeMessageOverManagementTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.management;

import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.TransportConfiguration;
import org.apache.activemq.artemis.api.core.client.ClientConsumer;
import org.apache.activemq.artemis.api.core.client.ClientMessage;
import org.apache.activemq.artemis.api.core.client.ClientSession;
import org.apache.activemq.artemis.api.core.client.ClientSessionFactory;
import org.apache.activemq.artemis.api.core.client.ServerLocator;
import org.apache.activemq.artemis.api.core.management.AddressControl;
import org.apache.activemq.artemis.api.core.management.QueueControl;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.utils.Base64;
import org.apache.activemq.artemis.utils.RandomUtil;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import java.util.HashMap;

public class LargeMessageOverManagementTest extends ManagementTestBase {

   private ClientSession session;
   private ServerLocator locator;
   private ClientSessionFactory sf;
   private ActiveMQServer server;

   protected AddressControl createManagementControl(final SimpleString address) throws Exception {
      return ManagementControlHelper.createAddressControl(address, mbeanServer);
   }

   @Override
   @Before
   public void setUp() throws Exception {
      super.setUp();

      Configuration config = createBasicConfig();


      TransportConfiguration acceptorConfig = createTransportConfiguration(false, true, generateParams(0, false));
      config.addAcceptorConfiguration(acceptorConfig);
      server = createServer(true, config);
      server.setMBeanServer(mbeanServer);
      server.start();

      locator = createInVMNonHALocator().setBlockOnNonDurableSend(true);
      sf = createSessionFactory(locator);
      session = sf.createSession(false, true, false);
      session.start();
      addClientSession(session);
   }

   @Test
   public void testSendOverSizeMessageOverQueueControl() throws Exception {
      SimpleString address = RandomUtil.randomSimpleString();
      SimpleString queue = RandomUtil.randomSimpleString();
      SimpleString emptyqueue = RandomUtil.randomSimpleString();

      session.createQueue(new QueueConfiguration(queue).setAddress(address));
      session.createQueue(new QueueConfiguration(emptyqueue).setAddress(address));

      QueueControl queueControl = createManagementControl(address, queue);

      int bodySize = (int) server.getStorageManager().getMaxRecordSize() + 100;
      byte[] bigData = createBytesData(bodySize);

      queueControl.sendMessage(new HashMap<String, String>(), Message.BYTES_TYPE, Base64.encodeBytes(bigData), true, "myUser", "myPassword");


      ClientConsumer consumer = session.createConsumer(queue);
      ClientMessage message = consumer.receive(1000);
      Assert.assertNotNull(message);
      Assert.assertEquals(bigData.length, message.getBodySize());
      Assert.assertTrue(message.isLargeMessage());



      byte[] bytesRead = new byte[bigData.length];
      message.getBodyBuffer().readBytes(bytesRead);

      for (int i = 0; i < bytesRead.length; i++) {
         Assert.assertEquals(bytesRead[i], bigData[i]);
      }


      consumer.close();

      // this is an extra check,
      consumer = session.createConsumer(emptyqueue);
      Assert.assertNull(consumer.receiveImmediate());

   }

   @Test
   public void testSendOverSizeMessageOverAddressControl() throws Exception {

      SimpleString address = RandomUtil.randomSimpleString();
      session.createAddress(address, RoutingType.ANYCAST, false);

      AddressControl addressControl = createManagementControl(address);
      session.createQueue(new QueueConfiguration(address).setRoutingType(RoutingType.ANYCAST));

      int bodySize = server.getConfiguration().getJournalBufferSize_AIO();
      byte[] bigData = createBytesData(bodySize);
      addressControl.sendMessage(null, Message.BYTES_TYPE, Base64.encodeBytes(bigData), false, null, null);

      ClientConsumer consumer = session.createConsumer(address);
      ClientMessage message = consumer.receive(1000);
      Assert.assertNotNull(message);
      Assert.assertEquals(bigData.length, message.getBodySize());
      Assert.assertTrue(message.isLargeMessage());

      byte[] bytesRead = new byte[bigData.length];
      message.getBodyBuffer().readBytes(bytesRead);

      for (int i = 0; i < bytesRead.length; i++) {
         Assert.assertEquals(bytesRead[i], bigData[i]);
      }

   }

   byte[] createBytesData(int nbytes) {
      byte[] result = new byte[nbytes];
      for (int i = 0; i < nbytes; i++) {
         result[i] = RandomUtil.randomByte();
      }
      return result;
   }
}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/paging/cursor/impl/PageReader.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.core.paging.cursor.impl;

import org.apache.activemq.artemis.core.paging.PagedMessage;
import org.apache.activemq.artemis.core.paging.cursor.NonExistentPage;
import org.apache.activemq.artemis.core.paging.cursor.PageCache;
import org.apache.activemq.artemis.core.paging.cursor.PagePosition;
import org.apache.activemq.artemis.core.paging.impl.Page;
import org.jboss.logging.Logger;

public class PageReader implements PageCache {
   private static final Logger logger = Logger.getLogger(PageReader.class);

   private final Page page;
   private final int numberOfMessages;

   public PageReader(Page page, int numberOfMessages) {
      this.page = page;
      this.numberOfMessages = numberOfMessages;
   }

   @Override
   public long getPageId() {
      return page.getPageId();
   }

   @Override
   public int getNumberOfMessages() {
      return numberOfMessages;
   }

   /**
    * Used just for testing purposes.
    */
   protected synchronized PagedMessage[] readMessages() {
      try {
         openPage();
         return page.read().toArray(new PagedMessage[numberOfMessages]);
      } catch (Exception e) {
         throw new RuntimeException(e.getMessage(), e);
      } finally {
         close();
      }
   }

   @Override
   public boolean isLive() {
      return false;
   }

   /**
    * @param pagePosition   page position
    * @param throwException if {@code true} exception will be thrown when message number is beyond the page
    * @param keepOpen       if {@code true} page file would keep open after reading message
    * @return the paged message
    */
   public synchronized PagedMessage getMessage(PagePosition pagePosition, boolean throwException, boolean keepOpen) {
      if (pagePosition.getMessageNr() >= getNumberOfMessages()) {
         if (throwException) {
            throw new NonExistentPage("Invalid messageNumber passed = " + pagePosition + " on " + this);
         }
         return null;
      }

      boolean previouslyClosed = true;
      try {
         previouslyClosed = openPage();
         PagedMessage msg;
         if (pagePosition.getFileOffset() != -1) {
            msg = page.readMessage(pagePosition.getFileOffset(), pagePosition.getMessageNr(), pagePosition.getMessageNr());
         } else {
            if (logger.isTraceEnabled()) {
               logger.trace("get message from pos " + pagePosition, new Exception("trace get message without file offset"));
            }
            msg = page.readMessage(0, 0, pagePosition.getMessageNr());
         }
         return msg;
      } catch (Exception e) {
         throw new RuntimeException(e.getMessage(), e);
      } finally {
         if (!keepOpen && previouslyClosed) {
            close();
         }
      }
   }

   @Override
   public synchronized PagedMessage getMessage(PagePosition pagePosition) {
      return getMessage(pagePosition, false, false);
   }

   /**
    * @return true if file was previously closed
    * @throws Exception
    */
   boolean openPage() throws Exception {
      if (!page.getFile().isOpen()) {
         page.getFile().open();
         return true;
      }
      return false;
   }

   @Override
   public synchronized void close() {
      try {
         page.close(false, false);
      } catch (Exception e) {
         logger.warn("Closing page " + page.getPageId() + " occurs exception:", e);
      }
   }

   @Override
   public String toString() {
      return "PageReader::page=" + getPageId() + " numberOfMessages = " + numberOfMessages;
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/stomp/StompWithSecurityPerAcceptorTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.stomp;

import java.lang.management.ManagementFactory;
import java.net.URI;
import java.net.URL;

import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.protocol.stomp.Stomp;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.ActiveMQServers;
import org.apache.activemq.artemis.spi.core.security.ActiveMQJAASSecurityManager;
import org.apache.activemq.artemis.tests.integration.stomp.util.ClientStompFrame;
import org.apache.activemq.artemis.tests.integration.stomp.util.StompClientConnection;
import org.apache.activemq.artemis.tests.integration.stomp.util.StompClientConnectionFactory;
import org.junit.Before;
import org.junit.Test;

public class StompWithSecurityPerAcceptorTest extends StompTestBase {

   static {
      String path = System.getProperty("java.security.auth.login.config");
      if (path == null) {
         URL resource = StompWithSecurityPerAcceptorTest.class.getClassLoader().getResource("login.config");
         if (resource != null) {
            path = resource.getFile();
            System.setProperty("java.security.auth.login.config", path);
         }
      }
   }

   @Override
   public boolean isSecurityEnabled() {
      return true;
   }

   @Override
   @Before
   public void setUp() throws Exception {
      uri = new URI(scheme + "://" + hostname + ":" + port);

      server = createServer();
      server.start();

      waitForServerToStart(server);
   }

   @Override
   protected ActiveMQServer createServer() throws Exception {
      Configuration config = createBasicConfig()
         .setSecurityEnabled(isSecurityEnabled())
         .setPersistenceEnabled(isPersistenceEnabled())
         .addAcceptorConfiguration("stomp", "tcp://localhost:61613?securityDomain=PropertiesLogin");

      server = addServer(ActiveMQServers.newActiveMQServer(config, ManagementFactory.getPlatformMBeanServer(), new ActiveMQJAASSecurityManager()));
      return server;
   }

   @Test
   public void testSecurityPerAcceptorPositive() throws Exception {
      StompClientConnection conn = StompClientConnectionFactory.createClientConnection(uri);
      ClientStompFrame frame = conn.connect("first", "secret");
      assertTrue(frame.getCommand().equals(Stomp.Responses.CONNECTED));
   }

   @Test
   public void testSecurityPerAcceptorNegative() throws Exception {
      StompClientConnection conn = StompClientConnectionFactory.createClientConnection(uri);
      ClientStompFrame frame = conn.connect("fail", "secret");
      assertTrue(frame.getCommand().equals(Stomp.Responses.ERROR));
   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/AmqpDLQReceiverTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.amqp;

import java.util.concurrent.TimeUnit;

import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.tests.util.Wait;
import org.apache.activemq.transport.amqp.client.AmqpClient;
import org.apache.activemq.transport.amqp.client.AmqpConnection;
import org.apache.activemq.transport.amqp.client.AmqpMessage;
import org.apache.activemq.transport.amqp.client.AmqpReceiver;
import org.apache.activemq.transport.amqp.client.AmqpSession;
import org.junit.Test;

/**
 * Tests for broker side support of the Durable Subscription mapping for JMS.
 */
public class AmqpDLQReceiverTest extends AmqpClientTestSupport {

   @Test(timeout = 60000)
   public void testCreateDurableReceiver() throws Exception {

      AmqpClient client = createAmqpClient();
      AmqpConnection connection = addConnection(client.connect());
      AmqpSession session = connection.createSession();

      AmqpReceiver receiver = session.createReceiver(getQueueName());
      sendMessages(getQueueName(), 1);
      Queue queue = getProxyToQueue(getQueueName());
      assertNotNull(queue);
      receiver.flow(100);
      for (int i = 0; i < 10; i++) {
         instanceLog.debug("i = " + i);
         AmqpMessage receive = receiver.receive(5000, TimeUnit.MILLISECONDS);
         receive.modified(true, false);
         Queue queueView = getProxyToQueue(getQueueName());
         instanceLog.debug("receive = " + receive.getWrappedMessage().getDeliveryCount());
         instanceLog.debug("queueView.getMessageCount() = " + queueView.getMessageCount());
         instanceLog.debug("queueView.getDeliveringCount() = " + queueView.getDeliveringCount());
         instanceLog.debug("queueView.getPersistentSize() = " + queueView.getPersistentSize());
      }

      receiver.close();
      connection.close();
      Queue queueView = getProxyToQueue(getQueueName());
      instanceLog.debug("queueView.getMessageCount() = " + queueView.getMessageCount());
      instanceLog.debug("queueView.getDeliveringCount() = " + queueView.getDeliveringCount());
      instanceLog.debug("queueView.getPersistentSize() = " + queueView.getPersistentSize());
      Wait.assertEquals(0, queueView::getMessageCount);
   }

}


<|start_filename|>artemis-server/src/main/java/org/apache/activemq/artemis/core/server/plugin/ActiveMQServerResourcePlugin.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.core.server.plugin;

import javax.transaction.xa.Xid;

import org.apache.activemq.artemis.api.core.ActiveMQException;
import org.apache.activemq.artemis.core.transaction.Transaction;
import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection;

/**
 *
 */
public interface ActiveMQServerResourcePlugin extends ActiveMQServerBasePlugin {

   /**
    * Before a transaction is put
    *
    * @param xid
    * @param tx
    * @param remotingConnection
    * @throws ActiveMQException
    */
   default void beforePutTransaction(Xid xid, Transaction tx, RemotingConnection remotingConnection) throws ActiveMQException {

   }

   /**
    * After a transaction is put
    *
    * @param xid
    * @param tx
    * @param remotingConnection
    * @throws ActiveMQException
    */
   default void afterPutTransaction(Xid xid, Transaction tx, RemotingConnection remotingConnection) throws ActiveMQException {

   }

   /**
    * Before a transaction is removed
    *
    * @param xid
    * @param remotingConnection
    * @throws ActiveMQException
    */
   default void beforeRemoveTransaction(Xid xid, RemotingConnection remotingConnection) throws ActiveMQException {

   }

   /**
    * After a transaction is removed
    *
    * @param xid
    * @param remotingConnection
    * @throws ActiveMQException
    */
   default void afterRemoveTransaction(Xid xid, RemotingConnection remotingConnection) throws ActiveMQException {

   }
}


<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/largemessages/InterruptedAMQPLargeMessage.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.tests.integration.amqp.largemessages;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;

import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.core.server.ActiveMQServer;
import org.apache.activemq.artemis.core.server.LargeServerMessage;
import org.apache.activemq.artemis.core.server.MessageReference;
import org.apache.activemq.artemis.core.server.Queue;
import org.apache.activemq.artemis.tests.integration.amqp.AmqpClientTestSupport;
import org.apache.activemq.artemis.utils.SpawnedVMSupport;
import org.apache.activemq.artemis.utils.collections.LinkedListIterator;
import org.apache.activemq.transport.amqp.client.AmqpClient;
import org.apache.activemq.transport.amqp.client.AmqpConnection;
import org.apache.activemq.transport.amqp.client.AmqpMessage;
import org.apache.activemq.transport.amqp.client.AmqpReceiver;
import org.apache.activemq.transport.amqp.client.AmqpSender;
import org.apache.activemq.transport.amqp.client.AmqpSession;
import org.apache.qpid.proton.amqp.messaging.Data;
import org.junit.Assert;
import org.junit.Test;

public class InterruptedAMQPLargeMessage extends AmqpClientTestSupport {

   private static final int NUMBER_OF_THREADS = 10;
   private static final int MINIMAL_SEND = 2;

   private static final int MESSAGE_SIZE = 1024 * 300;

   private static final String smallFrameAcceptor = new String("tcp://localhost:" + (AMQP_PORT + 8));

   @Override
   protected void addAdditionalAcceptors(ActiveMQServer server) throws Exception {
      server.getConfiguration().addAcceptorConfiguration("flow", smallFrameAcceptor + "?protocols=AMQP;useEpoll=false;maxFrameSize=" + 512 + ";amqpMinLargeMessageSize=" + 10000);
   }

   public static void main(String[] arg) {
      // have everybody aligned on sending before we start
      CyclicBarrier startFlag = new CyclicBarrier(NUMBER_OF_THREADS);

      CountDownLatch minimalKill = new CountDownLatch(MINIMAL_SEND * NUMBER_OF_THREADS);
      Runnable runnable = () -> {

         try {
            AmqpClient client = createLocalClient();
            AmqpConnection connection = client.createConnection();
            connection.setMaxFrameSize(2 * 1024);
            connection.connect();
            AmqpSession session = connection.createSession();

            AmqpSender sender = session.createSender(arg[0]);
            startFlag.await();
            for (int m = 0; m < 1000; m++) {
               AmqpMessage message = new AmqpMessage();
               message.setDurable(true);
               byte[] bytes = new byte[MESSAGE_SIZE];
               for (int i = 0; i < bytes.length; i++) {
                  bytes[i] = (byte) 'z';
               }

               message.setBytes(bytes);
               sender.send(message);
               minimalKill.countDown();
            }
            connection.close();
         } catch (Exception e) {
            e.printStackTrace();
         }
      };


      for (int t = 0; t < NUMBER_OF_THREADS; t++) {
         Thread thread = new Thread(runnable);
         thread.start();
      }

      try {
         minimalKill.await();
      } catch (Exception e) {
         e.printStackTrace();
      }
      System.exit(-1);
   }

   private static AmqpClient createLocalClient() throws URISyntaxException {
      return new AmqpClient(new URI(smallFrameAcceptor), null, null);
   }

   @Test
   public void testInterruptedLargeMessage() throws Exception {
      Process p = SpawnedVMSupport.spawnVM(InterruptedAMQPLargeMessage.class.getName(), getQueueName());
      p.waitFor();

      Queue serverQueue = server.locateQueue(getQueueName());

      Assert.assertTrue(serverQueue.getMessageCount() >= MINIMAL_SEND * NUMBER_OF_THREADS);

      LinkedListIterator<MessageReference> browserIterator = serverQueue.browserIterator();

      while (browserIterator.hasNext()) {
         MessageReference ref = browserIterator.next();
         Message message = ref.getMessage();

         Assert.assertNotNull(message);
         Assert.assertTrue(message instanceof LargeServerMessage);

         Assert.assertFalse(((LargeServerMessage)message).hasPendingRecord());
      }
      browserIterator.close();

      instanceLog.debug("There are " + serverQueue.getMessageCount() + " on the queue");
      int messageCount = (int)serverQueue.getMessageCount();

      AmqpClient client = createLocalClient();
      AmqpConnection connection = addConnection(client.createConnection());
      connection.setMaxFrameSize(2 * 1024);
      connection.connect();
      AmqpSession session = connection.createSession();
      AmqpReceiver receiver = session.createReceiver(getQueueName());

      int received = 0;
      receiver.flow((int) (messageCount + 10));
      for (int m = 0; m < messageCount; m++) {
         receiver.flow(1);
         AmqpMessage message = receiver.receive(10, TimeUnit.SECONDS);
         Assert.assertNotNull(message);
         message.accept(true);
         received++;

         instanceLog.debug("Received " + received);
         Data data = (Data)message.getWrappedMessage().getBody();
         byte[] byteArray = data.getValue().getArray();

         Assert.assertEquals(MESSAGE_SIZE, byteArray.length);
         for (int i = 0; i < byteArray.length; i++) {
            Assert.assertEquals((byte)'z', byteArray[i]);
         }
      }


      Assert.assertNull(receiver.receiveNoWait());

      validateNoFilesOnLargeDir();
   }

}


<|start_filename|>artemis-core-client/src/main/java/org/apache/activemq/artemis/core/config/federation/FederationQueuePolicyConfiguration.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.config.federation;

import java.io.Serializable;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;

import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.utils.Preconditions;

public class FederationQueuePolicyConfiguration implements FederationPolicy<FederationQueuePolicyConfiguration>, Serializable {

   private String name;
   private boolean includeFederated;
   private Set<Matcher> includes = new HashSet<>();
   private Set<Matcher> excludes = new HashSet<>();
   private Integer priorityAdjustment;
   private String transformerRef;

   @Override
   public String getName() {
      return name;
   }

   @Override
   public FederationQueuePolicyConfiguration setName(String name) {
      this.name = name;
      return this;
   }

   public Set<Matcher> getIncludes() {
      return includes;
   }

   public Set<Matcher> getExcludes() {
      return excludes;
   }

   public FederationQueuePolicyConfiguration addInclude(Matcher include) {
      includes.add(include);
      return this;
   }

   public FederationQueuePolicyConfiguration addExclude(Matcher exclude) {
      excludes.add(exclude);
      return this;
   }

   public boolean isIncludeFederated() {
      return includeFederated;
   }

   public FederationQueuePolicyConfiguration setIncludeFederated(boolean includeFederated) {
      this.includeFederated = includeFederated;
      return this;
   }

   public Integer getPriorityAdjustment() {
      return priorityAdjustment;
   }

   public FederationQueuePolicyConfiguration setPriorityAdjustment(Integer priorityAdjustment) {
      this.priorityAdjustment = priorityAdjustment;
      return this;
   }

   public String getTransformerRef() {
      return transformerRef;
   }

   public FederationQueuePolicyConfiguration setTransformerRef(String transformerRef) {
      this.transformerRef = transformerRef;
      return this;
   }

   @Override
   public void encode(ActiveMQBuffer buffer) {
      Preconditions.checkArgument(name != null, "name can not be null");
      buffer.writeString(name);
      buffer.writeBoolean(includeFederated);
      buffer.writeNullableInt(priorityAdjustment);
      buffer.writeNullableString(transformerRef);
      encodeMatchers(buffer, includes);
      encodeMatchers(buffer, excludes);
   }

   @Override
   public void decode(ActiveMQBuffer buffer) {
      name = buffer.readString();
      includeFederated = buffer.readBoolean();
      priorityAdjustment = buffer.readNullableInt();
      transformerRef = buffer.readNullableString();

      includes = new HashSet<>();
      excludes = new HashSet<>();
      decodeMatchers(buffer, includes);
      decodeMatchers(buffer, excludes);
   }

   private void encodeMatchers(final ActiveMQBuffer buffer, final Set<Matcher> matchers) {
      buffer.writeInt(matchers == null ? 0 : matchers.size());
      if (matchers != null) {
         for (Matcher matcher : matchers) {
            matcher.encode(buffer);
         }
      }
   }

   private void decodeMatchers(final ActiveMQBuffer buffer, final Set<Matcher> matchers) {
      final int size = buffer.readInt();

      for (int i = 0; i < size; i++) {
         Matcher matcher = new Matcher();
         matcher.decode(buffer);
         matchers.add(matcher);
      }
   }

   public static class Matcher implements Serializable {

      private String queueMatch;
      private String addressMatch;

      public String getQueueMatch() {
         return queueMatch;
      }

      public Matcher setQueueMatch(String queueMatch) {
         this.queueMatch = queueMatch;
         return this;
      }

      public String getAddressMatch() {
         return addressMatch;
      }

      public Matcher setAddressMatch(String addressMatch) {
         this.addressMatch = addressMatch;
         return this;
      }

      @Override
      public boolean equals(Object o) {
         if (this == o) return true;
         if (!(o instanceof Matcher)) return false;
         Matcher matcher = (Matcher) o;
         return Objects.equals(queueMatch, matcher.queueMatch) &&
               Objects.equals(addressMatch, matcher.addressMatch);
      }

      @Override
      public int hashCode() {
         return Objects.hash(queueMatch, addressMatch);
      }

      public void encode(ActiveMQBuffer buffer) {
         buffer.writeNullableString(addressMatch);
         buffer.writeNullableString(queueMatch);
      }

      public void decode(ActiveMQBuffer buffer) {
         addressMatch = buffer.readNullableString();
         queueMatch = buffer.readNullableString();
      }
   }

   @Override
   public boolean equals(Object o) {
      if (this == o) return true;
      if (!(o instanceof FederationQueuePolicyConfiguration)) return false;
      FederationQueuePolicyConfiguration that = (FederationQueuePolicyConfiguration) o;
      return includeFederated == that.includeFederated &&
            Objects.equals(name, that.name) &&
            Objects.equals(includes, that.includes) &&
            Objects.equals(excludes, that.excludes) &&
            Objects.equals(priorityAdjustment, that.priorityAdjustment) &&
            Objects.equals(transformerRef, that.transformerRef);
   }

   @Override
   public int hashCode() {
      return Objects.hash(name, includeFederated, includes, excludes, priorityAdjustment, transformerRef);
   }
}


<|start_filename|>artemis-journal/src/test/java/org/apache/activemq/artemis/core/journal/impl/VerifyUpdateFactorSystemProperty.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.core.journal.impl;

import org.apache.activemq.artemis.utils.SpawnedVMSupport;
import org.junit.Assert;
import org.junit.Test;

public class VerifyUpdateFactorSystemProperty {

   public static void main(String[] arg) {

      try {
         Assert.assertEquals(33.0, JournalImpl.UPDATE_FACTOR, 0);
         System.exit(0);
      } catch (Throwable e) {
         e.printStackTrace();
         System.exit(100);
      }
   }

   @Test
   public void testValidateUpdateRecordProperty() throws Exception {
      Process process = SpawnedVMSupport.spawnVM(VerifyUpdateFactorSystemProperty.class.getName(), new String[]{"-D" + JournalImpl.class.getName() + ".UPDATE_FACTOR=33.0"}, new String[]{});
      Assert.assertEquals(0, process.waitFor());
   }

}


<|start_filename|>tests/extra-tests/src/test/java/org/apache/activemq/artemis/tests/extras/byteman/critical/analyzer/CriticalAnalyzerFaultInjectionTestBase.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.extras.byteman.critical.analyzer;

import javax.jms.DeliveryMode;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;

import org.apache.activemq.artemis.api.core.QueueConfiguration;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.core.config.Configuration;
import org.apache.activemq.artemis.core.server.JournalType;
import org.apache.activemq.artemis.core.server.impl.AddressInfo;
import org.apache.activemq.artemis.tests.util.JMSTestBase;
import org.apache.activemq.artemis.tests.util.Wait;
import org.apache.activemq.artemis.utils.critical.CriticalAnalyzerPolicy;
import org.junit.Before;

public abstract class CriticalAnalyzerFaultInjectionTestBase extends JMSTestBase {

   // Critical Analyzer Settings
   private static long CHECK_PERIOD = 100;
   private static long TIMEOUT = 3000;

   protected SimpleString address = SimpleString.toSimpleString("faultInjectionTestAddress");

   private Thread t;

   @Override
   @Before
   public void setUp() throws Exception {
      super.setUp();
      server.addAddressInfo(new AddressInfo(address, RoutingType.ANYCAST));
      server.createQueue(new QueueConfiguration(address).setRoutingType(RoutingType.ANYCAST));
      conn = nettyCf.createConnection();
   }

   /*
   Checks every 100ms timesout after 3000ms.  Test should wait no longer than 3100s + Shutdown time.
    */
   @Override
   protected Configuration createDefaultConfig(boolean netty) throws Exception {
      return super.createDefaultConfig(netty).setCriticalAnalyzerPolicy(CriticalAnalyzerPolicy.SHUTDOWN).setCriticalAnalyzer(true).setCriticalAnalyzerCheckPeriod(CHECK_PERIOD).setCriticalAnalyzerTimeout(TIMEOUT).setJournalType(JournalType.NIO);
   }

   @Override
   public boolean usePersistence() {
      return true;
   }

   void testSendDurableMessage() throws Exception {
      try {
         t = new Thread(() -> {
            try {
               Session s = conn.createSession(true, Session.SESSION_TRANSACTED);

               Queue jmsQueue = s.createQueue(address.toString());
               MessageProducer p = s.createProducer(jmsQueue);
               p.setDeliveryMode(DeliveryMode.PERSISTENT);
               conn.start();
               for (int i = 0; i < 10; i++) {
                  p.send(s.createTextMessage("payload"));
               }
               s.commit();
            } catch (Throwable e) {
               e.printStackTrace();
            }
         });
         t.start();

         Wait.assertFalse(server::isStarted);
      } finally {
         t.interrupt();
      }
   }
}


<|start_filename|>artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ServerLocatorConfig.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.api.config;

import org.apache.activemq.artemis.api.core.client.ActiveMQClient;

public class ServerLocatorConfig {
   public long clientFailureCheckPeriod = ActiveMQClient.DEFAULT_CLIENT_FAILURE_CHECK_PERIOD;
   public long connectionTTL = ActiveMQClient.DEFAULT_CONNECTION_TTL;
   public long callTimeout = ActiveMQClient.DEFAULT_CALL_TIMEOUT;
   public long callFailoverTimeout = ActiveMQClient.DEFAULT_CALL_FAILOVER_TIMEOUT;
   public int minLargeMessageSize = ActiveMQClient.DEFAULT_MIN_LARGE_MESSAGE_SIZE;
   public int consumerWindowSize = ActiveMQClient.DEFAULT_CONSUMER_WINDOW_SIZE;
   public int consumerMaxRate = ActiveMQClient.DEFAULT_CONSUMER_MAX_RATE;
   public int confirmationWindowSize = ActiveMQClient.DEFAULT_CONFIRMATION_WINDOW_SIZE;
   public int producerWindowSize = ActiveMQClient.DEFAULT_PRODUCER_WINDOW_SIZE;
   public int producerMaxRate = ActiveMQClient.DEFAULT_PRODUCER_MAX_RATE;
   public boolean blockOnAcknowledge = ActiveMQClient.DEFAULT_BLOCK_ON_ACKNOWLEDGE;
   public boolean blockOnDurableSend = ActiveMQClient.DEFAULT_BLOCK_ON_DURABLE_SEND;
   public boolean blockOnNonDurableSend = ActiveMQClient.DEFAULT_BLOCK_ON_NON_DURABLE_SEND;
   public boolean autoGroup = ActiveMQClient.DEFAULT_AUTO_GROUP;
   public boolean preAcknowledge = ActiveMQClient.DEFAULT_PRE_ACKNOWLEDGE;
   public int ackBatchSize = ActiveMQClient.DEFAULT_ACK_BATCH_SIZE;
   public String connectionLoadBalancingPolicyClassName = ActiveMQClient.DEFAULT_CONNECTION_LOAD_BALANCING_POLICY_CLASS_NAME;
   public boolean useGlobalPools = ActiveMQClient.DEFAULT_USE_GLOBAL_POOLS;
   public int threadPoolMaxSize = ActiveMQClient.DEFAULT_THREAD_POOL_MAX_SIZE;
   public int scheduledThreadPoolMaxSize = ActiveMQClient.DEFAULT_SCHEDULED_THREAD_POOL_MAX_SIZE;
   public long retryInterval = ActiveMQClient.DEFAULT_RETRY_INTERVAL;
   public double retryIntervalMultiplier = ActiveMQClient.DEFAULT_RETRY_INTERVAL_MULTIPLIER;
   public long maxRetryInterval = ActiveMQClient.DEFAULT_MAX_RETRY_INTERVAL;
   public int reconnectAttempts = ActiveMQClient.DEFAULT_RECONNECT_ATTEMPTS;
   public int initialConnectAttempts = ActiveMQClient.INITIAL_CONNECT_ATTEMPTS;
   public int initialMessagePacketSize = ActiveMQClient.DEFAULT_INITIAL_MESSAGE_PACKET_SIZE;
   public boolean cacheLargeMessagesClient = ActiveMQClient.DEFAULT_CACHE_LARGE_MESSAGE_CLIENT;
   public boolean compressLargeMessage = ActiveMQClient.DEFAULT_COMPRESS_LARGE_MESSAGES;
   public boolean useTopologyForLoadBalancing = ActiveMQClient.DEFAULT_USE_TOPOLOGY_FOR_LOADBALANCING;

   public ServerLocatorConfig() {
   }

   public ServerLocatorConfig(final ServerLocatorConfig locator) {
      compressLargeMessage = locator.compressLargeMessage;
      cacheLargeMessagesClient = locator.cacheLargeMessagesClient;
      clientFailureCheckPeriod = locator.clientFailureCheckPeriod;
      connectionTTL = locator.connectionTTL;
      callTimeout = locator.callTimeout;
      callFailoverTimeout = locator.callFailoverTimeout;
      minLargeMessageSize = locator.minLargeMessageSize;
      consumerWindowSize = locator.consumerWindowSize;
      consumerMaxRate = locator.consumerMaxRate;
      confirmationWindowSize = locator.confirmationWindowSize;
      producerWindowSize = locator.producerWindowSize;
      producerMaxRate = locator.producerMaxRate;
      blockOnAcknowledge = locator.blockOnAcknowledge;
      blockOnDurableSend = locator.blockOnDurableSend;
      blockOnNonDurableSend = locator.blockOnNonDurableSend;
      autoGroup = locator.autoGroup;
      preAcknowledge = locator.preAcknowledge;
      connectionLoadBalancingPolicyClassName = locator.connectionLoadBalancingPolicyClassName;
      ackBatchSize = locator.ackBatchSize;
      useGlobalPools = locator.useGlobalPools;
      scheduledThreadPoolMaxSize = locator.scheduledThreadPoolMaxSize;
      threadPoolMaxSize = locator.threadPoolMaxSize;
      retryInterval = locator.retryInterval;
      retryIntervalMultiplier = locator.retryIntervalMultiplier;
      maxRetryInterval = locator.maxRetryInterval;
      reconnectAttempts = locator.reconnectAttempts;
      initialConnectAttempts = locator.initialConnectAttempts;
      initialMessagePacketSize = locator.initialMessagePacketSize;
      useTopologyForLoadBalancing = locator.useTopologyForLoadBalancing;
   }
}


<|start_filename|>artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/sasl/scram/SCRAMServerSASL.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.protocol.amqp.sasl.scram;

import java.nio.charset.StandardCharsets;
import java.security.GeneralSecurityException;
import java.security.NoSuchAlgorithmException;
import java.util.Collections;
import java.util.UUID;

import javax.security.auth.Subject;
import javax.security.auth.login.LoginException;

import org.apache.activemq.artemis.protocol.amqp.sasl.SASLResult;
import org.apache.activemq.artemis.protocol.amqp.sasl.ServerSASL;
import org.apache.activemq.artemis.spi.core.security.jaas.UserPrincipal;
import org.apache.activemq.artemis.spi.core.security.scram.SCRAM;
import org.apache.activemq.artemis.spi.core.security.scram.ScramException;
import org.apache.activemq.artemis.spi.core.security.scram.UserData;

public abstract class SCRAMServerSASL implements ServerSASL {

   protected final ScramServerFunctionality scram;
   protected final SCRAM mechanism;
   private SASLResult result;

   public SCRAMServerSASL(SCRAM mechanism) throws NoSuchAlgorithmException {
      this(mechanism, UUID.randomUUID().toString());
   }

   protected SCRAMServerSASL(SCRAM mechanism, String nonce) throws NoSuchAlgorithmException {
      this.mechanism = mechanism;
      this.scram = new ScramServerFunctionalityImpl(mechanism.getDigest(), mechanism.getHmac(), nonce);
   }

   @Override
   public String getName() {
      return mechanism.getName();
   }

   @Override
   public byte[] processSASL(byte[] bytes) {
      String message = new String(bytes, StandardCharsets.US_ASCII);
      try {
         switch (scram.getState()) {
            case INITIAL: {
               String userName = scram.handleClientFirstMessage(message);
               UserData userData = aquireUserData(userName);
               result = new SCRAMSASLResult(userName, scram, createSaslSubject(userName, userData));
               String challenge = scram.prepareFirstMessage(userData);
               return challenge.getBytes(StandardCharsets.US_ASCII);
            }
            case PREPARED_FIRST: {
               String finalMessage = scram.prepareFinalMessage(message);
               return finalMessage.getBytes(StandardCharsets.US_ASCII);
            }
            default:
               result = new SCRAMFailedSASLResult();
               break;
         }
      } catch (GeneralSecurityException | ScramException | RuntimeException e) {
         result = new SCRAMFailedSASLResult();
         failed(e);
      }
      return null;
   }

   protected abstract UserData aquireUserData(String userName) throws LoginException;

   protected abstract void failed(Exception e);

   protected Subject createSaslSubject(String userName, UserData userData) {
      UserPrincipal userPrincipal = new UserPrincipal(userName);
      Subject saslSubject = new Subject(true, Collections.singleton(userPrincipal), Collections.singleton(userData),
                                        Collections.emptySet());
      return saslSubject;
   }

   @Override
   public SASLResult result() {
      if (result instanceof SCRAMSASLResult) {
         return scram.isEnded() ? result : null;
      }
      return result;
   }

   public boolean isEnded() {
      return scram.isEnded();
   }

   private static final class SCRAMSASLResult implements SASLResult {

      private final String userName;
      private final ScramServerFunctionality scram;
      private final Subject subject;

      SCRAMSASLResult(String userName, ScramServerFunctionality scram, Subject subject) {
         this.userName = userName;
         this.scram = scram;
         this.subject = subject;
      }

      @Override
      public String getUser() {
         return userName;
      }

      @Override
      public Subject getSubject() {
         return subject;
      }

      @Override
      public boolean isSuccess() {
         return userName != null && scram.isEnded() && scram.isSuccessful();
      }

      @Override
      public String toString() {
         return "SCRAMSASLResult: userName = " + userName + ", state = " + scram.getState();
      }

   }

   private static final class SCRAMFailedSASLResult implements SASLResult {

      @Override
      public String getUser() {
         return null;
      }

      @Override
      public Subject getSubject() {
         return null;
      }

      @Override
      public boolean isSuccess() {
         return false;
      }

      @Override
      public String toString() {
         return "SCRAMFailedSASLResult";
      }

   }

}

<|start_filename|>tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/amqp/AmqpReceiverPriorityTest.java<|end_filename|>
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.activemq.artemis.tests.integration.amqp;

import org.apache.activemq.transport.amqp.client.AmqpClient;
import org.apache.activemq.transport.amqp.client.AmqpConnection;
import org.apache.activemq.transport.amqp.client.AmqpMessage;
import org.apache.activemq.transport.amqp.client.AmqpReceiver;
import org.apache.activemq.transport.amqp.client.AmqpSession;
import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.UnsignedInteger;
import org.junit.Test;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * Test various behaviors of AMQP receivers with the broker.
 */
public class AmqpReceiverPriorityTest extends AmqpClientTestSupport {

   @Test(timeout = 30000)
   public void testPriority() throws Exception {

      AmqpClient client = createAmqpClient();
      AmqpConnection connection = addConnection(client.connect());
      AmqpSession session = connection.createSession();

      Map<Symbol, Object> properties1 = new HashMap<>();
      properties1.put(Symbol.getSymbol("priority"), 5);
      AmqpReceiver receiver1 = session.createReceiver(getQueueName(), null, false, false, properties1);
      receiver1.flow(100);

      Map<Symbol, Object> properties2 = new HashMap<>();
      properties2.put(Symbol.getSymbol("priority"), 50);
      AmqpReceiver receiver2 = session.createReceiver(getQueueName(), null, false, false, properties2);
      receiver2.flow(100);

      Map<Symbol, Object> properties3 = new HashMap<>();
      properties3.put(Symbol.getSymbol("priority"), 10);
      AmqpReceiver receiver3 = session.createReceiver(getQueueName(), null, false, false, properties3);
      receiver3.flow(100);

      sendMessages(getQueueName(), 5);


      for (int i = 0; i < 5; i++) {
         AmqpMessage message1 = receiver1.receiveNoWait();
         AmqpMessage message2 = receiver2.receive(250, TimeUnit.MILLISECONDS);
         AmqpMessage message3 = receiver3.receiveNoWait();
         assertNotNull("did not receive message first time", message2);
         assertEquals("MessageID:" + i, message2.getMessageId());
         message2.accept();
         assertNull("message is not meant to goto lower priority receiver", message1);
         assertNull("message is not meant to goto lower priority receiver", message3);
      }
      assertNoMessage(receiver1);
      assertNoMessage(receiver3);

      //Close the high priority receiver
      receiver2.close();

      sendMessages(getQueueName(), 5);

      //Check messages now goto next priority receiver
      for (int i = 0; i < 5; i++) {
         AmqpMessage message1 = receiver1.receiveNoWait();
         AmqpMessage message3 = receiver3.receive(250, TimeUnit.MILLISECONDS);
         assertNotNull("did not receive message first time", message3);
         assertEquals("MessageID:" + i, message3.getMessageId());
         message3.accept();
         assertNull("message is not meant to goto lower priority receiver", message1);
      }
      assertNoMessage(receiver1);


      connection.close();
   }

   public void assertNoMessage(AmqpReceiver receiver) throws Exception {
      //A check to make sure no messages
      AmqpMessage message = receiver.receive(250, TimeUnit.MILLISECONDS);
      assertNull("message is not meant to goto lower priority receiver", message);
   }

   @Test(timeout = 30000)
   public void testPriorityProvidedAsByte() throws Exception {
      testPriorityNumber((byte) 5);
   }

   @Test(timeout = 30000)
   public void testPriorityProvidedAsUnsignedInteger() throws Exception {
      testPriorityNumber(UnsignedInteger.valueOf(5));
   }


   private void testPriorityNumber(Number number) throws Exception {

      AmqpClient client = createAmqpClient();
      AmqpConnection connection = addConnection(client.connect());
      AmqpSession session = connection.createSession();

      Map<Symbol, Object> properties1 = new HashMap<>();
      properties1.put(Symbol.getSymbol("priority"), number);
      AmqpReceiver receiver1 = session.createReceiver(getQueueName(), null, false, false, properties1);
      receiver1.flow(100);

      sendMessages(getQueueName(), 2);


      for (int i = 0; i < 2; i++) {
         AmqpMessage message1 = receiver1.receive(3000, TimeUnit.MILLISECONDS);
         assertNotNull("did not receive message" + i, message1);
         assertEquals("MessageID:" + i, message1.getMessageId());
         message1.accept();
      }
      connection.close();
   }
}


<|start_filename|>artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPMessagePersisterV3.java<|end_filename|>
/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements. See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.activemq.artemis.protocol.amqp.broker;

import org.apache.activemq.artemis.api.core.ActiveMQBuffer;
import org.apache.activemq.artemis.api.core.Message;
import org.apache.activemq.artemis.core.persistence.CoreMessageObjectPools;
import org.apache.activemq.artemis.utils.DataConstants;

import static org.apache.activemq.artemis.core.persistence.PersisterIDs.AMQPMessagePersisterV3_ID;

public class AMQPMessagePersisterV3 extends AMQPMessagePersisterV2 {

   public static final byte ID = AMQPMessagePersisterV3_ID;

   public static AMQPMessagePersisterV3 theInstance;

   public static AMQPMessagePersisterV3 getInstance() {
      if (theInstance == null) {
         theInstance = new AMQPMessagePersisterV3();
      }
      return theInstance;
   }

   @Override
   public byte getID() {
      return ID;
   }

   public AMQPMessagePersisterV3() {
      super();
   }


   @Override
   public int getEncodeSize(Message record) {
      int encodeSize = super.getEncodeSize(record) +
         DataConstants.SIZE_LONG; // expiration
      return encodeSize;
   }


   /** Sub classes must add the first short as the protocol-id */
   @Override
   public void encode(ActiveMQBuffer buffer, Message record) {
      super.encode(buffer, record);

      buffer.writeLong(record.getExpiration());
   }

   @Override
   public Message decode(ActiveMQBuffer buffer, Message ignore, CoreMessageObjectPools pool) {
      Message record = super.decode(buffer, ignore, pool);

      assert record != null && AMQPStandardMessage.class.equals(record.getClass());

      ((AMQPStandardMessage)record).reloadExpiration(buffer.readLong());

      return record;
   }

}
