/* * 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.qpid.jms.provider.mock; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.Message; import org.apache.qpid.jms.message.JmsOutboundMessageDispatch; import org.apache.qpid.jms.meta.JmsResource; /** * Context shared between all MockProvider instances. */ public class MockRemotePeer { public static MockRemotePeer INSTANCE; private final Map<String, MockProvider> activeProviders = new ConcurrentHashMap<String, MockProvider>(); private final MockProviderStats contextStats = new MockProviderStats(); private MockProvider lastRegistered; private JmsOutboundMessageDispatch lastRecordedMessage; private boolean offline; private ResourceLifecycleFilter createFilter; private ResourceLifecycleFilter startFilter; private ResourceLifecycleFilter stopFilter; private ResourceLifecycleFilter destroyFilter; private final Map<Destination, List<PendingCompletion>> pendingCompletions = new ConcurrentHashMap<Destination, List<PendingCompletion>>(); public void connect(MockProvider provider) throws IOException { if (offline) { throw new IOException(); } if (provider != null) { activeProviders.put(provider.getProviderId(), provider); lastRegistered = provider; } } public void disconnect(MockProvider provider) { if (provider != null) { activeProviders.remove(provider.getProviderId()); } } public void createResource(JmsResource resource) throws Exception { if (createFilter != null) { createFilter.onLifecycleEvent(resource); } } public void startResource(JmsResource resource) throws Exception { if (startFilter != null) { startFilter.onLifecycleEvent(resource); } } public void stopResource(JmsResource resource) throws Exception { if (stopFilter != null) { stopFilter.onLifecycleEvent(resource); } } public void destroyResource(JmsResource resource) throws Exception { if (destroyFilter != null) { destroyFilter.onLifecycleEvent(resource); } } public void start() { contextStats.reset(); activeProviders.clear(); lastRegistered = null; offline = false; MockRemotePeer.INSTANCE = this; } public void terminate() { shutdown(); MockRemotePeer.INSTANCE = null; } public void shutdown() { offline = true; List<MockProvider> active = new ArrayList<MockProvider>(activeProviders.values()); for (MockProvider provider : active) { provider.signalConnectionFailed(); } activeProviders.clear(); lastRegistered = null; } public void shutdownQuietly() { offline = true; activeProviders.clear(); lastRegistered = null; } public void silentlyCloseConnectedProviders() { List<MockProvider> active = new ArrayList<MockProvider>(activeProviders.values()); for (MockProvider provider : active) { provider.silentlyClose(); } } public MockProvider getProvider(String providerId) { return activeProviders.get(providerId); } public MockProvider getLastRegistered() { return lastRegistered; } public MockProviderStats getContextStats() { return contextStats; } public void setResourceCreateFilter(ResourceLifecycleFilter filter) { createFilter = filter; } public void setResourceStartFilter(ResourceLifecycleFilter filter) { startFilter = filter; } public void setResourceStopFilter(ResourceLifecycleFilter filter) { stopFilter = filter; } public void setResourceDestroyFilter(ResourceLifecycleFilter filter) { destroyFilter = filter; } public JmsOutboundMessageDispatch getLastReceivedMessage() { return lastRecordedMessage; } //----- Record operations for connected providers ------------------------// public void recordSend(MockProvider provider, JmsOutboundMessageDispatch envelope) { this.lastRecordedMessage = envelope; } //----- Controls handling of Message Send Completions --------------------// public void recordPendingCompletion(MockProvider provider, JmsOutboundMessageDispatch envelope) { Destination destination = envelope.getDestination(); if (!pendingCompletions.containsKey(destination)) { pendingCompletions.put(destination, new ArrayList<PendingCompletion>()); } pendingCompletions.get(destination).add(new PendingCompletion(provider, envelope)); } public void completeAllPendingSends(Destination destination) { if (pendingCompletions.containsKey(destination)) { for (List<PendingCompletion> pendingSends : pendingCompletions.values()) { for (PendingCompletion pending : pendingSends) { pending.provider.getProviderListener().onCompletedMessageSend(pending.envelope); } } pendingCompletions.remove(destination); } } public void failAllPendingSends(Destination destination, Exception error) { if (pendingCompletions.containsKey(destination)) { for (List<PendingCompletion> pendingSends : pendingCompletions.values()) { for (PendingCompletion pending : pendingSends) { pending.provider.getProviderListener().onFailedMessageSend(pending.envelope, error); } } pendingCompletions.remove(destination); } } public void completePendingSend(Message message) throws JMSException { List<PendingCompletion> pendingSends = pendingCompletions.get(message.getJMSDestination()); Iterator<PendingCompletion> iterator = pendingSends.iterator(); while (iterator.hasNext()) { PendingCompletion pending = iterator.next(); if (pending.envelope.getMessage().getJMSMessageID().equals(message.getJMSMessageID())) { pending.provider.getProviderListener().onCompletedMessageSend(pending.envelope); iterator.remove(); } } } public void completePendingSend(JmsOutboundMessageDispatch envelope) throws JMSException { List<PendingCompletion> pendingSends = pendingCompletions.get(envelope.getDestination()); Iterator<PendingCompletion> iterator = pendingSends.iterator(); while (iterator.hasNext()) { PendingCompletion pending = iterator.next(); if (pending.envelope.getMessage().getJMSMessageID().equals(envelope.getMessage().getJMSMessageID())) { pending.provider.getProviderListener().onCompletedMessageSend(pending.envelope); iterator.remove(); } } } public void failPendingSend(Message message, Exception error) throws JMSException { List<PendingCompletion> pendingSends = pendingCompletions.get(message.getJMSDestination()); Iterator<PendingCompletion> iterator = pendingSends.iterator(); while (iterator.hasNext()) { PendingCompletion pending = iterator.next(); if (pending.envelope.getMessage().getJMSMessageID().equals(message.getJMSMessageID())) { pending.provider.getProviderListener().onFailedMessageSend(pending.envelope, error); iterator.remove(); } } } public void failPendingSend(JmsOutboundMessageDispatch envelope, Exception error) throws JMSException { List<PendingCompletion> pendingSends = pendingCompletions.get(envelope.getDestination()); Iterator<PendingCompletion> iterator = pendingSends.iterator(); while (iterator.hasNext()) { PendingCompletion pending = iterator.next(); if (pending.envelope.getMessage().getJMSMessageID().equals(envelope.getMessage().getJMSMessageID())) { pending.provider.getProviderListener().onFailedMessageSend(pending.envelope, error); iterator.remove(); } } } public List<JmsOutboundMessageDispatch> getPendingCompletions(Destination destination) { List<JmsOutboundMessageDispatch> result = null; if (pendingCompletions.containsKey(destination)) { result = new ArrayList<JmsOutboundMessageDispatch>(); List<PendingCompletion> pendingMessages = pendingCompletions.get(destination); for (PendingCompletion pending : pendingMessages) { result.add(pending.envelope); } } else { result = Collections.emptyList(); } return result; } //----- Internal classes used for record state information ---------------// private class PendingCompletion { public final MockProvider provider; public final JmsOutboundMessageDispatch envelope; public PendingCompletion(MockProvider provider, JmsOutboundMessageDispatch envelope) { this.provider = provider; this.envelope = envelope; } } }