/*
* 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;
}
}
}