/** * */ package org.apache.activemq.artemis.tests.integration.plugin; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import java.util.concurrent.atomic.AtomicInteger; import com.google.common.base.Preconditions; 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.BridgeConfiguration; import org.apache.activemq.artemis.core.persistence.OperationContext; 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.QueueConfig; 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.tests.util.Wait; /** * 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. */ public class MethodCalledVerifier implements ActiveMQServerPlugin { private final Map<String, AtomicInteger> methodCalls; public static final String AFTER_CREATE_CONNECTION = "afterCreateConnection"; public static final String AFTER_DESTROY_CONNECTION = "afterDestroyConnection"; public static final String BEFORE_CREATE_SESSION = "beforeCreateSession"; public static final String AFTER_CREATE_SESSION = "afterCreateSession"; public static final String BEFORE_CLOSE_SESSION = "beforeCloseSession"; public static final String AFTER_CLOSE_SESSION = "afterCloseSession"; public static final String BEFORE_SESSION_METADATA_ADDED = "beforeSessionMetadataAdded"; public static final String AFTER_SESSION_METADATA_ADDED = "afterSessionMetadataAdded"; public static final String BEFORE_CREATE_CONSUMER = "beforeCreateConsumer"; public static final String AFTER_CREATE_CONSUMER = "afterCreateConsumer"; public static final String BEFORE_CLOSE_CONSUMER = "beforeCloseConsumer"; public static final String AFTER_CLOSE_CONSUMER = "afterCloseConsumer"; public static final String BEFORE_CREATE_QUEUE = "beforeCreateQueue"; public static final String AFTER_CREATE_QUEUE = "afterCreateQueue"; public static final String BEFORE_DESTROY_QUEUE = "beforeDestroyQueue"; public static final String AFTER_DESTROY_QUEUE = "afterDestroyQueue"; public static final String MESSAGE_EXPIRED = "messageExpired"; public static final String MESSAGE_ACKED = "messageAcknowledged"; public static final String BEFORE_SEND = "beforeSend"; public static final String AFTER_SEND = "afterSend"; public static final String BEFORE_MESSAGE_ROUTE = "beforeMessageRoute"; public static final String AFTER_MESSAGE_ROUTE = "afterMessageRoute"; public static final String BEFORE_DELIVER = "beforeDeliver"; public static final String AFTER_DELIVER = "afterDeliver"; public static final String BEFORE_DEPLOY_BRIDGE = "beforeDeployBridge"; public static final String AFTER_DEPLOY_BRIDGE = "afterDeployBridge"; /** * @param methods */ public MethodCalledVerifier(Map<String, AtomicInteger> methodCalls) { super(); this.methodCalls = methodCalls; } public MethodCalledVerifier() { this(new HashMap<String, AtomicInteger>()); } @Override public void afterCreateConnection(RemotingConnection connection) { Preconditions.checkNotNull(connection); methodCalled(AFTER_CREATE_CONNECTION); } @Override public void afterDestroyConnection(RemotingConnection connection) { Preconditions.checkNotNull(connection); methodCalled(AFTER_DESTROY_CONNECTION); } @Override public void beforeCreateSession(String name, String username, int minLargeMessageSize, RemotingConnection connection, boolean autoCommitSends, boolean autoCommitAcks, boolean preAcknowledge, boolean xa, String defaultAddress, SessionCallback callback, boolean autoCreateQueues, OperationContext context, Map<SimpleString, RoutingType> prefixes) { Preconditions.checkNotNull(connection); methodCalled(BEFORE_CREATE_SESSION); } @Override public void afterCreateSession(ServerSession session) { Preconditions.checkNotNull(session); methodCalled(AFTER_CREATE_SESSION); } @Override public void beforeCloseSession(ServerSession session, boolean failed) { Preconditions.checkNotNull(session); methodCalled(BEFORE_CLOSE_SESSION); } @Override public void afterCloseSession(ServerSession session, boolean failed) { Preconditions.checkNotNull(session); methodCalled(AFTER_CLOSE_SESSION); } @Override public void beforeSessionMetadataAdded(ServerSession session, String key, String data) { Preconditions.checkNotNull(key); methodCalled(BEFORE_SESSION_METADATA_ADDED); } @Override public void afterSessionMetadataAdded(ServerSession session, String key, String data) { Preconditions.checkNotNull(key); methodCalled(AFTER_SESSION_METADATA_ADDED); } @Override public void beforeCreateConsumer(long consumerID, SimpleString queueName, SimpleString filterString, boolean browseOnly, boolean supportLargeMessage) { Preconditions.checkNotNull(queueName); methodCalled(BEFORE_CREATE_CONSUMER); } @Override public void afterCreateConsumer(ServerConsumer consumer) { Preconditions.checkNotNull(consumer); methodCalled(AFTER_CREATE_CONSUMER); } @Override public void beforeCloseConsumer(ServerConsumer consumer, boolean failed) { Preconditions.checkNotNull(consumer); methodCalled(BEFORE_CLOSE_CONSUMER); } @Override public void afterCloseConsumer(ServerConsumer consumer, boolean failed) { Preconditions.checkNotNull(consumer); methodCalled(AFTER_CLOSE_CONSUMER); } @Override public void beforeCreateQueue(QueueConfig queueConfig) { Preconditions.checkNotNull(queueConfig); methodCalled(BEFORE_CREATE_QUEUE); } @Override public void afterCreateQueue(org.apache.activemq.artemis.core.server.Queue queue) { Preconditions.checkNotNull(queue); methodCalled(AFTER_CREATE_QUEUE); } @Override public void beforeDestroyQueue(SimpleString queueName, SecurityAuth session, boolean checkConsumerCount, boolean removeConsumers, boolean autoDeleteAddress) { Preconditions.checkNotNull(queueName); methodCalled(BEFORE_DESTROY_QUEUE); } @Override public void afterDestroyQueue(Queue queue, SimpleString address, SecurityAuth session, boolean checkConsumerCount, boolean removeConsumers, boolean autoDeleteAddress) { Preconditions.checkNotNull(queue); methodCalled(AFTER_DESTROY_QUEUE); } @Override public void messageExpired(MessageReference message, SimpleString messageExpiryAddress) { Preconditions.checkNotNull(message); methodCalled(MESSAGE_EXPIRED); } @Override public void messageAcknowledged(MessageReference ref, AckReason reason) { Preconditions.checkNotNull(ref); Preconditions.checkNotNull(reason); methodCalled(MESSAGE_ACKED); } @Override public void beforeSend(Transaction tx, Message message, boolean direct, boolean noAutoCreateQueue) { Preconditions.checkNotNull(message); methodCalled(BEFORE_SEND); } @Override public void afterSend(Transaction tx, Message message, boolean direct, boolean noAutoCreateQueue, RoutingStatus result) { Preconditions.checkNotNull(message); Preconditions.checkNotNull(result); methodCalled(AFTER_SEND); } @Override public void beforeMessageRoute(Message message, RoutingContext context, boolean direct, boolean rejectDuplicates) { Preconditions.checkNotNull(message); Preconditions.checkNotNull(context); methodCalled(BEFORE_MESSAGE_ROUTE); } @Override public void afterMessageRoute(Message message, RoutingContext context, boolean direct, boolean rejectDuplicates, RoutingStatus result) { Preconditions.checkNotNull(message); Preconditions.checkNotNull(context); Preconditions.checkNotNull(result); methodCalled(AFTER_MESSAGE_ROUTE); } @Override public void beforeDeliver(MessageReference reference) { Preconditions.checkNotNull(reference); methodCalled(BEFORE_DELIVER); } @Override public void afterDeliver(MessageReference reference) { Preconditions.checkNotNull(reference); methodCalled(AFTER_DELIVER); } @Override public void beforeDeployBridge(BridgeConfiguration config) { Preconditions.checkNotNull(config); methodCalled(BEFORE_DEPLOY_BRIDGE); } @Override public void afterDeployBridge(Bridge bridge) { Preconditions.checkNotNull(bridge); methodCalled(AFTER_DEPLOY_BRIDGE); } public void validatePluginMethodsEquals(int count, String... names) { Arrays.asList(names).forEach(name -> { assertEquals("validating method " + name, count, methodCalls.getOrDefault(name, new AtomicInteger()).get()); }); } public void validatePluginMethodsAtLeast(int count, String... names) { Arrays.asList(names).forEach(name -> { try { Wait.waitFor(() -> count <= methodCalls.getOrDefault(name, new AtomicInteger()).get()); } catch (Exception e) { e.printStackTrace(); } assertTrue("validating method " + name, count <= methodCalls.getOrDefault(name, new AtomicInteger()).get()); }); } private void methodCalled(String name) { methodCalls.computeIfAbsent(name, k -> new AtomicInteger()).incrementAndGet(); } }