summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Greig <rgreig@apache.org>2006-12-21 21:08:38 +0000
committerRobert Greig <rgreig@apache.org>2006-12-21 21:08:38 +0000
commit7cedc91fe5ec9859d932e63dc1f7c809860126d0 (patch)
tree9b368e30db8554c7d7da1fbbcae4a1dec2fdf3ed
parentc3343495a4b4da8d894d5ac89c2e8856b413ecdf (diff)
downloadqpid-python-7cedc91fe5ec9859d932e63dc1f7c809860126d0.tar.gz
Merge from trunk up to revision 487903
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/branches/new_persistence@489461 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/DestNameExchange.java34
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/DestWildExchange.java45
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java30
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java27
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/Index.java11
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeBoundHandler.java163
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AMQMinaProtocolSession.java251
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java241
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java453
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java366
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/ManagedQueue.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java5
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQDestination.java15
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQSession.java309
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQTemporaryQueue.java30
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQTemporaryTopic.java28
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQTopic.java31
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java31
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java301
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/JMSAMQException.java34
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/QueueSenderAdapter.java67
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/TemporaryDestination.java17
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/TopicSubscriberAdaptor.java10
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/ExchangeBoundOkMethodHandler.java54
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/QueueDeleteOkMethodHandler.java53
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java84
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSBytesMessage.java34
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessage.java238
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java10
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessage.java6
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java6
-rw-r--r--java/client/src/main/java/org/apache/qpid/jms/Message.java28
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/transacted/Config.java (renamed from java/client/src/test/java/org/apache/qpid/transacted/Config.java)0
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/transacted/Ping.java (renamed from java/client/src/test/java/org/apache/qpid/transacted/Ping.java)0
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/transacted/Pong.java (renamed from java/client/src/test/java/org/apache/qpid/transacted/Pong.java)0
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/transacted/Relay.java (renamed from java/client/src/test/java/org/apache/qpid/transacted/Relay.java)0
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/transacted/Start.java (renamed from java/client/src/test/java/org/apache/qpid/transacted/Start.java)0
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/weblogic/ServiceProvider.java (renamed from java/client/src/test/java/org/apache/qpid/weblogic/ServiceProvider.java)0
-rw-r--r--java/client/src/old_test/java/org/apache/qpid/weblogic/ServiceRequestingClient.java (renamed from java/client/src/test/java/org/apache/qpid/weblogic/ServiceRequestingClient.java)0
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/ack/RecoverTest.java89
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableMessageTest.java7
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/basic/MapMessageTest.java39
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java24
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/basic/PubSubTwoConnectionTest.java67
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/basic/TextMessageTest.java3
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/client/message/BytesMessageTest.java10
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/client/message/MapMessageTest.java33
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/client/message/ObjectMessageTest.java6
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/client/message/TextMessageTest.java251
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/client/temporaryqueue/TemporaryQueueTest.java80
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/message/StreamMessageTest.java2
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java199
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/transacted/TransactedTest.java (renamed from java/client/src/old_test/java/org/apache/qpid/transacted/TransactedTest.java)2
-rw-r--r--java/common/pom.xml4
-rw-r--r--java/common/src/main/java/org/apache/qpid/AMQPInvalidClassException.java30
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/AMQBody.java2
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/AMQFrame.java2
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/AMQMethodBody.java2
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java25
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/ContentBody.java2
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java2
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java10
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/FieldTable.java2
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/HeartbeatBody.java2
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/JMSPropertyFieldTable.java471
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/PropertyFieldTable.java834
-rw-r--r--java/common/src/main/java/org/apache/qpid/pool/Event.java2
-rw-r--r--java/common/src/test/java/org/apache/qpid/framing/JMSPropertyFieldTableTest.java1020
-rw-r--r--java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java885
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Activator.java12
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Application.java4
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java4
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchWindowAdvisor.java6
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Constants.java5
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedBean.java5
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedObject.java4
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedServer.java4
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Perspective.java21
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/exceptions/ManagementConsoleException.java10
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/MBeanUtility.java181
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/AttributesTabControl.java41
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/OperationTabControl.java9
82 files changed, 5645 insertions, 1782 deletions
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/DestNameExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/DestNameExchange.java
index c7722d0e67..b5c7a2ba23 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/DestNameExchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/DestNameExchange.java
@@ -7,9 +7,9 @@
* 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
@@ -196,4 +196,34 @@ public class DestNameExchange extends AbstractExchange
}
}
}
+
+ public boolean isBound(String routingKey, AMQQueue queue) throws AMQException
+ {
+ final List<AMQQueue> queues = _index.get(routingKey);
+ return queues != null && queues.contains(queue);
+ }
+
+ public boolean isBound(String routingKey) throws AMQException
+ {
+ final List<AMQQueue> queues = _index.get(routingKey);
+ return queues != null && !queues.isEmpty();
+ }
+
+ public boolean isBound(AMQQueue queue) throws AMQException
+ {
+ Map<String, List<AMQQueue>> bindings = _index.getBindingsMap();
+ for (List<AMQQueue> queues : bindings.values())
+ {
+ if (queues.contains(queue))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean hasBindings() throws AMQException
+ {
+ return !_index.getBindingsMap().isEmpty();
+ }
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/DestWildExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/DestWildExchange.java
index 6ac73c4484..c341f30ab6 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/DestWildExchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/DestWildExchange.java
@@ -7,9 +7,9 @@
* 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
@@ -126,10 +126,11 @@ public class DestWildExchange extends AbstractExchange
} // End of MBean class
- public void registerQueue(String routingKey, AMQQueue queue, FieldTable args) throws AMQException
+ public synchronized void registerQueue(String routingKey, AMQQueue queue, FieldTable args) throws AMQException
{
assert queue != null;
assert routingKey != null;
+ _logger.debug("Registering queue " + queue.getName() + " with routing key " + routingKey);
// we need to use putIfAbsent, which is an atomic operation, to avoid a race condition
List<AMQQueue> queueList = _routingKey2queues.putIfAbsent(routingKey, new CopyOnWriteArrayList<AMQQueue>());
// if we got null back, no previous value was associated with the specified routing key hence
@@ -159,6 +160,8 @@ public class DestWildExchange extends AbstractExchange
// TODO: add support for the immediate flag
if (queues == null)
{
+ _logger.warn("No queues found for routing key " + routingKey);
+ _logger.warn("Routing map contains: " + _routingKey2queues);
//todo Check for valid topic - mritchie
return;
}
@@ -172,7 +175,37 @@ public class DestWildExchange extends AbstractExchange
}
}
- public void deregisterQueue(String routingKey, AMQQueue queue) throws AMQException
+ public boolean isBound(String routingKey, AMQQueue queue) throws AMQException
+ {
+ List<AMQQueue> queues = _routingKey2queues.get(routingKey);
+ return queues != null && queues.contains(queue);
+ }
+
+
+ public boolean isBound(String routingKey) throws AMQException
+ {
+ List<AMQQueue> queues = _routingKey2queues.get(routingKey);
+ return queues != null && !queues.isEmpty();
+ }
+
+ public boolean isBound(AMQQueue queue) throws AMQException
+ {
+ for (List<AMQQueue> queues : _routingKey2queues.values())
+ {
+ if (queues.contains(queue))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean hasBindings() throws AMQException
+ {
+ return !_routingKey2queues.isEmpty();
+ }
+
+ public synchronized void deregisterQueue(String routingKey, AMQQueue queue) throws AMQException
{
assert queue != null;
assert routingKey != null;
@@ -190,6 +223,10 @@ public class DestWildExchange extends AbstractExchange
throw new AMQException("Queue " + queue + " was not registered with exchange " + this.getName() +
" with routing key " + routingKey);
}
+ if (queues.isEmpty())
+ {
+ _routingKey2queues.remove(queues);
+ }
}
protected ExchangeMBean createMBean() throws AMQException
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java
index f6d84dea02..8ef5f0ab29 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/Exchange.java
@@ -7,9 +7,9 @@
* 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
@@ -47,4 +47,30 @@ public interface Exchange
void deregisterQueue(String routingKey, AMQQueue queue) throws AMQException;
void route(AMQMessage message) throws AMQException;
+
+ /**
+ * Determines whether a message would be isBound to a particular queue using a specific routing key
+ * @param routingKey
+ * @param queue
+ * @return
+ * @throws AMQException
+ */
+ boolean isBound(String routingKey, AMQQueue queue) throws AMQException;
+
+ /**
+ * Determines whether a message is routing to any queue using a specific routing key
+ * @param routingKey
+ * @return
+ * @throws AMQException
+ */
+ boolean isBound(String routingKey) throws AMQException;
+
+ boolean isBound(AMQQueue queue) throws AMQException;
+
+ /**
+ * Returns true if this exchange has at least one binding associated with it.
+ * @return
+ * @throws AMQException
+ */
+ boolean hasBindings() throws AMQException;
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java
index dbf4ef91db..97b4adecdd 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java
@@ -221,6 +221,33 @@ public class HeadersExchange extends AbstractExchange
}
}
+ public boolean isBound(String routingKey, AMQQueue queue) throws AMQException
+ {
+ return isBound(queue);
+ }
+
+ public boolean isBound(String routingKey) throws AMQException
+ {
+ return hasBindings();
+ }
+
+ public boolean isBound(AMQQueue queue) throws AMQException
+ {
+ for (Registration r : _bindings)
+ {
+ if (r.queue.equals(queue))
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean hasBindings() throws AMQException
+ {
+ return !_bindings.isEmpty();
+ }
+
protected Map getHeaders(ContentHeaderBody contentHeaderFrame)
{
//what if the content type is not 'basic'? 'file' and 'stream' content classes also define headers,
diff --git a/java/broker/src/main/java/org/apache/qpid/server/exchange/Index.java b/java/broker/src/main/java/org/apache/qpid/server/exchange/Index.java
index fb48729c9e..485c4739bd 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/exchange/Index.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/exchange/Index.java
@@ -7,9 +7,9 @@
* 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
@@ -24,6 +24,7 @@ import org.apache.qpid.server.queue.AMQQueue;
import java.util.List;
import java.util.Map;
+import java.util.HashMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -37,7 +38,7 @@ class Index
private ConcurrentMap<String, List<AMQQueue>> _index
= new ConcurrentHashMap<String, List<AMQQueue>>();
- boolean add(String key, AMQQueue queue)
+ synchronized boolean add(String key, AMQQueue queue)
{
List<AMQQueue> queues = _index.get(key);
if(queues == null)
@@ -61,7 +62,7 @@ class Index
}
}
- boolean remove(String key, AMQQueue queue)
+ synchronized boolean remove(String key, AMQQueue queue)
{
List<AMQQueue> queues = _index.get(key);
if (queues != null)
@@ -83,6 +84,6 @@ class Index
Map<String, List<AMQQueue>> getBindingsMap()
{
- return _index;
+ return new HashMap<String, List<AMQQueue>>(_index);
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeBoundHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeBoundHandler.java
new file mode 100644
index 0000000000..5aaf78d6b7
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/ExchangeBoundHandler.java
@@ -0,0 +1,163 @@
+/*
+ *
+ * Copyright (c) 2006 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.qpid.server.handler;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.AMQFrame;
+import org.apache.qpid.framing.ExchangeBoundBody;
+import org.apache.qpid.framing.ExchangeBoundOkBody;
+import org.apache.qpid.server.exchange.Exchange;
+import org.apache.qpid.server.exchange.ExchangeRegistry;
+import org.apache.qpid.server.protocol.AMQMethodEvent;
+import org.apache.qpid.server.protocol.AMQProtocolSession;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.queue.QueueRegistry;
+import org.apache.qpid.server.state.AMQStateManager;
+import org.apache.qpid.server.state.StateAwareMethodListener;
+
+/**
+ * @author Apache Software Foundation
+ */
+public class ExchangeBoundHandler implements StateAwareMethodListener<ExchangeBoundBody>
+{
+ private static final ExchangeBoundHandler _instance = new ExchangeBoundHandler();
+
+ public static final int OK = 0;
+
+ public static final int EXCHANGE_NOT_FOUND = 1;
+
+ public static final int QUEUE_NOT_FOUND = 2;
+
+ public static final int NO_BINDINGS = 3;
+
+ public static final int QUEUE_NOT_BOUND = 4;
+
+ public static final int NO_QUEUE_BOUND_WITH_RK = 5;
+
+ public static final int SPECIFIC_QUEUE_NOT_BOUND_WITH_RK = 6;
+
+ public static ExchangeBoundHandler getInstance()
+ {
+ return _instance;
+ }
+
+ private ExchangeBoundHandler()
+ {
+ }
+
+ public void methodReceived(AMQStateManager stateManager, QueueRegistry queueRegistry,
+ ExchangeRegistry exchangeRegistry, AMQProtocolSession protocolSession,
+ AMQMethodEvent<ExchangeBoundBody> evt) throws AMQException
+ {
+ ExchangeBoundBody body = evt.getMethod();
+
+ String exchangeName = body.exchange;
+ String queueName = body.queue;
+ String routingKey = body.routingKey;
+ if (exchangeName == null)
+ {
+ throw new AMQException("Exchange exchange must not be null");
+ }
+ Exchange exchange = exchangeRegistry.getExchange(exchangeName);
+ AMQFrame response;
+ if (exchange == null)
+ {
+ response = ExchangeBoundOkBody.createAMQFrame(evt.getChannelId(), EXCHANGE_NOT_FOUND,
+ "Exchange " + exchangeName + " not found");
+ }
+ else if (routingKey == null)
+ {
+ if (queueName == null)
+ {
+ if (exchange.hasBindings())
+ {
+ response = ExchangeBoundOkBody.createAMQFrame(evt.getChannelId(), OK, null);
+ }
+ else
+ {
+ response = ExchangeBoundOkBody.createAMQFrame(evt.getChannelId(), NO_BINDINGS, null);
+ }
+ }
+ else
+ {
+ AMQQueue queue = queueRegistry.getQueue(queueName);
+ if (queue == null)
+ {
+ response = ExchangeBoundOkBody.createAMQFrame(evt.getChannelId(), QUEUE_NOT_FOUND,
+ "Queue " + queueName + " not found");
+ }
+ else
+ {
+ if (exchange.isBound(queue))
+ {
+ response = ExchangeBoundOkBody.createAMQFrame(evt.getChannelId(), OK, null);
+ }
+ else
+ {
+ response = ExchangeBoundOkBody.createAMQFrame(evt.getChannelId(), QUEUE_NOT_BOUND,
+ "Queue " + queueName + " not bound to exchange " +
+ exchangeName);
+ }
+ }
+ }
+ }
+ else if (queueName != null)
+ {
+ AMQQueue queue = queueRegistry.getQueue(queueName);
+ if (queue == null)
+ {
+ response = ExchangeBoundOkBody.createAMQFrame(evt.getChannelId(), QUEUE_NOT_FOUND,
+ "Queue " + queueName + " not found");
+ }
+ else
+ {
+ if (exchange.isBound(body.routingKey, queue))
+ {
+ response = ExchangeBoundOkBody.createAMQFrame(evt.getChannelId(), OK,
+ null);
+ }
+ else
+ {
+ response = ExchangeBoundOkBody.createAMQFrame(evt.getChannelId(),
+ SPECIFIC_QUEUE_NOT_BOUND_WITH_RK,
+ "Queue " + queueName +
+ " not bound with routing key " +
+ body.routingKey + " to exchange " +
+ exchangeName);
+ }
+ }
+ }
+ else
+ {
+ if (exchange.isBound(body.routingKey))
+ {
+ response = ExchangeBoundOkBody.createAMQFrame(evt.getChannelId(), OK,
+ null);
+ }
+ else
+ {
+ response = ExchangeBoundOkBody.createAMQFrame(evt.getChannelId(),
+ NO_QUEUE_BOUND_WITH_RK,
+ "No queue bound with routing key " +
+ body.routingKey + " to exchange " +
+ exchangeName);
+ }
+ }
+ protocolSession.writeFrame(response);
+ }
+}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQMinaProtocolSession.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQMinaProtocolSession.java
index fd97bf0d96..1832f01b7a 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQMinaProtocolSession.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQMinaProtocolSession.java
@@ -31,22 +31,19 @@ import org.apache.qpid.codec.AMQDecoder;
import org.apache.qpid.framing.*;
import org.apache.qpid.server.AMQChannel;
import org.apache.qpid.server.exchange.ExchangeRegistry;
-import org.apache.qpid.server.management.*;
+import org.apache.qpid.server.management.Managable;
+import org.apache.qpid.server.management.ManagedObject;
import org.apache.qpid.server.queue.QueueRegistry;
import org.apache.qpid.server.registry.ApplicationRegistry;
import org.apache.qpid.server.state.AMQStateManager;
import javax.management.JMException;
-import javax.management.MBeanException;
-import javax.management.MBeanNotificationInfo;
-import javax.management.Notification;
-import javax.management.monitor.MonitorNotification;
-import javax.management.openmbean.*;
import javax.security.sasl.SaslServer;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
-import java.util.Date;
+import java.util.ArrayList;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.concurrent.CopyOnWriteArraySet;
@@ -72,7 +69,7 @@ public class AMQMinaProtocolSession implements AMQProtocolSession,
private AMQCodecFactory _codecFactory;
- private ManagedAMQProtocolSession _managedObject;
+ private AMQProtocolSessionMBean _managedObject;
private SaslServer _saslServer;
@@ -81,11 +78,10 @@ public class AMQMinaProtocolSession implements AMQProtocolSession,
private Object _lastSent;
private boolean _closed;
-
+ // maximum number of channels this session should have
private long _maxNoOfChannels = 1000;
/* AMQP Version for this session */
-
private byte _major;
private byte _minor;
@@ -94,190 +90,6 @@ public class AMQMinaProtocolSession implements AMQProtocolSession,
return _managedObject;
}
- /**
- * This class implements the management interface (is an MBean). In order to
- * make more attributes, operations and notifications available over JMX simply
- * augment the ManagedConnection interface and add the appropriate implementation here.
- */
- @MBeanDescription("Management Bean for an AMQ Broker Connection")
- private final class ManagedAMQProtocolSession extends AMQManagedObject implements ManagedConnection
- {
- private String _name = null;
- //openmbean data types for representing the channel attributes
- private String[] _channelAtttibuteNames = { "Channel Id", "Transactional", "Default Queue", "Unacknowledged Message Count"};
- private String[] _indexNames = {_channelAtttibuteNames[0]};
- private OpenType[] _channelAttributeTypes = {SimpleType.INTEGER, SimpleType.BOOLEAN, SimpleType.STRING, SimpleType.INTEGER};
- private CompositeType _channelType = null; // represents the data type for channel data
- private TabularType _channelsType = null; // Data type for list of channels type
- private TabularDataSupport _channelsList = null;
-
- @MBeanConstructor("Creates an MBean exposing an AMQ Broker Connection")
- public ManagedAMQProtocolSession() throws JMException
- {
- super(ManagedConnection.class, ManagedConnection.TYPE);
- init();
- }
-
- /**
- * initialises the openmbean data types
- */
- private void init() throws OpenDataException
- {
- String remote = getRemoteAddress();
- remote = "anonymous".equals(remote) ? remote + hashCode() : remote;
- _name = jmxEncode(new StringBuffer(remote), 0).toString();
- _channelType = new CompositeType("Channel", "Channel Details", _channelAtttibuteNames,
- _channelAtttibuteNames, _channelAttributeTypes);
- _channelsType = new TabularType("Channels", "Channels", _channelType, _indexNames);
- }
-
- public Date getLastIoTime()
- {
- return new Date(_minaProtocolSession.getLastIoTime());
- }
-
- public String getRemoteAddress()
- {
- return _minaProtocolSession.getRemoteAddress().toString();
- }
-
- public Long getWrittenBytes()
- {
- return _minaProtocolSession.getWrittenBytes();
- }
-
- public Long getReadBytes()
- {
- return _minaProtocolSession.getReadBytes();
- }
-
- public Long getMaximumNumberOfChannels()
- {
- return _maxNoOfChannels;
- }
-
- public void setMaximumNumberOfChannels(Long value)
- {
- _maxNoOfChannels = value;
- }
-
- public String getObjectInstanceName()
- {
- return _name;
- }
-
- public void commitTransactions(int channelId) throws JMException
- {
- try
- {
- AMQChannel channel = _channelMap.get(channelId);
- if (channel == null)
- {
- throw new JMException("The channel (channel Id = " + channelId + ") does not exist");
- }
- if (channel.isTransactional())
- {
- channel.commit();
- }
- }
- catch(AMQException ex)
- {
- throw new MBeanException(ex, ex.toString());
- }
- }
-
- public void rollbackTransactions(int channelId) throws JMException
- {
- try
- {
- AMQChannel channel = _channelMap.get(channelId);
- if (channel == null)
- {
- throw new JMException("The channel (channel Id = " + channelId + ") does not exist");
- }
- if (channel.isTransactional())
- {
- channel.rollback();
- }
- }
- catch(AMQException ex)
- {
- throw new MBeanException(ex, ex.toString());
- }
- }
-
- /**
- * Creates the list of channels in tabular form from the _channelMap.
- * @return list of channels in tabular form.
- * @throws OpenDataException
- */
- public TabularData channels() throws OpenDataException
- {
- _channelsList = new TabularDataSupport(_channelsType);
-
- for (Map.Entry<Integer, AMQChannel> entry : _channelMap.entrySet())
- {
- AMQChannel channel = entry.getValue();
- Object[] itemValues = {channel.getChannelId(), channel.isTransactional(),
- (channel.getDefaultQueue() != null) ? channel.getDefaultQueue().getName() : null,
- channel.getUnacknowledgedMessageMap().size()};
-
- CompositeData channelData = new CompositeDataSupport(_channelType, _channelAtttibuteNames, itemValues);
- _channelsList.put(channelData);
- }
-
- return _channelsList;
- }
-
- public void closeChannel(int id) throws Exception
- {
- try
- {
- AMQMinaProtocolSession.this.closeChannel(id);
- }
- catch (AMQException ex)
- {
- throw new Exception(ex.toString());
- }
- }
-
- public void closeConnection() throws Exception
- {
- try
- {
- AMQMinaProtocolSession.this.closeSession();
- }
- catch (AMQException ex)
- {
- throw new Exception(ex.toString());
- }
- }
-
- @Override
- public MBeanNotificationInfo[] getNotificationInfo()
- {
- String[] notificationTypes = new String[] {MonitorNotification.THRESHOLD_VALUE_EXCEEDED};
- String name = MonitorNotification.class.getName();
- String description = "Channel count has reached threshold value";
- MBeanNotificationInfo info1 = new MBeanNotificationInfo(notificationTypes, name, description);
-
- return new MBeanNotificationInfo[] {info1};
- }
-
- private void checkForNotification()
- {
- int channelsCount = _channelMap.size();
- if (channelsCount >= getMaximumNumberOfChannels())
- {
- Notification n = new Notification(MonitorNotification.THRESHOLD_VALUE_EXCEEDED, this,
- ++_notificationSequenceNumber, System.currentTimeMillis(),
- "Channel count (" + channelsCount + ") has reached the threshold value");
-
- _broadcaster.sendNotification(n);
- }
- }
-
- } // End of MBean class
public AMQMinaProtocolSession(IoSession session, QueueRegistry queueRegistry, ExchangeRegistry exchangeRegistry,
AMQCodecFactory codecFactory)
@@ -301,11 +113,11 @@ public class AMQMinaProtocolSession implements AMQProtocolSession,
_managedObject.register();
}
- private ManagedAMQProtocolSession createMBean() throws AMQException
+ private AMQProtocolSessionMBean createMBean() throws AMQException
{
try
{
- return new ManagedAMQProtocolSession();
+ return new AMQProtocolSessionMBean(this);
}
catch(JMException ex)
{
@@ -314,6 +126,11 @@ public class AMQMinaProtocolSession implements AMQProtocolSession,
}
}
+ public IoSession getIOSession()
+ {
+ return _minaProtocolSession;
+ }
+
public static AMQProtocolSession getAMQProtocolSession(IoSession minaProtocolSession)
{
return (AMQProtocolSession) minaProtocolSession.getAttachment();
@@ -467,6 +284,11 @@ public class AMQMinaProtocolSession implements AMQProtocolSession,
_contextKey = contextKey;
}
+ public List<AMQChannel> getChannels()
+ {
+ return new ArrayList<AMQChannel>(_channelMap.values());
+ }
+
public AMQChannel getChannel(int channelId) throws AMQException
{
return _channelMap.get(channelId);
@@ -475,7 +297,42 @@ public class AMQMinaProtocolSession implements AMQProtocolSession,
public void addChannel(AMQChannel channel)
{
_channelMap.put(channel.getChannelId(), channel);
- _managedObject.checkForNotification();
+ checkForNotification();
+ }
+
+ private void checkForNotification()
+ {
+ int channelsCount = _channelMap.size();
+ if (channelsCount >= _maxNoOfChannels)
+ {
+ _managedObject.notifyClients("Channel count (" + channelsCount + ") has reached the threshold value");
+ }
+ }
+
+ public Long getMaximumNumberOfChannels()
+ {
+ return _maxNoOfChannels;
+ }
+
+ public void setMaximumNumberOfChannels(Long value)
+ {
+ _maxNoOfChannels = value;
+ }
+
+ public void commitTransactions(AMQChannel channel) throws AMQException
+ {
+ if (channel != null && channel.isTransactional())
+ {
+ channel.commit();
+ }
+ }
+
+ public void rollbackTransactions(AMQChannel channel) throws AMQException
+ {
+ if (channel != null && channel.isTransactional())
+ {
+ channel.rollback();
+ }
}
/**
diff --git a/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java
new file mode 100644
index 0000000000..a47d462810
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/protocol/AMQProtocolSessionMBean.java
@@ -0,0 +1,241 @@
+/*
+ *
+ * Copyright (c) 2006 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.qpid.server.protocol;
+
+import org.apache.qpid.AMQException;
+import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.server.management.AMQManagedObject;
+import org.apache.qpid.server.management.MBeanConstructor;
+import org.apache.qpid.server.management.MBeanDescription;
+
+import javax.management.JMException;
+import javax.management.MBeanException;
+import javax.management.MBeanNotificationInfo;
+import javax.management.Notification;
+import javax.management.monitor.MonitorNotification;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenDataException;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.SimpleType;
+import javax.management.openmbean.TabularData;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.TabularType;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * This MBean class implements the management interface. In order to make more attributes, operations and notifications
+ * available over JMX simply augment the ManagedConnection interface and add the appropriate implementation here.
+ */
+@MBeanDescription("Management Bean for an AMQ Broker Connection")
+public class AMQProtocolSessionMBean extends AMQManagedObject implements ManagedConnection
+{
+ private AMQMinaProtocolSession _session = null;
+ private String _name = null;
+ //openmbean data types for representing the channel attributes
+ private String[] _channelAtttibuteNames = {"Channel Id", "Transactional", "Default Queue", "Unacknowledged Message Count"};
+ private String[] _indexNames = {_channelAtttibuteNames[0]};
+ private OpenType[] _channelAttributeTypes = {SimpleType.INTEGER, SimpleType.BOOLEAN, SimpleType.STRING, SimpleType.INTEGER};
+ private CompositeType _channelType = null; // represents the data type for channel data
+ private TabularType _channelsType = null; // Data type for list of channels type
+
+ @MBeanConstructor("Creates an MBean exposing an AMQ Broker Connection")
+ public AMQProtocolSessionMBean(AMQMinaProtocolSession session) throws JMException
+ {
+ super(ManagedConnection.class, ManagedConnection.TYPE);
+ _session = session;
+ init();
+ }
+
+ /**
+ * initialises the openmbean data types
+ */
+ private void init() throws OpenDataException
+ {
+ String remote = getRemoteAddress();
+ remote = "anonymous".equals(remote) ? remote + hashCode() : remote;
+ _name = jmxEncode(new StringBuffer(remote), 0).toString();
+ _channelType = new CompositeType("Channel", "Channel Details", _channelAtttibuteNames,
+ _channelAtttibuteNames, _channelAttributeTypes);
+ _channelsType = new TabularType("Channels", "Channels", _channelType, _indexNames);
+ }
+
+ public Date getLastIoTime()
+ {
+ return new Date(_session.getIOSession().getLastIoTime());
+ }
+
+ public String getRemoteAddress()
+ {
+ return _session.getIOSession().getRemoteAddress().toString();
+ }
+
+ public Long getWrittenBytes()
+ {
+ return _session.getIOSession().getWrittenBytes();
+ }
+
+ public Long getReadBytes()
+ {
+ return _session.getIOSession().getReadBytes();
+ }
+
+ public Long getMaximumNumberOfChannels()
+ {
+ return _session.getMaximumNumberOfChannels();
+ }
+
+ public void setMaximumNumberOfChannels(Long value)
+ {
+ _session.setMaximumNumberOfChannels(value);
+ }
+
+ public String getObjectInstanceName()
+ {
+ return _name;
+ }
+
+ /**
+ * commits transactions for a transactional channel
+ *
+ * @param channelId
+ * @throws JMException if channel with given id doesn't exist or if commit fails
+ */
+ public void commitTransactions(int channelId) throws JMException
+ {
+ try
+ {
+ AMQChannel channel = _session.getChannel(channelId);
+ if (channel == null)
+ {
+ throw new JMException("The channel (channel Id = " + channelId + ") does not exist");
+ }
+ _session.commitTransactions(channel);
+ }
+ catch (AMQException ex)
+ {
+ throw new MBeanException(ex, ex.toString());
+ }
+ }
+
+ /**
+ * rollsback the transactions for a transactional channel
+ *
+ * @param channelId
+ * @throws JMException if channel with given id doesn't exist or if rollback fails
+ */
+ public void rollbackTransactions(int channelId) throws JMException
+ {
+ try
+ {
+ AMQChannel channel = _session.getChannel(channelId);
+ if (channel == null)
+ {
+ throw new JMException("The channel (channel Id = " + channelId + ") does not exist");
+ }
+ _session.rollbackTransactions(channel);
+ }
+ catch (AMQException ex)
+ {
+ throw new MBeanException(ex, ex.toString());
+ }
+ }
+
+ /**
+ * Creates the list of channels in tabular form from the _channelMap.
+ *
+ * @return list of channels in tabular form.
+ * @throws OpenDataException
+ */
+ public TabularData channels() throws OpenDataException
+ {
+ TabularDataSupport channelsList = new TabularDataSupport(_channelsType);
+ List<AMQChannel> list = _session.getChannels();
+
+ for (AMQChannel channel : list)
+ {
+ Object[] itemValues = {channel.getChannelId(), channel.isTransactional(),
+ (channel.getDefaultQueue() != null) ? channel.getDefaultQueue().getName() : null,
+ channel.getUnacknowledgedMessageMap().size()};
+
+ CompositeData channelData = new CompositeDataSupport(_channelType, _channelAtttibuteNames, itemValues);
+ channelsList.put(channelData);
+ }
+
+ return channelsList;
+ }
+
+ /**
+ * @see AMQMinaProtocolSession#closeChannel(int)
+ */
+ public void closeChannel(int id) throws JMException
+ {
+ try
+ {
+ AMQChannel channel = _session.getChannel(id);
+ if (channel == null)
+ {
+ throw new JMException("The channel (channel Id = " + id + ") does not exist");
+ }
+
+ _session.closeChannel(id);
+ }
+ catch (AMQException ex)
+ {
+ throw new MBeanException(ex, ex.toString());
+ }
+ }
+
+ /**
+ * closes the connection. The administrator can use this management operation to close connection to free up
+ * resources.
+ * @throws JMException
+ */
+ public void closeConnection() throws JMException
+ {
+ try
+ {
+ _session.closeSession();
+ }
+ catch (AMQException ex)
+ {
+ throw new MBeanException(ex, ex.toString());
+ }
+ }
+
+ @Override
+ public MBeanNotificationInfo[] getNotificationInfo()
+ {
+ String[] notificationTypes = new String[]{MonitorNotification.THRESHOLD_VALUE_EXCEEDED};
+ String name = MonitorNotification.class.getName();
+ String description = "Channel count has reached threshold value";
+ MBeanNotificationInfo info1 = new MBeanNotificationInfo(notificationTypes, name, description);
+
+ return new MBeanNotificationInfo[]{info1};
+ }
+
+ public void notifyClients(String notificationMsg)
+ {
+ Notification n = new Notification(MonitorNotification.THRESHOLD_VALUE_EXCEEDED, this,
+ ++_notificationSequenceNumber, System.currentTimeMillis(), notificationMsg);
+ _broadcaster.sendNotification(n);
+ }
+
+} // End of MBean class
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
index 7f3d772e47..5f6d4c2939 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java
@@ -22,19 +22,15 @@ package org.apache.qpid.server.queue;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
-import org.apache.qpid.framing.ContentBody;
-import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.server.exchange.Exchange;
-import org.apache.qpid.server.management.*;
+import org.apache.qpid.server.management.Managable;
+import org.apache.qpid.server.management.ManagedObject;
import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.mina.common.ByteBuffer;
-import javax.management.*;
-import javax.management.monitor.MonitorNotification;
-import javax.management.openmbean.*;
+import javax.management.JMException;
import java.text.MessageFormat;
-import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Executor;
@@ -100,7 +96,7 @@ public class AMQQueue implements Managable, Comparable
* max allowed number of messages on a queue.
*/
private Integer _maxMessageCount = 10000;
-
+
/**
* max queue depth(KB) for the queue
*/
@@ -116,340 +112,6 @@ public class AMQQueue implements Managable, Comparable
return _name.compareTo(((AMQQueue) o).getName());
}
- /**
- * MBean class for AMQQueue. It implements all the management features exposed
- * for an AMQQueue.
- */
- @MBeanDescription("Management Interface for AMQQueue")
- private final class AMQQueueMBean extends AMQManagedObject implements ManagedQueue
- {
- private String _queueName = null;
- // OpenMBean data types for viewMessages method
- private String[] _msgAttributeNames = {"Message Id", "Header", "Size(bytes)", "Redelivered"};
- private String[] _msgAttributeIndex = {_msgAttributeNames[0]};
- private OpenType[] _msgAttributeTypes = new OpenType[4]; // AMQ message attribute types.
- private CompositeType _messageDataType = null; // Composite type for representing AMQ Message data.
- private TabularType _messagelistDataType = null; // Datatype for representing AMQ messages list.
-
- // OpenMBean data types for viewMessageContent method
- private CompositeType _msgContentType = null;
- private String[] _msgContentAttributes = {"Message Id", "MimeType", "Encoding", "Content"};
- private OpenType[] _msgContentAttributeTypes = new OpenType[4];
-
- @MBeanConstructor("Creates an MBean exposing an AMQQueue")
- public AMQQueueMBean() throws JMException
- {
- super(ManagedQueue.class, ManagedQueue.TYPE);
- init();
- }
-
- /**
- * initialises the openmbean data types
- */
- private void init() throws OpenDataException
- {
- _queueName = jmxEncode(new StringBuffer(_name), 0).toString();
- _msgContentAttributeTypes[0] = SimpleType.LONG; // For message id
- _msgContentAttributeTypes[1] = SimpleType.STRING; // For MimeType
- _msgContentAttributeTypes[2] = SimpleType.STRING; // For Encoding
- _msgContentAttributeTypes[3] = new ArrayType(1, SimpleType.BYTE); // For message content
- _msgContentType = new CompositeType("Message Content", "AMQ Message Content", _msgContentAttributes,
- _msgContentAttributes, _msgContentAttributeTypes);
-
- _msgAttributeTypes[0] = SimpleType.LONG; // For message id
- _msgAttributeTypes[1] = new ArrayType(1, SimpleType.STRING); // For header attributes
- _msgAttributeTypes[2] = SimpleType.LONG; // For size
- _msgAttributeTypes[3] = SimpleType.BOOLEAN; // For redelivered
-
- _messageDataType = new CompositeType("Message","AMQ Message", _msgAttributeNames, _msgAttributeNames, _msgAttributeTypes);
- _messagelistDataType = new TabularType("Messages", "List of messages", _messageDataType, _msgAttributeIndex);
- }
-
- public String getObjectInstanceName()
- {
- return _queueName;
- }
-
- public String getName()
- {
- return _name;
- }
-
- public boolean isDurable()
- {
- return _durable;
- }
-
- public String getOwner()
- {
- return _owner;
- }
-
- public boolean isAutoDelete()
- {
- return _autoDelete;
- }
-
- public Integer getMessageCount()
- {
- return _deliveryMgr.getQueueMessageCount();
- }
-
- public Long getMaximumMessageSize()
- {
- return _maxMessageSize;
- }
-
- public void setMaximumMessageSize(Long value)
- {
- _maxMessageSize = value;
- }
-
- public Integer getConsumerCount()
- {
- return _subscribers.size();
- }
-
- public Integer getActiveConsumerCount()
- {
- return _subscribers.getWeight();
- }
-
- public Long getReceivedMessageCount()
- {
- return _totalMessagesReceived;
- }
-
- public Integer getMaximumMessageCount()
- {
- return _maxMessageCount;
- }
-
- public void setMaximumMessageCount(Integer value)
- {
- _maxMessageCount = value;
- }
-
- public Long getMaximumQueueDepth()
- {
- return _maxQueueDepth;
- }
-
- // Sets the queue depth, the max queue size
- public void setMaximumQueueDepth(Long value)
- {
- _maxQueueDepth = value;
- }
-
- /**
- * returns the size of messages(KB) in the queue.
- */
- public Long getQueueDepth()
- {
- /* TODO: this must return a maintained count not
- * iterate through all messages
- */
- return 0L;
- /*List<AMQMessage> list = _deliveryMgr.getMessages();
- if (list.size() == 0)
- {
- return 0l;
- }
-
- long queueDepth = 0;
- for (AMQMessage message : list)
- {
- queueDepth = queueDepth + getMessageSize(message);
- }
- return (long)Math.round(queueDepth / 1000);
- */
- }
- // Operations
-
- /**
- * returns size of message in bytes
- */
- private long getMessageSize(AMQMessage msg) throws AMQException
- {
- if (msg == null)
- {
- return 0L;
- }
-
- return msg.getContentHeaderBody().bodySize;
- }
-
- /**
- * Checks if there is any notification to be send to the listeners
- */
- private void checkForNotification(AMQMessage msg) throws AMQException
- {
- // Check for threshold message count
- Integer msgCount = getMessageCount();
- if (msgCount >= getMaximumMessageCount())
- {
- notifyClients("Message count(" + msgCount + ") has reached or exceeded the threshold high value");
- }
-
- // Check for threshold message size
- long messageSize = getMessageSize(msg);
- if (messageSize >= _maxMessageSize)
- {
- notifyClients("Message size(ID=" + msg.getMessageId() + ", size=" + messageSize + " bytes) is higher than the threshold value");
- }
-
- // Check for threshold queue depth in bytes
- long queueDepth = getQueueDepth();
- if (queueDepth >= _maxQueueDepth)
- {
- notifyClients("Queue depth(" + queueDepth + "), Queue size has reached the threshold high value");
- }
- }
-
- /**
- * Sends the notification to the listeners
- */
- private void notifyClients(String notificationMsg)
- {
- Notification n = new Notification(MonitorNotification.THRESHOLD_VALUE_EXCEEDED, this,
- ++_notificationSequenceNumber, System.currentTimeMillis(), notificationMsg);
-
- _broadcaster.sendNotification(n);
- }
-
- public void deleteMessageFromTop() throws JMException
- {
- try
- {
- _deliveryMgr.removeAMessageFromTop();
- }
- catch (AMQException ex)
- {
- throw new MBeanException(ex, ex.toString());
- }
- }
-
- public void clearQueue() throws JMException
- {
- try
- {
- _deliveryMgr.clearAllMessages();
- }
- catch (AMQException ex)
- {
- throw new MBeanException(ex, ex.toString());
- }
- }
-
- /**
- * returns message content as byte array and related attributes for the given message id.
- */
- public CompositeData viewMessageContent(long msgId) throws JMException
- {
- List<AMQMessage> list = _deliveryMgr.getMessages();
- AMQMessage msg = null;
- for (AMQMessage message : list)
- {
- if (message.getMessageId() == msgId)
- {
- msg = message;
- break;
- }
- }
-
- if (msg != null)
- {
- try
- {
- // get message content
- Iterator<ContentBody> cBodies = msg.getContentBodyIterator();
- List<Byte> msgContent = new ArrayList<Byte>();
- while (cBodies.hasNext())
- {
- ContentBody body = cBodies.next();
- if (body.getSize() != 0)
- {
- ByteBuffer slice = body.payload.slice();
- for (int j = 0; j < slice.limit(); j++)
- {
- msgContent.add(slice.get());
- }
- }
- }
-
- // Create header attributes list
- BasicContentHeaderProperties headerProperties = (BasicContentHeaderProperties)msg.getContentHeaderBody().properties;
- String mimeType = headerProperties.getContentType();
- String encoding = headerProperties.getEncoding() == null ? "" : headerProperties.getEncoding();
- Object[] itemValues = {msgId, mimeType, encoding, msgContent.toArray(new Byte[0])};
-
- return new CompositeDataSupport(_msgContentType, _msgContentAttributes, itemValues);
- }
- catch (AMQException e)
- {
- throw new JMException(e.getMessage());
- }
- }
- else
- {
- throw new OperationsException("AMQMessage with message id = " + msgId + " is not in the " + _queueName);
- }
- }
-
- /**
- * Returns the header contents of the messages stored in this queue in tabular form.
- */
- public TabularData viewMessages(int beginIndex, int endIndex) throws JMException, AMQException
- {
- if ((beginIndex > endIndex) || (beginIndex < 1))
- {
- throw new JMException("From Index = " + beginIndex + ", To Index = " + endIndex +
- "\nFrom Index should be greater than 0 and less than To Index");
- }
-
- List<AMQMessage> list = _deliveryMgr.getMessages();
- TabularDataSupport _messageList = new TabularDataSupport(_messagelistDataType);
-
- // Create the tabular list of message header contents
- for (int i = beginIndex; i <= endIndex && i <= list.size(); i++)
- {
- AMQMessage msg = list.get(i - 1);
- ContentHeaderBody headerBody = msg.getContentHeaderBody();
- long size = headerBody.bodySize;
- // Create header attributes list
- BasicContentHeaderProperties headerProperties = (BasicContentHeaderProperties)headerBody.properties;
- List<String> headerAttribsList = new ArrayList<String>();
- headerAttribsList.add("App Id=" + headerProperties.getAppId());
- headerAttribsList.add("MimeType=" + headerProperties.getContentType());
- headerAttribsList.add("Correlation Id=" + headerProperties.getCorrelationId());
- headerAttribsList.add("Encoding=" + headerProperties.getEncoding());
- headerAttribsList.add(headerProperties.toString());
-
- Object[] itemValues = {msg.getMessageId(), headerAttribsList.toArray(new String[0]),
- headerBody.bodySize, msg.isRedelivered()};
- CompositeData messageData = new CompositeDataSupport(_messageDataType, _msgAttributeNames, itemValues);
- _messageList.put(messageData);
- }
-
- return _messageList;
- }
-
- /**
- * returns Notifications sent by this MBean.
- */
- @Override
- public MBeanNotificationInfo[] getNotificationInfo()
- {
- String[] notificationTypes = new String[] {MonitorNotification.THRESHOLD_VALUE_EXCEEDED};
- String name = MonitorNotification.class.getName();
- String description = "Either Message count or Queue depth or Message size has reached threshold high value";
- MBeanNotificationInfo info1 = new MBeanNotificationInfo(notificationTypes, name, description);
-
- return new MBeanNotificationInfo[]{info1};
- }
-
- } // End of AMQMBean class
-
public AMQQueue(String name, boolean durable, String owner,
boolean autoDelete, QueueRegistry queueRegistry)
throws AMQException
@@ -543,7 +205,7 @@ public class AMQQueue implements Managable, Comparable
{
try
{
- return new AMQQueueMBean();
+ return new AMQQueueMBean(this);
}
catch (JMException ex)
{
@@ -576,16 +238,112 @@ public class AMQQueue implements Managable, Comparable
return _autoDelete;
}
+ /**
+ * @return no of messages(undelivered) on the queue.
+ */
public int getMessageCount()
{
return _deliveryMgr.getQueueMessageCount();
}
+ /**
+ * @return List of messages(undelivered) on the queue.
+ */
+ public List<AMQMessage> getMessagesOnTheQueue()
+ {
+ return _deliveryMgr.getMessages();
+ }
+
+ /**
+ * @param messageId
+ * @return AMQMessage with give id if exists. null if AMQMessage with given id doesn't exist.
+ */
+ public AMQMessage getMessageOnTheQueue(long messageId)
+ {
+ List<AMQMessage> list = getMessagesOnTheQueue();
+ AMQMessage msg = null;
+ for (AMQMessage message : list)
+ {
+ if (message.getMessageId() == messageId)
+ {
+ msg = message;
+ break;
+ }
+ }
+
+ return msg;
+ }
+
+ /**
+ * @return MBean object associated with this Queue
+ */
public ManagedObject getManagedObject()
{
return _managedObject;
}
+ public Long getMaximumMessageSize()
+ {
+ return _maxMessageSize;
+ }
+
+ public void setMaximumMessageSize(Long value)
+ {
+ _maxMessageSize = value;
+ }
+
+ public Integer getConsumerCount()
+ {
+ return _subscribers.size();
+ }
+
+ public Integer getActiveConsumerCount()
+ {
+ return _subscribers.getWeight();
+ }
+
+ public Long getReceivedMessageCount()
+ {
+ return _totalMessagesReceived;
+ }
+
+ public Integer getMaximumMessageCount()
+ {
+ return _maxMessageCount;
+ }
+
+ public void setMaximumMessageCount(Integer value)
+ {
+ _maxMessageCount = value;
+ }
+
+ public Long getMaximumQueueDepth()
+ {
+ return _maxQueueDepth;
+ }
+
+ // Sets the queue depth, the max queue size
+ public void setMaximumQueueDepth(Long value)
+ {
+ _maxQueueDepth = value;
+ }
+
+ /**
+ * Removes the AMQMessage from the top of the queue.
+ */
+ public void deleteMessageFromTop() throws AMQException
+ {
+ _deliveryMgr.removeAMessageFromTop();
+ }
+
+ /**
+ * removes all the messages from the queue.
+ */
+ public void clearQueue() throws AMQException
+ {
+ _deliveryMgr.clearAllMessages();
+ }
+
public void bind(String routingKey, Exchange exchange)
{
_bindings.addBinding(routingKey, exchange);
@@ -729,7 +487,14 @@ public class AMQQueue implements Managable, Comparable
protected void updateReceivedMessageCount(AMQMessage msg) throws AMQException
{
_totalMessagesReceived++;
- _managedObject.checkForNotification(msg);
+ try
+ {
+ _managedObject.checkForNotification(msg);
+ }
+ catch (JMException e)
+ {
+ throw new AMQException("Unable to get notification from manage queue: " + e, e);
+ }
}
public boolean equals(Object o)
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java
new file mode 100644
index 0000000000..e09b177fb9
--- /dev/null
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueueMBean.java
@@ -0,0 +1,366 @@
+/*
+ *
+ * Copyright (c) 2006 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.qpid.server.queue;
+
+import org.apache.qpid.server.management.MBeanDescription;
+import org.apache.qpid.server.management.AMQManagedObject;
+import org.apache.qpid.server.management.MBeanConstructor;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.ContentBody;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
+import org.apache.qpid.framing.ContentHeaderBody;
+import org.apache.mina.common.ByteBuffer;
+
+import javax.management.openmbean.*;
+import javax.management.JMException;
+import javax.management.Notification;
+import javax.management.MBeanException;
+import javax.management.MBeanNotificationInfo;
+import javax.management.OperationsException;
+import javax.management.monitor.MonitorNotification;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Iterator;
+
+/**
+ * MBean class for AMQQueue. It implements all the management features exposed
+ * for an AMQQueue.
+ */
+@MBeanDescription("Management Interface for AMQQueue")
+public class AMQQueueMBean extends AMQManagedObject implements ManagedQueue
+{
+ private AMQQueue _queue = null;
+ private String _queueName = null;
+ // OpenMBean data types for viewMessages method
+ private String[] _msgAttributeNames = {"Message Id", "Header", "Size(bytes)", "Redelivered"};
+ private String[] _msgAttributeIndex = {_msgAttributeNames[0]};
+ private OpenType[] _msgAttributeTypes = new OpenType[4]; // AMQ message attribute types.
+ private CompositeType _messageDataType = null; // Composite type for representing AMQ Message data.
+ private TabularType _messagelistDataType = null; // Datatype for representing AMQ messages list.
+
+ // OpenMBean data types for viewMessageContent method
+ private CompositeType _msgContentType = null;
+ private String[] _msgContentAttributes = {"Message Id", "MimeType", "Encoding", "Content"};
+ private OpenType[] _msgContentAttributeTypes = new OpenType[4];
+
+ @MBeanConstructor("Creates an MBean exposing an AMQQueue")
+ public AMQQueueMBean(AMQQueue queue) throws JMException
+ {
+ super(ManagedQueue.class, ManagedQueue.TYPE);
+ _queue = queue;
+ _queueName = jmxEncode(new StringBuffer(queue.getName()), 0).toString();
+ init();
+ }
+
+ /**
+ * initialises the openmbean data types
+ */
+ private void init() throws OpenDataException
+ {
+ _msgContentAttributeTypes[0] = SimpleType.LONG; // For message id
+ _msgContentAttributeTypes[1] = SimpleType.STRING; // For MimeType
+ _msgContentAttributeTypes[2] = SimpleType.STRING; // For Encoding
+ _msgContentAttributeTypes[3] = new ArrayType(1, SimpleType.BYTE); // For message content
+ _msgContentType = new CompositeType("Message Content", "AMQ Message Content", _msgContentAttributes,
+ _msgContentAttributes, _msgContentAttributeTypes);
+
+ _msgAttributeTypes[0] = SimpleType.LONG; // For message id
+ _msgAttributeTypes[1] = new ArrayType(1, SimpleType.STRING); // For header attributes
+ _msgAttributeTypes[2] = SimpleType.LONG; // For size
+ _msgAttributeTypes[3] = SimpleType.BOOLEAN; // For redelivered
+
+ _messageDataType = new CompositeType("Message", "AMQ Message", _msgAttributeNames, _msgAttributeNames, _msgAttributeTypes);
+ _messagelistDataType = new TabularType("Messages", "List of messages", _messageDataType, _msgAttributeIndex);
+ }
+
+ public String getObjectInstanceName()
+ {
+ return _queueName;
+ }
+
+ public String getName()
+ {
+ return _queueName;
+ }
+
+ public boolean isDurable()
+ {
+ return _queue.isDurable();
+ }
+
+ public String getOwner()
+ {
+ return _queue.getOwner();
+ }
+
+ public boolean isAutoDelete()
+ {
+ return _queue.isAutoDelete();
+ }
+
+ public Integer getMessageCount()
+ {
+ return _queue.getMessageCount();
+ }
+
+ public Long getMaximumMessageSize()
+ {
+ return _queue.getMaximumMessageSize();
+ }
+
+ public void setMaximumMessageSize(Long value)
+ {
+ _queue.setMaximumMessageSize(value);
+ }
+
+ public Integer getConsumerCount()
+ {
+ return _queue.getConsumerCount();
+ }
+
+ public Integer getActiveConsumerCount()
+ {
+ return _queue.getActiveConsumerCount();
+ }
+
+ public Long getReceivedMessageCount()
+ {
+ return _queue.getReceivedMessageCount();
+ }
+
+ public Integer getMaximumMessageCount()
+ {
+ return _queue.getMaximumMessageCount();
+ }
+
+ public void setMaximumMessageCount(Integer value)
+ {
+ _queue.setMaximumMessageCount(value);
+ }
+
+ public Long getMaximumQueueDepth()
+ {
+ return _queue.getMaximumQueueDepth();
+ }
+
+ public void setMaximumQueueDepth(Long value)
+ {
+ _queue.setMaximumQueueDepth(value);
+ }
+
+ /**
+ * returns the size of messages(KB) in the queue.
+ */
+ public Long getQueueDepth() throws JMException
+ {
+ List<AMQMessage> list = _queue.getMessagesOnTheQueue();
+ if (list.size() == 0)
+ {
+ return 0l;
+ }
+
+ long queueDepth = 0;
+ try
+ {
+ for (AMQMessage message : list)
+ {
+ queueDepth = queueDepth + getMessageSize(message);
+ }
+ }
+ catch (AMQException e)
+ {
+ throw new JMException("Unable to get message size: " + e);
+ }
+ return (long) Math.round(queueDepth / 1000);
+ }
+
+ /**
+ * returns size of message in bytes
+ */
+ private long getMessageSize(AMQMessage msg) throws AMQException
+ {
+ if (msg == null)
+ {
+ return 0l;
+ }
+
+ return msg.getContentHeaderBody().bodySize;
+ }
+
+ /**
+ * Checks if there is any notification to be send to the listeners
+ */
+ public void checkForNotification(AMQMessage msg) throws AMQException, JMException
+ {
+ // Check for threshold message count
+ Integer msgCount = getMessageCount();
+ if (msgCount >= getMaximumMessageCount())
+ {
+ notifyClients("Message count(" + msgCount + ") has reached or exceeded the threshold high value");
+ }
+
+ // Check for threshold message size
+ long messageSize = getMessageSize(msg);
+ if (messageSize >= _queue.getMaximumMessageSize())
+ {
+ notifyClients("Message size(ID=" + msg.getMessageId() + ", size=" + messageSize + " bytes) is higher than the threshold value");
+ }
+
+ // Check for threshold queue depth in bytes
+ long queueDepth = getQueueDepth();
+ if (queueDepth >= _queue.getMaximumQueueDepth())
+ {
+ notifyClients("Queue depth(" + queueDepth + "), Queue size has reached the threshold high value");
+ }
+ }
+
+ /**
+ * Sends the notification to the listeners
+ */
+ private void notifyClients(String notificationMsg)
+ {
+ Notification n = new Notification(MonitorNotification.THRESHOLD_VALUE_EXCEEDED, this,
+ ++_notificationSequenceNumber, System.currentTimeMillis(), notificationMsg);
+
+ _broadcaster.sendNotification(n);
+ }
+
+ /**
+ * @see org.apache.qpid.server.queue.AMQQueue#deleteMessageFromTop()
+ */
+ public void deleteMessageFromTop() throws JMException
+ {
+ try
+ {
+ _queue.deleteMessageFromTop();
+ }
+ catch (AMQException ex)
+ {
+ throw new MBeanException(ex, ex.toString());
+ }
+ }
+
+ /**
+ * @see org.apache.qpid.server.queue.AMQQueue#clearQueue()
+ */
+ public void clearQueue() throws JMException
+ {
+ try
+ {
+ _queue.clearQueue();
+ }
+ catch (AMQException ex)
+ {
+ throw new MBeanException(ex, ex.toString());
+ }
+ }
+
+ /**
+ * returns message content as byte array and related attributes for the given message id.
+ */
+ public CompositeData viewMessageContent(long msgId) throws JMException
+ {
+ AMQMessage msg = _queue.getMessageOnTheQueue(msgId);
+ if (msg == null)
+ {
+ throw new OperationsException("AMQMessage with message id = " + msgId + " is not in the " + _queueName);
+ }
+ // get message content
+ Iterator<ContentBody> cBodies = msg.getContentBodyIterator();
+ List<Byte> msgContent = new ArrayList<Byte>();
+ while (cBodies.hasNext())
+ {
+ ContentBody body = cBodies.next();
+ if (body.getSize() != 0)
+ {
+ ByteBuffer slice = body.payload.slice();
+ for (int j = 0; j < slice.limit(); j++)
+ {
+ msgContent.add(slice.get());
+ }
+ }
+ }
+
+ try
+ {
+ // Create header attributes list
+ BasicContentHeaderProperties headerProperties = (BasicContentHeaderProperties) msg.getContentHeaderBody().properties;
+ String mimeType = headerProperties.getContentType();
+ String encoding = headerProperties.getEncoding() == null ? "" : headerProperties.getEncoding();
+ Object[] itemValues = {msgId, mimeType, encoding, msgContent.toArray(new Byte[0])};
+
+ return new CompositeDataSupport(_msgContentType, _msgContentAttributes, itemValues);
+ }
+ catch (AMQException e)
+ {
+ throw new JMException("Error create header attributes list: " + e);
+ }
+ }
+
+ /**
+ * Returns the header contents of the messages stored in this queue in tabular form.
+ */
+ public TabularData viewMessages(int beginIndex, int endIndex) throws JMException
+ {
+ if ((beginIndex > endIndex) || (beginIndex < 1))
+ {
+ throw new OperationsException("From Index = " + beginIndex + ", To Index = " + endIndex +
+ "\n\"From Index\" should be greater than 0 and less than \"To Index\"");
+ }
+
+ List<AMQMessage> list = _queue.getMessagesOnTheQueue();
+ TabularDataSupport _messageList = new TabularDataSupport(_messagelistDataType);
+
+ try
+ {
+ // Create the tabular list of message header contents
+ for (int i = beginIndex; i <= endIndex && i <= list.size(); i++)
+ {
+ AMQMessage msg = list.get(i - 1);
+ ContentHeaderBody headerBody = msg.getContentHeaderBody();
+ // Create header attributes list
+ BasicContentHeaderProperties headerProperties = (BasicContentHeaderProperties) headerBody.properties;
+ String[] headerAttributes = headerProperties.toString().split(",");
+ Object[] itemValues = {msg.getMessageId(), headerAttributes, headerBody.bodySize, msg.isRedelivered()};
+ CompositeData messageData = new CompositeDataSupport(_messageDataType, _msgAttributeNames, itemValues);
+ _messageList.put(messageData);
+ }
+ }
+ catch (AMQException e)
+ {
+ throw new JMException("Error creating message contents: " + e);
+ }
+
+ return _messageList;
+ }
+
+ /**
+ * returns Notifications sent by this MBean.
+ */
+ @Override
+ public MBeanNotificationInfo[] getNotificationInfo()
+ {
+ String[] notificationTypes = new String[]{MonitorNotification.THRESHOLD_VALUE_EXCEEDED};
+ String name = MonitorNotification.class.getName();
+ String description = "Either Message count or Queue depth or Message size has reached threshold high value";
+ MBeanNotificationInfo info1 = new MBeanNotificationInfo(notificationTypes, name, description);
+
+ return new MBeanNotificationInfo[]{info1};
+ }
+
+} // End of AMQMBean class
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/ManagedQueue.java b/java/broker/src/main/java/org/apache/qpid/server/queue/ManagedQueue.java
index 8925ed9450..c36cc6bd7b 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/ManagedQueue.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/ManagedQueue.java
@@ -71,7 +71,7 @@ public interface ManagedQueue
* @throws IOException
*/
@MBeanAttribute(name="QueueDepth", description="Size of messages(KB) in the queue")
- Long getQueueDepth() throws IOException;
+ Long getQueueDepth() throws IOException, JMException;
/**
* Returns the total number of active subscribers to the queue.
diff --git a/java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java b/java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java
index 5e88ff7f2d..4e9deeb8db 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/state/AMQStateManager.java
@@ -7,9 +7,9 @@
* 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
@@ -109,6 +109,7 @@ public class AMQStateManager implements AMQMethodListener
frame2handlerMap.put(ConnectionCloseBody.class, ConnectionCloseMethodHandler.getInstance());
frame2handlerMap.put(ExchangeDeclareBody.class, ExchangeDeclareHandler.getInstance());
frame2handlerMap.put(ExchangeDeleteBody.class, ExchangeDeleteHandler.getInstance());
+ frame2handlerMap.put(ExchangeBoundBody.class, ExchangeBoundHandler.getInstance());
frame2handlerMap.put(BasicAckBody.class, BasicAckMethodHandler.getInstance());
frame2handlerMap.put(BasicRecoverBody.class, BasicRecoverMethodHandler.getInstance());
frame2handlerMap.put(BasicConsumeBody.class, BasicConsumeMethodHandler.getInstance());
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java b/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java
index 5c13e7861f..c6f3f9c492 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQDestination.java
@@ -7,9 +7,9 @@
* 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
@@ -79,13 +79,19 @@ public abstract class AMQDestination implements Destination, Referenceable
protected AMQDestination(String exchangeName, String exchangeClass, String destinationName, boolean isExclusive,
boolean isAutoDelete, String queueName)
{
+ this(exchangeName, exchangeClass, destinationName, isExclusive, isAutoDelete, queueName, false);
+ }
+
+ protected AMQDestination(String exchangeName, String exchangeClass, String destinationName, boolean isExclusive,
+ boolean isAutoDelete, String queueName, boolean isDurable)
+ {
if (destinationName == null)
{
- throw new IllegalArgumentException("Destination name must not be null");
+ throw new IllegalArgumentException("Destination exchange must not be null");
}
if (exchangeName == null)
{
- throw new IllegalArgumentException("Exchange name must not be null");
+ throw new IllegalArgumentException("Exchange exchange must not be null");
}
if (exchangeClass == null)
{
@@ -97,6 +103,7 @@ public abstract class AMQDestination implements Destination, Referenceable
_isExclusive = isExclusive;
_isAutoDelete = isAutoDelete;
_queueName = queueName;
+ _isDurable = isDurable;
}
public String getEncodedName()
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQSession.java b/java/client/src/main/java/org/apache/qpid/client/AMQSession.java
index 8e93b19eea..21fc5c89c5 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQSession.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQSession.java
@@ -23,13 +23,15 @@ package org.apache.qpid.client;
import org.apache.log4j.Logger;
import org.apache.qpid.AMQException;
import org.apache.qpid.AMQUndeliveredException;
+import org.apache.qpid.server.handler.ExchangeBoundHandler;
+import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.client.failover.FailoverSupport;
import org.apache.qpid.client.message.AbstractJMSMessage;
import org.apache.qpid.client.message.JMSStreamMessage;
import org.apache.qpid.client.message.MessageFactoryRegistry;
import org.apache.qpid.client.message.UnprocessedMessage;
-import org.apache.qpid.client.protocol.AMQMethodEvent;
import org.apache.qpid.client.protocol.AMQProtocolHandler;
+import org.apache.qpid.client.protocol.AMQMethodEvent;
import org.apache.qpid.client.util.FlowControllingBlockingQueue;
import org.apache.qpid.framing.*;
import org.apache.qpid.jms.Session;
@@ -37,6 +39,7 @@ import org.apache.qpid.protocol.AMQConstant;
import org.apache.qpid.url.AMQBindingURL;
import org.apache.qpid.url.URLSyntaxException;
+
import javax.jms.*;
import javax.jms.IllegalStateException;
import java.io.Serializable;
@@ -46,6 +49,8 @@ import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
public class AMQSession extends Closeable implements Session, QueueSession, TopicSession
{
@@ -66,6 +71,17 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
private int _defaultPrefetchLowMark = DEFAULT_PREFETCH_LOW_MARK;
/**
+ * Used to reference durable subscribers so they requests for unsubscribe can be handled
+ * correctly. Note this only keeps a record of subscriptions which have been created
+ * in the current instance. It does not remember subscriptions between executions of the
+ * client
+ */
+ private final ConcurrentHashMap<String, TopicSubscriberAdaptor> _subscriptions =
+ new ConcurrentHashMap<String, TopicSubscriberAdaptor>();
+ private final ConcurrentHashMap<BasicMessageConsumer, String> _reverseSubscriptionMap =
+ new ConcurrentHashMap<BasicMessageConsumer, String>();
+
+ /**
* Used in the consume method. We generate the consume tag on the client so that we can use the nowait
* feature.
*/
@@ -91,6 +107,12 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
private Map _consumers = new ConcurrentHashMap();
/**
+ * Maps from destination to count of JMSMessageConsumers
+ */
+ private ConcurrentHashMap<Destination, AtomicInteger> _destinationConsumerCount =
+ new ConcurrentHashMap<Destination, AtomicInteger>();
+
+ /**
* Default value for immediate flag used by producers created by this session is false, i.e. a consumer does not
* need to be attached to a queue
*/
@@ -116,6 +138,9 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
*/
private volatile AtomicBoolean _stopped = new AtomicBoolean(true);
+ private final AtomicLong _lastDeliveryTag = new AtomicLong();
+
+
/**
* Responsible for decoding a message fragment and passing it to the appropriate message consumer.
*/
@@ -154,10 +179,14 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
if (consumer == null)
{
_logger.warn("Received a message from queue " + message.deliverBody.consumerTag + " without a handler - ignoring...");
+ _logger.warn("Consumers that exist: " + _consumers);
+ _logger.warn("Session hashcode: " + System.identityHashCode(this));
}
else
{
+
consumer.notifyMessage(message, _channelId);
+
}
}
else
@@ -673,6 +702,27 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
_connection.getProtocolHandler().writeFrame(BasicRecoverBody.createAMQFrame(_channelId, false));
}
+
+ public void acknowledge() throws JMSException
+ {
+ if (getAMQConnection().isClosed())
+ {
+ throw new javax.jms.IllegalStateException("Connection is already closed");
+ }
+ if (isClosed())
+ {
+ throw new javax.jms.IllegalStateException("Session is already closed");
+ }
+ acknowledgeMessage(_lastDeliveryTag.get(), true);
+
+ }
+
+ void setLastDeliveredMessage(AbstractJMSMessage message)
+ {
+ _lastDeliveryTag.set(message.getDeliveryTag());
+ }
+
+
public MessageListener getMessageListener() throws JMSException
{
checkNotClosed();
@@ -775,20 +825,38 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
public MessageConsumer createConsumer(Destination destination) throws JMSException
{
checkValidDestination(destination);
- return createConsumer(destination, _defaultPrefetchHighMark, _defaultPrefetchLowMark, false, false, null);
+ return createConsumerImpl(destination,
+ _defaultPrefetchHighMark,
+ _defaultPrefetchLowMark,
+ false,
+ false,
+ null,
+ null);
}
public MessageConsumer createConsumer(Destination destination, String messageSelector) throws JMSException
{
checkValidDestination(destination);
- return createConsumer(destination, _defaultPrefetchHighMark, _defaultPrefetchLowMark, false, false, messageSelector);
+ return createConsumerImpl(destination,
+ _defaultPrefetchHighMark,
+ _defaultPrefetchLowMark,
+ false,
+ false,
+ messageSelector,
+ null);
}
public MessageConsumer createConsumer(Destination destination, String messageSelector, boolean noLocal)
throws JMSException
{
checkValidDestination(destination);
- return createConsumer(destination, _defaultPrefetchHighMark, _defaultPrefetchLowMark, noLocal, false, messageSelector);
+ return createConsumerImpl(destination,
+ _defaultPrefetchHighMark,
+ _defaultPrefetchLowMark,
+ noLocal,
+ false,
+ messageSelector,
+ null);
}
public MessageConsumer createConsumer(Destination destination,
@@ -798,7 +866,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
String selector) throws JMSException
{
checkValidDestination(destination);
- return createConsumer(destination, prefetch, prefetch, noLocal, exclusive, selector, null);
+ return createConsumerImpl(destination, prefetch, prefetch, noLocal, exclusive, selector, null);
}
@@ -810,7 +878,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
String selector) throws JMSException
{
checkValidDestination(destination);
- return createConsumer(destination, prefetchHigh, prefetchLow, noLocal, exclusive, selector, null);
+ return createConsumerImpl(destination, prefetchHigh, prefetchLow, noLocal, exclusive, selector, null);
}
public MessageConsumer createConsumer(Destination destination,
@@ -846,6 +914,8 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
final String selector,
final FieldTable rawSelector) throws JMSException
{
+ checkTemporaryDestination(destination);
+
return (org.apache.qpid.jms.MessageConsumer) new FailoverSupport()
{
public Object operation() throws JMSException
@@ -870,7 +940,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
try
{
- registerConsumer(consumer);
+ registerConsumer(consumer, false);
}
catch (AMQException e)
{
@@ -879,11 +949,46 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
throw ex;
}
+ synchronized(destination)
+ {
+ _destinationConsumerCount.putIfAbsent(destination,new AtomicInteger());
+ _destinationConsumerCount.get(destination).incrementAndGet();
+ }
+
return consumer;
}
}.execute(_connection);
}
+ private void checkTemporaryDestination(Destination destination)
+ throws JMSException
+ {
+ if((destination instanceof TemporaryDestination))
+ {
+ _logger.debug("destination is temporary");
+ final TemporaryDestination tempDest = (TemporaryDestination) destination;
+ if(tempDest.getSession() != this)
+ {
+ _logger.debug("destination is on different session");
+ throw new JMSException("Cannot consume from a temporary destination created onanother session");
+ }
+ if(tempDest.isDeleted())
+ {
+ _logger.debug("destination is deleted");
+ throw new JMSException("Cannot consume from a deleted destination");
+ }
+ }
+ }
+
+
+ public boolean hasConsumer(Destination destination)
+ {
+ AtomicInteger counter = _destinationConsumerCount.get(destination);
+
+ return (counter != null) && (counter.get() != 0);
+ }
+
+
public void declareExchange(String name, String type)
{
declareExchange(name, type, _connection.getProtocolHandler());
@@ -947,20 +1052,38 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
* @param queueName
* @return the consumer tag generated by the broker
*/
- private String consumeFromQueue(String queueName, AMQProtocolHandler protocolHandler, int prefetchHigh, int prefetchLow,
- boolean noLocal, boolean exclusive, int acknowledgeMode) throws AMQException
+ private void consumeFromQueue(BasicMessageConsumer consumer, String queueName, AMQProtocolHandler protocolHandler,
+ boolean nowait) throws AMQException
{
//fixme prefetch values are not used here. Do we need to have them as parametsrs?
//need to generate a consumer tag on the client so we can exploit the nowait flag
String tag = Integer.toString(_nextTag++);
- AMQFrame jmsConsume = BasicConsumeBody.createAMQFrame(_channelId, 0,
- queueName, tag, noLocal,
- acknowledgeMode == Session.NO_ACKNOWLEDGE,
- exclusive, true);
+ consumer.setConsumerTag(tag);
+ // we must register the consumer in the map before we actually start listening
+ _consumers.put(tag, consumer);
- protocolHandler.writeFrame(jmsConsume);
- return tag;
+ try
+ {
+ AMQFrame jmsConsume = BasicConsumeBody.createAMQFrame(_channelId, 0,
+ queueName, tag, consumer.isNoLocal(),
+ consumer.getAcknowledgeMode() == Session.NO_ACKNOWLEDGE,
+ consumer.isExclusive(), nowait, null);
+ if (nowait)
+ {
+ protocolHandler.writeFrame(jmsConsume);
+ }
+ else
+ {
+ protocolHandler.syncWrite(jmsConsume, BasicConsumeOkBody.class);
+ }
+ }
+ catch (AMQException e)
+ {
+ // clean-up the map in the event of an error
+ _consumers.remove(tag);
+ throw e;
+ }
}
public Queue createQueue(String queueName) throws JMSException
@@ -1081,19 +1204,55 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
return new TopicSubscriberAdaptor(dest, (BasicMessageConsumer) createConsumer(dest, messageSelector, noLocal));
}
- /**
- * Note, currently this does not handle reuse of the same name with different topics correctly.
- * If a name is reused in creating a new subscriber with a different topic/selecto or no-local
- * flag then the subcriber will receive messages matching the old subscription AND the new one.
- * The spec states that the new one should replace the old one.
- * TODO: fix it.
- */
public TopicSubscriber createDurableSubscriber(Topic topic, String name) throws JMSException
{
checkNotClosed();
checkValidTopic(topic);
- AMQTopic dest = new AMQTopic((AMQTopic) topic, _connection.getClientID(), name);
- return new TopicSubscriberAdaptor(dest, (BasicMessageConsumer) createConsumer(dest));
+ AMQTopic dest = AMQTopic.createDurableTopic((AMQTopic)topic, name, _connection);
+ TopicSubscriberAdaptor subscriber = _subscriptions.get(name);
+ if (subscriber != null)
+ {
+ if (subscriber.getTopic().equals(topic))
+ {
+ throw new IllegalStateException("Already subscribed to topic " + topic + " with subscription exchange " +
+ name);
+ }
+ else
+ {
+ unsubscribe(name);
+ }
+ }
+ else
+ {
+ // if the queue is bound to the exchange but NOT for this topic, then the JMS spec
+ // says we must trash the subscription.
+ if (isQueueBound(dest.getQueueName()) &&
+ !isQueueBound(dest.getQueueName(), topic.getTopicName()))
+ {
+ deleteQueue(dest.getQueueName());
+ }
+ }
+
+ subscriber = new TopicSubscriberAdaptor(dest, (BasicMessageConsumer) createConsumer(dest));
+
+ _subscriptions.put(name,subscriber);
+ _reverseSubscriptionMap.put(subscriber.getMessageConsumer(),name);
+
+ return subscriber;
+ }
+
+ void deleteQueue(String queueName) throws JMSException
+ {
+ try
+ {
+ AMQFrame queueDeleteFrame = QueueDeleteBody.createAMQFrame(_channelId, 0, queueName, false,
+ false, true);
+ _connection.getProtocolHandler().syncWrite(queueDeleteFrame, QueueDeleteOkBody.class);
+ }
+ catch (AMQException e)
+ {
+ throw new JMSAMQException(e);
+ }
}
/**
@@ -1104,9 +1263,12 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
{
checkNotClosed();
checkValidTopic(topic);
- AMQTopic dest = new AMQTopic((AMQTopic) topic, _connection.getClientID(), name);
+ AMQTopic dest = AMQTopic.createDurableTopic((AMQTopic) topic, name, _connection);
BasicMessageConsumer consumer = (BasicMessageConsumer) createConsumer(dest, messageSelector, noLocal);
- return new TopicSubscriberAdaptor(dest, consumer);
+ TopicSubscriberAdaptor subscriber = new TopicSubscriberAdaptor(dest, consumer);
+ _subscriptions.put(name,subscriber);
+ _reverseSubscriptionMap.put(subscriber.getMessageConsumer(),name);
+ return subscriber;
}
public TopicPublisher createPublisher(Topic topic) throws JMSException
@@ -1132,32 +1294,59 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
public TemporaryQueue createTemporaryQueue() throws JMSException
{
checkNotClosed();
- return new AMQTemporaryQueue();
+ return new AMQTemporaryQueue(this);
}
public TemporaryTopic createTemporaryTopic() throws JMSException
{
checkNotClosed();
- return new AMQTemporaryTopic();
+ return new AMQTemporaryTopic(this);
}
public void unsubscribe(String name) throws JMSException
{
checkNotClosed();
-
- String queue = _connection.getClientID() + ":" + name;
-
- AMQFrame queueDeclareFrame = QueueDeclareBody.createAMQFrame(_channelId,0,queue,true,false, false, false, true, null);
-
- try {
- AMQMethodEvent event = _connection.getProtocolHandler().syncWrite(queueDeclareFrame,QueueDeclareOkBody.class);
- // if this method doen't throw an exception means we have received a queue declare ok.
- } catch (AMQException e) {
- throw new javax.jms.InvalidDestinationException("This destination doesn't exist");
- }
- //send a queue.delete for the subscription
- AMQFrame frame = QueueDeleteBody.createAMQFrame(_channelId, 0, queue, false, false, true);
- _connection.getProtocolHandler().writeFrame(frame);
+ TopicSubscriberAdaptor subscriber = _subscriptions.get(name);
+ if (subscriber != null)
+ {
+ // send a queue.delete for the subscription
+ deleteQueue(AMQTopic.getDurableTopicQueueName(name, _connection));
+ _subscriptions.remove(name);
+ _reverseSubscriptionMap.remove(subscriber);
+ }
+ else
+ {
+ if (isQueueBound(AMQTopic.getDurableTopicQueueName(name, _connection)))
+ {
+ deleteQueue(AMQTopic.getDurableTopicQueueName(name, _connection));
+ }
+ else
+ {
+ throw new InvalidDestinationException("Unknown subscription exchange:" + name);
+ }
+ }
+ }
+
+ boolean isQueueBound(String queueName) throws JMSException
+ {
+ return isQueueBound(queueName, null);
+ }
+
+ boolean isQueueBound(String queueName, String routingKey) throws JMSException
+ {
+ AMQFrame boundFrame = ExchangeBoundBody.createAMQFrame(_channelId, ExchangeDefaults.TOPIC_EXCHANGE_NAME,
+ routingKey, queueName);
+ AMQMethodEvent response = null;
+ try
+ {
+ response = _connection.getProtocolHandler().syncWrite(boundFrame, ExchangeBoundOkBody.class);
+ }
+ catch (AMQException e)
+ {
+ throw new JMSAMQException(e);
+ }
+ ExchangeBoundOkBody responseBody = (ExchangeBoundOkBody) response.getMethod();
+ return (responseBody.replyCode == ExchangeBoundHandler.OK);
}
private void checkTransacted() throws JMSException
@@ -1263,7 +1452,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
* @param consumer
* @throws AMQException
*/
- void registerConsumer(BasicMessageConsumer consumer) throws AMQException
+ void registerConsumer(BasicMessageConsumer consumer, boolean nowait) throws AMQException
{
AMQDestination amqd = consumer.getDestination();
@@ -1275,22 +1464,32 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
bindQueue(amqd, queueName, protocolHandler, consumer.getRawSelectorFieldTable());
- String consumerTag = consumeFromQueue(queueName, protocolHandler, consumer.getPrefetchHigh(), consumer.getPrefetchLow(),
- consumer.isNoLocal(), consumer.isExclusive(), consumer.getAcknowledgeMode());
-
- consumer.setConsumerTag(consumerTag);
- _consumers.put(consumerTag, consumer);
+ consumeFromQueue(consumer, queueName, protocolHandler, nowait);
}
/**
* Called by the MessageConsumer when closing, to deregister the consumer from the
* map from consumerTag to consumer instance.
*
- * @param consumerTag the consumer tag, that was broker-generated
+ * @param consumer the consum
*/
- void deregisterConsumer(String consumerTag)
+ void deregisterConsumer(BasicMessageConsumer consumer)
{
- _consumers.remove(consumerTag);
+ _consumers.remove(consumer.getConsumerTag());
+ String subscriptionName = _reverseSubscriptionMap.remove(consumer);
+ if(subscriptionName != null)
+ {
+ _subscriptions.remove(subscriptionName);
+ }
+
+ Destination dest = consumer.getDestination();
+ synchronized(dest)
+ {
+ if(_destinationConsumerCount.get(dest).decrementAndGet() == 0)
+ {
+ _destinationConsumerCount.remove(dest);
+ }
+ }
}
private void registerProducer(long producerId, MessageProducer producer)
@@ -1338,7 +1537,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
for (Iterator it = consumers.iterator(); it.hasNext();)
{
BasicMessageConsumer consumer = (BasicMessageConsumer) it.next();
- registerConsumer(consumer);
+ registerConsumer(consumer, true);
}
}
@@ -1359,12 +1558,16 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
/*
* I could have combined the last 3 methods, but this way it improves readability
*/
- private void checkValidTopic(Topic topic) throws InvalidDestinationException
+ private void checkValidTopic(Topic topic) throws JMSException
{
if (topic == null)
{
throw new javax.jms.InvalidDestinationException("Invalid Topic");
}
+ if((topic instanceof TemporaryDestination) && ((TemporaryDestination)topic).getSession() != this)
+ {
+ throw new JMSException("Cannot create a subscription on a temporary topic created in another session");
+ }
}
private void checkValidQueue(Queue queue) throws InvalidDestinationException
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQTemporaryQueue.java b/java/client/src/main/java/org/apache/qpid/client/AMQTemporaryQueue.java
index 6b41ea0112..81fee69f90 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQTemporaryQueue.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQTemporaryQueue.java
@@ -26,25 +26,45 @@ import javax.jms.TemporaryQueue;
/**
* AMQ implementation of a TemporaryQueue.
*/
-final class AMQTemporaryQueue extends AMQQueue implements TemporaryQueue
+final class AMQTemporaryQueue extends AMQQueue implements TemporaryQueue, TemporaryDestination
{
+ private final AMQSession _session;
+ private boolean _deleted;
+
/**
* Create a new instance of an AMQTemporaryQueue
*/
- public AMQTemporaryQueue()
+ public AMQTemporaryQueue(AMQSession session)
{
super("TempQueue" + Long.toString(System.currentTimeMillis()), true);
+ _session = session;
}
/**
* @see javax.jms.TemporaryQueue#delete()
*/
- public void delete() throws JMSException
+ public synchronized void delete() throws JMSException
{
- throw new UnsupportedOperationException("Delete not supported, " +
- "will auto-delete when connection closed");
+ if(_session.hasConsumer(this))
+ {
+ throw new JMSException("Temporary Queue has consumers so cannot be deleted");
+ }
+ _deleted = true;
+
+ // Currently TemporaryQueue is set to be auto-delete which means that the queue will be deleted
+ // by the server when there are no more subscriptions to that queue. This is probably not
+ // quite right for JMSCompliance.
}
+ public AMQSession getSession()
+ {
+ return _session;
+ }
+
+ public boolean isDeleted()
+ {
+ return _deleted;
+ }
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQTemporaryTopic.java b/java/client/src/main/java/org/apache/qpid/client/AMQTemporaryTopic.java
index 0ba5cb3c3a..241a9abc9b 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQTemporaryTopic.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQTemporaryTopic.java
@@ -26,15 +26,18 @@ import javax.jms.TemporaryTopic;
/**
* AMQ implementation of TemporaryTopic.
*/
-class AMQTemporaryTopic extends AMQTopic implements TemporaryTopic
+class AMQTemporaryTopic extends AMQTopic implements TemporaryTopic, TemporaryDestination
{
+ private final AMQSession _session;
+ private boolean _deleted;
/**
* Create new temporary topic.
*/
- public AMQTemporaryTopic()
+ public AMQTemporaryTopic(AMQSession session)
{
super("TempQueue" + Long.toString(System.currentTimeMillis()));
+ _session = session;
}
/**
@@ -42,8 +45,25 @@ class AMQTemporaryTopic extends AMQTopic implements TemporaryTopic
*/
public void delete() throws JMSException
{
- throw new UnsupportedOperationException("Delete not supported, " +
- "will auto-delete when connection closed");
+ if(_session.hasConsumer(this))
+ {
+ throw new JMSException("Temporary Topic has consumers so cannot be deleted");
+ }
+
+ _deleted = true;
+ // Currently TemporaryQueue is set to be auto-delete which means that the queue will be deleted
+ // by the server when there are no more subscriptions to that queue. This is probably not
+ // quite right for JMSCompliance.
+ }
+
+ public AMQSession getSession()
+ {
+ return _session;
+ }
+
+ public boolean isDeleted()
+ {
+ return _deleted;
}
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/AMQTopic.java b/java/client/src/main/java/org/apache/qpid/client/AMQTopic.java
index 4dd38eea18..39304f3f4c 100644
--- a/java/client/src/main/java/org/apache/qpid/client/AMQTopic.java
+++ b/java/client/src/main/java/org/apache/qpid/client/AMQTopic.java
@@ -7,9 +7,9 @@
* 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
@@ -40,20 +40,25 @@ public class AMQTopic extends AMQDestination implements Topic
public AMQTopic(String name)
{
- super(ExchangeDefaults.TOPIC_EXCHANGE_NAME, ExchangeDefaults.TOPIC_EXCHANGE_CLASS, name, true, true, null);
- _isDurable = false;
+ this(name, true, null, false);
}
- /**
- * Constructor for use in creating a topic to represent a durable subscription
- * @param topic
- * @param clientId
- * @param subscriptionName
- */
- public AMQTopic(AMQTopic topic, String clientId, String subscriptionName)
+ public AMQTopic(String name, boolean isAutoDelete, String queueName, boolean isDurable)
+ {
+ super(ExchangeDefaults.TOPIC_EXCHANGE_NAME, ExchangeDefaults.TOPIC_EXCHANGE_CLASS, name, true, isAutoDelete,
+ queueName, isDurable);
+ }
+
+ public static AMQTopic createDurableTopic(AMQTopic topic, String subscriptionName, AMQConnection connection)
+ throws JMSException
+ {
+ return new AMQTopic(topic.getDestinationName(), false, getDurableTopicQueueName(subscriptionName, connection),
+ true);
+ }
+
+ public static String getDurableTopicQueueName(String subscriptionName, AMQConnection connection) throws JMSException
{
- super(ExchangeDefaults.TOPIC_EXCHANGE_NAME, ExchangeDefaults.TOPIC_EXCHANGE_CLASS, topic.getDestinationName(), true, false, clientId + ":" + subscriptionName);
- _isDurable = true;
+ return connection.getClientID() + ":" + subscriptionName;
}
public String getTopicName() throws JMSException
diff --git a/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java b/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java
index 4fb62b49fc..9f9038fddd 100644
--- a/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java
+++ b/java/client/src/main/java/org/apache/qpid/client/BasicMessageConsumer.java
@@ -7,9 +7,9 @@
* 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
@@ -214,10 +214,10 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
{
//handle case where connection has already been started, and the dispatcher is blocked
//doing a put on the _synchronousQueue
- Object msg = _synchronousQueue.poll();
- if (msg != null)
+ AbstractJMSMessage jmsMsg = (AbstractJMSMessage)_synchronousQueue.poll();
+ if (jmsMsg != null)
{
- AbstractJMSMessage jmsMsg = (AbstractJMSMessage) msg;
+ _session.setLastDeliveredMessage(jmsMsg);
messageListener.onMessage(jmsMsg);
postDeliver(jmsMsg);
}
@@ -280,7 +280,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
public Message receive(long l) throws JMSException
{
checkPreConditions();
-
+
acquireReceiving();
try
@@ -297,12 +297,15 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
final AbstractJMSMessage m = returnMessageOrThrow(o);
if (m != null)
{
+ _session.setLastDeliveredMessage(m);
postDeliver(m);
}
+
return m;
}
catch (InterruptedException e)
{
+ _logger.warn("Interrupted: " + e, e);
return null;
}
finally
@@ -323,8 +326,10 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
final AbstractJMSMessage m = returnMessageOrThrow(o);
if (m != null)
{
+ _session.setLastDeliveredMessage(m);
postDeliver(m);
}
+
return m;
}
finally
@@ -423,6 +428,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
{
//we do not need a lock around the test above, and the dispatch below as it is invalid
//for an application to alter an installed listener while the session is started
+ _session.setLastDeliveredMessage(jmsMessage);
getMessageListener().onMessage(jmsMessage);
postDeliver(jmsMessage);
}
@@ -459,8 +465,9 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
}
}
- private void postDeliver(AbstractJMSMessage msg)
+ private void postDeliver(AbstractJMSMessage msg) throws JMSException
{
+ msg.setJMSDestination(_destination);
switch (_acknowledgeMode)
{
case Session.DUPS_OK_ACKNOWLEDGE:
@@ -522,7 +529,7 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
*/
private void deregisterConsumer()
{
- _session.deregisterConsumer(_consumerTag);
+ _session.deregisterConsumer(this);
}
public String getConsumerTag()
@@ -531,18 +538,18 @@ public class BasicMessageConsumer extends Closeable implements MessageConsumer
}
public void setConsumerTag(String consumerTag)
- {
+ {
_consumerTag = consumerTag;
}
public AMQSession getSession() {
return _session;
}
-
+
private void checkPreConditions() throws JMSException{
-
+
this.checkNotClosed();
-
+
if(_session == null || _session.isClosed()){
throw new javax.jms.IllegalStateException("Invalid Session");
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java b/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java
index 8c53d93de6..e11d70cf41 100644
--- a/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java
+++ b/java/client/src/main/java/org/apache/qpid/client/BasicMessageProducer.java
@@ -24,11 +24,13 @@ import org.apache.log4j.Logger;
import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.AMQException;
import org.apache.qpid.client.message.AbstractJMSMessage;
+import org.apache.qpid.client.message.JMSBytesMessage;
import org.apache.qpid.client.protocol.AMQProtocolHandler;
import org.apache.qpid.framing.*;
import javax.jms.*;
import java.io.UnsupportedEncodingException;
+import java.util.Enumeration;
public class BasicMessageProducer extends Closeable implements org.apache.qpid.jms.MessageProducer
{
@@ -140,7 +142,7 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j
public void setDisableMessageID(boolean b) throws JMSException
{
- checkPreConditions();
+ checkPreConditions();
checkNotClosed();
// IGNORED
}
@@ -154,7 +156,7 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j
public void setDisableMessageTimestamp(boolean b) throws JMSException
{
- checkPreConditions();
+ checkPreConditions();
_disableTimestamps = b;
}
@@ -166,11 +168,11 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j
public void setDeliveryMode(int i) throws JMSException
{
- checkPreConditions();
+ checkPreConditions();
if (i != DeliveryMode.NON_PERSISTENT && i != DeliveryMode.PERSISTENT)
{
throw new JMSException("DeliveryMode must be either NON_PERSISTENT or PERSISTENT. Value of " + i +
- " is illegal");
+ " is illegal");
}
_deliveryMode = i;
}
@@ -183,7 +185,7 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j
public void setPriority(int i) throws JMSException
{
- checkPreConditions();
+ checkPreConditions();
if (i < 0 || i > 9)
{
throw new IllegalArgumentException("Priority of " + i + " is illegal. Value must be in range 0 to 9");
@@ -199,7 +201,7 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j
public void setTimeToLive(long l) throws JMSException
{
- checkPreConditions();
+ checkPreConditions();
if (l < 0)
{
throw new IllegalArgumentException("Time to live must be non-negative - supplied value was " + l);
@@ -227,33 +229,36 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j
public void send(Message message) throws JMSException
{
- checkPreConditions();
- checkInitialDestination();
+ checkPreConditions();
+ checkInitialDestination();
+
+
synchronized (_connection.getFailoverMutex())
{
- sendImpl(_destination, (AbstractJMSMessage) message, _deliveryMode, _messagePriority, _timeToLive,
+ sendImpl(_destination, message, _deliveryMode, _messagePriority, _timeToLive,
_mandatory, _immediate);
}
}
public void send(Message message, int deliveryMode) throws JMSException
{
- checkPreConditions();
- checkInitialDestination();
+ checkPreConditions();
+ checkInitialDestination();
+
synchronized (_connection.getFailoverMutex())
{
- sendImpl(_destination, (AbstractJMSMessage) message, deliveryMode, _messagePriority, _timeToLive,
+ sendImpl(_destination, message, deliveryMode, _messagePriority, _timeToLive,
_mandatory, _immediate);
}
}
public void send(Message message, int deliveryMode, boolean immediate) throws JMSException
{
- checkPreConditions();
- checkInitialDestination();
+ checkPreConditions();
+ checkInitialDestination();
synchronized (_connection.getFailoverMutex())
{
- sendImpl(_destination, (AbstractJMSMessage) message, deliveryMode, _messagePriority, _timeToLive,
+ sendImpl(_destination, message, deliveryMode, _messagePriority, _timeToLive,
_mandatory, immediate);
}
}
@@ -261,23 +266,23 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j
public void send(Message message, int deliveryMode, int priority,
long timeToLive) throws JMSException
{
- checkPreConditions();
- checkInitialDestination();
+ checkPreConditions();
+ checkInitialDestination();
synchronized (_connection.getFailoverMutex())
{
- sendImpl(_destination, (AbstractJMSMessage)message, deliveryMode, priority, timeToLive, _mandatory,
+ sendImpl(_destination, message, deliveryMode, priority, timeToLive, _mandatory,
_immediate);
}
}
public void send(Destination destination, Message message) throws JMSException
{
- checkPreConditions();
- checkDestination(destination);
+ checkPreConditions();
+ checkDestination(destination);
synchronized (_connection.getFailoverMutex())
{
validateDestination(destination);
- sendImpl((AMQDestination) destination, (AbstractJMSMessage) message, _deliveryMode, _messagePriority, _timeToLive,
+ sendImpl((AMQDestination) destination, message, _deliveryMode, _messagePriority, _timeToLive,
_mandatory, _immediate);
}
}
@@ -286,12 +291,12 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j
int priority, long timeToLive)
throws JMSException
{
- checkPreConditions();
- checkDestination(destination);
+ checkPreConditions();
+ checkDestination(destination);
synchronized (_connection.getFailoverMutex())
{
validateDestination(destination);
- sendImpl((AMQDestination) destination, (AbstractJMSMessage) message, deliveryMode, priority, timeToLive,
+ sendImpl((AMQDestination) destination, message, deliveryMode, priority, timeToLive,
_mandatory, _immediate);
}
}
@@ -305,7 +310,7 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j
synchronized (_connection.getFailoverMutex())
{
validateDestination(destination);
- sendImpl((AMQDestination) destination, (AbstractJMSMessage) message, deliveryMode, priority, timeToLive,
+ sendImpl((AMQDestination) destination, message, deliveryMode, priority, timeToLive,
mandatory, _immediate);
}
}
@@ -314,12 +319,12 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j
int priority, long timeToLive, boolean mandatory, boolean immediate)
throws JMSException
{
- checkPreConditions();
- checkDestination(destination);
+ checkPreConditions();
+ checkDestination(destination);
synchronized (_connection.getFailoverMutex())
{
validateDestination(destination);
- sendImpl((AMQDestination) destination, (AbstractJMSMessage) message, deliveryMode, priority, timeToLive,
+ sendImpl((AMQDestination) destination, message, deliveryMode, priority, timeToLive,
mandatory, immediate);
}
}
@@ -329,27 +334,158 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j
boolean immediate, boolean waitUntilSent)
throws JMSException
{
- checkPreConditions();
- checkDestination(destination);
+ checkPreConditions();
+ checkDestination(destination);
synchronized (_connection.getFailoverMutex())
{
validateDestination(destination);
- sendImpl((AMQDestination) destination, (AbstractJMSMessage) message, deliveryMode, priority, timeToLive,
+ sendImpl((AMQDestination) destination, message, deliveryMode, priority, timeToLive,
mandatory, immediate, waitUntilSent);
}
}
+
+ private AbstractJMSMessage convertToNativeMessage(Message message) throws JMSException
+ {
+ if (message instanceof AbstractJMSMessage)
+ {
+ return (AbstractJMSMessage) message;
+ }
+ else
+ {
+ AbstractJMSMessage newMessage;
+
+ if (message instanceof BytesMessage)
+ {
+ BytesMessage bytesMessage = (BytesMessage) message;
+ bytesMessage.reset();
+
+ JMSBytesMessage nativeMsg = (JMSBytesMessage) _session.createBytesMessage();
+
+
+ byte[] buf = new byte[1024];
+
+ int len;
+
+ while ((len = bytesMessage.readBytes(buf)) != -1)
+ {
+ nativeMsg.writeBytes(buf, 0, len);
+ }
+
+ newMessage = nativeMsg;
+ }
+ else if (message instanceof MapMessage)
+ {
+ MapMessage origMessage = (MapMessage) message;
+ MapMessage nativeMessage = _session.createMapMessage();
+
+ Enumeration mapNames = origMessage.getMapNames();
+ while (mapNames.hasMoreElements())
+ {
+ String name = (String) mapNames.nextElement();
+ nativeMessage.setObject(name, origMessage.getObject(name));
+ }
+ newMessage = (AbstractJMSMessage) nativeMessage;
+ }
+ else if (message instanceof ObjectMessage)
+ {
+ ObjectMessage origMessage = (ObjectMessage) message;
+ ObjectMessage nativeMessage = _session.createObjectMessage();
+
+ nativeMessage.setObject(origMessage.getObject());
+
+ newMessage = (AbstractJMSMessage) nativeMessage;
+ }
+ else if (message instanceof TextMessage)
+ {
+ TextMessage origMessage = (TextMessage) message;
+ TextMessage nativeMessage = _session.createTextMessage();
+
+ nativeMessage.setText(origMessage.getText());
+
+ newMessage = (AbstractJMSMessage) nativeMessage;
+ }
+ else if (message instanceof StreamMessage)
+ {
+ StreamMessage origMessage = (StreamMessage) message;
+ StreamMessage nativeMessage = _session.createStreamMessage();
+
+
+ try
+ {
+ origMessage.reset();
+ while (true)
+ {
+ nativeMessage.writeObject(origMessage.readObject());
+ }
+ }
+ catch (MessageEOFException e)
+ {
+ ;//
+ }
+ newMessage = (AbstractJMSMessage) nativeMessage;
+ }
+ else
+ {
+ newMessage = (AbstractJMSMessage) _session.createMessage();
+
+ }
+
+ Enumeration propertyNames = message.getPropertyNames();
+ while (propertyNames.hasMoreElements())
+ {
+ String propertyName = String.valueOf(propertyNames.nextElement());
+ if (!propertyName.startsWith("JMSX_"))
+ {
+ Object value = message.getObjectProperty(propertyName);
+ newMessage.setObjectProperty(propertyName, value);
+ }
+ }
+
+ newMessage.setJMSDeliveryMode(message.getJMSDeliveryMode());
+
+
+ int priority = message.getJMSPriority();
+ if (priority < 0)
+ {
+ priority = 0;
+ }
+ else if (priority > 9)
+ {
+ priority = 9;
+ }
+
+ newMessage.setJMSPriority(priority);
+ if (message.getJMSReplyTo() != null)
+ {
+ newMessage.setJMSReplyTo(message.getJMSReplyTo());
+ }
+ newMessage.setJMSType(message.getJMSType());
+
+
+ if (newMessage != null)
+ {
+ return newMessage;
+ }
+ else
+ {
+ throw new JMSException("Unable to send message, due to class conversion error: " + message.getClass().getName());
+ }
+ }
+ }
+
+
private void validateDestination(Destination destination) throws JMSException
{
if (!(destination instanceof AMQDestination))
{
throw new JMSException("Unsupported destination class: " +
- (destination != null ? destination.getClass() : null));
+ (destination != null ? destination.getClass() : null));
}
- declareDestination((AMQDestination)destination);
+ declareDestination((AMQDestination) destination);
}
- protected void sendImpl(AMQDestination destination, AbstractJMSMessage message, int deliveryMode, int priority,
+ protected void sendImpl(AMQDestination destination, Message message, int deliveryMode, int priority,
long timeToLive, boolean mandatory, boolean immediate) throws JMSException
{
sendImpl(destination, message, deliveryMode, priority, timeToLive, mandatory, immediate, _waitUntilSent);
@@ -357,8 +493,9 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j
/**
* The caller of this method must hold the failover mutex.
+ *
* @param destination
- * @param message
+ * @param origMessage
* @param deliveryMode
* @param priority
* @param timeToLive
@@ -366,9 +503,12 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j
* @param immediate
* @throws JMSException
*/
- protected void sendImpl(AMQDestination destination, AbstractJMSMessage message, int deliveryMode, int priority,
+ protected void sendImpl(AMQDestination destination, Message origMessage, int deliveryMode, int priority,
long timeToLive, boolean mandatory, boolean immediate, boolean wait) throws JMSException
{
+ checkTemporaryDestination(destination);
+
+ AbstractJMSMessage message = convertToNativeMessage(origMessage);
AMQFrame publishFrame = BasicPublishBody.createAMQFrame(_channelId, 0, destination.getExchangeName(),
destination.getRoutingKey(), mandatory, immediate);
@@ -424,11 +564,42 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j
frames[1] = contentHeaderFrame;
CompositeAMQDataBlock compositeFrame = new CompositeAMQDataBlock(frames);
_protocolHandler.writeFrame(compositeFrame, wait);
+
+
+ if (message != origMessage)
+ {
+ _logger.warn("Updating original message");
+ origMessage.setJMSPriority(message.getJMSPriority());
+ origMessage.setJMSTimestamp(message.getJMSTimestamp());
+ _logger.warn("Setting JMSExpiration:" + message.getJMSExpiration());
+ origMessage.setJMSExpiration(message.getJMSExpiration());
+ origMessage.setJMSMessageID(message.getJMSMessageID());
+ }
+ }
+
+ private void checkTemporaryDestination(AMQDestination destination) throws JMSException
+ {
+ if(destination instanceof TemporaryDestination)
+ {
+ _logger.debug("destination is temporary destination");
+ TemporaryDestination tempDest = (TemporaryDestination) destination;
+ if(tempDest.getSession().isClosed())
+ {
+ _logger.debug("session is closed");
+ throw new JMSException("Session for temporary destination has been closed");
+ }
+ if(tempDest.isDeleted())
+ {
+ _logger.debug("destination is deleted");
+ throw new JMSException("Cannot send to a deleted temporary destination");
+ }
+ }
}
/**
* Create content bodies. This will split a large message into numerous bodies depending on the negotiated
* maximum frame size.
+ *
* @param payload
* @return the array of content bodies
*/
@@ -458,8 +629,8 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j
for (int i = 0; i < bodies.length; i++)
{
bodies[i] = new ContentBody();
- payload.position((int)framePayloadMax * i);
- int length = (remaining >= framePayloadMax) ? (int)framePayloadMax : (int)remaining;
+ payload.position((int) framePayloadMax * i);
+ int length = (remaining >= framePayloadMax) ? (int) framePayloadMax : (int) remaining;
payload.limit(payload.position() + length);
bodies[i].payload = payload.slice();
remaining -= length;
@@ -480,32 +651,42 @@ public class BasicMessageProducer extends Closeable implements org.apache.qpid.j
_encoding = encoding;
}
- private void checkPreConditions() throws javax.jms.IllegalStateException, JMSException {
- checkNotClosed();
+ private void checkPreConditions() throws javax.jms.IllegalStateException, JMSException
+ {
+ checkNotClosed();
+
+ if (_session == null || _session.isClosed())
+ {
+ throw new javax.jms.IllegalStateException("Invalid Session");
+ }
+ }
+
+ private void checkInitialDestination()
+ {
+ if (_destination == null)
+ {
+ throw new UnsupportedOperationException("Destination is null");
+ }
+ }
- if(_session == null || _session.isClosed()){
- throw new javax.jms.IllegalStateException("Invalid Session");
- }
- }
+ private void checkDestination(Destination suppliedDestination) throws InvalidDestinationException
+ {
+ if (_destination != null && suppliedDestination != null)
+ {
+ throw new UnsupportedOperationException("This message producer was created with a Destination, therefore you cannot use an unidentified Destination");
+ }
- private void checkInitialDestination(){
- if(_destination == null){
- throw new UnsupportedOperationException("Destination is null");
- }
- }
+ if (suppliedDestination == null)
+ {
+ throw new InvalidDestinationException("Supplied Destination was invalid");
+ }
- private void checkDestination(Destination suppliedDestination) throws InvalidDestinationException{
- if (_destination != null && suppliedDestination != null){
- throw new UnsupportedOperationException("This message producer was created with a Destination, therefore you cannot use an unidentified Destination");
- }
- if (suppliedDestination == null){
- throw new InvalidDestinationException("Supplied Destination was invalid");
- }
- }
+ }
- public AMQSession getSession() {
- return _session;
- }
+ public AMQSession getSession()
+ {
+ return _session;
+ }
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/JMSAMQException.java b/java/client/src/main/java/org/apache/qpid/client/JMSAMQException.java
new file mode 100644
index 0000000000..34ec49436e
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/client/JMSAMQException.java
@@ -0,0 +1,34 @@
+/*
+ *
+ * Copyright (c) 2006 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.qpid.client;
+
+import org.apache.qpid.AMQException;
+
+import javax.jms.JMSException;
+
+/**
+ * @author Apache Software Foundation
+ */
+public class JMSAMQException extends JMSException
+{
+ public JMSAMQException(AMQException s)
+ {
+ super(s.getMessage(), String.valueOf(s.getErrorCode()));
+ setLinkedException(s);
+ }
+}
diff --git a/java/client/src/main/java/org/apache/qpid/client/QueueSenderAdapter.java b/java/client/src/main/java/org/apache/qpid/client/QueueSenderAdapter.java
index f90cc97a80..c8de298ba1 100644
--- a/java/client/src/main/java/org/apache/qpid/client/QueueSenderAdapter.java
+++ b/java/client/src/main/java/org/apache/qpid/client/QueueSenderAdapter.java
@@ -10,119 +10,124 @@ import javax.jms.QueueSender;
public class QueueSenderAdapter implements QueueSender {
- private MessageProducer delegate;
- private Queue queue;
+ private MessageProducer _delegate;
+ private Queue _queue;
private boolean closed = false;
public QueueSenderAdapter(MessageProducer msgProducer, Queue queue){
- delegate = msgProducer;
- this.queue = queue;
+ _delegate = msgProducer;
+ _queue = queue;
}
public Queue getQueue() throws JMSException {
checkPreConditions();
- return queue;
+ return _queue;
}
public void send(Message msg) throws JMSException {
checkPreConditions();
- delegate.send(msg);
+ _delegate.send(msg);
}
public void send(Queue queue, Message msg) throws JMSException {
- checkPreConditions();
- delegate.send(queue, msg);
+ checkPreConditions(queue);
+ _delegate.send(queue, msg);
}
public void publish(Message msg, int deliveryMode, int priority, long timeToLive)
throws JMSException {
checkPreConditions();
- delegate.send(msg, deliveryMode,priority,timeToLive);
+ _delegate.send(msg, deliveryMode,priority,timeToLive);
}
public void send(Queue queue,Message msg, int deliveryMode, int priority, long timeToLive)
throws JMSException {
- checkPreConditions();
- delegate.send(queue,msg, deliveryMode,priority,timeToLive);
+ checkPreConditions(queue);
+ _delegate.send(queue,msg, deliveryMode,priority,timeToLive);
}
public void close() throws JMSException {
- delegate.close();
+ _delegate.close();
closed = true;
}
public int getDeliveryMode() throws JMSException {
checkPreConditions();
- return delegate.getDeliveryMode();
+ return _delegate.getDeliveryMode();
}
public Destination getDestination() throws JMSException {
checkPreConditions();
- return delegate.getDestination();
+ return _delegate.getDestination();
}
public boolean getDisableMessageID() throws JMSException {
checkPreConditions();
- return delegate.getDisableMessageID();
+ return _delegate.getDisableMessageID();
}
public boolean getDisableMessageTimestamp() throws JMSException {
checkPreConditions();
- return delegate.getDisableMessageTimestamp();
+ return _delegate.getDisableMessageTimestamp();
}
public int getPriority() throws JMSException {
checkPreConditions();
- return delegate.getPriority();
+ return _delegate.getPriority();
}
public long getTimeToLive() throws JMSException {
checkPreConditions();
- return delegate.getTimeToLive();
+ return _delegate.getTimeToLive();
}
public void send(Destination dest, Message msg) throws JMSException {
- checkPreConditions();
- delegate.send(dest,msg);
+ checkPreConditions((Queue)dest);
+ _delegate.send(dest,msg);
}
public void send(Message msg, int deliveryMode, int priority, long timeToLive)
throws JMSException {
checkPreConditions();
- delegate.send(msg, deliveryMode,priority,timeToLive);
+ _delegate.send(msg, deliveryMode,priority,timeToLive);
}
public void send(Destination dest, Message msg, int deliveryMode, int priority, long timeToLive) throws JMSException {
- checkPreConditions();
- delegate.send(dest,msg, deliveryMode,priority,timeToLive);
+ checkPreConditions((Queue)dest);
+ _delegate.send(dest,msg, deliveryMode,priority,timeToLive);
}
public void setDeliveryMode(int deliveryMode) throws JMSException {
checkPreConditions();
- delegate.setDeliveryMode(deliveryMode);
+ _delegate.setDeliveryMode(deliveryMode);
}
public void setDisableMessageID(boolean disableMessageID) throws JMSException {
checkPreConditions();
- delegate.setDisableMessageID(disableMessageID);
+ _delegate.setDisableMessageID(disableMessageID);
}
public void setDisableMessageTimestamp(boolean disableMessageTimestamp) throws JMSException {
checkPreConditions();
- delegate.setDisableMessageTimestamp(disableMessageTimestamp);
+ _delegate.setDisableMessageTimestamp(disableMessageTimestamp);
}
public void setPriority(int priority) throws JMSException {
checkPreConditions();
- delegate.setPriority(priority);
+ _delegate.setPriority(priority);
}
public void setTimeToLive(long timeToLive) throws JMSException {
checkPreConditions();
- delegate.setTimeToLive(timeToLive);
+ _delegate.setTimeToLive(timeToLive);
}
-
- private void checkPreConditions() throws IllegalStateException, IllegalStateException {
+
+ private void checkPreConditions() throws IllegalStateException, IllegalStateException
+ {
+ checkPreConditions(_queue);
+ }
+
+ private void checkPreConditions(Queue queue) throws IllegalStateException, IllegalStateException {
if (closed){
throw new javax.jms.IllegalStateException("Publisher is closed");
}
@@ -131,7 +136,7 @@ public class QueueSenderAdapter implements QueueSender {
throw new UnsupportedOperationException("Queue is null");
}
- AMQSession session = ((BasicMessageProducer)delegate).getSession();
+ AMQSession session = ((BasicMessageProducer) _delegate).getSession();
if(session == null || session.isClosed()){
throw new javax.jms.IllegalStateException("Invalid Session");
diff --git a/java/client/src/main/java/org/apache/qpid/client/TemporaryDestination.java b/java/client/src/main/java/org/apache/qpid/client/TemporaryDestination.java
new file mode 100644
index 0000000000..8c11672a65
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/client/TemporaryDestination.java
@@ -0,0 +1,17 @@
+package org.apache.qpid.client;
+
+import javax.jms.*;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+/**
+ * Provides support for covenience interface implemented by both AMQTemporaryTopic and AMQTemporaryQueue
+ * so that operations related to their "temporary-ness" can be abstracted out.
+ */
+interface TemporaryDestination extends Destination
+{
+
+ public void delete() throws JMSException;
+ public AMQSession getSession();
+ public boolean isDeleted();
+
+}
diff --git a/java/client/src/main/java/org/apache/qpid/client/TopicSubscriberAdaptor.java b/java/client/src/main/java/org/apache/qpid/client/TopicSubscriberAdaptor.java
index 014c7c3311..dbc7b72813 100644
--- a/java/client/src/main/java/org/apache/qpid/client/TopicSubscriberAdaptor.java
+++ b/java/client/src/main/java/org/apache/qpid/client/TopicSubscriberAdaptor.java
@@ -35,10 +35,10 @@ import javax.jms.TopicSubscriber;
class TopicSubscriberAdaptor implements TopicSubscriber
{
private final Topic _topic;
- private final MessageConsumer _consumer;
+ private final BasicMessageConsumer _consumer;
private final boolean _noLocal;
- TopicSubscriberAdaptor(Topic topic, MessageConsumer consumer, boolean noLocal)
+ TopicSubscriberAdaptor(Topic topic, BasicMessageConsumer consumer, boolean noLocal)
{
_topic = topic;
_consumer = consumer;
@@ -119,4 +119,10 @@ class TopicSubscriberAdaptor implements TopicSubscriber
throw new javax.jms.IllegalStateException("Invalid Session");
}
}
+
+ BasicMessageConsumer getMessageConsumer()
+ {
+ return _consumer;
+ }
+
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ExchangeBoundOkMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/ExchangeBoundOkMethodHandler.java
new file mode 100644
index 0000000000..858726745e
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/ExchangeBoundOkMethodHandler.java
@@ -0,0 +1,54 @@
+/*
+ *
+ * Copyright (c) 2006 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.qpid.client.handler;
+
+import org.apache.log4j.Logger;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.client.protocol.AMQMethodEvent;
+import org.apache.qpid.client.state.AMQStateManager;
+import org.apache.qpid.client.state.StateAwareMethodListener;
+import org.apache.qpid.framing.ExchangeBoundOkBody;
+
+/**
+ * @author Apache Software Foundation
+ */
+public class ExchangeBoundOkMethodHandler implements StateAwareMethodListener
+{
+ private static final Logger _logger = Logger.getLogger(ExchangeBoundOkMethodHandler.class);
+ private static final ExchangeBoundOkMethodHandler _instance = new ExchangeBoundOkMethodHandler();
+
+ public static ExchangeBoundOkMethodHandler getInstance()
+ {
+ return _instance;
+ }
+
+ private ExchangeBoundOkMethodHandler()
+ {
+ }
+
+ public void methodReceived(AMQStateManager stateManager, AMQMethodEvent evt) throws AMQException
+ {
+ if (_logger.isDebugEnabled())
+ {
+ ExchangeBoundOkBody body = (ExchangeBoundOkBody) evt.getMethod();
+ _logger.debug("Received Exchange.Bound-Ok message, response code: " + body.replyCode + " text: " +
+ body.replyText);
+ }
+ }
+}
+
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/QueueDeleteOkMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/QueueDeleteOkMethodHandler.java
new file mode 100644
index 0000000000..3271a715a2
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/QueueDeleteOkMethodHandler.java
@@ -0,0 +1,53 @@
+/*
+ *
+ * Copyright (c) 2006 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.qpid.client.handler;
+
+import org.apache.qpid.client.state.StateAwareMethodListener;
+import org.apache.qpid.client.state.AMQStateManager;
+import org.apache.qpid.client.protocol.AMQMethodEvent;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.QueueDeleteOkBody;
+import org.apache.log4j.Logger;
+
+/**
+ * @author Apache Software Foundation
+ */
+public class QueueDeleteOkMethodHandler implements StateAwareMethodListener
+{
+ private static final Logger _logger = Logger.getLogger(QueueDeleteOkMethodHandler.class);
+ private static final QueueDeleteOkMethodHandler _instance = new QueueDeleteOkMethodHandler();
+
+ public static QueueDeleteOkMethodHandler getInstance()
+ {
+ return _instance;
+ }
+
+ private QueueDeleteOkMethodHandler()
+ {
+ }
+
+ public void methodReceived(AMQStateManager stateManager, AMQMethodEvent evt) throws AMQException
+ {
+ if (_logger.isDebugEnabled())
+ {
+ QueueDeleteOkBody body = (QueueDeleteOkBody) evt.getMethod();
+ _logger.debug("Received Queue.Delete-Ok message, message count: " + body.messageCount);
+ }
+ }
+}
+
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java
index c1ed88b167..75e84fee96 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java
@@ -32,16 +32,18 @@ import org.apache.qpid.client.AMQTopic;
import org.apache.qpid.client.JmsNotImplementedException;
import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.framing.JMSPropertyFieldTable;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageNotReadableException;
import javax.jms.MessageNotWriteableException;
+import javax.jms.MessageFormatException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Map;
-public abstract class AbstractJMSMessage extends AMQMessage implements javax.jms.Message
+public abstract class AbstractJMSMessage extends AMQMessage implements org.apache.qpid.jms.Message
{
private static final Map _destinationCache = Collections.synchronizedMap(new ReferenceMap());
@@ -50,7 +52,8 @@ public abstract class AbstractJMSMessage extends AMQMessage implements javax.jms
protected ByteBuffer _data;
private boolean _readableProperties = false;
private boolean _readableMessage = false;
-
+ private Destination _destination;
+
protected AbstractJMSMessage(ByteBuffer data)
{
super(new BasicContentHeaderProperties());
@@ -174,12 +177,12 @@ public abstract class AbstractJMSMessage extends AMQMessage implements javax.jms
public Destination getJMSDestination() throws JMSException
{
// TODO: implement this once we have sorted out how to figure out the exchange class
- throw new JmsNotImplementedException();
+ return _destination;
}
public void setJMSDestination(Destination destination) throws JMSException
{
- throw new JmsNotImplementedException();
+ _destination = destination;
}
public int getJMSDeliveryMode() throws JMSException
@@ -234,7 +237,7 @@ public abstract class AbstractJMSMessage extends AMQMessage implements javax.jms
public void clearProperties() throws JMSException
{
- getJmsContentHeaderProperties().getHeaders().clear();
+ getJmsContentHeaderProperties().getJMSHeaders().clear();
_readableProperties = false;
}
@@ -249,138 +252,139 @@ public abstract class AbstractJMSMessage extends AMQMessage implements javax.jms
public boolean propertyExists(String propertyName) throws JMSException
{
checkPropertyName(propertyName);
- return getJmsContentHeaderProperties().getHeaders().propertyExists(propertyName);
+ return getJmsContentHeaderProperties().getJMSHeaders().propertyExists(propertyName);
}
public boolean getBooleanProperty(String propertyName) throws JMSException
{
checkPropertyName(propertyName);
- return getJmsContentHeaderProperties().getHeaders().getBoolean(propertyName);
+
+ return getJmsContentHeaderProperties().getJMSHeaders().getBoolean(propertyName);
}
public byte getByteProperty(String propertyName) throws JMSException
{
checkPropertyName(propertyName);
- return getJmsContentHeaderProperties().getHeaders().getByte(propertyName);
+ return getJmsContentHeaderProperties().getJMSHeaders().getByte(propertyName);
}
public short getShortProperty(String propertyName) throws JMSException
{
checkPropertyName(propertyName);
- return getJmsContentHeaderProperties().getHeaders().getShort(propertyName);
+ return getJmsContentHeaderProperties().getJMSHeaders().getShort(propertyName);
}
public int getIntProperty(String propertyName) throws JMSException
{
checkPropertyName(propertyName);
- return getJmsContentHeaderProperties().getHeaders().getInteger(propertyName);
+ return getJmsContentHeaderProperties().getJMSHeaders().getInteger(propertyName);
}
public long getLongProperty(String propertyName) throws JMSException
{
checkPropertyName(propertyName);
- return getJmsContentHeaderProperties().getHeaders().getLong(propertyName);
+ return getJmsContentHeaderProperties().getJMSHeaders().getLong(propertyName);
}
public float getFloatProperty(String propertyName) throws JMSException
{
checkPropertyName(propertyName);
- return getJmsContentHeaderProperties().getHeaders().getFloat(propertyName);
+ return getJmsContentHeaderProperties().getJMSHeaders().getFloat(propertyName);
}
public double getDoubleProperty(String propertyName) throws JMSException
{
checkPropertyName(propertyName);
- return getJmsContentHeaderProperties().getHeaders().getDouble(propertyName);
+ return getJmsContentHeaderProperties().getJMSHeaders().getDouble(propertyName);
}
public String getStringProperty(String propertyName) throws JMSException
{
checkPropertyName(propertyName);
- return getJmsContentHeaderProperties().getHeaders().getString(propertyName);
+ return getJmsContentHeaderProperties().getJMSHeaders().getString(propertyName);
}
public Object getObjectProperty(String propertyName) throws JMSException
{
checkPropertyName(propertyName);
- return getJmsContentHeaderProperties().getHeaders().getObject(propertyName);
+ return getJmsContentHeaderProperties().getJMSHeaders().getObject(propertyName);
}
public Enumeration getPropertyNames() throws JMSException
{
- return getJmsContentHeaderProperties().getHeaders().getPropertyNames();
+ return getJmsContentHeaderProperties().getJMSHeaders().getPropertyNames();
}
public void setBooleanProperty(String propertyName, boolean b) throws JMSException
{
checkWritableProperties();
checkPropertyName(propertyName);
- getJmsContentHeaderProperties().getHeaders().setBoolean(propertyName, b);
+ getJmsContentHeaderProperties().getJMSHeaders().setBoolean(propertyName, b);
}
public void setByteProperty(String propertyName, byte b) throws JMSException
{
checkWritableProperties();
checkPropertyName(propertyName);
- getJmsContentHeaderProperties().getHeaders().setByte(propertyName, new Byte(b));
+ getJmsContentHeaderProperties().getJMSHeaders().setByte(propertyName, new Byte(b));
}
public void setShortProperty(String propertyName, short i) throws JMSException
{
checkWritableProperties();
checkPropertyName(propertyName);
- getJmsContentHeaderProperties().getHeaders().setShort(propertyName, new Short(i));
+ getJmsContentHeaderProperties().getJMSHeaders().setShort(propertyName, new Short(i));
}
public void setIntProperty(String propertyName, int i) throws JMSException
{
checkWritableProperties();
checkPropertyName(propertyName);
- getJmsContentHeaderProperties().getHeaders().setInteger(propertyName, new Integer(i));
+ getJmsContentHeaderProperties().getJMSHeaders().setInteger(propertyName, new Integer(i));
}
public void setLongProperty(String propertyName, long l) throws JMSException
{
checkWritableProperties();
checkPropertyName(propertyName);
- getJmsContentHeaderProperties().getHeaders().setLong(propertyName, new Long(l));
+ getJmsContentHeaderProperties().getJMSHeaders().setLong(propertyName, new Long(l));
}
public void setFloatProperty(String propertyName, float f) throws JMSException
{
checkWritableProperties();
checkPropertyName(propertyName);
- getJmsContentHeaderProperties().getHeaders().setFloat(propertyName, new Float(f));
+ getJmsContentHeaderProperties().getJMSHeaders().setFloat(propertyName, new Float(f));
}
public void setDoubleProperty(String propertyName, double v) throws JMSException
{
checkWritableProperties();
checkPropertyName(propertyName);
- getJmsContentHeaderProperties().getHeaders().setDouble(propertyName, new Double(v));
+ getJmsContentHeaderProperties().getJMSHeaders().setDouble(propertyName, new Double(v));
}
public void setStringProperty(String propertyName, String value) throws JMSException
{
checkWritableProperties();
checkPropertyName(propertyName);
- getJmsContentHeaderProperties().getHeaders().setString(propertyName, value);
+ getJmsContentHeaderProperties().getJMSHeaders().setString(propertyName, value);
}
public void setObjectProperty(String propertyName, Object object) throws JMSException
{
checkWritableProperties();
checkPropertyName(propertyName);
- getJmsContentHeaderProperties().getHeaders().setObject(propertyName, object);
+ getJmsContentHeaderProperties().getJMSHeaders().setObject(propertyName, object);
}
protected void removeProperty(String propertyName) throws JMSException
{
checkPropertyName(propertyName);
- getJmsContentHeaderProperties().getHeaders().remove(propertyName);
+ getJmsContentHeaderProperties().getJMSHeaders().remove(propertyName);
}
- public void acknowledge() throws JMSException
+ public void acknowledgeThis() throws JMSException
{
// the JMS 1.1 spec says in section 3.6 that calls to acknowledge are ignored when client acknowledge
// is not specified. In our case, we only set the session field where client acknowledge mode is specified.
@@ -397,6 +401,14 @@ public abstract class AbstractJMSMessage extends AMQMessage implements javax.jms
}
}
+ public void acknowledge() throws JMSException
+ {
+ if(_session != null)
+ {
+ _session.acknowledge();
+ }
+ }
+
/**
* This forces concrete classes to implement clearBody()
@@ -426,13 +438,13 @@ public abstract class AbstractJMSMessage extends AMQMessage implements javax.jms
buf.append("\nJMS reply to: ").append(String.valueOf(getJMSReplyTo()));
buf.append("\nAMQ message number: ").append(_deliveryTag);
buf.append("\nProperties:");
- if (getJmsContentHeaderProperties().getHeaders().isEmpty())
+ if (getJmsContentHeaderProperties().getJMSHeaders().isEmpty())
{
buf.append("<NONE>");
}
else
{
- buf.append('\n').append(getJmsContentHeaderProperties().getHeaders());
+ buf.append('\n').append(getJmsContentHeaderProperties().getJMSHeaders());
}
return buf.toString();
}
@@ -462,9 +474,6 @@ public abstract class AbstractJMSMessage extends AMQMessage implements javax.jms
{
throw new IllegalArgumentException("Property name must not be the empty string");
}
-
- // Call to ensure that the it has been set.
- getJmsContentHeaderProperties().getHeaders();
}
public BasicContentHeaderProperties getJmsContentHeaderProperties()
@@ -478,14 +487,7 @@ public abstract class AbstractJMSMessage extends AMQMessage implements javax.jms
// position beyond the start
if (_data != null)
{
- if (!_readableMessage)
- {
- _data.flip();
- }
- else
- {
- _data.rewind();
- }
+ reset();
}
return _data;
}
@@ -524,7 +526,7 @@ public abstract class AbstractJMSMessage extends AMQMessage implements javax.jms
return !_readableMessage;
}
- public void reset() throws JMSException
+ public void reset()
{
if (_readableMessage)
{
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSBytesMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSBytesMessage.java
index 456d4d520c..debabfd559 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/JMSBytesMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSBytesMessage.java
@@ -30,6 +30,9 @@ import javax.jms.MessageFormatException;
import javax.jms.MessageEOFException;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+import java.nio.charset.CharsetDecoder;
+import java.nio.CharBuffer;
public class JMSBytesMessage extends AbstractBytesMessage implements BytesMessage
{
@@ -149,10 +152,27 @@ public class JMSBytesMessage extends AbstractBytesMessage implements BytesMessag
checkReadable();
// we check only for one byte since theoretically the string could be only a
// single byte when using UTF-8 encoding
- checkAvailable(1);
+
try
{
- return _data.getString(Charset.forName("UTF-8").newDecoder());
+ short length = readShort();
+ if(length == 0)
+ {
+ return "";
+ }
+ else
+ {
+ CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
+ ByteBuffer encodedString = _data.slice();
+ encodedString.limit(length);
+ _data.position(_data.position()+length);
+ CharBuffer string = decoder.decode(encodedString.buf());
+
+ return string.toString();
+ }
+
+
+
}
catch (CharacterCodingException e)
{
@@ -257,9 +277,15 @@ public class JMSBytesMessage extends AbstractBytesMessage implements BytesMessag
checkWritable();
try
{
- _data.putString(string, Charset.forName("UTF-8").newEncoder());
+ CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
+ java.nio.ByteBuffer encodedString = encoder.encode(CharBuffer.wrap(string));
+
+ _data.putShort((short)encodedString.limit());
+ _data.put(encodedString);
+
+ //_data.putString(string, Charset.forName("UTF-8").newEncoder());
// we must add the null terminator manually
- _data.put((byte)0);
+ //_data.put((byte)0);
}
catch (CharacterCodingException e)
{
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessage.java
index 85d434e4eb..f69bed0fc0 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessage.java
@@ -25,6 +25,8 @@ import org.apache.qpid.framing.PropertyFieldTable;
import org.apache.qpid.framing.FieldTableFactory;
import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.EncodingUtils;
+import org.apache.qpid.framing.JMSPropertyFieldTable;
+import org.apache.qpid.framing.AMQFrameDecodingException;
import org.apache.qpid.AMQException;
import org.apache.log4j.Logger;
@@ -39,7 +41,7 @@ public class JMSMapMessage extends JMSBytesMessage implements javax.jms.MapMessa
public static final String MIME_TYPE = "jms/map-message";
- private PropertyFieldTable _map;
+ private JMSPropertyFieldTable _properties;
JMSMapMessage() throws JMSException
{
@@ -49,10 +51,9 @@ public class JMSMapMessage extends JMSBytesMessage implements javax.jms.MapMessa
JMSMapMessage(ByteBuffer data) throws JMSException
{
super(data); // this instantiates a content header
- _map = new PropertyFieldTable();
+ _properties = new JMSPropertyFieldTable();
}
-
JMSMapMessage(long messageNbr, ContentHeaderBody contentHeader, ByteBuffer data)
throws AMQException
{
@@ -62,19 +63,33 @@ public class JMSMapMessage extends JMSBytesMessage implements javax.jms.MapMessa
{
long tableSize = EncodingUtils.readInteger(_data);
- _map = (PropertyFieldTable) FieldTableFactory.newFieldTable(_data, tableSize);
-
+ try
+ {
+ _properties = new JMSPropertyFieldTable(_data, tableSize);
+ }
+ catch (JMSException e)
+ {
+ Exception error = e.getLinkedException();
+ if (error instanceof AMQFrameDecodingException)
+ {
+ throw(AMQFrameDecodingException) error;
+ }
+ else
+ {
+ throw new AMQException(e.getMessage(), e);
+ }
+ }
}
else
{
- _map = (PropertyFieldTable) FieldTableFactory.newFieldTable();
+ _properties = new JMSPropertyFieldTable();
}
}
public String toBodyString() throws JMSException
{
- return "MapSize:" + _map.getEncodedSize() + "\nMapData:\n" + _map.toString();
+ return _properties.toString();
}
public String getMimeType()
@@ -82,85 +97,43 @@ public class JMSMapMessage extends JMSBytesMessage implements javax.jms.MapMessa
return MIME_TYPE;
}
- // MapMessage Interface
- public boolean getBoolean(String string) throws JMSException
+ public ByteBuffer getData()
{
- Boolean b = _map.getBoolean(string);
-
- if (b == null)
- {
- if (_map.containsKey(string))
- {
- Object str = _map.getObject(string);
+ //What if _data is null?
+ _properties.writeToBuffer(_data);
+ return super.getData();
+ }
- if (str == null || !(str instanceof String))
- {
- throw new MessageFormatException("getBoolean can't use " + string + " item.");
- }
- else
- {
- return Boolean.valueOf((String) str);
- }
- }
- else
- {
- b = Boolean.valueOf(null);
- }
- }
+ @Override
+ public void clearBodyImpl() throws JMSException
+ {
+ super.clearBodyImpl();
+ _properties.clear();
+ }
- return b;
+ public boolean getBoolean(String string) throws JMSException
+ {
+ return _properties.getBoolean(string);
}
public byte getByte(String string) throws JMSException
{
- Byte b = _map.getByte(string);
- if (b == null)
- {
- if (_map.containsKey(string))
- {
- Object str = _map.getObject(string);
-
- if (str == null || !(str instanceof String))
- {
- throw new MessageFormatException("getByte can't use " + string + " item.");
- }
- else
- {
- return Byte.valueOf((String) str);
- }
- }
- else
- {
- b = Byte.valueOf(null);
- }
- }
-
- return b;
+ return _properties.getByte(string);
}
public short getShort(String string) throws JMSException
{
- {
- Short s = _map.getShort(string);
-
- if (s == null)
- {
- s = Short.valueOf(getByte(string));
- }
-
- return s;
- }
+ return _properties.getShort(string);
}
public char getChar(String string) throws JMSException
{
-
- Character result = _map.getCharacter(string);
+ Character result = _properties.getCharacter(string);
if (result == null)
{
- throw new MessageFormatException("getChar couldn't find " + string + " item.");
+ throw new NullPointerException("getChar couldn't find " + string + " item.");
}
else
{
@@ -170,179 +143,97 @@ public class JMSMapMessage extends JMSBytesMessage implements javax.jms.MapMessa
public int getInt(String string) throws JMSException
{
- Integer i = _map.getInteger(string);
-
- if (i == null)
- {
- i = Integer.valueOf(getShort(string));
- }
-
- return i;
+ return _properties.getInteger(string);
}
public long getLong(String string) throws JMSException
{
-
- Long l = _map.getLong(string);
-
- if (l == null)
- {
- l = Long.valueOf(getInt(string));
- }
-
- return l;
-
+ return _properties.getLong(string);
}
public float getFloat(String string) throws JMSException
{
-
- Float f = _map.getFloat(string);
-
- if (f == null)
- {
- if (_map.containsKey(string))
- {
- Object str = _map.getObject(string);
-
- if (str == null || !(str instanceof String))
- {
- throw new MessageFormatException("getFloat can't use " + string + " item.");
- }
- else
- {
- return Float.valueOf((String) str);
- }
- }
- else
- {
- f = Float.valueOf(null);
- }
-
- }
-
- return f;
-
+ return _properties.getFloat(string);
}
public double getDouble(String string) throws JMSException
{
- Double d = _map.getDouble(string);
-
- if (d == null)
- {
- d = Double.valueOf(getFloat(string));
- }
-
- return d;
+ return _properties.getDouble(string);
}
public String getString(String string) throws JMSException
{
- String s = _map.getString(string);
-
- if (s == null)
- {
- if (_map.containsKey(string))
- {
- Object o = _map.getObject(string);
- if (o instanceof byte[])
- {
- throw new MessageFormatException("getObject couldn't find " + string + " item.");
- }
- else
- {
- if (o == null)
- {
- return null;
- }
- else
- {
- s = String.valueOf(o);
- }
- }
- }
- }
-
- return s;
+ return _properties.getString(string);
}
public byte[] getBytes(String string) throws JMSException
{
-
- byte[] result = _map.getBytes(string);
-
- if (result == null)
- {
- throw new MessageFormatException("getBytes couldn't find " + string + " item.");
- }
-
- return result;
-
+ return _properties.getBytes(string);
}
public Object getObject(String string) throws JMSException
{
- return _map.getObject(string);
+ return _properties.getObject(string);
}
public Enumeration getMapNames() throws JMSException
{
- return _map.getPropertyNames();
+ return _properties.getMapNames();
}
+
public void setBoolean(String string, boolean b) throws JMSException
{
checkWritable();
- _map.setBoolean(string, b);
+ _properties.setBoolean(string, b);
}
public void setByte(String string, byte b) throws JMSException
{
checkWritable();
- _map.setByte(string, b);
+ _properties.setByte(string, b);
}
public void setShort(String string, short i) throws JMSException
{
checkWritable();
- _map.setShort(string, i);
+ _properties.setShort(string, i);
}
public void setChar(String string, char c) throws JMSException
{
checkWritable();
- _map.setChar(string, c);
+ _properties.setChar(string, c);
}
public void setInt(String string, int i) throws JMSException
{
checkWritable();
- _map.setInteger(string, i);
+ _properties.setInteger(string, i);
}
public void setLong(String string, long l) throws JMSException
{
checkWritable();
- _map.setLong(string, l);
+ _properties.setLong(string, l);
}
public void setFloat(String string, float v) throws JMSException
{
checkWritable();
- _map.setFloat(string, v);
+ _properties.setFloat(string, v);
}
public void setDouble(String string, double v) throws JMSException
{
checkWritable();
- _map.setDouble(string, v);
+ _properties.setDouble(string, v);
}
public void setString(String string, String string1) throws JMSException
{
checkWritable();
- _map.setString(string, string1);
+ _properties.setString(string, string1);
}
public void setBytes(String string, byte[] bytes) throws JMSException
@@ -353,25 +244,18 @@ public class JMSMapMessage extends JMSBytesMessage implements javax.jms.MapMessa
public void setBytes(String string, byte[] bytes, int i, int i1) throws JMSException
{
checkWritable();
- _map.setBytes(string, bytes, i, i1);
+ _properties.setBytes(string, bytes, i, i1);
}
public void setObject(String string, Object object) throws JMSException
{
checkWritable();
- _map.setObject(string, object);
+ _properties.setObject(string, object);
}
public boolean itemExists(String string) throws JMSException
{
- return _map.itemExists(string);
- }
-
- public ByteBuffer getData()
- {
- //What if _data is null?
- _map.writeToBuffer(_data);
- return super.getData();
+ return _properties.itemExists(string);
}
}
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java
index 7393cea714..4fb070d2ff 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSObjectMessage.java
@@ -72,6 +72,7 @@ public class JMSObjectMessage extends AbstractJMSMessage implements ObjectMessag
_data.release();
}
_data = null;
+
}
public String toBodyString() throws JMSException
@@ -97,6 +98,7 @@ public class JMSObjectMessage extends AbstractJMSMessage implements ObjectMessag
{
_data.rewind();
}
+
try
{
ObjectOutputStream out = new ObjectOutputStream(_data.asOutputStream());
@@ -108,6 +110,7 @@ public class JMSObjectMessage extends AbstractJMSMessage implements ObjectMessag
{
throw new MessageFormatException("Message not serializable: " + e);
}
+
}
public Serializable getObject() throws JMSException
@@ -120,15 +123,18 @@ public class JMSObjectMessage extends AbstractJMSMessage implements ObjectMessag
try
{
+ _data.rewind();
in = new ObjectInputStream(_data.asInputStream());
return (Serializable) in.readObject();
}
catch (IOException e)
- {
- throw new MessageFormatException("Could not deserialize message: " + e);
+ {
+ e.printStackTrace();
+ throw new MessageFormatException("Could not deserialize message: " + e);
}
catch (ClassNotFoundException e)
{
+ e.printStackTrace();
throw new MessageFormatException("Could not deserialize message: " + e);
}
finally
diff --git a/java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessage.java b/java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessage.java
index 04f3c5ee17..c2dfdc1b65 100644
--- a/java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessage.java
+++ b/java/client/src/main/java/org/apache/qpid/client/message/JMSStreamMessage.java
@@ -226,6 +226,10 @@ public class JMSStreamMessage extends AbstractBytesMessage implements StreamMess
byte wireType = readWireType();
try
{
+ if(wireType == NULL_STRING_TYPE){
+ throw new NullPointerException();
+ }
+
if (wireType != CHAR_TYPE)
{
_data.position(position);
@@ -428,7 +432,7 @@ public class JMSStreamMessage extends AbstractBytesMessage implements StreamMess
break;
case NULL_STRING_TYPE:
result = null;
- break;
+ throw new NullPointerException("data is null");
case BOOLEAN_TYPE:
checkAvailable(1);
result = String.valueOf(readBooleanImpl());
diff --git a/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java b/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java
index ab707bb51d..887850c06e 100644
--- a/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java
+++ b/java/client/src/main/java/org/apache/qpid/client/state/AMQStateManager.java
@@ -7,9 +7,9 @@
* 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
@@ -104,6 +104,8 @@ public class AMQStateManager implements AMQMethodListener
frame2handlerMap.put(BasicDeliverBody.class, BasicDeliverMethodHandler.getInstance());
frame2handlerMap.put(BasicReturnBody.class, BasicReturnMethodHandler.getInstance());
frame2handlerMap.put(ChannelFlowOkBody.class, ChannelFlowOkMethodHandler.getInstance());
+ frame2handlerMap.put(QueueDeleteOkBody.class, QueueDeleteOkMethodHandler.getInstance());
+ frame2handlerMap.put(ExchangeBoundOkBody.class, ExchangeBoundOkMethodHandler.getInstance());
_state2HandlersMap.put(AMQState.CONNECTION_OPEN, frame2handlerMap);
}
diff --git a/java/client/src/main/java/org/apache/qpid/jms/Message.java b/java/client/src/main/java/org/apache/qpid/jms/Message.java
new file mode 100644
index 0000000000..d73e51d755
--- /dev/null
+++ b/java/client/src/main/java/org/apache/qpid/jms/Message.java
@@ -0,0 +1,28 @@
+/*
+ *
+ * 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;
+
+import javax.jms.*;
+
+public interface Message extends javax.jms.Message
+{
+ public void acknowledgeThis() throws JMSException;
+}
diff --git a/java/client/src/test/java/org/apache/qpid/transacted/Config.java b/java/client/src/old_test/java/org/apache/qpid/transacted/Config.java
index bd104e5407..bd104e5407 100644
--- a/java/client/src/test/java/org/apache/qpid/transacted/Config.java
+++ b/java/client/src/old_test/java/org/apache/qpid/transacted/Config.java
diff --git a/java/client/src/test/java/org/apache/qpid/transacted/Ping.java b/java/client/src/old_test/java/org/apache/qpid/transacted/Ping.java
index e0af4422a6..e0af4422a6 100644
--- a/java/client/src/test/java/org/apache/qpid/transacted/Ping.java
+++ b/java/client/src/old_test/java/org/apache/qpid/transacted/Ping.java
diff --git a/java/client/src/test/java/org/apache/qpid/transacted/Pong.java b/java/client/src/old_test/java/org/apache/qpid/transacted/Pong.java
index 13295c137a..13295c137a 100644
--- a/java/client/src/test/java/org/apache/qpid/transacted/Pong.java
+++ b/java/client/src/old_test/java/org/apache/qpid/transacted/Pong.java
diff --git a/java/client/src/test/java/org/apache/qpid/transacted/Relay.java b/java/client/src/old_test/java/org/apache/qpid/transacted/Relay.java
index cede95e5f0..cede95e5f0 100644
--- a/java/client/src/test/java/org/apache/qpid/transacted/Relay.java
+++ b/java/client/src/old_test/java/org/apache/qpid/transacted/Relay.java
diff --git a/java/client/src/test/java/org/apache/qpid/transacted/Start.java b/java/client/src/old_test/java/org/apache/qpid/transacted/Start.java
index 5564ed93ab..5564ed93ab 100644
--- a/java/client/src/test/java/org/apache/qpid/transacted/Start.java
+++ b/java/client/src/old_test/java/org/apache/qpid/transacted/Start.java
diff --git a/java/client/src/test/java/org/apache/qpid/weblogic/ServiceProvider.java b/java/client/src/old_test/java/org/apache/qpid/weblogic/ServiceProvider.java
index 71d806b338..71d806b338 100644
--- a/java/client/src/test/java/org/apache/qpid/weblogic/ServiceProvider.java
+++ b/java/client/src/old_test/java/org/apache/qpid/weblogic/ServiceProvider.java
diff --git a/java/client/src/test/java/org/apache/qpid/weblogic/ServiceRequestingClient.java b/java/client/src/old_test/java/org/apache/qpid/weblogic/ServiceRequestingClient.java
index a1e15258c3..a1e15258c3 100644
--- a/java/client/src/test/java/org/apache/qpid/weblogic/ServiceRequestingClient.java
+++ b/java/client/src/old_test/java/org/apache/qpid/weblogic/ServiceRequestingClient.java
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/ack/RecoverTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/ack/RecoverTest.java
index bd68f32c23..dc0ade76c4 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/ack/RecoverTest.java
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/ack/RecoverTest.java
@@ -36,18 +36,21 @@ public class RecoverTest extends TestCase
{
private static final Logger _logger = Logger.getLogger(RecoverTest.class);
- static
+ protected void setUp() throws Exception
{
- String workdir = System.getProperty("QPID_WORK");
- if (workdir == null || workdir.equals(""))
- {
- String tempdir = System.getProperty("java.io.tmpdir");
- System.out.println("QPID_WORK not set using tmp directory: " + tempdir);
- System.setProperty("QPID_WORK", tempdir);
- }
- DOMConfigurator.configure("../broker/etc/log4j.xml");
+ super.setUp();
+ TransportConnection.createVMBroker(1);
}
+ protected void tearDown() throws Exception
+ {
+ super.tearDown();
+ TransportConnection.killAllVMBrokers();
+ //Thread.sleep(2000);
+ }
+
+
+
public void testRecoverResendsMsgs() throws Exception
{
Connection con = new AMQConnection("vm://:1", "guest", "guest", "consumer1", "/test");
@@ -104,8 +107,74 @@ public class RecoverTest extends TestCase
con.close();
}
+
+ public void testRecoverResendsMsgsAckOnEarlier() throws Exception
+ {
+ Connection con = new AMQConnection("vm://:1", "guest", "guest", "consumer1", "/test");
+
+ Session consumerSession = con.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+ Queue queue = new AMQQueue("someQ", "someQ", false, true);
+ MessageConsumer consumer = consumerSession.createConsumer(queue);
+ //force synch to ensure the consumer has resulted in a bound queue
+ ((AMQSession) consumerSession).declareExchangeSynch("amq.direct", "direct");
+
+ Connection con2 = new AMQConnection("vm://:1", "guest", "guest", "producer1", "/test");
+ Session producerSession = con2.createSession(false, Session.CLIENT_ACKNOWLEDGE);
+ MessageProducer producer = producerSession.createProducer(queue);
+
+ _logger.info("Sending four messages");
+ producer.send(producerSession.createTextMessage("msg1"));
+ producer.send(producerSession.createTextMessage("msg2"));
+ producer.send(producerSession.createTextMessage("msg3"));
+ producer.send(producerSession.createTextMessage("msg4"));
+
+ con2.close();
+
+ _logger.info("Starting connection");
+ con.start();
+ TextMessage tm = (TextMessage) consumer.receive();
+ TextMessage tm2 = (TextMessage) consumer.receive();
+ tm.acknowledge();
+ _logger.info("Received 2 messages, acknowledge() first message, should acknowledge both");
+
+ consumer.receive();
+ consumer.receive();
+ _logger.info("Received all four messages. Calling recover with two outstanding messages");
+ // no ack for last three messages so when I call recover I expect to get three messages back
+ consumerSession.recover();
+ TextMessage tm3 = (TextMessage) consumer.receive(3000);
+ assertEquals("msg3", tm3.getText());
+
+ TextMessage tm4 = (TextMessage) consumer.receive(3000);
+ assertEquals("msg4", tm4.getText());
+
+
+ _logger.info("Received redelivery of two messages. calling acknolwedgeThis() first of those message");
+ ((org.apache.qpid.jms.Message)tm3).acknowledgeThis();
+
+ _logger.info("Calling recover");
+ // all acked so no messages to be delivered
+ consumerSession.recover();
+
+ tm4 = (TextMessage) consumer.receive(3000);
+ assertEquals("msg4", tm4.getText());
+ ((org.apache.qpid.jms.Message)tm4).acknowledgeThis();
+
+ _logger.info("Calling recover");
+ // all acked so no messages to be delivered
+ consumerSession.recover();
+
+
+ tm = (TextMessage) consumer.receiveNoWait();
+ assertNull(tm);
+ _logger.info("No messages redelivered as is expected");
+
+ con.close();
+ }
+
+
public static junit.framework.Test suite()
{
- return new VMBrokerSetup(new junit.framework.TestSuite(RecoverTest.class));
+ return new junit.framework.TestSuite(RecoverTest.class);
}
}
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableMessageTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableMessageTest.java
index 3fb1dd3f7d..f4efd64dbb 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableMessageTest.java
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableMessageTest.java
@@ -26,7 +26,6 @@ import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.message.JMSBytesMessage;
import org.apache.qpid.framing.AMQFrameDecodingException;
-import org.apache.qpid.framing.FieldTableTest;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.FieldTableFactory;
import org.apache.qpid.testutil.VMBrokerSetup;
@@ -134,7 +133,11 @@ public class FieldTableMessageTest extends TestCase implements MessageListener
{
ByteBuffer buffer = ((JMSBytesMessage) m).getData();
FieldTable actual = FieldTableFactory.newFieldTable(buffer, buffer.remaining());
- new FieldTableTest().assertEquivalent(_expected, actual);
+ for (Object o : _expected.keySet())
+ {
+ String key = (String) o;
+ assertEquals("Values for " + key + " did not match", _expected.get(key), actual.get(key));
+ }
}
}
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/MapMessageTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/basic/MapMessageTest.java
index 1a469c1d12..02a98f67d9 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/MapMessageTest.java
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/basic/MapMessageTest.java
@@ -20,20 +20,19 @@
*/
package org.apache.qpid.test.unit.basic;
+import junit.framework.Assert;
+import junit.framework.TestCase;
+import org.apache.log4j.Logger;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.message.JMSMapMessage;
-import org.apache.qpid.testutil.VMBrokerSetup;
-import org.apache.log4j.Logger;
+import org.apache.qpid.client.transport.TransportConnection;
+import javax.jms.*;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
-import javax.jms.*;
-
-import junit.framework.TestCase;
-import junit.framework.Assert;
public class MapMessageTest extends TestCase implements MessageListener
{
@@ -56,7 +55,7 @@ public class MapMessageTest extends TestCase implements MessageListener
super.setUp();
try
{
- //TransportConnection.createVMBroker(1);
+ TransportConnection.createVMBroker(1);
init(new AMQConnection(_connectionString, "guest", "guest", randomize("Client"), "/test_path"));
}
catch (Exception e)
@@ -69,7 +68,7 @@ public class MapMessageTest extends TestCase implements MessageListener
{
_logger.info("Tearing Down unit.basic.MapMessageTest");
super.tearDown();
- //TransportConnection.killAllVMBrokers();
+ TransportConnection.killAllVMBrokers();
}
private void init(AMQConnection connection) throws Exception
@@ -166,12 +165,12 @@ public class MapMessageTest extends TestCase implements MessageListener
testMapValues(m, count);
+ testCorrectExceptions(m);
+
testMessageWriteStatus(m);
testPropertyWriteStatus(m);
- testCorrectExceptions(m);
-
count++;
}
}
@@ -230,7 +229,7 @@ public class MapMessageTest extends TestCase implements MessageListener
m.getChar("message");
fail("Exception Expected.");
}
- catch (MessageFormatException nfe)
+ catch (MessageFormatException npe)
{
//normal execution
}
@@ -320,7 +319,7 @@ public class MapMessageTest extends TestCase implements MessageListener
m.getChar("short");
fail("Exception Expected.");
}
- catch (MessageFormatException nfe)
+ catch (MessageFormatException npe)
{
//normal execution
}
@@ -403,7 +402,7 @@ public class MapMessageTest extends TestCase implements MessageListener
m.getChar("long");
fail("Exception Expected.");
}
- catch (MessageFormatException nfe)
+ catch (MessageFormatException npe)
{
//normal execution
}
@@ -494,7 +493,7 @@ public class MapMessageTest extends TestCase implements MessageListener
m.getChar("double");
fail("Exception Expected.");
}
- catch (MessageFormatException nfe)
+ catch (MessageFormatException npe)
{
//normal execution
}
@@ -587,7 +586,7 @@ public class MapMessageTest extends TestCase implements MessageListener
m.getChar("float");
fail("Exception Expected.");
}
- catch (MessageFormatException nfe)
+ catch (MessageFormatException npe)
{
//normal execution
}
@@ -671,7 +670,7 @@ public class MapMessageTest extends TestCase implements MessageListener
m.getChar("int");
fail("Exception Expected.");
}
- catch (MessageFormatException nfe)
+ catch (MessageFormatException npe)
{
//normal execution
}
@@ -843,7 +842,7 @@ public class MapMessageTest extends TestCase implements MessageListener
m.getChar("bytes");
fail("Exception Expected.");
}
- catch (MessageFormatException nfe)
+ catch (MessageFormatException npe)
{
//normal execution
}
@@ -928,7 +927,7 @@ public class MapMessageTest extends TestCase implements MessageListener
m.getChar("byte");
fail("Exception Expected.");
}
- catch (MessageFormatException nfe)
+ catch (MessageFormatException npe)
{
//normal execution
}
@@ -1005,7 +1004,7 @@ public class MapMessageTest extends TestCase implements MessageListener
m.getChar("odd");
fail("Exception Expected.");
}
- catch (MessageFormatException nfe)
+ catch (MessageFormatException npe)
{
//normal execution
}
@@ -1249,6 +1248,6 @@ public class MapMessageTest extends TestCase implements MessageListener
public static junit.framework.Test suite()
{
- return new VMBrokerSetup(new junit.framework.TestSuite(MapMessageTest.class));
+ return new junit.framework.TestSuite(MapMessageTest.class);
}
}
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java
index 80af81652e..c88024f39f 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/basic/MultipleConnectionTest.java
@@ -6,9 +6,9 @@
* 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
@@ -19,18 +19,15 @@
*/
package org.apache.qpid.test.unit.basic;
+import junit.framework.TestCase;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.AMQTopic;
-import org.apache.qpid.client.vmbroker.AMQVMBrokerCreationException;
import org.apache.qpid.client.transport.TransportConnection;
-import org.apache.qpid.testutil.VMBrokerSetup;
import javax.jms.*;
-import junit.framework.TestCase;
-
public class MultipleConnectionTest extends TestCase
{
public static final String _defaultBroker = "vm://:1";
@@ -138,6 +135,19 @@ public class MultipleConnectionTest extends TestCase
}
}
+
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ TransportConnection.createVMBroker(1);
+ }
+
+ protected void tearDown() throws Exception
+ {
+ super.tearDown();
+ TransportConnection.killAllVMBrokers();
+ }
+
private static void waitForCompletion(int expected, long wait, Receiver[] receivers) throws InterruptedException
{
for (int i = 0; i < receivers.length; i++)
@@ -209,6 +219,6 @@ public class MultipleConnectionTest extends TestCase
public static junit.framework.Test suite()
{
- return new VMBrokerSetup(new junit.framework.TestSuite(MultipleConnectionTest.class));
+ return new junit.framework.TestSuite(MultipleConnectionTest.class);
}
}
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/PubSubTwoConnectionTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/basic/PubSubTwoConnectionTest.java
new file mode 100644
index 0000000000..f4814795c4
--- /dev/null
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/basic/PubSubTwoConnectionTest.java
@@ -0,0 +1,67 @@
+/*
+ *
+ * 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.test.unit.basic;
+
+import junit.framework.TestCase;
+import org.apache.qpid.client.transport.TransportConnection;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQSession;
+import org.apache.qpid.client.AMQTopic;
+
+import javax.jms.*;
+
+/**
+ * @author Apache Software Foundation
+ */
+public class PubSubTwoConnectionTest extends TestCase
+{
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ TransportConnection.createVMBroker(1);
+ }
+
+ protected void tearDown() throws Exception
+ {
+ super.tearDown();
+ }
+
+ /**
+ * This tests that a consumer is set up synchronously
+ * @throws Exception
+ */
+ public void testTwoConnections() throws Exception
+ {
+ Topic topic = new AMQTopic("MyTopic");
+ Connection con1 = new AMQConnection("vm://:1", "guest", "guest", "Client1", "/test_path");
+ Session session1 = con1.createSession(false, AMQSession.NO_ACKNOWLEDGE);
+ MessageProducer producer = session1.createProducer(topic);
+
+ Connection con2 = new AMQConnection("vm://:1", "guest", "guest", "Client2", "/test_path");
+ Session session2 = con2.createSession(false, AMQSession.NO_ACKNOWLEDGE);
+ MessageConsumer consumer = session2.createConsumer(topic);
+ con2.start();
+ producer.send(session1.createTextMessage("Hello"));
+ TextMessage tm1 = (TextMessage) consumer.receive(2000);
+ assertNotNull(tm1);
+ assertEquals("Hello", tm1.getText());
+ }
+}
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/TextMessageTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/basic/TextMessageTest.java
index 04ad15da7a..903f6a9da9 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/TextMessageTest.java
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/basic/TextMessageTest.java
@@ -21,11 +21,8 @@
package org.apache.qpid.test.unit.basic;
import org.apache.qpid.client.AMQConnection;
-import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.client.vmbroker.AMQVMBrokerCreationException;
-import org.apache.qpid.client.transport.TransportConnection;
import org.apache.qpid.client.message.JMSTextMessage;
import org.apache.qpid.testutil.VMBrokerSetup;
import org.apache.log4j.Logger;
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/message/BytesMessageTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/client/message/BytesMessageTest.java
index 7ffb3ca469..a0e4aa9787 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/message/BytesMessageTest.java
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/client/message/BytesMessageTest.java
@@ -552,16 +552,6 @@ public class BytesMessageTest extends TestCase
assertEquals((byte)0, result[2]);
}
- public void testToBodyString() throws Exception
- {
- JMSBytesMessage bm = TestMessageHelper.newJMSBytesMessage();
- final String testText = "This is a test";
- bm.writeUTF(testText);
- bm.reset();
- String result = bm.toBodyString();
- assertEquals(testText, result);
- }
-
public void testToBodyStringWithNull() throws Exception
{
JMSBytesMessage bm = TestMessageHelper.newJMSBytesMessage();
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/message/MapMessageTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/client/message/MapMessageTest.java
index e5458fd89e..bd4b3b3987 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/message/MapMessageTest.java
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/client/message/MapMessageTest.java
@@ -14,18 +14,16 @@
* "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.
+ * under the License.
+ *
*
- *
*/
package org.apache.qpid.test.unit.client.message;
-import junit.framework.TestCase;
import junit.framework.Assert;
-import org.apache.qpid.framing.PropertyFieldTable;
+import junit.framework.TestCase;
import org.apache.qpid.client.message.JMSMapMessage;
import org.apache.qpid.client.message.TestMessageHelper;
-import org.apache.log4j.Logger;
import javax.jms.JMSException;
import javax.jms.MessageFormatException;
@@ -104,6 +102,27 @@ public class MapMessageTest extends TestCase
{
Assert.fail("JMSException received." + e);
}
+
+ try
+ {
+ JMSMapMessage mm = TestMessageHelper.newJMSMapMessage();
+
+ mm.setString("value", null);
+ char c = mm.getChar("value");
+ fail("Expected NullPointerException");
+
+ }
+ catch (NullPointerException e)
+ {
+ ; // pass
+ }
+ catch (JMSException e)
+ {
+ Assert.fail("JMSException received." + e);
+ }
+
+
+
}
public void testDoubleLookup()
@@ -204,7 +223,7 @@ public class MapMessageTest extends TestCase
{
JMSMapMessage mm = TestMessageHelper.newJMSMapMessage();
mm.getByte("random");
- Assert.fail("MessageFormatException expected");
+ Assert.fail("NumberFormatException expected");
}
catch (NumberFormatException e)
{
@@ -331,7 +350,7 @@ public class MapMessageTest extends TestCase
{
JMSMapMessage mm = TestMessageHelper.newJMSMapMessage();
mm.getShort("random");
- Assert.fail("NumberFormatException should be received.");
+ Assert.fail("NumberFormatException should be received.");
}
catch (NumberFormatException e)
{
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/message/ObjectMessageTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/client/message/ObjectMessageTest.java
index 07eedc8bb9..bbd1870168 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/message/ObjectMessageTest.java
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/client/message/ObjectMessageTest.java
@@ -167,6 +167,12 @@ public class ObjectMessageTest extends TestCase implements MessageListener
}
+ public void testSetObjectForNull() throws Exception
+ {
+ ObjectMessage msg = session.createObjectMessage();
+ msg.setObject(null);
+ assertNull(msg.getObject());
+ }
private void send() throws Exception
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/message/TextMessageTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/client/message/TextMessageTest.java
index 337b0f3bbc..64d10fb13f 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/message/TextMessageTest.java
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/client/message/TextMessageTest.java
@@ -7,9 +7,9 @@
* 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
@@ -22,8 +22,13 @@ package org.apache.qpid.test.unit.client.message;
import org.apache.qpid.client.message.TestMessageHelper;
import org.apache.qpid.client.message.JMSTextMessage;
+import org.apache.qpid.client.message.JMSMapMessage;
import junit.framework.TestCase;
+import junit.framework.Assert;
+
+import javax.jms.JMSException;
+import javax.jms.MessageFormatException;
public class TextMessageTest extends TestCase
{
@@ -47,6 +52,248 @@ public class TextMessageTest extends TestCase
assertEquals(val, "Banana");
}
+
+ public void testBooleanPropertyLookup()
+ {
+ try
+ {
+ JMSTextMessage tm = TestMessageHelper.newJMSTextMessage();
+
+ tm.setBooleanProperty("value", true);
+ Assert.assertEquals(true, tm.getBooleanProperty("value"));
+ Assert.assertEquals("true", tm.getStringProperty("value"));
+ }
+ catch (JMSException e)
+ {
+ Assert.fail("JMSException received." + e);
+ }
+ }
+
+ public void testBytePropertyLookup()
+ {
+ try
+ {
+ JMSMapMessage mm = TestMessageHelper.newJMSMapMessage();
+ mm.setByteProperty("value", Byte.MAX_VALUE);
+
+ Assert.assertEquals(Byte.MAX_VALUE, mm.getByteProperty("value"));
+ Assert.assertEquals((short) Byte.MAX_VALUE, mm.getShortProperty("value"));
+ Assert.assertEquals(Byte.MAX_VALUE, mm.getIntProperty("value"));
+ Assert.assertEquals((long) Byte.MAX_VALUE, mm.getLongProperty("value"));
+ Assert.assertEquals("" + Byte.MAX_VALUE, mm.getStringProperty("value"));
+
+ }
+ catch (JMSException e)
+ {
+ Assert.fail("JMSException received." + e);
+ }
+ }
+
+ public void testShortPropertyLookup()
+ {
+ try
+ {
+ JMSMapMessage mm = TestMessageHelper.newJMSMapMessage();
+ mm.setShortProperty("value", Short.MAX_VALUE);
+ Assert.assertEquals(Short.MAX_VALUE, mm.getShortProperty("value"));
+ Assert.assertEquals((int) Short.MAX_VALUE, mm.getIntProperty("value"));
+ Assert.assertEquals((long) Short.MAX_VALUE, mm.getLongProperty("value"));
+ Assert.assertEquals("" + Short.MAX_VALUE, mm.getStringProperty("value"));
+ }
+ catch (JMSException e)
+ {
+ Assert.fail("JMSException received." + e);
+ }
+ }
+
+ public void testDoublePropertyLookup()
+ {
+ try
+ {
+ JMSMapMessage mm = TestMessageHelper.newJMSMapMessage();
+ mm.setDoubleProperty("value", Double.MAX_VALUE);
+ Assert.assertEquals(Double.MAX_VALUE, mm.getDoubleProperty("value"));
+ Assert.assertEquals("" + Double.MAX_VALUE, mm.getStringProperty("value"));
+ }
+ catch (JMSException e)
+ {
+ Assert.fail("JMSException received." + e);
+ }
+ }
+
+ public void testFloatPropertyLookup()
+ {
+ try
+ {
+ JMSMapMessage mm = TestMessageHelper.newJMSMapMessage();
+ mm.setFloatProperty("value", Float.MAX_VALUE);
+ Assert.assertEquals(Float.MAX_VALUE, mm.getFloatProperty("value"));
+ Assert.assertEquals((double) Float.MAX_VALUE, mm.getDoubleProperty("value"));
+ Assert.assertEquals("" + Float.MAX_VALUE, mm.getStringProperty("value"));
+ }
+ catch (JMSException e)
+ {
+ Assert.fail("JMSException received." + e);
+ }
+ }
+
+ public void testIntPropertyLookup()
+ {
+ try
+ {
+ JMSMapMessage mm = TestMessageHelper.newJMSMapMessage();
+ mm.setIntProperty("value", Integer.MAX_VALUE);
+ Assert.assertEquals(Integer.MAX_VALUE, mm.getIntProperty("value"));
+ Assert.assertEquals((long) Integer.MAX_VALUE, mm.getLongProperty("value"));
+ Assert.assertEquals("" + Integer.MAX_VALUE, mm.getStringProperty("value"));
+ }
+ catch (JMSException e)
+ {
+ Assert.fail("JMSException received." + e);
+ }
+ }
+
+ public void testLongPropertyLookup()
+ {
+ try
+ {
+ JMSMapMessage mm = TestMessageHelper.newJMSMapMessage();
+ mm.setLongProperty("value", Long.MAX_VALUE);
+ Assert.assertEquals(Long.MAX_VALUE, mm.getLongProperty("value"));
+ Assert.assertEquals("" + Long.MAX_VALUE, mm.getStringProperty("value"));
+ }
+ catch (JMSException e)
+ {
+ Assert.fail("JMSException received." + e);
+ }
+ }
+
+
+ // Failed Lookups
+
+ public void testFailedBooleanPropertyLookup()
+ {
+ try
+ {
+ JMSMapMessage mm = TestMessageHelper.newJMSMapMessage();
+ Assert.assertEquals(false, mm.getBooleanProperty("int"));
+ }
+ catch (JMSException e)
+ {
+ Assert.fail("JMSException received." + e);
+ }
+ }
+
+ public void testFailedBytePropertyLookup()
+ {
+ try
+ {
+ JMSMapMessage mm = TestMessageHelper.newJMSMapMessage();
+ mm.getByteProperty("random");
+ Assert.fail("NumberFormatException expected");
+ }
+ catch (NumberFormatException e)
+ {
+ //normal execution
+ }
+ catch (JMSException e)
+ {
+ Assert.fail("JMSException received:" + e);
+ }
+
+ }
+
+ public void testFailedDoublePropertyLookup()
+ {
+ try
+ {
+ JMSMapMessage mm = TestMessageHelper.newJMSMapMessage();
+ mm.getDoubleProperty("random");
+ Assert.fail("NullPointerException should be received.");
+ }
+ catch (NullPointerException e)
+ {
+ //normal execution
+ }
+ catch (JMSException e)
+ {
+ Assert.fail("JMSException received:" + e);
+ }
+ }
+
+ public void testFailedFloatPropertyLookup()
+ {
+ try
+ {
+ JMSMapMessage mm = TestMessageHelper.newJMSMapMessage();
+ mm.getFloatProperty("random");
+ Assert.fail("NullPointerException should be received.");
+ }
+ catch (NullPointerException e)
+ {
+ //normal execution
+ }
+ catch (JMSException e)
+ {
+ Assert.fail("JMSException received:" + e);
+ }
+ }
+
+ public void testFailedIntPropertyLookup()
+ {
+ try
+ {
+ JMSMapMessage mm = TestMessageHelper.newJMSMapMessage();
+ mm.getIntProperty("random");
+ Assert.fail("NumberFormatException should be received.");
+ }
+ catch (NumberFormatException e)
+ {
+ //normal execution
+ }
+ catch (JMSException e)
+ {
+ Assert.fail("JMSException received:" + e);
+ }
+ }
+
+ public void testFailedLongPropertyLookup()
+ {
+ try
+ {
+ JMSMapMessage mm = TestMessageHelper.newJMSMapMessage();
+ mm.getLongProperty("random");
+ Assert.fail("NumberFormatException should be received.");
+ }
+ catch (NumberFormatException e)
+ {
+ //normal execution
+ }
+ catch (JMSException e)
+ {
+ Assert.fail("JMSException received:" + e);
+ }
+ }
+
+ public void testFailedShortPropertyLookup()
+ {
+ try
+ {
+ JMSMapMessage mm = TestMessageHelper.newJMSMapMessage();
+ mm.getShortProperty("random");
+ Assert.fail("NumberFormatException should be received.");
+ }
+ catch (NumberFormatException e)
+ {
+ //normal execution
+ }
+ catch (JMSException e)
+ {
+ Assert.fail("JMSException received:" + e);
+ }
+ }
+
+
public static junit.framework.Test suite()
{
return new junit.framework.TestSuite(TextMessageTest.class);
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/temporaryqueue/TemporaryQueueTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/client/temporaryqueue/TemporaryQueueTest.java
new file mode 100644
index 0000000000..1e13962f01
--- /dev/null
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/client/temporaryqueue/TemporaryQueueTest.java
@@ -0,0 +1,80 @@
+package org.apache.qpid.test.unit.client.temporaryqueue;
+
+import junit.framework.TestCase;
+import org.apache.qpid.client.transport.TransportConnection;
+import org.apache.qpid.client.AMQConnection;
+import org.apache.qpid.client.AMQAuthenticationException;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.AMQConnectionException;
+import org.apache.qpid.AMQUnresolvedAddressException;
+import org.apache.qpid.url.URLSyntaxException;
+
+import javax.jms.*;
+
+public class TemporaryQueueTest extends TestCase
+{
+
+ String _broker = "vm://:1";
+
+
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ TransportConnection.createVMBroker(1);
+ }
+
+ protected void tearDown() throws Exception
+ {
+ TransportConnection.killAllVMBrokers();
+ }
+
+ protected Connection createConnection() throws AMQException, URLSyntaxException
+ {
+ return new AMQConnection(_broker, "guest", "guest",
+ "fred", "/test");
+ }
+
+ public void testTempoaryQueue() throws Exception
+ {
+ Connection conn = createConnection();
+ Session session = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
+ TemporaryQueue queue = session.createTemporaryQueue();
+ assertNotNull(queue);
+ MessageProducer producer = session.createProducer(queue);
+ MessageConsumer consumer = session.createConsumer(queue);
+ conn.start();
+ producer.send(session.createTextMessage("hello"));
+ TextMessage tm = (TextMessage) consumer.receive(2000);
+ assertNotNull(tm);
+ assertEquals("hello",tm.getText());
+
+ try
+ {
+ queue.delete();
+ fail("Expected JMSException : should not be able to delete while there are active consumers");
+ }
+ catch(JMSException je)
+ {
+ ; //pass
+ }
+
+ consumer.close();
+
+ try
+ {
+ queue.delete();
+ }
+ catch(JMSException je)
+ {
+ fail("Unexpected Exception: " + je.getMessage());
+ }
+
+ conn.close();
+ }
+
+
+ public static junit.framework.Test suite()
+ {
+ return new junit.framework.TestSuite(TemporaryQueueTest.class);
+ }
+}
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/message/StreamMessageTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/message/StreamMessageTest.java
index 50944730c3..315ba6ae4c 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/message/StreamMessageTest.java
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/message/StreamMessageTest.java
@@ -73,7 +73,7 @@ public class StreamMessageTest extends TestCase
MessageProducer mandatoryProducer = producerSession.createProducer(queue);
// Third test - should be routed
- _logger.info("Sending routable message");
+ _logger.info("Sending isBound message");
StreamMessage msg = producerSession.createStreamMessage();
msg.setStringProperty("F1000","1");
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java
index fa46a4bcfb..14ceaa75f1 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/topic/TopicSessionTest.java
@@ -26,10 +26,8 @@ import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.AMQTopic;
import org.apache.qpid.client.transport.TransportConnection;
-import javax.jms.TopicSession;
-import javax.jms.TextMessage;
-import javax.jms.TopicPublisher;
-import javax.jms.MessageConsumer;
+import javax.jms.*;
+
/**
* @author Apache Software Foundation
@@ -46,12 +44,126 @@ public class TopicSessionTest extends TestCase
{
super.tearDown();
TransportConnection.killAllVMBrokers();
+ //Thread.sleep(2000);
}
- public void testTextMessageCreation() throws Exception
+
+ public void testTopicSubscriptionUnsubscription() throws Exception
{
AMQTopic topic = new AMQTopic("MyTopic");
- AMQConnection con = new AMQConnection("vm://:1", "guest", "guest", "test", "/test");
+ AMQConnection con = new AMQConnection("vm://:1?retries='0'", "guest", "guest", "test", "/test");
+ TopicSession session1 = con.createTopicSession(false, AMQSession.NO_ACKNOWLEDGE);
+ TopicSubscriber sub = session1.createDurableSubscriber(topic,"subscription0");
+ TopicPublisher publisher = session1.createPublisher(topic);
+
+ con.start();
+
+ TextMessage tm = session1.createTextMessage("Hello");
+ publisher.publish(tm);
+
+ tm = (TextMessage) sub.receive(2000);
+ assertNotNull(tm);
+
+ session1.unsubscribe("subscription0");
+
+ try
+ {
+ session1.unsubscribe("not a subscription");
+ fail("expected InvalidDestinationException when unsubscribing from unknown subscription");
+ }
+ catch(InvalidDestinationException e)
+ {
+ ; // PASS
+ }
+ catch(Exception e)
+ {
+ fail("expected InvalidDestinationException when unsubscribing from unknown subscription, got: " + e);
+ }
+
+ con.close();
+ }
+
+ public void testSubscriptionNameReuseForDifferentTopicSingleConnection() throws Exception
+ {
+ subscriptionNameReuseForDifferentTopic(false);
+ }
+
+ public void testSubscriptionNameReuseForDifferentTopicTwoConnections() throws Exception
+ {
+ subscriptionNameReuseForDifferentTopic(true);
+ }
+
+ private void subscriptionNameReuseForDifferentTopic(boolean shutdown) throws Exception
+ {
+ AMQTopic topic = new AMQTopic("MyTopic1" + String.valueOf(shutdown));
+ AMQTopic topic2 = new AMQTopic("MyOtherTopic1" + String.valueOf(shutdown));
+ AMQConnection con = new AMQConnection("vm://:1?retries='0'", "guest", "guest", "test", "/test");
+ TopicSession session1 = con.createTopicSession(false, AMQSession.NO_ACKNOWLEDGE);
+ TopicSubscriber sub = session1.createDurableSubscriber(topic, "subscription0");
+ TopicPublisher publisher = session1.createPublisher(null);
+
+ con.start();
+
+ publisher.publish(topic, session1.createTextMessage("hello"));
+ TextMessage m = (TextMessage) sub.receive(2000);
+ assertNotNull(m);
+
+ if (shutdown)
+ {
+ session1.close();
+ con.close();
+ con = new AMQConnection("vm://:1?retries='0'", "guest", "guest", "test", "/test");
+ con.start();
+ session1 = con.createTopicSession(false, AMQSession.NO_ACKNOWLEDGE);
+ publisher = session1.createPublisher(null);
+ }
+ TopicSubscriber sub2 = session1.createDurableSubscriber(topic2, "subscription0");
+ publisher.publish(topic, session1.createTextMessage("hello"));
+ if (!shutdown)
+ {
+ m = (TextMessage) sub.receive(2000);
+ assertNull(m);
+ }
+ publisher.publish(topic2, session1.createTextMessage("goodbye"));
+ m = (TextMessage) sub2.receive(2000);
+ assertNotNull(m);
+ assertEquals("goodbye", m.getText());
+ con.close();
+ }
+
+ public void testUnsubscriptionAfterConnectionClose() throws Exception
+ {
+ AMQTopic topic = new AMQTopic("MyTopic3");
+ AMQConnection con1 = new AMQConnection("vm://:1?retries='0'", "guest", "guest", "test", "/test");
+ TopicSession session1 = con1.createTopicSession(false, AMQSession.NO_ACKNOWLEDGE);
+ TopicPublisher publisher = session1.createPublisher(topic);
+
+ AMQConnection con2 = new AMQConnection("vm://:1?retries='0'", "guest", "guest", "test2", "/test");
+ TopicSession session2 = con2.createTopicSession(false, AMQSession.NO_ACKNOWLEDGE);
+ TopicSubscriber sub = session2.createDurableSubscriber(topic, "subscription0");
+
+ con2.start();
+
+ publisher.publish(session1.createTextMessage("Hello"));
+ TextMessage tm = (TextMessage) sub.receive(2000);
+ assertNotNull(tm);
+ con2.close();
+ publisher.publish(session1.createTextMessage("Hello2"));
+ con2 = new AMQConnection("vm://:1?retries='0'", "guest", "guest", "test2", "/test");
+ session2 = con2.createTopicSession(false, AMQSession.NO_ACKNOWLEDGE);
+ sub = session2.createDurableSubscriber(topic, "subscription0");
+ con2.start();
+ tm = (TextMessage) sub.receive(2000);
+ assertNotNull(tm);
+ assertEquals("Hello2", tm.getText());
+ con1.close();
+ con2.close();
+ }
+
+ public void testTextMessageCreation() throws Exception
+ {
+ AMQTopic topic = new AMQTopic("MyTopic4");
+ AMQConnection con = new AMQConnection("vm://:1?retries='0'", "guest", "guest", "test", "/test");
TopicSession session1 = con.createTopicSession(false, AMQSession.NO_ACKNOWLEDGE);
TopicPublisher publisher = session1.createPublisher(topic);
MessageConsumer consumer1 = session1.createConsumer(topic);
@@ -85,8 +197,83 @@ public class TopicSessionTest extends TestCase
tm = (TextMessage) consumer1.receive(2000);
assertNotNull(tm);
assertEquals("Empty string not returned", "", msgText);
+ con.close();
}
+ public void testSendingSameMessage() throws Exception
+ {
+ AMQConnection conn = new AMQConnection("vm://:1?retries='0'", "guest", "guest", "test", "/test");
+ TopicSession session = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
+ TemporaryTopic topic = session.createTemporaryTopic();
+ assertNotNull(topic);
+ TopicPublisher producer = session.createPublisher(topic);
+ MessageConsumer consumer = session.createConsumer(topic);
+ conn.start();
+ TextMessage sentMessage = session.createTextMessage("Test Message");
+ producer.send(sentMessage);
+ TextMessage receivedMessage = (TextMessage) consumer.receive(2000);
+ assertNotNull(receivedMessage);
+ assertEquals(sentMessage.getText(),receivedMessage.getText());
+ producer.send(sentMessage);
+ receivedMessage = (TextMessage) consumer.receive(2000);
+ assertNotNull(receivedMessage);
+ assertEquals(sentMessage.getText(),receivedMessage.getText());
+
+
+ }
+
+ public void testTemporaryTopic() throws Exception
+ {
+ AMQConnection conn = new AMQConnection("vm://:1?retries='0'", "guest", "guest", "test", "/test");
+ TopicSession session = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
+ TemporaryTopic topic = session.createTemporaryTopic();
+ assertNotNull(topic);
+ TopicPublisher producer = session.createPublisher(topic);
+ MessageConsumer consumer = session.createConsumer(topic);
+ conn.start();
+ producer.send(session.createTextMessage("hello"));
+ TextMessage tm = (TextMessage) consumer.receive(2000);
+ assertNotNull(tm);
+ assertEquals("hello",tm.getText());
+
+ try
+ {
+ topic.delete();
+ fail("Expected JMSException : should not be able to delete while there are active consumers");
+ }
+ catch(JMSException je)
+ {
+ ; //pass
+ }
+
+ consumer.close();
+
+ try
+ {
+ topic.delete();
+ }
+ catch(JMSException je)
+ {
+ fail("Unexpected Exception: " + je.getMessage());
+ }
+
+ TopicSession session2 = conn.createTopicSession(false, Session.AUTO_ACKNOWLEDGE);
+ try
+ {
+ MessageConsumer consumer2 = session2.createConsumer(topic);
+ fail("Expected a JMSException when subscribing to a temporary topic created on adifferent session");
+ }
+ catch (JMSException je)
+ {
+ ; // pass
+ }
+
+
+
+ conn.close();
+ }
+
+
public static junit.framework.Test suite()
{
return new junit.framework.TestSuite(TopicSessionTest.class);
diff --git a/java/client/src/old_test/java/org/apache/qpid/transacted/TransactedTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/transacted/TransactedTest.java
index e858e1ad36..90a11307b8 100644
--- a/java/client/src/old_test/java/org/apache/qpid/transacted/TransactedTest.java
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/transacted/TransactedTest.java
@@ -23,8 +23,6 @@ package org.apache.qpid.test.unit.transacted;
import org.apache.qpid.client.AMQConnection;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
-import org.apache.qpid.client.transport.TransportConnection;
-import org.apache.qpid.client.vmbroker.AMQVMBrokerCreationException;
import org.apache.qpid.testutil.VMBrokerSetup;
import javax.jms.*;
diff --git a/java/common/pom.xml b/java/common/pom.xml
index bbc70bf7f6..653b2a8a9d 100644
--- a/java/common/pom.xml
+++ b/java/common/pom.xml
@@ -90,5 +90,9 @@
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-jms_1.1_spec</artifactId>
+ </dependency>
</dependencies>
</project>
diff --git a/java/common/src/main/java/org/apache/qpid/AMQPInvalidClassException.java b/java/common/src/main/java/org/apache/qpid/AMQPInvalidClassException.java
new file mode 100644
index 0000000000..883e13e5e6
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/AMQPInvalidClassException.java
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+
+public class AMQPInvalidClassException extends RuntimeException
+{
+ public AMQPInvalidClassException(String s)
+ {
+ super(s);
+ }
+}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQBody.java b/java/common/src/main/java/org/apache/qpid/framing/AMQBody.java
index 37efe1a34f..d829144b11 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/AMQBody.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/AMQBody.java
@@ -24,7 +24,7 @@ import org.apache.mina.common.ByteBuffer;
public abstract class AMQBody
{
- protected abstract byte getType();
+ protected abstract byte getFrameType();
/**
* Get the size of the body
diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQFrame.java b/java/common/src/main/java/org/apache/qpid/framing/AMQFrame.java
index 21c4bc8d5b..e75f37d623 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/AMQFrame.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/AMQFrame.java
@@ -45,7 +45,7 @@ public class AMQFrame extends AMQDataBlock implements EncodableAMQDataBlock
public void writePayload(ByteBuffer buffer)
{
- buffer.put(bodyFrame.getType());
+ buffer.put(bodyFrame.getFrameType());
// TODO: how does channel get populated
EncodingUtils.writeUnsignedShort(buffer, channel);
EncodingUtils.writeUnsignedInteger(buffer, bodyFrame.getSize());
diff --git a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBody.java b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBody.java
index c3e02aed56..6659b4ff8f 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBody.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/AMQMethodBody.java
@@ -42,7 +42,7 @@ public abstract class AMQMethodBody extends AMQBody
protected abstract void writeMethodPayload(ByteBuffer buffer);
- protected byte getType()
+ protected byte getFrameType()
{
return TYPE;
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java b/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java
index a908c76286..61837f65cc 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java
@@ -57,6 +57,8 @@ public class BasicContentHeaderProperties implements ContentHeaderProperties
private FieldTable _headers;
+ private JMSPropertyFieldTable _jmsHeaders;
+
private byte _deliveryMode;
private byte _priority;
@@ -276,6 +278,7 @@ public class BasicContentHeaderProperties implements ContentHeaderProperties
if ((_propertyFlags & (1 << 13)) > 0)
{
_headers = EncodingUtils.readFieldTable(buffer);
+ setJMSHeaders();
}
if ((_propertyFlags & (1 << 12)) > 0)
{
@@ -358,6 +361,8 @@ public class BasicContentHeaderProperties implements ContentHeaderProperties
if ((_propertyFlags & (1 << 13)) > 0)
{
_headers = EncodingUtils.readFieldTable(buffer);
+ setJMSHeaders();
+
}
_decodedHeaders = true;
}
@@ -446,6 +451,26 @@ public class BasicContentHeaderProperties implements ContentHeaderProperties
clearEncodedForm();
_propertyFlags |= (1 << 13);
_headers = headers;
+ setJMSHeaders();
+ }
+
+ private void setJMSHeaders()
+ {
+ if (_jmsHeaders == null)
+ {
+ _jmsHeaders = new JMSPropertyFieldTable(_headers);
+ }
+ else
+ {
+ _jmsHeaders.setFieldTable(_headers);
+ }
+ }
+
+ public JMSPropertyFieldTable getJMSHeaders()
+ {
+ //This will ensure we have a blank header
+ getHeaders();
+ return _jmsHeaders;
}
public byte getDeliveryMode()
diff --git a/java/common/src/main/java/org/apache/qpid/framing/ContentBody.java b/java/common/src/main/java/org/apache/qpid/framing/ContentBody.java
index 2aae833fcd..3a2e4b3b3c 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/ContentBody.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/ContentBody.java
@@ -28,7 +28,7 @@ public class ContentBody extends AMQBody
public ByteBuffer payload;
- protected byte getType()
+ protected byte getFrameType()
{
return TYPE;
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java
index 46b933b2c3..a59869b1d8 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/ContentHeaderBody.java
@@ -53,7 +53,7 @@ public class ContentHeaderBody extends AMQBody
this.bodySize = bodySize;
}
- protected byte getType()
+ protected byte getFrameType()
{
return TYPE;
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java b/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java
index 61a0787fcd..46dff9ffa8 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java
@@ -461,7 +461,7 @@ public class EncodingUtils
//**** new methods
- // BOOLEAN_PROPERTY_PREFIX
+ // AMQP_BOOLEAN_PROPERTY_PREFIX
public static void writeBoolean(ByteBuffer buffer, Boolean aBoolean)
{
@@ -479,7 +479,7 @@ public class EncodingUtils
return 1;
}
- // BYTE_PROPERTY_PREFIX
+ // AMQP_BYTE_PROPERTY_PREFIX
public static void writeByte(ByteBuffer buffer, Byte aByte)
{
buffer.put(aByte);
@@ -496,7 +496,7 @@ public class EncodingUtils
}
- // SHORT_PROPERTY_PREFIX
+ // AMQP_SHORT_PROPERTY_PREFIX
public static void writeShort(ByteBuffer buffer, Short aShort)
{
buffer.putShort(aShort);
@@ -528,7 +528,7 @@ public class EncodingUtils
return 4;
}
- // LONG_PROPERTY_PREFIX
+ // AMQP_LONG_PROPERTY_PREFIX
public static void writeLong(ByteBuffer buffer, Long aLong)
{
buffer.putLong(aLong);
@@ -610,7 +610,7 @@ public class EncodingUtils
}
//CHAR_PROPERTY
- public static long encodedCharLength()
+ public static int encodedCharLength()
{
return encodedByteLength();
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java b/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java
index 44d0268561..193c7adf1c 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/FieldTable.java
@@ -93,4 +93,6 @@ public interface FieldTable extends Map
public Object setObject(String string, Object object);
+ public boolean isNullStringValue(String name);
+
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBody.java b/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBody.java
index 6bbdaaeed5..7a160ef471 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBody.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/HeartbeatBody.java
@@ -27,7 +27,7 @@ public class HeartbeatBody extends AMQBody
public static final byte TYPE = 8;
public static AMQFrame FRAME = new HeartbeatBody().toFrame();
- protected byte getType()
+ protected byte getFrameType()
{
return TYPE;
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/JMSPropertyFieldTable.java b/java/common/src/main/java/org/apache/qpid/framing/JMSPropertyFieldTable.java
new file mode 100644
index 0000000000..142a689a01
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/framing/JMSPropertyFieldTable.java
@@ -0,0 +1,471 @@
+/*
+ * 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.framing;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.qpid.AMQPInvalidClassException;
+
+import javax.jms.MessageFormatException;
+import javax.jms.JMSException;
+import java.util.Enumeration;
+
+
+public class JMSPropertyFieldTable
+{
+ private FieldTable _fieldtable;
+
+ public JMSPropertyFieldTable()
+ {
+ _fieldtable = new PropertyFieldTable();
+ }
+
+ public JMSPropertyFieldTable(FieldTable table)
+ {
+ _fieldtable = table;
+ }
+
+ public JMSPropertyFieldTable(ByteBuffer buffer, long length) throws JMSException
+ {
+ try
+ {
+ _fieldtable = new PropertyFieldTable(buffer, length);
+ }
+ catch (AMQFrameDecodingException e)
+ {
+ JMSException error = new JMSException(e.getMessage());
+ error.setLinkedException(e);
+ throw error;
+ }
+ }
+
+ private void checkPropertyName(String propertyName)
+ {
+ if (propertyName == null)
+ {
+ throw new IllegalArgumentException("Property name must not be null");
+ }
+ else if ("".equals(propertyName))
+ {
+ throw new IllegalArgumentException("Property name must not be the empty string");
+ }
+
+ checkIdentiferFormat(propertyName);
+ }
+
+ protected static void checkIdentiferFormat(String propertyName)
+ {
+// JMS requirements 3.5.1 Property Names
+// Identifiers:
+// - An identifier is an unlimited-length character sequence that must begin
+// with a Java identifier start character; all following characters must be Java
+// identifier part characters. An identifier start character is any character for
+// which the method Character.isJavaIdentifierStart returns true. This includes
+// '_' and '$'. An identifier part character is any character for which the
+// method Character.isJavaIdentifierPart returns true.
+// - Identifiers cannot be the names NULL, TRUE, or FALSE.
+// – Identifiers cannot be NOT, AND, OR, BETWEEN, LIKE, IN, IS, or
+// ESCAPE.
+// – Identifiers are either header field references or property references. The
+// type of a property value in a message selector corresponds to the type
+// used to set the property. If a property that does not exist in a message is
+// referenced, its value is NULL. The semantics of evaluating NULL values
+// in a selector are described in Section 3.8.1.2, “Null Values.”
+// – The conversions that apply to the get methods for properties do not
+// apply when a property is used in a message selector expression. For
+// example, suppose you set a property as a string value, as in the
+// following:
+// myMessage.setStringProperty("NumberOfOrders", "2");
+// The following expression in a message selector would evaluate to false,
+// because a string cannot be used in an arithmetic expression:
+// "NumberOfOrders > 1"
+// – Identifiers are case sensitive.
+// – Message header field references are restricted to JMSDeliveryMode,
+// JMSPriority, JMSMessageID, JMSTimestamp, JMSCorrelationID, and
+// JMSType. JMSMessageID, JMSCorrelationID, and JMSType values may be
+// null and if so are treated as a NULL value.
+
+ if (Boolean.getBoolean("strict-jms"))
+ {
+ // JMS start character
+ if (!(Character.isJavaIdentifierStart(propertyName.charAt(0))))
+ {
+ throw new IllegalArgumentException("Identifier '" + propertyName + "' does not start with a valid JMS identifier start character");
+ }
+
+ // JMS part character
+ int length = propertyName.length();
+ for (int c = 1; c < length; c++)
+ {
+ if (!(Character.isJavaIdentifierPart(propertyName.charAt(c))))
+ {
+ throw new IllegalArgumentException("Identifier '" + propertyName + "' contains an invalid JMS identifier character");
+ }
+ }
+
+ // JMS invalid names
+ if ((propertyName.equals("NULL")
+ || propertyName.equals("TRUE")
+ || propertyName.equals("FALSE")
+ || propertyName.equals("NOT")
+ || propertyName.equals("AND")
+ || propertyName.equals("OR")
+ || propertyName.equals("BETWEEN")
+ || propertyName.equals("LIKE")
+ || propertyName.equals("IN")
+ || propertyName.equals("IS")
+ || propertyName.equals("ESCAPE")))
+ {
+ throw new IllegalArgumentException("Identifier '" + propertyName + "' is not allowed in JMS");
+ }
+ }
+
+ }
+
+ // MapMessage Interface
+ public boolean getBoolean(String string) throws JMSException
+ {
+ Boolean b = _fieldtable.getBoolean(string);
+
+ if (b == null)
+ {
+ if (_fieldtable.containsKey(string))
+ {
+ Object str = _fieldtable.getObject(string);
+
+ if (str == null || !(str instanceof String))
+ {
+ throw new MessageFormatException("getBoolean can't use " + string + " item.");
+ }
+ else
+ {
+ return Boolean.valueOf((String) str);
+ }
+ }
+ else
+ {
+ b = Boolean.valueOf(null);
+ }
+ }
+
+ return b;
+ }
+
+ public char getCharacter(String string) throws JMSException
+ {
+ Character c = _fieldtable.getCharacter(string);
+
+ if (c == null)
+ {
+ if (_fieldtable.isNullStringValue(string))
+ {
+ throw new NullPointerException("Cannot convert null char");
+ }
+ else
+ {
+ throw new MessageFormatException("getChar can't use " + string + " item.");
+ }
+ }
+ else
+ {
+ return (char) c;
+ }
+ }
+
+ public byte[] getBytes(String string) throws JMSException
+ {
+ byte[] bs = _fieldtable.getBytes(string);
+
+ if (bs == null)
+ {
+ throw new MessageFormatException("getBytes can't use " + string + " item.");
+ }
+ else
+ {
+ return bs;
+ }
+ }
+
+ public byte getByte(String string) throws JMSException
+ {
+ Byte b = _fieldtable.getByte(string);
+ if (b == null)
+ {
+ if (_fieldtable.containsKey(string))
+ {
+ Object str = _fieldtable.getObject(string);
+
+ if (str == null || !(str instanceof String))
+ {
+ throw new MessageFormatException("getByte can't use " + string + " item.");
+ }
+ else
+ {
+ return Byte.valueOf((String) str);
+ }
+ }
+ else
+ {
+ b = Byte.valueOf(null);
+ }
+ }
+
+ return b;
+ }
+
+ public short getShort(String string) throws JMSException
+ {
+ Short s = _fieldtable.getShort(string);
+
+ if (s == null)
+ {
+ s = Short.valueOf(getByte(string));
+ }
+
+ return s;
+ }
+
+ public int getInteger(String string) throws JMSException
+ {
+ Integer i = _fieldtable.getInteger(string);
+
+ if (i == null)
+ {
+ i = Integer.valueOf(getShort(string));
+ }
+
+ return i;
+ }
+
+ public long getLong(String string) throws JMSException
+ {
+ Long l = _fieldtable.getLong(string);
+
+ if (l == null)
+ {
+ l = Long.valueOf(getInteger(string));
+ }
+
+ return l;
+ }
+
+ public float getFloat(String string) throws JMSException
+ {
+ Float f = _fieldtable.getFloat(string);
+
+ if (f == null)
+ {
+ if (_fieldtable.containsKey(string))
+ {
+ Object str = _fieldtable.getObject(string);
+
+ if (str == null || !(str instanceof String))
+ {
+ throw new MessageFormatException("getFloat can't use " + string + " item.");
+ }
+ else
+ {
+ return Float.valueOf((String) str);
+ }
+ }
+ else
+ {
+ f = Float.valueOf(null);
+ }
+
+ }
+
+ return f;
+ }
+
+ public double getDouble(String string) throws JMSException
+ {
+ Double d = _fieldtable.getDouble(string);
+
+ if (d == null)
+ {
+ d = Double.valueOf(getFloat(string));
+ }
+
+ return d;
+ }
+
+ public String getString(String string) throws JMSException
+ {
+ String s = _fieldtable.getString(string);
+
+ if (s == null)
+ {
+ if (_fieldtable.containsKey(string))
+ {
+ Object o = _fieldtable.getObject(string);
+ if (o instanceof byte[])
+ {
+ throw new MessageFormatException("getObject couldn't find " + string + " item.");
+ }
+ else
+ {
+ if (o == null)
+ {
+ return null;
+ }
+ else
+ {
+ s = String.valueOf(o);
+ }
+ }
+ }
+ }
+
+ return s;
+ }
+
+ public Object getObject(String string) throws JMSException
+ {
+ return _fieldtable.getObject(string);
+ }
+
+ public void setBoolean(String string, boolean b) throws JMSException
+ {
+ checkPropertyName(string);
+ _fieldtable.setBoolean(string, b);
+ }
+
+ public void setChar(String string, char c) throws JMSException
+ {
+ checkPropertyName(string);
+ _fieldtable.setChar(string, c);
+ }
+
+ public Object setBytes(String string, byte[] bytes)
+ {
+ return _fieldtable.setBytes(string, bytes, 0, bytes.length);
+ }
+
+ public Object setBytes(String string, byte[] bytes, int start, int length)
+ {
+ return _fieldtable.setBytes(string, bytes, start, length);
+ }
+
+ public void setByte(String string, byte b) throws JMSException
+ {
+ checkPropertyName(string);
+ _fieldtable.setByte(string, b);
+ }
+
+ public void setShort(String string, short i) throws JMSException
+ {
+ checkPropertyName(string);
+ _fieldtable.setShort(string, i);
+ }
+
+ public void setInteger(String string, int i) throws JMSException
+ {
+ checkPropertyName(string);
+ _fieldtable.setInteger(string, i);
+ }
+
+ public void setLong(String string, long l) throws JMSException
+ {
+ checkPropertyName(string);
+ _fieldtable.setLong(string, l);
+ }
+
+ public void setFloat(String string, float v) throws JMSException
+ {
+ checkPropertyName(string);
+ _fieldtable.setFloat(string, v);
+ }
+
+ public void setDouble(String string, double v) throws JMSException
+ {
+ checkPropertyName(string);
+ _fieldtable.setDouble(string, v);
+ }
+
+ public void setString(String string, String string1) throws JMSException
+ {
+ checkPropertyName(string);
+ _fieldtable.setString(string, string1);
+ }
+
+ public void setObject(String string, Object object) throws JMSException
+ {
+ checkPropertyName(string);
+ try
+ {
+ _fieldtable.setObject(string, object);
+ }
+ catch (AMQPInvalidClassException aice)
+ {
+ throw new MessageFormatException("Only primatives are allowed object is:" + object.getClass());
+ }
+ }
+
+ public boolean itemExists(String string) throws JMSException
+ {
+ return _fieldtable.containsKey(string);
+ }
+
+ public void setFieldTable(FieldTable headers)
+ {
+ _fieldtable = headers;
+ }
+
+ public Enumeration getPropertyNames()
+ {
+ return _fieldtable.getPropertyNames();
+ }
+
+ public void clear()
+ {
+ _fieldtable.clear();
+ }
+
+ public boolean propertyExists(String propertyName)
+ {
+ return _fieldtable.propertyExists(propertyName);
+ }
+
+ public Object put(Object key, Object value)
+ {
+ return _fieldtable.put(key, value);
+ }
+
+ public Object remove(String propertyName)
+ {
+ return _fieldtable.remove(propertyName);
+ }
+
+ public boolean isEmpty()
+ {
+ return _fieldtable.isEmpty();
+ }
+
+ public void writeToBuffer(ByteBuffer data)
+ {
+ _fieldtable.writeToBuffer(data);
+ }
+
+ public Enumeration getMapNames()
+ {
+ return getPropertyNames();
+ }
+}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/PropertyFieldTable.java b/java/common/src/main/java/org/apache/qpid/framing/PropertyFieldTable.java
index 8c9b5f3b4c..1292ff2f6e 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/PropertyFieldTable.java
+++ b/java/common/src/main/java/org/apache/qpid/framing/PropertyFieldTable.java
@@ -22,6 +22,7 @@ package org.apache.qpid.framing;
import org.apache.log4j.Logger;
import org.apache.mina.common.ByteBuffer;
+import org.apache.qpid.AMQPInvalidClassException;
import java.util.Collection;
import java.util.Enumeration;
@@ -31,38 +32,13 @@ import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.Vector;
+import java.util.HashMap;
//extends FieldTable
public class PropertyFieldTable implements FieldTable
{
private static final Logger _logger = Logger.getLogger(PropertyFieldTable.class);
- public static final char AMQP_DECIMAL_PROPERTY_PREFIX = 'D';
- public static final char AMQP_UNSIGNEDINT_PROPERTY_PREFIX = 'I';
- public static final char AMQP_TIMESTAMP_PROPERTY_PREFIX = 'T';
- public static final char AMQP_STRING_PROPERTY_PREFIX = 'S';
- public static final char AMQP_ASCII_CHARACTER_PROPERTY_PREFIX = 'k';
- public static final char AMQP_ASCII_STRING_PROPERTY_PREFIX = 'c';
- public static final char AMQP_WIDE_STRING_PROPERTY_PREFIX = 'C';
- public static final char AMQP_BINARY_PROPERTY_PREFIX = 'x';
- public static final char AMQP_NULL_STRING_PROPERTY_PREFIX = 'n';
-
- public static final char BOOLEAN_PROPERTY_PREFIX = 't';
- public static final char BYTE_PROPERTY_PREFIX = 'b';
- public static final char SHORT_PROPERTY_PREFIX = 's';
- public static final char INT_PROPERTY_PREFIX = 'i';
- public static final char LONG_PROPERTY_PREFIX = 'l';
- public static final char FLOAT_PROPERTY_PREFIX = 'f';
- public static final char DOUBLE_PROPERTY_PREFIX = 'd';
-
- public static final char NULL_STRING_PROPERTY_PREFIX = AMQP_NULL_STRING_PROPERTY_PREFIX;
- public static final char STRING_PROPERTY_PREFIX = AMQP_STRING_PROPERTY_PREFIX;
- public static final char CHAR_PROPERTY_PREFIX = AMQP_ASCII_CHARACTER_PROPERTY_PREFIX;
- public static final char BYTES_PROPERTY_PREFIX = AMQP_BINARY_PROPERTY_PREFIX;
-
- //Our custom prefix for encoding across the wire
- private static final char XML_PROPERTY_PREFIX = 'X';
-
private static final String BOOLEAN = "boolean";
private static final String BYTE = "byte";
private static final String BYTES = "bytes";
@@ -72,6 +48,7 @@ public class PropertyFieldTable implements FieldTable
private static final String FLOAT = "float";
private static final String DOUBLE = "double";
private static final String STRING = "string";
+ private static final String NULL_STRING = "nullstring";
private static final String CHAR = "char";
private static final String UNKNOWN = "unknown type";
@@ -80,15 +57,67 @@ public class PropertyFieldTable implements FieldTable
private static final String BYTES_CLOSE_XML = "</" + BYTES + ">";
private static final String BYTES_OPEN_XML_START = "<" + BYTES;
+ public static enum Prefix
+ {
+ //AMQP FieldTable Wire Types
+ AMQP_DECIMAL_PROPERTY_PREFIX('D'),
+ AMQP_UNSIGNED_SHORT_PROPERTY_PREFIX('S'),
+ AMQP_UNSIGNED_INT_PROPERTY_PREFIX('I'),
+ AMQP_UNSIGNED_LONG_PROPERTY_PREFIX('L'),
+ AMQP_DOUBLE_EXTTENDED_PROPERTY_PREFIX('D'),
+
+ AMQP_TIMESTAMP_PROPERTY_PREFIX('T'),
+ AMQP_BINARY_PROPERTY_PREFIX('x'),
+
+ //Strings
+ AMQP_ASCII_STRING_PROPERTY_PREFIX('c'),
+ AMQP_WIDE_STRING_PROPERTY_PREFIX('C'),
+ AMQP_NULL_STRING_PROPERTY_PREFIX('n'),
+
+ //Java Primative Types
+ AMQP_BOOLEAN_PROPERTY_PREFIX('t'),
+ AMQP_BYTE_PROPERTY_PREFIX('b'),
+ AMQP_ASCII_CHARACTER_PROPERTY_PREFIX('k'),
+ AMQP_SHORT_PROPERTY_PREFIX('s'),
+ AMQP_INT_PROPERTY_PREFIX('i'),
+ AMQP_LONG_PROPERTY_PREFIX('l'),
+ AMQP_FLOAT_PROPERTY_PREFIX('f'),
+ AMQP_DOUBLE_PROPERTY_PREFIX('d');
+
+ private final char _identifier;
+
+ Prefix(char identifier)
+ {
+ _identifier = identifier;
+ //_reverseTypeMap.put(identifier, this);
+ }
+
+ public final char identifier()
+ {
+ return _identifier;
+ }
+
+ }
+
+ public static Map<Character, Prefix> _reverseTypeMap = new HashMap<Character, Prefix>();
+
+ static
+ {
+ for (Prefix p : Prefix.values())
+ {
+ _reverseTypeMap.put(p.identifier(), p);
+ }
+ }
+
private LinkedHashMap<String, Object> _properties;
- private LinkedHashMap<String, String> _propertyNamesTypeMap;
- private long _encodedSize = 0;//EncodingUtils.unsignedIntegerLength();
+ private LinkedHashMap<String, Prefix> _propertyNamesTypeMap;
+ private long _encodedSize = 0;
public PropertyFieldTable()
{
super();
_properties = new LinkedHashMap<String, Object>();
- _propertyNamesTypeMap = new LinkedHashMap<String, String>();
+ _propertyNamesTypeMap = new LinkedHashMap<String, Prefix>();
}
public PropertyFieldTable(String textFormat)
@@ -100,7 +129,8 @@ public class PropertyFieldTable implements FieldTable
}
catch (Exception e)
{
- _logger.error("Unable to decode PropertyFieldTable format:" + textFormat, e);
+ _logger.warn("Unable to decode PropertyFieldTable format:" + textFormat, e);
+ throw new IllegalArgumentException("Unable to decode PropertyFieldTable format:" + textFormat);
}
}
@@ -118,17 +148,17 @@ public class PropertyFieldTable implements FieldTable
}
// ************ Getters
-
- private Object get(String propertyName, char prefix)
+ private Object get(String propertyName, Prefix prefix)
{
- String type = _propertyNamesTypeMap.get(propertyName);
+ //Retrieve the type associated with this name
+ Prefix type = _propertyNamesTypeMap.get(propertyName);
if (type == null)
{
return null;
}
- if (type.equals("" + prefix))
+ if (type.equals(prefix))
{
return _properties.get(propertyName);
}
@@ -140,7 +170,7 @@ public class PropertyFieldTable implements FieldTable
public Boolean getBoolean(String string)
{
- Object o = get(string, BOOLEAN_PROPERTY_PREFIX);
+ Object o = get(string, Prefix.AMQP_BOOLEAN_PROPERTY_PREFIX);
if (o != null && o instanceof Boolean)
{
return (Boolean) o;
@@ -153,7 +183,7 @@ public class PropertyFieldTable implements FieldTable
public Byte getByte(String string)
{
- Object o = get(string, BYTE_PROPERTY_PREFIX);
+ Object o = get(string, Prefix.AMQP_BYTE_PROPERTY_PREFIX);
if (o != null)
{
return (Byte) o;
@@ -166,7 +196,7 @@ public class PropertyFieldTable implements FieldTable
public Short getShort(String string)
{
- Object o = get(string, SHORT_PROPERTY_PREFIX);
+ Object o = get(string, Prefix.AMQP_SHORT_PROPERTY_PREFIX);
if (o != null)
{
return (Short) o;
@@ -179,7 +209,7 @@ public class PropertyFieldTable implements FieldTable
public Integer getInteger(String string)
{
- Object o = get(string, INT_PROPERTY_PREFIX);
+ Object o = get(string, Prefix.AMQP_INT_PROPERTY_PREFIX);
if (o != null)
{
return (Integer) o;
@@ -192,7 +222,7 @@ public class PropertyFieldTable implements FieldTable
public Long getLong(String string)
{
- Object o = get(string, LONG_PROPERTY_PREFIX);
+ Object o = get(string, Prefix.AMQP_LONG_PROPERTY_PREFIX);
if (o != null)
{
return (Long) o;
@@ -205,20 +235,20 @@ public class PropertyFieldTable implements FieldTable
public Float getFloat(String string)
{
- Object o = get(string, FLOAT_PROPERTY_PREFIX);
+ Object o = get(string, Prefix.AMQP_FLOAT_PROPERTY_PREFIX);
if (o != null)
{
return (Float) o;
}
else
{
- return null; //Float.valueOf(null); ???
+ return null;
}
}
public Double getDouble(String string)
{
- Object o = get(string, DOUBLE_PROPERTY_PREFIX);
+ Object o = get(string, Prefix.AMQP_DOUBLE_PROPERTY_PREFIX);
if (o != null)
{
return (Double) o;
@@ -231,50 +261,55 @@ public class PropertyFieldTable implements FieldTable
public String getString(String string)
{
- Object o = get(string, STRING_PROPERTY_PREFIX);
+ Object o = get(string, Prefix.AMQP_ASCII_STRING_PROPERTY_PREFIX);
if (o != null)
{
return (String) o;
}
else
{
-
-
- String type = _propertyNamesTypeMap.get(string);
-
- if (type == null || type.equals("" + NULL_STRING_PROPERTY_PREFIX))
+ o = get(string, Prefix.AMQP_WIDE_STRING_PROPERTY_PREFIX);
+ if (o != null)
{
- return null;
+ return (String) o;
}
else
{
- char itype = type.charAt(0);
- Object value = _properties.get(string);
+ Prefix type = _propertyNamesTypeMap.get(string);
- switch (itype)
+ if (type == null || type.equals(Prefix.AMQP_NULL_STRING_PROPERTY_PREFIX))
{
- case STRING_PROPERTY_PREFIX:
- case BYTES_PROPERTY_PREFIX:
- return null;
- default:
- case BYTE_PROPERTY_PREFIX:
- case BOOLEAN_PROPERTY_PREFIX:
- case SHORT_PROPERTY_PREFIX:
- case INT_PROPERTY_PREFIX:
- case LONG_PROPERTY_PREFIX:
- case FLOAT_PROPERTY_PREFIX:
- case DOUBLE_PROPERTY_PREFIX:
- return String.valueOf(value);
- case CHAR_PROPERTY_PREFIX:
- if (value == null)
- {
- throw new NullPointerException("null char cannot be converted to String");
- }
- else
- {
- return String.valueOf(value);
- }
+ return null;
+ }
+ else
+ {
+ switch (type)
+ {
+ case AMQP_ASCII_STRING_PROPERTY_PREFIX:
+ case AMQP_WIDE_STRING_PROPERTY_PREFIX:
+ case AMQP_BINARY_PROPERTY_PREFIX:
+ return null;
+ default:
+ case AMQP_BYTE_PROPERTY_PREFIX:
+ case AMQP_BOOLEAN_PROPERTY_PREFIX:
+ case AMQP_SHORT_PROPERTY_PREFIX:
+ case AMQP_INT_PROPERTY_PREFIX:
+ case AMQP_LONG_PROPERTY_PREFIX:
+ case AMQP_FLOAT_PROPERTY_PREFIX:
+ case AMQP_DOUBLE_PROPERTY_PREFIX:
+ return String.valueOf(_properties.get(string));
+ case AMQP_ASCII_CHARACTER_PROPERTY_PREFIX:
+ Object value = _properties.get(string);
+ if (value == null)
+ {
+ throw new NullPointerException("null char cannot be converted to String");
+ }
+ else
+ {
+ return String.valueOf(value);
+ }
+ }
}
}
}
@@ -282,7 +317,7 @@ public class PropertyFieldTable implements FieldTable
public Character getCharacter(String string)
{
- Object o = get(string, CHAR_PROPERTY_PREFIX);
+ Object o = get(string, Prefix.AMQP_ASCII_CHARACTER_PROPERTY_PREFIX);
if (o != null)
{
return (Character) o;
@@ -295,7 +330,7 @@ public class PropertyFieldTable implements FieldTable
public byte[] getBytes(String string)
{
- Object o = get(string, BYTES_PROPERTY_PREFIX);
+ Object o = get(string, Prefix.AMQP_BINARY_PROPERTY_PREFIX);
if (o != null)
{
return (byte[]) o;
@@ -315,54 +350,62 @@ public class PropertyFieldTable implements FieldTable
public Object setBoolean(String string, boolean b)
{
- return put(BOOLEAN_PROPERTY_PREFIX + string, b);
+ return put(Prefix.AMQP_BOOLEAN_PROPERTY_PREFIX, string, b);
}
public Object setByte(String string, byte b)
{
- return put(BYTE_PROPERTY_PREFIX + string, b);
+ return put(Prefix.AMQP_BYTE_PROPERTY_PREFIX, string, b);
}
public Object setShort(String string, short i)
{
- return put(SHORT_PROPERTY_PREFIX + string, i);
+ return put(Prefix.AMQP_SHORT_PROPERTY_PREFIX, string, i);
}
public Object setInteger(String string, int i)
{
- return put(INT_PROPERTY_PREFIX + string, i);
+ return put(Prefix.AMQP_INT_PROPERTY_PREFIX, string, i);
}
public Object setLong(String string, long l)
{
- return put(LONG_PROPERTY_PREFIX + string, l);
+ return put(Prefix.AMQP_LONG_PROPERTY_PREFIX, string, l);
}
public Object setFloat(String string, float v)
{
- return put(FLOAT_PROPERTY_PREFIX + string, v);
+ return put(Prefix.AMQP_FLOAT_PROPERTY_PREFIX, string, v);
}
public Object setDouble(String string, double v)
{
- return put(DOUBLE_PROPERTY_PREFIX + string, v);
+ return put(Prefix.AMQP_DOUBLE_PROPERTY_PREFIX, string, v);
}
public Object setString(String string, String string1)
{
if (string1 == null)
{
- return put(NULL_STRING_PROPERTY_PREFIX + string, null);
+ return put(Prefix.AMQP_NULL_STRING_PROPERTY_PREFIX, string, null);
}
else
{
- return put(STRING_PROPERTY_PREFIX + string, string1);
+ //FIXME: determine string encoding and set either WIDE or ASCII string
+// if ()
+ {
+ return put(Prefix.AMQP_WIDE_STRING_PROPERTY_PREFIX, string, string1);
+ }
+// else
+// {
+// return put(Prefix.AMQP_ASCII_STRING_PROPERTY_PREFIX, string, string1);
+// }
}
}
public Object setChar(String string, char c)
{
- return put(CHAR_PROPERTY_PREFIX + string, c);
+ return put(Prefix.AMQP_ASCII_CHARACTER_PROPERTY_PREFIX, string, c);
}
public Object setBytes(String string, byte[] bytes)
@@ -372,7 +415,7 @@ public class PropertyFieldTable implements FieldTable
public Object setBytes(String string, byte[] bytes, int start, int length)
{
- return put(BYTES_PROPERTY_PREFIX + string, sizeByteArray(bytes, start, length));
+ return put(Prefix.AMQP_BINARY_PROPERTY_PREFIX, string, sizeByteArray(bytes, start, length));
}
private byte[] sizeByteArray(byte[] bytes, int start, int length)
@@ -395,70 +438,53 @@ public class PropertyFieldTable implements FieldTable
{
return setBoolean(string, (Boolean) object);
}
- else
+ else if (object instanceof Byte)
{
- if (object instanceof Byte)
- {
- return setByte(string, (Byte) object);
- }
- else
- {
- if (object instanceof Short)
- {
- return setShort(string, (Short) object);
- }
- else
- {
- if (object instanceof Integer)
- {
- return setInteger(string, (Integer) object);
- }
- else
- {
- if (object instanceof Long)
- {
- return setLong(string, (Long) object);
- }
- else
- {
- if (object instanceof Float)
- {
- return setFloat(string, (Float) object);
- }
- else
- {
- if (object instanceof Double)
- {
- return setDouble(string, (Double) object);
- }
- else
- {
- if (object instanceof String)
- {
- return setString(string, (String) object);
- }
- else
- {
- if (object instanceof Character)
- {
- return setChar(string, (Character) object);
- }
- else
- {
- if (object instanceof byte[])
- {
- return setBytes(string, (byte[]) object);
- }
- }
- }
- }
- }
- }
- }
- }
- }
+ return setByte(string, (Byte) object);
+ }
+ else if (object instanceof Short)
+ {
+ return setShort(string, (Short) object);
+ }
+ else if (object instanceof Integer)
+ {
+ return setInteger(string, (Integer) object);
+ }
+ else if (object instanceof Long)
+ {
+ return setLong(string, (Long) object);
+ }
+ else if (object instanceof Float)
+ {
+ return setFloat(string, (Float) object);
+ }
+ else if (object instanceof Double)
+ {
+ return setDouble(string, (Double) object);
+ }
+ else if (object instanceof String)
+ {
+ return setString(string, (String) object);
+ }
+ else if (object instanceof Character)
+ {
+ return setChar(string, (Character) object);
}
- return null;
+ else if (object instanceof byte[])
+ {
+ return setBytes(string, (byte[]) object);
+ }
+
+ throw new AMQPInvalidClassException("Only Primatives objects allowed Object is:" + object.getClass());
+ }
+
+
+ public boolean isNullStringValue(String name)
+ {
+ return _properties.containsKey(name) && (_properties.get(name) == null) &&
+ _propertyNamesTypeMap.get(name).equals(Prefix.AMQP_NULL_STRING_PROPERTY_PREFIX);
+
+
}
// ***** Methods
@@ -481,23 +507,12 @@ public class PropertyFieldTable implements FieldTable
public boolean propertyExists(String propertyName)
{
- return _propertyNamesTypeMap.containsKey(propertyName);
+ return itemExists(propertyName);
}
public boolean itemExists(String string)
{
- Iterator keys = _properties.keySet().iterator();
-
- while (keys.hasNext())
- {
- String key = (String) keys.next();
-
- if (key.endsWith(string))
- {
- return true;
- }
- }
- return false;
+ return _properties.containsKey(string);
}
public String toString()
@@ -515,16 +530,9 @@ public class PropertyFieldTable implements FieldTable
{
final Map.Entry entry = (Map.Entry) it.next();
final String propertyName = (String) entry.getKey();
- if (propertyName == null)
- {
- buf.append("\nInternal error: Property with NULL key defined");
- }
- else
- {
- buf.append('\n');
- buf.append(valueAsXML(table._propertyNamesTypeMap.get(propertyName) + propertyName, entry.getValue()));
- }
+ buf.append('\n');
+ buf.append(valueAsXML(table._propertyNamesTypeMap.get(propertyName), propertyName, entry.getValue()));
}
buf.append("\n");
buf.append(PROPERTY_FIELD_TABLE_CLOSE_XML);
@@ -532,18 +540,14 @@ public class PropertyFieldTable implements FieldTable
return buf.toString();
}
- private static String valueAsXML(String name, Object value)
+ private static String valueAsXML(Prefix type, String propertyName, Object value)
{
- char propertyPrefix = name.charAt(0);
- String propertyName = name.substring(1);
-
-
StringBuffer buf = new StringBuffer();
// Start Tag
- buf.append(propertyXML(name, true));
+ buf.append(propertyXML(type, propertyName, true));
// Value
- if (propertyPrefix == BYTES_PROPERTY_PREFIX)
+ if (type.equals(Prefix.AMQP_BINARY_PROPERTY_PREFIX))
{
//remove '>'
buf.deleteCharAt(buf.length() - 1);
@@ -555,22 +559,19 @@ public class PropertyFieldTable implements FieldTable
}
else
{
- buf.append(String.valueOf(value));
+ if (!type.equals(Prefix.AMQP_NULL_STRING_PROPERTY_PREFIX))
+ {
+ buf.append(String.valueOf(value));
+ }
}
-
//End Tag
- buf.append(propertyXML(name, false));
+ buf.append(propertyXML(type, propertyName, false));
return buf.toString();
}
- private Object checkPropertyName(String name)
+ private void checkPropertyName(String propertyName)
{
- String propertyName = name.substring(1);
- char propertyPrefix = name.charAt(0);
-
- Object previous = null;
-
if (propertyName == null)
{
throw new IllegalArgumentException("Property name must not be null");
@@ -581,34 +582,11 @@ public class PropertyFieldTable implements FieldTable
}
checkIdentiferFormat(propertyName);
-
- String currentValue = _propertyNamesTypeMap.get(propertyName);
-
- if (currentValue != null)
- {
- previous = _properties.remove(currentValue + propertyName);
-
- // If we are in effect deleting the value (see comment on null values being deleted
- // below) then we also need to remove the name from the encoding length.
- if (previous == null)
- {
- _encodedSize -= EncodingUtils.encodedShortStringLength(propertyName);
- }
-
- // FIXME: Should be able to short-cut this process if the old and new values are
- // the same object and/or type and size...
- _encodedSize -= getEncodingSize(currentValue + propertyName, previous) + 1;
- }
-
- _propertyNamesTypeMap.put(propertyName, "" + propertyPrefix);
-
- return previous;
}
protected static void checkIdentiferFormat(String propertyName)
{
-
// AMQP Spec: 4.2.5.5 Field Tables
// Guidelines for implementers:
// * Field names MUST start with a letter, '$' or '#' and may continue with
@@ -619,96 +597,23 @@ public class PropertyFieldTable implements FieldTable
// 503 (syntax error). Conformance test: amq_wlp_table_01.
// * A peer MUST handle duplicate fields by using only the first instance.
-// JMS requirements 3.5.1 Property Names
-// Identifiers:
-// - An identifier is an unlimited-length character sequence that must begin
-// with a Java identifier start character; all following characters must be Java
-// identifier part characters. An identifier start character is any character for
-// which the method Character.isJavaIdentifierStart returns true. This includes
-// '_' and '$'. An identifier part character is any character for which the
-// method Character.isJavaIdentifierPart returns true.
-// - Identifiers cannot be the names NULL, TRUE, or FALSE.
-// – Identifiers cannot be NOT, AND, OR, BETWEEN, LIKE, IN, IS, or
-// ESCAPE.
-// – Identifiers are either header field references or property references. The
-// type of a property value in a message selector corresponds to the type
-// used to set the property. If a property that does not exist in a message is
-// referenced, its value is NULL. The semantics of evaluating NULL values
-// in a selector are described in Section 3.8.1.2, “Null Values.”
-// – The conversions that apply to the get methods for properties do not
-// apply when a property is used in a message selector expression. For
-// example, suppose you set a property as a string value, as in the
-// following:
-// myMessage.setStringProperty("NumberOfOrders", "2");
-// The following expression in a message selector would evaluate to false,
-// because a string cannot be used in an arithmetic expression:
-// "NumberOfOrders > 1"
-// – Identifiers are case sensitive.
-// – Message header field references are restricted to JMSDeliveryMode,
-// JMSPriority, JMSMessageID, JMSTimestamp, JMSCorrelationID, and
-// JMSType. JMSMessageID, JMSCorrelationID, and JMSType values may be
-// null and if so are treated as a NULL value.
-
-
- if (Boolean.getBoolean("strict-jms"))
- {
- // JMS start character
- if (!(Character.isJavaIdentifierStart(propertyName.charAt(0))))
- {
- throw new IllegalArgumentException("Identifier '" + propertyName + "' does not start with a valid JMS identifier start character");
- }
-
- // JMS part character
- int length = propertyName.length();
- for (int c = 1; c < length; c++)
- {
- if (!(Character.isJavaIdentifierPart(propertyName.charAt(c))))
- {
- throw new IllegalArgumentException("Identifier '" + propertyName + "' contains an invalid JMS identifier character");
- }
- }
-
- // JMS invalid names
- if (!(propertyName.equals("NULL")
- || propertyName.equals("TRUE")
- || propertyName.equals("FALSE")
- || propertyName.equals("NOT")
- || propertyName.equals("AND")
- || propertyName.equals("OR")
- || propertyName.equals("BETWEEN")
- || propertyName.equals("LIKE")
- || propertyName.equals("IN")
- || propertyName.equals("IS")
- || propertyName.equals("ESCAPE")))
- {
- throw new IllegalArgumentException("Identifier '" + propertyName + "' is not allowed in JMS");
- }
-
- }
- else
+ // AMQP length limit
+ if (propertyName.length() > 128)
{
- // AMQP length limit
- if (propertyName.length() > 128)
- {
- throw new IllegalArgumentException("AMQP limits property names to 128 characters");
- }
-
- // AMQ start character
- if (!(Character.isLetter(propertyName.charAt(0))
- || propertyName.charAt(0) == '$'
- || propertyName.charAt(0) == '#'))
- {
- throw new IllegalArgumentException("Identifier '" + propertyName + "' does not start with a valid AMQP start character");
- }
+ throw new IllegalArgumentException("AMQP limits property names to 128 characters");
}
+ // AMQ start character
+ if (!(Character.isLetter(propertyName.charAt(0))
+ || propertyName.charAt(0) == '$'
+ || propertyName.charAt(0) == '#'))
+ {
+ throw new IllegalArgumentException("Identifier '" + propertyName + "' does not start with a valid AMQP start character");
+ }
}
- private static String propertyXML(String name, boolean start)
+ private static String propertyXML(Prefix type, String propertyName, boolean start)
{
- char propertyPrefix = name.charAt(0);
- String propertyName = name.substring(1);
-
StringBuffer buf = new StringBuffer();
if (start)
@@ -720,40 +625,44 @@ public class PropertyFieldTable implements FieldTable
buf.append("</");
}
- switch (propertyPrefix)
+ switch (type)
{
- case BOOLEAN_PROPERTY_PREFIX:
+ case AMQP_BOOLEAN_PROPERTY_PREFIX:
buf.append(BOOLEAN);
break;
- case BYTE_PROPERTY_PREFIX:
+ case AMQP_BYTE_PROPERTY_PREFIX:
buf.append(BYTE);
break;
- case BYTES_PROPERTY_PREFIX:
+ case AMQP_BINARY_PROPERTY_PREFIX:
buf.append(BYTES);
break;
- case SHORT_PROPERTY_PREFIX:
+ case AMQP_SHORT_PROPERTY_PREFIX:
buf.append(SHORT);
break;
- case INT_PROPERTY_PREFIX:
+ case AMQP_INT_PROPERTY_PREFIX:
buf.append(INT);
break;
- case LONG_PROPERTY_PREFIX:
+ case AMQP_LONG_PROPERTY_PREFIX:
buf.append(LONG);
break;
- case FLOAT_PROPERTY_PREFIX:
+ case AMQP_FLOAT_PROPERTY_PREFIX:
buf.append(FLOAT);
break;
- case DOUBLE_PROPERTY_PREFIX:
+ case AMQP_DOUBLE_PROPERTY_PREFIX:
buf.append(DOUBLE);
break;
- case STRING_PROPERTY_PREFIX:
+ case AMQP_NULL_STRING_PROPERTY_PREFIX:
+ buf.append(NULL_STRING);
+ break;
+ case AMQP_ASCII_STRING_PROPERTY_PREFIX:
+ case AMQP_WIDE_STRING_PROPERTY_PREFIX:
buf.append(STRING);
break;
- case CHAR_PROPERTY_PREFIX:
+ case AMQP_ASCII_CHARACTER_PROPERTY_PREFIX:
buf.append(CHAR);
break;
default:
- buf.append(UNKNOWN + " (identifier ").append(propertyPrefix).append(")");
+ buf.append(UNKNOWN + " (identifier ").append(type.identifier()).append(")");
break;
}
@@ -774,9 +683,9 @@ public class PropertyFieldTable implements FieldTable
for (int index = 0; index < bytes.length; index++)
{
buf.append("\n");
- buf.append(propertyXML(BYTE_PROPERTY_PREFIX + propertyName + "[" + index + "]", true));
+ buf.append(propertyXML(Prefix.AMQP_BYTE_PROPERTY_PREFIX, propertyName + "[" + index + "]", true));
buf.append(bytes[index]);
- buf.append(propertyXML(BYTE_PROPERTY_PREFIX + propertyName + "[" + index + "]", false));
+ buf.append(propertyXML(Prefix.AMQP_BYTE_PROPERTY_PREFIX, propertyName + "[" + index + "]", false));
}
buf.append("\n");
return buf.toString();
@@ -800,16 +709,26 @@ public class PropertyFieldTable implements FieldTable
{
StringTokenizer tokenizer = new StringTokenizer(textFormat, "\n");
+ boolean finished = false;
boolean processing = false;
boolean processing_bytes = false;
+ if (!tokenizer.hasMoreTokens())
+ {
+ throw new IllegalArgumentException("XML has no tokens to parse.");
+ }
+
while (tokenizer.hasMoreTokens())
{
String token = tokenizer.nextToken();
- if (token.equals(PROPERTY_FIELD_TABLE_CLOSE_XML)
- || token.equals(BYTES_CLOSE_XML))
+ if (token.equals(PROPERTY_FIELD_TABLE_CLOSE_XML))
+ {
+ processing = false;
+ finished = true;
+ }
+ if (token.equals(BYTES_CLOSE_XML))
{
processing = false;
}
@@ -840,6 +759,12 @@ public class PropertyFieldTable implements FieldTable
processing = true;
}
}
+
+ if (!finished)
+ {
+ throw new IllegalArgumentException("XML was not in a valid format.");
+ }
+
}
private void processXMLLine(String xmlline)
@@ -887,6 +812,7 @@ public class PropertyFieldTable implements FieldTable
int byteStart = xmlline.indexOf('<', headerEnd);
+ //Don't think this is required.
if (byteStart > 0)
{
while (!xmlline.startsWith(BYTES_CLOSE_XML, byteStart))
@@ -924,8 +850,12 @@ public class PropertyFieldTable implements FieldTable
{
setDouble(propertyName, Double.parseDouble(value));
}
- if (type.equals(STRING))
+ if (type.equals(STRING) || type.equals(NULL_STRING))
{
+ if (type.equals(NULL_STRING))
+ {
+ value = null;
+ }
setString(propertyName, value);
}
if (type.equals(CHAR))
@@ -934,7 +864,7 @@ public class PropertyFieldTable implements FieldTable
}
if (type.equals(UNKNOWN))
{
- _logger.error("Ignoring unknown property value:" + xmlline);
+ _logger.warn("Ignoring unknown property value:" + xmlline);
}
}
@@ -942,16 +872,14 @@ public class PropertyFieldTable implements FieldTable
public void writeToBuffer(ByteBuffer buffer)
{
- final boolean debug = _logger.isDebugEnabled();
+ final boolean trace = _logger.isTraceEnabled();
- if (debug)
+ if (trace)
{
- _logger.debug("FieldTable::writeToBuffer: Writing encoded size of " + _encodedSize + "...");
+ _logger.trace("FieldTable::writeToBuffer: Writing encoded size of " + _encodedSize + "...");
}
EncodingUtils.writeUnsignedInteger(buffer, _encodedSize);
- //EncodingUtils.writeLong(buffer, _encodedSize);
-
putDataInBuffer(buffer);
}
@@ -1001,43 +929,39 @@ public class PropertyFieldTable implements FieldTable
return setObject(key.toString(), value);
}
- protected Object put(String key, Object value)
+ protected Object put(Prefix type, String propertyName, Object value)
{
- Object previous = checkPropertyName(key);
+ checkPropertyName(propertyName);
+ //remove the previous value
+ Object previous = remove(propertyName);
- String propertyName = key.substring(1);
- char propertyPrefix = _propertyNamesTypeMap.get(propertyName).charAt(0);
- if (_logger.isDebugEnabled())
+ if (_logger.isTraceEnabled())
{
- _logger.debug("Put:" + propertyName +
- " encoding Now:" + _encodedSize +
+ int valueSize = 0;
+ if (value != null)
+ {
+ valueSize = getEncodingSize(type, value);
+ }
+ _logger.trace("Put:" + propertyName +
+ " encoding size Now:" + _encodedSize +
" name size= " + EncodingUtils.encodedShortStringLength(propertyName) +
- " value size= " + getEncodingSize(key, value));
+ " value size= " + valueSize);
}
- // This prevents the item from being sent.
- // JMS needs these propertyNames for lookups.
- //if (value != null)
- {
- //Add the size of the propertyName
- _encodedSize += EncodingUtils.encodedShortStringLength(propertyName);
-
- // For now: Setting a null value is the equivalent of deleting it.
- // This is ambiguous in the JMS spec and needs thrashing out and potentially
- // testing against other implementations.
+ //Add the size of the propertyName plus one for the type identifier
+ _encodedSize += EncodingUtils.encodedShortStringLength(propertyName) + 1;
- //Add the size of the content plus one for the type identifier
- _encodedSize += getEncodingSize(key, value) + 1;
- }
-
- if (_logger.isDebugEnabled())
+ if (value != null)
{
- _logger.debug("Put: new encodingSize " + _encodedSize);
+ //Add the size of the content
+ _encodedSize += getEncodingSize(type, value);
}
- _properties.put((String) propertyName, value);
+ //Store new values
+ _propertyNamesTypeMap.put(propertyName, type);
+ _properties.put(propertyName, value);
return previous;
}
@@ -1047,14 +971,14 @@ public class PropertyFieldTable implements FieldTable
if (_properties.containsKey(key))
{
final Object value = _properties.remove(key);
- String typePrefix = _propertyNamesTypeMap.remove(key);
+ Prefix type = _propertyNamesTypeMap.remove(key);
// plus one for the type
_encodedSize -= EncodingUtils.encodedShortStringLength(((String) key)) + 1;
// This check is, for now, unnecessary (we don't store null values).
if (value != null)
{
- _encodedSize -= getEncodingSize(typePrefix, value);
+ _encodedSize -= getEncodingSize(type, value);
}
return value;
}
@@ -1077,6 +1001,7 @@ public class PropertyFieldTable implements FieldTable
public void clear()
{
+ _encodedSize = 0;
_properties.clear();
_propertyNamesTypeMap.clear();
}
@@ -1113,93 +1038,82 @@ public class PropertyFieldTable implements FieldTable
while (it.hasNext())
{
-
Map.Entry me = (Map.Entry) it.next();
String propertyName = (String) me.getKey();
//The type value
- char propertyPrefix = _propertyNamesTypeMap.get(propertyName).charAt(0);
+ Prefix type = _propertyNamesTypeMap.get(propertyName);
Object value = me.getValue();
try
{
-
- if (_logger.isDebugEnabled())
+ if (_logger.isTraceEnabled())
{
- _logger.debug("Writing Property:" + propertyName +
- " Type:" + propertyPrefix +
+ _logger.trace("Writing Property:" + propertyName +
+ " Type:" + type +
" Value:" + value);
- _logger.debug("Buffer Position:" + buffer.position() +
+ _logger.trace("Buffer Position:" + buffer.position() +
" Remaining:" + buffer.remaining());
}
- //The actual param name skipping type
+ //Write the actual parameter name
EncodingUtils.writeShortStringBytes(buffer, propertyName);
-
- switch (propertyPrefix)
+ switch (type)
{
-
- case BOOLEAN_PROPERTY_PREFIX:
- buffer.put((byte) BOOLEAN_PROPERTY_PREFIX);
+ case AMQP_BOOLEAN_PROPERTY_PREFIX:
+ buffer.put((byte) Prefix.AMQP_BOOLEAN_PROPERTY_PREFIX.identifier());
EncodingUtils.writeBoolean(buffer, (Boolean) value);
break;
- case BYTE_PROPERTY_PREFIX:
- buffer.put((byte) BYTE_PROPERTY_PREFIX);
+ case AMQP_BYTE_PROPERTY_PREFIX:
+ buffer.put((byte) Prefix.AMQP_BYTE_PROPERTY_PREFIX.identifier());
EncodingUtils.writeByte(buffer, (Byte) value);
break;
- case SHORT_PROPERTY_PREFIX:
- buffer.put((byte) SHORT_PROPERTY_PREFIX);
+ case AMQP_SHORT_PROPERTY_PREFIX:
+ buffer.put((byte) Prefix.AMQP_SHORT_PROPERTY_PREFIX.identifier());
EncodingUtils.writeShort(buffer, (Short) value);
break;
- case INT_PROPERTY_PREFIX:
- buffer.put((byte) INT_PROPERTY_PREFIX);
+ case AMQP_INT_PROPERTY_PREFIX:
+ buffer.put((byte) Prefix.AMQP_INT_PROPERTY_PREFIX.identifier());
EncodingUtils.writeInteger(buffer, (Integer) value);
break;
- case AMQP_UNSIGNEDINT_PROPERTY_PREFIX: // Currently we don't create these
- buffer.put((byte) AMQP_UNSIGNEDINT_PROPERTY_PREFIX);
+ case AMQP_UNSIGNED_INT_PROPERTY_PREFIX: // Currently we don't create these
+ buffer.put((byte) Prefix.AMQP_UNSIGNED_INT_PROPERTY_PREFIX.identifier());
EncodingUtils.writeUnsignedInteger(buffer, (Long) value);
break;
- case LONG_PROPERTY_PREFIX:
- buffer.put((byte) LONG_PROPERTY_PREFIX);
+ case AMQP_LONG_PROPERTY_PREFIX:
+ buffer.put((byte) Prefix.AMQP_LONG_PROPERTY_PREFIX.identifier());
EncodingUtils.writeLong(buffer, (Long) value);
break;
- case FLOAT_PROPERTY_PREFIX:
- buffer.put((byte) FLOAT_PROPERTY_PREFIX);
+ case AMQP_FLOAT_PROPERTY_PREFIX:
+ buffer.put((byte) Prefix.AMQP_FLOAT_PROPERTY_PREFIX.identifier());
EncodingUtils.writeFloat(buffer, (Float) value);
break;
- case DOUBLE_PROPERTY_PREFIX:
- buffer.put((byte) DOUBLE_PROPERTY_PREFIX);
+ case AMQP_DOUBLE_PROPERTY_PREFIX:
+ buffer.put((byte) Prefix.AMQP_DOUBLE_PROPERTY_PREFIX.identifier());
EncodingUtils.writeDouble(buffer, (Double) value);
break;
- case NULL_STRING_PROPERTY_PREFIX:
- buffer.put((byte) NULL_STRING_PROPERTY_PREFIX);
+ case AMQP_NULL_STRING_PROPERTY_PREFIX:
+ buffer.put((byte) Prefix.AMQP_NULL_STRING_PROPERTY_PREFIX.identifier());
break;
-
case AMQP_WIDE_STRING_PROPERTY_PREFIX:
- // TODO: look at using proper charset encoder
- buffer.put((byte) STRING_PROPERTY_PREFIX);
+ buffer.put((byte) Prefix.AMQP_WIDE_STRING_PROPERTY_PREFIX.identifier());
+ // FIXME: use proper charset encoder
EncodingUtils.writeLongStringBytes(buffer, (String) value);
break;
case AMQP_ASCII_STRING_PROPERTY_PREFIX:
- case STRING_PROPERTY_PREFIX: // AMQP_STRING_PROPERTY_PREFIX:
//This is a simple ASCII string
- buffer.put((byte) STRING_PROPERTY_PREFIX);
+ buffer.put((byte) Prefix.AMQP_ASCII_STRING_PROPERTY_PREFIX.identifier());
EncodingUtils.writeLongStringBytes(buffer, (String) value);
break;
- case CHAR_PROPERTY_PREFIX:
- buffer.put((byte) CHAR_PROPERTY_PREFIX);
+ case AMQP_ASCII_CHARACTER_PROPERTY_PREFIX:
+ buffer.put((byte) Prefix.AMQP_ASCII_CHARACTER_PROPERTY_PREFIX.identifier());
EncodingUtils.writeChar(buffer, (Character) value);
break;
- case BYTES_PROPERTY_PREFIX:
- buffer.put((byte) BYTES_PROPERTY_PREFIX);
+ case AMQP_BINARY_PROPERTY_PREFIX:
+ buffer.put((byte) Prefix.AMQP_BINARY_PROPERTY_PREFIX.identifier());
EncodingUtils.writeBytes(buffer, (byte[]) value);
break;
- case XML_PROPERTY_PREFIX:
- // Encode as XML
- buffer.put((byte) XML_PROPERTY_PREFIX);
- EncodingUtils.writeLongStringBytes(buffer, valueAsXML(propertyPrefix + propertyName, value));
- break;
default:
{
// Should never get here
@@ -1209,172 +1123,158 @@ public class PropertyFieldTable implements FieldTable
}
catch (Exception e)
{
- if (_logger.isDebugEnabled())
+ if (_logger.isTraceEnabled())
{
- _logger.debug("Exception thrown:" + e);
- _logger.debug("Writing Property:" + propertyName +
- " Type:" + propertyPrefix +
+ _logger.trace("Exception thrown:" + e);
+ _logger.trace("Writing Property:" + propertyName +
+ " Type:" + type +
" Value:" + value);
- _logger.debug("Buffer Position:" + buffer.position() +
+ _logger.trace("Buffer Position:" + buffer.position() +
" Remaining:" + buffer.remaining());
}
throw new RuntimeException(e);
}
}
-
}
public void setFromBuffer(ByteBuffer buffer, long length) throws AMQFrameDecodingException
{
- final boolean debug = _logger.isDebugEnabled();
+ final boolean trace = _logger.isTraceEnabled();
int sizeRead = 0;
while (sizeRead < length)
{
int sizeRemaining = buffer.remaining();
final String key = EncodingUtils.readShortString(buffer);
- // TODO: use proper charset decoder
+
byte iType = buffer.get();
- final char type = (char) iType;
- Object value = null;
+
+ Character mapKey = new Character((char) iType);
+ Prefix type = _reverseTypeMap.get(mapKey);
+
+ if (type == null)
+ {
+ String msg = "Field '" + key + "' - unsupported field table type: " + type + ".";
+ //some extra trace information...
+ msg += " (" + iType + "), length=" + length + ", sizeRead=" + sizeRead + ", sizeRemaining=" + sizeRemaining;
+ throw new AMQFrameDecodingException(msg);
+ }
+ Object value;
switch (type)
{
- case BOOLEAN_PROPERTY_PREFIX:
+ case AMQP_BOOLEAN_PROPERTY_PREFIX:
value = EncodingUtils.readBoolean(buffer);
break;
- case BYTE_PROPERTY_PREFIX:
+ case AMQP_BYTE_PROPERTY_PREFIX:
value = EncodingUtils.readByte(buffer);
break;
- case SHORT_PROPERTY_PREFIX:
+ case AMQP_SHORT_PROPERTY_PREFIX:
value = EncodingUtils.readShort(buffer);
break;
- case INT_PROPERTY_PREFIX:
+ case AMQP_INT_PROPERTY_PREFIX:
value = EncodingUtils.readInteger(buffer);
break;
- case AMQP_UNSIGNEDINT_PROPERTY_PREFIX:// This will only fit in a long
- case LONG_PROPERTY_PREFIX:
+ case AMQP_UNSIGNED_INT_PROPERTY_PREFIX:// This will only fit in a long
+ //Change this type for java lookups
+ type = Prefix.AMQP_LONG_PROPERTY_PREFIX;
+ case AMQP_LONG_PROPERTY_PREFIX:
value = EncodingUtils.readLong(buffer);
break;
- case FLOAT_PROPERTY_PREFIX:
+ case AMQP_FLOAT_PROPERTY_PREFIX:
value = EncodingUtils.readFloat(buffer);
break;
- case DOUBLE_PROPERTY_PREFIX:
+ case AMQP_DOUBLE_PROPERTY_PREFIX:
value = EncodingUtils.readDouble(buffer);
break;
-
- // TODO: use proper charset decoder
case AMQP_WIDE_STRING_PROPERTY_PREFIX:
+ // FIXME: use proper charset encoder
case AMQP_ASCII_STRING_PROPERTY_PREFIX:
- case STRING_PROPERTY_PREFIX: // AMQP_STRING_PROPERTY_PREFIX:
value = EncodingUtils.readLongString(buffer);
break;
- case NULL_STRING_PROPERTY_PREFIX:
+ case AMQP_NULL_STRING_PROPERTY_PREFIX:
value = null;
break;
- case CHAR_PROPERTY_PREFIX:
+ case AMQP_ASCII_CHARACTER_PROPERTY_PREFIX:
value = EncodingUtils.readChar((buffer));
break;
- case BYTES_PROPERTY_PREFIX:
+ case AMQP_BINARY_PROPERTY_PREFIX:
value = EncodingUtils.readBytes(buffer);
break;
- case XML_PROPERTY_PREFIX:
- processXMLLine(EncodingUtils.readLongString(buffer));
- break;
default:
- String msg = "Field '" + key + "' - unsupported field table type: " + type + ".";
- //some extra debug information...
- msg += " (" + iType + "), length=" + length + ", sizeRead=" + sizeRead + ", sizeRemaining=" + sizeRemaining;
+ String msg = "Internal error, the following type identifier is not handled: " + type;
throw new AMQFrameDecodingException(msg);
}
sizeRead += (sizeRemaining - buffer.remaining());
- if (debug)
+ if (trace)
{
- _logger.debug("FieldTable::PropFieldTable(buffer," + length + "): Read type '" + type + "', key '" + key + "', value '" + value + "' (now read " + sizeRead + " of " + length + " encoded bytes)...");
+ _logger.trace("FieldTable::PropFieldTable(buffer," + length + "): Read type '" + type + "', key '" + key + "', value '" + value + "' (now read " + sizeRead + " of " + length + " encoded bytes)...");
}
- if (type != XML_PROPERTY_PREFIX)
- {
- setObject(key, value);
- if (value == null)
- {
- _logger.debug("setFromBuffer: value is null for key:" + key);
- _propertyNamesTypeMap.put(key, "" + type);
- _properties.put(key, null);
- }
- }
+ put(type, key, value);
}
- if (debug)
+ if (trace)
{
- _logger.debug("FieldTable::FieldTable(buffer," + length + "): Done.");
+ _logger.trace("FieldTable::FieldTable(buffer," + length + "): Done.");
}
}
-
/**
- * @param name the property name with type prefix
+ * @param type the type to calucluate encoding for
* @param value the property value
* @return integer
*/
- private static int getEncodingSize(String name, Object value)
+ private static int getEncodingSize(Prefix type, Object value)
{
int encodingSize = 0;
- char propertyPrefix = name.charAt(0);
-
- switch (propertyPrefix)
+ switch (type)
{
- case BOOLEAN_PROPERTY_PREFIX:
- encodingSize += EncodingUtils.encodedBooleanLength();
+ case AMQP_BOOLEAN_PROPERTY_PREFIX:
+ encodingSize = EncodingUtils.encodedBooleanLength();
break;
- case BYTE_PROPERTY_PREFIX:
- encodingSize += EncodingUtils.encodedByteLength();
+ case AMQP_BYTE_PROPERTY_PREFIX:
+ encodingSize = EncodingUtils.encodedByteLength();
break;
- case SHORT_PROPERTY_PREFIX:
- encodingSize += EncodingUtils.encodedShortLength();
+ case AMQP_SHORT_PROPERTY_PREFIX:
+ encodingSize = EncodingUtils.encodedShortLength();
break;
- case INT_PROPERTY_PREFIX:
- encodingSize += EncodingUtils.encodedIntegerLength();
+ case AMQP_INT_PROPERTY_PREFIX:
+ encodingSize = EncodingUtils.encodedIntegerLength();
break;
- case LONG_PROPERTY_PREFIX:
- encodingSize += EncodingUtils.encodedLongLength();
+ case AMQP_LONG_PROPERTY_PREFIX:
+ encodingSize = EncodingUtils.encodedLongLength();
break;
- case FLOAT_PROPERTY_PREFIX:
- encodingSize += EncodingUtils.encodedFloatLength();
+ case AMQP_FLOAT_PROPERTY_PREFIX:
+ encodingSize = EncodingUtils.encodedFloatLength();
break;
- case DOUBLE_PROPERTY_PREFIX:
- encodingSize += EncodingUtils.encodedDoubleLength();
+ case AMQP_DOUBLE_PROPERTY_PREFIX:
+ encodingSize = EncodingUtils.encodedDoubleLength();
break;
case AMQP_WIDE_STRING_PROPERTY_PREFIX:
+ // FIXME: use proper charset encoder
case AMQP_ASCII_STRING_PROPERTY_PREFIX:
- case STRING_PROPERTY_PREFIX: //AMQP_STRING_PROPERTY_PREFIX:
- encodingSize += EncodingUtils.encodedLongStringLength((String) value);
- break;
- case NULL_STRING_PROPERTY_PREFIX:
- // There is no need for additional size beyond the prefix
- break;
- case CHAR_PROPERTY_PREFIX:
- encodingSize += EncodingUtils.encodedCharLength();
+ encodingSize = EncodingUtils.encodedLongStringLength((String) value);
break;
- case BYTES_PROPERTY_PREFIX:
- encodingSize += 1 + ((byte[]) value).length;
+// This is not required as this method is never called if the value is null
+// case AMQP_NULL_STRING_PROPERTY_PREFIX:
+// // There is no need for additional size beyond the prefix
+// break;
+ case AMQP_ASCII_CHARACTER_PROPERTY_PREFIX:
+ encodingSize = EncodingUtils.encodedCharLength();
break;
- case XML_PROPERTY_PREFIX:
- encodingSize += EncodingUtils.encodedLongStringLength(valueAsXML(name, value));
+ case AMQP_BINARY_PROPERTY_PREFIX:
+ encodingSize = 1 + ((byte[]) value).length;
break;
default:
- //encodingSize = 1 + EncodingUtils.encodedLongstrLength(String.valueOf(value));
- // We are using XML String encoding
throw new IllegalArgumentException("Unsupported type in field table: " + value.getClass());
}
-// the extra byte for the type indicator is calculated in the name
+ // the extra byte for the type indicator is calculated in the name
return encodingSize;
}
-
-
}
diff --git a/java/common/src/main/java/org/apache/qpid/pool/Event.java b/java/common/src/main/java/org/apache/qpid/pool/Event.java
index 71ab6e7863..7364b9293a 100644
--- a/java/common/src/main/java/org/apache/qpid/pool/Event.java
+++ b/java/common/src/main/java/org/apache/qpid/pool/Event.java
@@ -109,6 +109,6 @@ class Event
public String toString()
{
- return "Event: type " + type + ", data: " + data;
+ return "Event: type " + type + ", data: " + data;
}
}
diff --git a/java/common/src/test/java/org/apache/qpid/framing/JMSPropertyFieldTableTest.java b/java/common/src/test/java/org/apache/qpid/framing/JMSPropertyFieldTableTest.java
new file mode 100644
index 0000000000..865735499b
--- /dev/null
+++ b/java/common/src/test/java/org/apache/qpid/framing/JMSPropertyFieldTableTest.java
@@ -0,0 +1,1020 @@
+/*
+ * 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.framing;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.HashMap;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.log4j.Logger;
+
+import javax.jms.JMSException;
+import javax.jms.MessageFormatException;
+
+public class JMSPropertyFieldTableTest extends TestCase
+{
+
+ private static final Logger _logger = Logger.getLogger(JMSPropertyFieldTableTest.class);
+
+
+ public void setUp()
+ {
+ System.getProperties().setProperty("strict-jms", "true");
+ }
+
+ public void tearDown()
+ {
+ System.getProperties().remove("strict-jms");
+ }
+
+ /**
+ * Test that setting a similar named value replaces any previous value set on that name
+ */
+ public void testReplacement() throws JMSException
+ {
+ JMSPropertyFieldTable table1 = new JMSPropertyFieldTable();
+ //Set a boolean value
+ table1.setBoolean("value", true);
+
+ // reset value to an integer
+ table1.setInteger("value", Integer.MAX_VALUE);
+
+ //Check boolean value is null
+ try
+ {
+ table1.getBoolean("value");
+ }
+ catch (MessageFormatException mfe)
+ {
+ //normal execution
+ }
+ // ... and integer value is good
+ Assert.assertEquals(Integer.MAX_VALUE, table1.getInteger("value"));
+ }
+
+ public void testRemoval() throws JMSException
+ {
+ JMSPropertyFieldTable table1 = new JMSPropertyFieldTable();
+ //Set a boolean value
+ table1.setBoolean("value", true);
+
+ Assert.assertTrue(table1.getBoolean("value"));
+
+ table1.remove("value");
+
+ //Check boolean value is null
+ try
+ {
+ table1.getBoolean("value");
+ }
+ catch (MessageFormatException mfe)
+ {
+ //normal execution
+ }
+ }
+
+
+ /**
+ * Set a boolean and check that we can only get it back as a boolean and a string
+ * Check that attempting to lookup a non existent value returns null
+ */
+ public void testBoolean() throws JMSException
+ {
+ JMSPropertyFieldTable table1 = new JMSPropertyFieldTable();
+ table1.setBoolean("value", true);
+ Assert.assertTrue(table1.propertyExists("value"));
+
+ //Test Getting right value back
+ Assert.assertEquals(true, table1.getBoolean("value"));
+
+ //Check we don't get anything back for other gets
+ try
+ {
+ table1.getByte("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+
+ try
+ {
+ table1.getByte("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+
+ try
+ {
+ table1.getShort("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+
+ try
+ {
+ table1.getDouble("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+
+ try
+ {
+ table1.getFloat("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+
+ try
+ {
+ table1.getInteger("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+
+ try
+ {
+ table1.getLong("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+
+ //except value as a string
+ Assert.assertEquals("true", table1.getString("value"));
+
+ table1.remove("value");
+ //but after a remove it doesn't
+ Assert.assertFalse(table1.propertyExists("value"));
+
+ // Table should now have zero size for encoding
+ checkEmpty(table1);
+
+ //Looking up an invalid value will return false
+ Assert.assertFalse(table1.getBoolean("Rubbish"));
+ }
+
+ /**
+ * Set a byte and check that we can only get it back as a byte and a string
+ * Check that attempting to lookup a non existent value returns null
+ */
+ public void testByte() throws JMSException
+ {
+ JMSPropertyFieldTable table1 = new JMSPropertyFieldTable();
+ table1.setByte("value", Byte.MAX_VALUE);
+ Assert.assertTrue(table1.propertyExists("value"));
+
+ //Tets lookups we shouldn't get anything back for other gets
+ //we should get right value back for this type ....
+ try
+ {
+ table1.getBoolean("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+
+ try
+ {
+ table1.getDouble("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+ try
+ {
+ table1.getFloat("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+
+ Assert.assertEquals(Byte.MAX_VALUE, (byte) table1.getShort("value"));
+ Assert.assertEquals(Byte.MAX_VALUE, (byte) table1.getInteger("value"));
+ Assert.assertEquals(Byte.MAX_VALUE, (byte) table1.getLong("value"));
+ Assert.assertEquals(Byte.MAX_VALUE, table1.getByte("value"));
+ //... and a the string value of it.
+ Assert.assertEquals("" + Byte.MAX_VALUE, table1.getString("value"));
+
+ table1.remove("value");
+ //but after a remove it doesn't
+ Assert.assertFalse(table1.propertyExists("value"));
+
+ // Table should now have zero size for encoding
+ checkEmpty(table1);
+
+ //Looking up an invalid value returns null
+ try
+ {
+ table1.getByte("Rubbish");
+ fail("Should throw NumberFormatException");
+ }
+ catch (NumberFormatException mfs)
+ {
+ //normal Execution
+ }
+
+ }
+
+
+ /**
+ * Set a short and check that we can only get it back as a short and a string
+ * Check that attempting to lookup a non existent value returns null
+ */
+ public void testShort() throws JMSException
+ {
+ JMSPropertyFieldTable table1 = new JMSPropertyFieldTable();
+ table1.setShort("value", Short.MAX_VALUE);
+ Assert.assertTrue(table1.propertyExists("value"));
+
+ //Tets lookups we shouldn't get anything back for other gets
+ //we should get right value back for this type ....
+
+ try
+ {
+ table1.getBoolean("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+ try
+ {
+ table1.getByte("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+
+ try
+ {
+ table1.getDouble("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+ try
+ {
+ table1.getFloat("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+
+
+ Assert.assertEquals(Short.MAX_VALUE, (short) table1.getLong("value"));
+ Assert.assertEquals(Short.MAX_VALUE, (short) table1.getInteger("value"));
+ Assert.assertEquals(Short.MAX_VALUE, table1.getShort("value"));
+
+ //... and a the string value of it.
+ Assert.assertEquals("" + Short.MAX_VALUE, table1.getString("value"));
+
+ table1.remove("value");
+ //but after a remove it doesn't
+ Assert.assertFalse(table1.propertyExists("value"));
+
+ // Table should now have zero size for encoding
+ checkEmpty(table1);
+
+ //Looking up an invalid value returns null
+ try
+ {
+ table1.getShort("Rubbish");
+ fail("Should throw NumberFormatException");
+ }
+ catch (NumberFormatException mfe)
+ {
+ //normal path
+ }
+ }
+
+
+ /**
+ * Set a double and check that we can only get it back as a double
+ * Check that attempting to lookup a non existent value returns null
+ */
+ public void testDouble() throws JMSException
+ {
+ JMSPropertyFieldTable table1 = new JMSPropertyFieldTable();
+ table1.setDouble("value", Double.MAX_VALUE);
+ Assert.assertTrue(table1.propertyExists("value"));
+
+ //Tets lookups we shouldn't get anything back for other gets
+ //we should get right value back for this type ....
+ try
+ {
+ table1.getBoolean("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+ try
+ {
+ table1.getByte("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+ try
+ {
+ table1.getShort("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+ try
+ {
+ table1.getFloat("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+ try
+ {
+ table1.getInteger("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+ try
+ {
+ table1.getLong("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+
+ Assert.assertEquals(Double.MAX_VALUE, table1.getDouble("value"));
+ //... and a the string value of it.
+ Assert.assertEquals("" + Double.MAX_VALUE, table1.getString("value"));
+
+ table1.remove("value");
+ //but after a remove it doesn't
+ Assert.assertFalse(table1.propertyExists("value"));
+
+ // Table should now have zero size for encoding
+ checkEmpty(table1);
+
+ //Looking up an invalid value returns null
+ try
+ {
+ table1.getDouble("Rubbish");
+ fail("Should throw NullPointerException as float.valueOf will try sunreadJavaFormatString");
+ }
+ catch (NullPointerException mfe)
+ {
+ //normal path
+ }
+
+ }
+
+
+ /**
+ * Set a float and check that we can only get it back as a float
+ * Check that attempting to lookup a non existent value returns null
+ */
+ public void testFloat() throws JMSException
+ {
+ JMSPropertyFieldTable table1 = new JMSPropertyFieldTable();
+ table1.setFloat("value", Float.MAX_VALUE);
+ Assert.assertTrue(table1.propertyExists("value"));
+
+ //Tets lookups we shouldn't get anything back for other gets
+ //we should get right value back for this type ....
+ try
+ {
+ table1.getBoolean("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+ try
+ {
+ table1.getByte("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+ try
+ {
+ table1.getShort("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+ try
+ {
+ table1.getInteger("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+ try
+ {
+ table1.getLong("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+
+
+ Assert.assertEquals(Float.MAX_VALUE, table1.getFloat("value"));
+ Assert.assertEquals(Float.MAX_VALUE, (float) table1.getDouble("value"));
+
+ //... and a the string value of it.
+ Assert.assertEquals("" + Float.MAX_VALUE, table1.getString("value"));
+
+ table1.remove("value");
+ //but after a remove it doesn't
+ Assert.assertFalse(table1.propertyExists("value"));
+
+ // Table should now have zero size for encoding
+ checkEmpty(table1);
+
+ //Looking up an invalid value returns null
+ try
+ {
+ table1.getFloat("Rubbish");
+ fail("Should throw NullPointerException as float.valueOf will try sunreadJavaFormatString");
+ }
+ catch (NullPointerException mfe)
+ {
+ //normal path
+ }
+ }
+
+
+ /**
+ * Set an int and check that we can only get it back as an int
+ * Check that attempting to lookup a non existent value returns null
+ */
+ public void testInt() throws JMSException
+ {
+ JMSPropertyFieldTable table1 = new JMSPropertyFieldTable();
+ table1.setInteger("value", Integer.MAX_VALUE);
+ Assert.assertTrue(table1.propertyExists("value"));
+
+ //Tets lookups we shouldn't get anything back for other gets
+ //we should get right value back for this type ....
+ try
+ {
+ table1.getBoolean("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+ try
+ {
+ table1.getByte("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+ try
+ {
+ table1.getShort("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+ try
+ {
+ table1.getDouble("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+ try
+ {
+ table1.getFloat("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+
+
+ Assert.assertEquals(Integer.MAX_VALUE, table1.getLong("value"));
+
+ Assert.assertEquals(Integer.MAX_VALUE, table1.getInteger("value"));
+
+ //... and a the string value of it.
+ Assert.assertEquals("" + Integer.MAX_VALUE, table1.getString("value"));
+
+ table1.remove("value");
+ //but after a remove it doesn't
+ Assert.assertFalse(table1.propertyExists("value"));
+
+ // Table should now have zero size for encoding
+ checkEmpty(table1);
+
+ //Looking up an invalid value returns null
+ try
+ {
+ table1.getInteger("Rubbish");
+ fail("Should throw NumberFormatException");
+ }
+ catch (NumberFormatException mfe)
+ {
+ //normal path
+ }
+ }
+
+
+ /**
+ * Set a long and check that we can only get it back as a long
+ * Check that attempting to lookup a non existent value returns null
+ */
+ public void testLong() throws JMSException
+ {
+ JMSPropertyFieldTable table1 = new JMSPropertyFieldTable();
+ table1.setLong("value", Long.MAX_VALUE);
+ Assert.assertTrue(table1.propertyExists("value"));
+
+ //Tets lookups we shouldn't get anything back for other gets
+ //we should get right value back for this type ....
+ try
+ {
+ table1.getBoolean("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+ try
+ {
+ table1.getByte("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+ try
+ {
+ table1.getShort("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+ try
+ {
+ table1.getDouble("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+ try
+ {
+ table1.getFloat("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+ try
+ {
+ table1.getInteger("value");
+ fail("Should throw MessageFormatException");
+ }
+ catch (MessageFormatException mfs)
+ {
+ //normal Execution
+ }
+
+
+ Assert.assertEquals(Long.MAX_VALUE, table1.getLong("value"));
+
+ //... and a the string value of it.
+ Assert.assertEquals("" + Long.MAX_VALUE, table1.getString("value"));
+
+ table1.remove("value");
+ //but after a remove it doesn't
+ Assert.assertFalse(table1.propertyExists("value"));
+
+ // Table should now have zero size for encoding
+ checkEmpty(table1);
+
+ //Looking up an invalid value
+ try
+ {
+ table1.getLong("Rubbish");
+ fail("Should throw NumberFormatException");
+ }
+ catch (NumberFormatException mfs)
+ {
+ //normal Execution
+ }
+
+ }
+
+
+ /**
+ * Calls all methods that can be used to check the table is empty
+ * - getEncodedSize
+ * - isEmpty
+ * - size
+ *
+ * @param table to check is empty
+ */
+ private void checkEmpty(JMSPropertyFieldTable table)
+ {
+ Assert.assertFalse(table.getPropertyNames().hasMoreElements());
+ }
+
+
+ /**
+ * Set a String and check that we can only get it back as a String
+ * Check that attempting to lookup a non existent value returns null
+ */
+ public void testString() throws JMSException
+ {
+ JMSPropertyFieldTable table1 = new JMSPropertyFieldTable();
+ table1.setString("value", "Hello");
+ Assert.assertTrue(table1.propertyExists("value"));
+
+ //Tets lookups we shouldn't get anything back for other gets
+ //we should get right value back for this type ....
+ Assert.assertEquals(false, table1.getBoolean("value"));
+
+ try
+ {
+ table1.getByte("value");
+ fail("Should throw NumberFormatException");
+ }
+ catch (NumberFormatException nfs)
+ {
+ //normal Execution
+ }
+ try
+ {
+ table1.getShort("value");
+ fail("Should throw NumberFormatException");
+ }
+ catch (NumberFormatException nfs)
+ {
+ //normal Execution
+ }
+ try
+ {
+ table1.getDouble("value");
+ fail("Should throw NumberFormatException");
+ }
+ catch (NumberFormatException nfs)
+ {
+ //normal Execution
+ }
+ try
+ {
+ table1.getFloat("value");
+ fail("Should throw NumberFormatException");
+ }
+ catch (NumberFormatException nfs)
+ {
+ //normal Execution
+ }
+ try
+ {
+ table1.getInteger("value");
+ fail("Should throw NumberFormatException");
+ }
+ catch (NumberFormatException nfs)
+ {
+ //normal Execution
+ }
+ try
+ {
+ table1.getLong("value");
+ fail("Should throw NumberFormatException");
+ }
+ catch (NumberFormatException nfs)
+ {
+ //normal Execution
+ }
+
+ Assert.assertEquals("Hello", table1.getString("value"));
+
+ table1.remove("value");
+ //but after a remove it doesn't
+ Assert.assertFalse(table1.propertyExists("value"));
+
+ checkEmpty(table1);
+
+ //Looking up an invalid value returns null
+ Assert.assertEquals(null, table1.getString("Rubbish"));
+
+ //Additional Test that haven't been covered for string
+ table1.setObject("value", "Hello");
+ //Check that it was set correctly
+ Assert.assertEquals("Hello", table1.getString("value"));
+ }
+
+
+ public void testValues() throws JMSException
+ {
+ JMSPropertyFieldTable table = new JMSPropertyFieldTable();
+ table.setBoolean("bool", true);
+ table.setDouble("double", Double.MAX_VALUE);
+ table.setFloat("float", Float.MAX_VALUE);
+ table.setInteger("int", Integer.MAX_VALUE);
+ table.setLong("long", Long.MAX_VALUE);
+ table.setShort("short", Short.MAX_VALUE);
+ table.setString("string", "Hello");
+ table.setString("nullstring", null);
+
+ table.setObject("objectbool", true);
+ table.setObject("objectdouble", Double.MAX_VALUE);
+ table.setObject("objectfloat", Float.MAX_VALUE);
+ table.setObject("objectint", Integer.MAX_VALUE);
+ table.setObject("objectlong", Long.MAX_VALUE);
+ table.setObject("objectshort", Short.MAX_VALUE);
+ table.setObject("objectstring", "Hello");
+
+
+ Assert.assertEquals(true, table.getBoolean("bool"));
+
+ Assert.assertEquals(Double.MAX_VALUE, table.getDouble("double"));
+ Assert.assertEquals(Float.MAX_VALUE, table.getFloat("float"));
+ Assert.assertEquals(Integer.MAX_VALUE, table.getInteger("int"));
+ Assert.assertEquals(Long.MAX_VALUE, table.getLong("long"));
+ Assert.assertEquals(Short.MAX_VALUE, table.getShort("short"));
+ Assert.assertEquals("Hello", table.getString("string"));
+ Assert.assertEquals(null, table.getString("null-string"));
+
+ Assert.assertEquals(true, table.getObject("objectbool"));
+ Assert.assertEquals(Double.MAX_VALUE, table.getObject("objectdouble"));
+ Assert.assertEquals(Float.MAX_VALUE, table.getObject("objectfloat"));
+ Assert.assertEquals(Integer.MAX_VALUE, table.getObject("objectint"));
+ Assert.assertEquals(Long.MAX_VALUE, table.getObject("objectlong"));
+ Assert.assertEquals(Short.MAX_VALUE, table.getObject("objectshort"));
+ Assert.assertEquals("Hello", table.getObject("objectstring"));
+ }
+
+ /**
+ * Additional test checkPropertyName doesn't accept Null
+ */
+ public void testCheckPropertyNameasNull() throws JMSException
+ {
+ JMSPropertyFieldTable table = new JMSPropertyFieldTable();
+
+ try
+ {
+ table.setObject(null, "String");
+ fail("Null property name is not allowed");
+ }
+ catch (IllegalArgumentException iae)
+ {
+ //normal path
+ }
+ checkEmpty(table);
+ }
+
+
+ /**
+ * Additional test checkPropertyName doesn't accept an empty String
+ */
+ public void testCheckPropertyNameasEmptyString() throws JMSException
+ {
+ JMSPropertyFieldTable table = new JMSPropertyFieldTable();
+
+ try
+ {
+ table.setObject("", "String");
+ fail("empty property name is not allowed");
+ }
+ catch (IllegalArgumentException iae)
+ {
+ //normal path
+ }
+ checkEmpty(table);
+ }
+
+
+ /**
+ * Additional test checkPropertyName doesn't accept an empty String
+ */
+ public void testCheckPropertyNamehasMaxLength() throws JMSException
+ {
+ JMSPropertyFieldTable table = new JMSPropertyFieldTable();
+
+ StringBuffer longPropertyName = new StringBuffer(129);
+
+ for (int i = 0; i < 129; i++)
+ {
+ longPropertyName.append("x");
+ }
+
+ try
+ {
+ table.setObject(longPropertyName.toString(), "String");
+ fail("property name must be < 128 characters");
+ }
+ catch (IllegalArgumentException iae)
+ {
+ _logger.warn("JMS requires infinite property names AMQP limits us to 128 characters");
+ }
+
+ checkEmpty(table);
+ }
+
+
+ /**
+ * Additional test checkPropertyName starts with a letter
+ */
+ public void testCheckPropertyNameStartCharacterIsLetter() throws JMSException
+ {
+ JMSPropertyFieldTable table = new JMSPropertyFieldTable();
+
+ //Try a name that starts with a number
+ try
+ {
+ table.setObject("1", "String");
+ fail("property name must start with a letter");
+ }
+ catch (IllegalArgumentException iae)
+ {
+ //normal path
+ }
+
+ checkEmpty(table);
+ }
+
+ /**
+ * Additional test checkPropertyName starts with a letter
+ */
+ public void testCheckPropertyNameContainsInvalidCharacter() throws JMSException
+ {
+ JMSPropertyFieldTable table = new JMSPropertyFieldTable();
+
+ //Try a name that starts with a number
+ try
+ {
+ table.setObject("hello there", "String");
+ fail("property name cannot contain spaces");
+ }
+ catch (IllegalArgumentException iae)
+ {
+ //normal path
+ }
+
+ checkEmpty(table);
+ }
+
+
+ /**
+ * Additional test checkPropertyName starts with a letter
+ */
+ public void testCheckPropertyNameIsInvalid() throws JMSException
+ {
+ JMSPropertyFieldTable table = new JMSPropertyFieldTable();
+
+ //Try a name that starts with a number
+ try
+ {
+ table.setObject("ESCAPE", "String");
+ fail("property name must not contains spaces");
+ }
+ catch (IllegalArgumentException iae)
+ {
+ //normal path
+ }
+
+ checkEmpty(table);
+ }
+
+ /**
+ * Additional test checkPropertyName starts with a hash or a dollar
+ */
+ public void testCheckPropertyNameStartCharacterIsHashorDollar() throws JMSException
+ {
+ _logger.warn("Test:testCheckPropertyNameStartCharacterIsHashorDollar will fail JMS compilance as # and $ are not valid in a jms identifier");
+// JMSPropertyFieldTable table = new JMSPropertyFieldTable();
+//
+// //Try a name that starts with a number
+// try
+// {
+// table.setObject("#", "String");
+// table.setObject("$", "String");
+// }
+// catch (IllegalArgumentException iae)
+// {
+// fail("property name are allowed to start with # and $s in AMQP");
+// }
+ }
+
+ /**
+ * Test the contents of the sets
+ */
+ public void testSets()
+ {
+
+ JMSPropertyFieldTable table = new JMSPropertyFieldTable();
+
+ table.put("n1", "1");
+ table.put("n2", "2");
+ table.put("n3", "3");
+
+ Enumeration enumerator = table.getPropertyNames();
+ Assert.assertEquals("n1", enumerator.nextElement());
+ Assert.assertEquals("n2", enumerator.nextElement());
+ Assert.assertEquals("n3", enumerator.nextElement());
+ Assert.assertFalse(enumerator.hasMoreElements());
+ }
+
+ public static junit.framework.Test suite()
+ {
+ return new junit.framework.TestSuite(JMSPropertyFieldTableTest.class);
+ }
+
+}
diff --git a/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java b/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java
index f2067a5649..5256c62054 100644
--- a/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java
+++ b/java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java
@@ -24,14 +24,22 @@ import junit.framework.Assert;
import junit.framework.TestCase;
import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.HashMap;
import org.apache.mina.common.ByteBuffer;
+import org.apache.log4j.Logger;
+import org.apache.qpid.AMQPInvalidClassException;
public class PropertyFieldTableTest extends TestCase
{
- //Test byte modification
+ private static final Logger _logger = Logger.getLogger(PropertyFieldTableTest.class);
+ /**
+ * Test that modifying a byte[] after setting property doesn't change property
+ */
public void testByteModification()
{
PropertyFieldTable table = new PropertyFieldTable();
@@ -46,197 +54,518 @@ public class PropertyFieldTableTest extends TestCase
assertBytesNotEqual(bytes, table.getBytes("bytes"));
}
- //Test replacement
-
+ /**
+ * Test that setting a similar named value replaces any previous value set on that name
+ */
public void testReplacement()
{
PropertyFieldTable table1 = new PropertyFieldTable();
+ //Set a boolean value
table1.setBoolean("value", true);
+ //Check size of table is correct (<Value length> + <type> + <Boolean length>)
+ int size = EncodingUtils.encodedShortStringLength("value") + 1 + EncodingUtils.encodedBooleanLength();
+ Assert.assertEquals(size, table1.getEncodedSize());
+
+ // reset value to an integer
table1.setInteger("value", Integer.MAX_VALUE);
+
+ // Check the size has changed accordingly (<Value length> + <type> + <Integer length>)
+ size = EncodingUtils.encodedShortStringLength("value") + 1 + EncodingUtils.encodedIntegerLength();
+ Assert.assertEquals(size, table1.getEncodedSize());
+
+ //Check boolean value is null
Assert.assertEquals(null, table1.getBoolean("value"));
+ // ... and integer value is good
Assert.assertEquals((Integer) Integer.MAX_VALUE, table1.getInteger("value"));
}
- //Test Lookups
- public void testBooleanLookup()
+ /**
+ * Set a boolean and check that we can only get it back as a boolean and a string
+ * Check that attempting to lookup a non existent value returns null
+ */
+ public void testBoolean()
{
PropertyFieldTable table1 = new PropertyFieldTable();
table1.setBoolean("value", true);
+ Assert.assertTrue(table1.propertyExists("value"));
+
//Test Getting right value back
Assert.assertEquals((Boolean) true, table1.getBoolean("value"));
- //Looking up an invalid value returns null
- Assert.assertTrue(table1.getBoolean("Rubbish") == null);
-
- //Try reading value as a string
+ //Check we don't get anything back for other gets
+ Assert.assertEquals(null, table1.getByte("value"));
+ Assert.assertEquals(null, table1.getByte("value"));
+ Assert.assertEquals(null, table1.getShort("value"));
+ Assert.assertEquals(null, table1.getCharacter("value"));
+ Assert.assertEquals(null, table1.getDouble("value"));
+ Assert.assertEquals(null, table1.getFloat("value"));
+ Assert.assertEquals(null, table1.getInteger("value"));
+ Assert.assertEquals(null, table1.getLong("value"));
+ Assert.assertEquals(null, table1.getBytes("value"));
+
+ //except value as a string
Assert.assertEquals("true", table1.getString("value"));
+
+ //Try setting a null value and read it back
+ table1.put(PropertyFieldTable.Prefix.AMQP_BOOLEAN_PROPERTY_PREFIX, "value", null);
+
+ // Should be able to get the null back
+ Assert.assertEquals(null, table1.getBoolean("value"));
+ //but still contains the value
+ Assert.assertTrue(table1.containsKey("value"));
+
+ table1.remove("value");
+ //but after a remove it doesn't
+ Assert.assertFalse(table1.containsKey("value"));
+
+ // Table should now have zero size for encoding
+ checkEmpty(table1);
+
+ //Looking up an invalid value returns null
+ Assert.assertEquals(null, table1.getBoolean("Rubbish"));
}
- public void testByteLookup()
+ /**
+ * Set a byte and check that we can only get it back as a byte and a string
+ * Check that attempting to lookup a non existent value returns null
+ */
+ public void testByte()
{
PropertyFieldTable table1 = new PropertyFieldTable();
- table1.setByte("value", (byte) 1);
- Assert.assertEquals((Byte) (byte) 1, table1.getByte("value"));
+ table1.setByte("value", Byte.MAX_VALUE);
+ Assert.assertTrue(table1.propertyExists("value"));
- //Looking up an invalid value returns null
- Assert.assertTrue(table1.getByte("Rubbish") == null);
+ //Tets lookups we shouldn't get anything back for other gets
+ //we should get right value back for this type ....
+ Assert.assertEquals(null, table1.getBoolean("value"));
+ Assert.assertEquals(Byte.MAX_VALUE, (byte) table1.getByte("value"));
+ Assert.assertEquals(null, table1.getShort("value"));
+ Assert.assertEquals(null, table1.getCharacter("value"));
+ Assert.assertEquals(null, table1.getDouble("value"));
+ Assert.assertEquals(null, table1.getFloat("value"));
+ Assert.assertEquals(null, table1.getInteger("value"));
+ Assert.assertEquals(null, table1.getLong("value"));
+ Assert.assertEquals(null, table1.getBytes("value"));
+
+ //... and a the string value of it.
+ Assert.assertEquals("" + Byte.MAX_VALUE, table1.getString("value"));
+
+ //Try setting a null value and read it back
+ table1.put(PropertyFieldTable.Prefix.AMQP_BYTE_PROPERTY_PREFIX, "value", null);
+
+ // Should be able to get the null back
+ Assert.assertEquals(null, table1.getByte("value"));
- //Try reading value as a string
- Assert.assertEquals("1", table1.getString("value"));
+ //but still contains the value
+ Assert.assertTrue(table1.containsKey("value"));
+
+ table1.remove("value");
+ //but after a remove it doesn't
+ Assert.assertFalse(table1.containsKey("value"));
+
+ // Table should now have zero size for encoding
+ checkEmpty(table1);
+
+ //Looking up an invalid value returns null
+ Assert.assertEquals(null, table1.getByte("Rubbish"));
}
- public void testShortLookup()
+ /**
+ * Set a short and check that we can only get it back as a short and a string
+ * Check that attempting to lookup a non existent value returns null
+ */
+ public void testShort()
{
PropertyFieldTable table1 = new PropertyFieldTable();
table1.setShort("value", Short.MAX_VALUE);
- Assert.assertEquals((Short) Short.MAX_VALUE, table1.getShort("value"));
+ Assert.assertTrue(table1.propertyExists("value"));
- //Looking up an invalid value returns null
- Assert.assertTrue(table1.getShort("Rubbish") == null);
-
- //Try reading value as a string
+ //Tets lookups we shouldn't get anything back for other gets
+ //we should get right value back for this type ....
+ Assert.assertEquals(null, table1.getBoolean("value"));
+ Assert.assertEquals(null, table1.getByte("value"));
+ Assert.assertEquals(Short.MAX_VALUE, (short) table1.getShort("value"));
+ Assert.assertEquals(null, table1.getCharacter("value"));
+ Assert.assertEquals(null, table1.getDouble("value"));
+ Assert.assertEquals(null, table1.getFloat("value"));
+ Assert.assertEquals(null, table1.getInteger("value"));
+ Assert.assertEquals(null, table1.getLong("value"));
+ Assert.assertEquals(null, table1.getBytes("value"));
+
+ //... and a the string value of it.
Assert.assertEquals("" + Short.MAX_VALUE, table1.getString("value"));
+
+ //Try setting a null value and read it back
+ table1.put(PropertyFieldTable.Prefix.AMQP_SHORT_PROPERTY_PREFIX, "value", null);
+
+ // Should be able to get the null back
+ Assert.assertEquals(null, table1.getShort("value"));
+
+ //but still contains the value
+ Assert.assertTrue(table1.containsKey("value"));
+
+ table1.remove("value");
+ //but after a remove it doesn't
+ Assert.assertFalse(table1.containsKey("value"));
+
+ // Table should now have zero size for encoding
+ checkEmpty(table1);
+
+ //Looking up an invalid value returns null
+ Assert.assertEquals(null, table1.getShort("Rubbish"));
}
- public void testCharLookup()
+ /**
+ * Set a char and check that we can only get it back as a char
+ * Check that attempting to lookup a non existent value returns null
+ */
+ public void testChar()
{
PropertyFieldTable table1 = new PropertyFieldTable();
- table1.setChar("value", 'b');
- Assert.assertEquals((Character) 'b', table1.getCharacter("value"));
+ table1.setChar("value", 'c');
+ Assert.assertTrue(table1.propertyExists("value"));
- //Looking up an invalid value returns null
- Assert.assertTrue(table1.getCharacter("Rubbish") == null);
+ //Tets lookups we shouldn't get anything back for other gets
+ //we should get right value back for this type ....
+ Assert.assertEquals(null, table1.getBoolean("value"));
+ Assert.assertEquals(null, table1.getByte("value"));
+ Assert.assertEquals(null, table1.getShort("value"));
+ Assert.assertEquals('c', (char) table1.getCharacter("value"));
+ Assert.assertEquals(null, table1.getDouble("value"));
+ Assert.assertEquals(null, table1.getFloat("value"));
+ Assert.assertEquals(null, table1.getInteger("value"));
+ Assert.assertEquals(null, table1.getLong("value"));
+ Assert.assertEquals(null, table1.getBytes("value"));
+
+ //... and a the string value of it.
+ Assert.assertEquals("c", table1.getString("value"));
+
+ //Try setting a null value and read it back
+ table1.put(PropertyFieldTable.Prefix.AMQP_ASCII_CHARACTER_PROPERTY_PREFIX, "value", null);
+
+ try
+ {
+ table1.getString("value");
+ fail("Should throw NullPointerException");
+ }
+ catch (NullPointerException npe)
+ {
+ //Normal Path
+ }
+ //but still contains the value
+ Assert.assertTrue(table1.containsKey("value"));
+
+ table1.remove("value");
+ //but after a remove it doesn't
+ Assert.assertFalse(table1.containsKey("value"));
+
+ // Table should now have zero size for encoding
+ checkEmpty(table1);
- //Try reading value as a string
- Assert.assertEquals("b", table1.getString("value"));
+ //Looking up an invalid value returns null
+ Assert.assertEquals(null, table1.getCharacter("Rubbish"));
}
- public void testDoubleLookup()
+
+ /**
+ * Set a double and check that we can only get it back as a double
+ * Check that attempting to lookup a non existent value returns null
+ */
+ public void testDouble()
{
PropertyFieldTable table1 = new PropertyFieldTable();
table1.setDouble("value", Double.MAX_VALUE);
- Assert.assertEquals(Double.MAX_VALUE, table1.getDouble("value"));
-
- //Looking up an invalid value returns null
- Assert.assertTrue(table1.getDouble("Rubbish") == null);
+ Assert.assertTrue(table1.propertyExists("value"));
- //Try reading value as a string
+ //Tets lookups we shouldn't get anything back for other gets
+ //we should get right value back for this type ....
+ Assert.assertEquals(null, table1.getBoolean("value"));
+ Assert.assertEquals(null, table1.getByte("value"));
+ Assert.assertEquals(null, table1.getShort("value"));
+ Assert.assertEquals(null, table1.getCharacter("value"));
+ Assert.assertEquals(Double.MAX_VALUE, (double) table1.getDouble("value"));
+ Assert.assertEquals(null, table1.getFloat("value"));
+ Assert.assertEquals(null, table1.getInteger("value"));
+ Assert.assertEquals(null, table1.getLong("value"));
+ Assert.assertEquals(null, table1.getBytes("value"));
+
+ //... and a the string value of it.
Assert.assertEquals("" + Double.MAX_VALUE, table1.getString("value"));
+ //Try setting a null value and read it back
+ table1.put(PropertyFieldTable.Prefix.AMQP_DOUBLE_PROPERTY_PREFIX, "value", null);
+
+ Assert.assertEquals(null, table1.getDouble("value"));
+
+ //but still contains the value
+ Assert.assertTrue(table1.containsKey("value"));
+
+ table1.remove("value");
+ //but after a remove it doesn't
+ Assert.assertFalse(table1.containsKey("value"));
+
+ // Table should now have zero size for encoding
+ checkEmpty(table1);
+
+ //Looking up an invalid value returns null
+ Assert.assertEquals(null, table1.getDouble("Rubbish"));
}
- public void testFloatLookup()
+
+ /**
+ * Set a float and check that we can only get it back as a float
+ * Check that attempting to lookup a non existent value returns null
+ */
+ public void testFloat()
{
PropertyFieldTable table1 = new PropertyFieldTable();
table1.setFloat("value", Float.MAX_VALUE);
- Assert.assertEquals(Float.MAX_VALUE, table1.getFloat("value"));
+ Assert.assertTrue(table1.propertyExists("value"));
- //Looking up an invalid value returns null
- Assert.assertTrue(table1.getFloat("Rubbish") == null);
-
- //Try reading value as a string
+ //Tets lookups we shouldn't get anything back for other gets
+ //we should get right value back for this type ....
+ Assert.assertEquals(null, table1.getBoolean("value"));
+ Assert.assertEquals(null, table1.getByte("value"));
+ Assert.assertEquals(null, table1.getShort("value"));
+ Assert.assertEquals(null, table1.getCharacter("value"));
+ Assert.assertEquals(null, table1.getDouble("value"));
+ Assert.assertEquals(Float.MAX_VALUE, (float) table1.getFloat("value"));
+ Assert.assertEquals(null, table1.getInteger("value"));
+ Assert.assertEquals(null, table1.getLong("value"));
+ Assert.assertEquals(null, table1.getBytes("value"));
+
+ //... and a the string value of it.
Assert.assertEquals("" + Float.MAX_VALUE, table1.getString("value"));
+ //Try setting a null value and read it back
+ table1.put(PropertyFieldTable.Prefix.AMQP_FLOAT_PROPERTY_PREFIX, "value", null);
+
+ Assert.assertEquals(null, table1.getFloat("value"));
+
+ //but still contains the value
+ Assert.assertTrue(table1.containsKey("value"));
+
+ table1.remove("value");
+ //but after a remove it doesn't
+ Assert.assertFalse(table1.containsKey("value"));
+
+ // Table should now have zero size for encoding
+ checkEmpty(table1);
+
+ //Looking up an invalid value returns null
+ Assert.assertEquals(null, table1.getFloat("Rubbish"));
}
- public void testIntLookup()
+
+ /**
+ * Set an int and check that we can only get it back as an int
+ * Check that attempting to lookup a non existent value returns null
+ */
+ public void testInt()
{
PropertyFieldTable table1 = new PropertyFieldTable();
table1.setInteger("value", Integer.MAX_VALUE);
- Assert.assertEquals((Integer) Integer.MAX_VALUE, table1.getInteger("value"));
+ Assert.assertTrue(table1.propertyExists("value"));
- //Looking up an invalid value returns null
- Assert.assertTrue(table1.getInteger("Rubbish") == null);
-
- //Try reading value as a string
+ //Tets lookups we shouldn't get anything back for other gets
+ //we should get right value back for this type ....
+ Assert.assertEquals(null, table1.getBoolean("value"));
+ Assert.assertEquals(null, table1.getByte("value"));
+ Assert.assertEquals(null, table1.getShort("value"));
+ Assert.assertEquals(null, table1.getCharacter("value"));
+ Assert.assertEquals(null, table1.getDouble("value"));
+ Assert.assertEquals(null, table1.getFloat("value"));
+ Assert.assertEquals(Integer.MAX_VALUE, (int) table1.getInteger("value"));
+ Assert.assertEquals(null, table1.getLong("value"));
+ Assert.assertEquals(null, table1.getBytes("value"));
+
+ //... and a the string value of it.
Assert.assertEquals("" + Integer.MAX_VALUE, table1.getString("value"));
+ //Try setting a null value and read it back
+ table1.put(PropertyFieldTable.Prefix.AMQP_INT_PROPERTY_PREFIX, "value", null);
+
+ Assert.assertEquals(null, table1.getInteger("value"));
+
+ //but still contains the value
+ Assert.assertTrue(table1.containsKey("value"));
+
+ table1.remove("value");
+ //but after a remove it doesn't
+ Assert.assertFalse(table1.containsKey("value"));
+
+ // Table should now have zero size for encoding
+ checkEmpty(table1);
+
+ //Looking up an invalid value returns null
+ Assert.assertEquals(null, table1.getInteger("Rubbish"));
}
- public void testLongLookup()
+
+ /**
+ * Set a long and check that we can only get it back as a long
+ * Check that attempting to lookup a non existent value returns null
+ */
+ public void testLong()
{
PropertyFieldTable table1 = new PropertyFieldTable();
table1.setLong("value", Long.MAX_VALUE);
- Assert.assertEquals((Long) Long.MAX_VALUE, table1.getLong("value"));
-
- //Looking up an invalid value returns null
- Assert.assertTrue(table1.getLong("Rubbish") == null);
+ Assert.assertTrue(table1.propertyExists("value"));
- //Try reading value as a string
+ //Tets lookups we shouldn't get anything back for other gets
+ //we should get right value back for this type ....
+ Assert.assertEquals(null, table1.getBoolean("value"));
+ Assert.assertEquals(null, table1.getByte("value"));
+ Assert.assertEquals(null, table1.getShort("value"));
+ Assert.assertEquals(null, table1.getCharacter("value"));
+ Assert.assertEquals(null, table1.getDouble("value"));
+ Assert.assertEquals(null, table1.getFloat("value"));
+ Assert.assertEquals(null, table1.getInteger("value"));
+ Assert.assertEquals(Long.MAX_VALUE, (long) table1.getLong("value"));
+ Assert.assertEquals(null, table1.getBytes("value"));
+
+ //... and a the string value of it.
Assert.assertEquals("" + Long.MAX_VALUE, table1.getString("value"));
- }
+ //Try setting a null value and read it back
+ table1.put(PropertyFieldTable.Prefix.AMQP_LONG_PROPERTY_PREFIX, "value", null);
- public void testBytesLookup()
- {
- PropertyFieldTable table1 = new PropertyFieldTable();
- byte[] bytes = {99, 98, 97, 96, 95};
- table1.setBytes("bytes", bytes);
- assertBytesEqual(bytes, table1.getBytes("bytes"));
+ Assert.assertEquals(null, table1.getLong("value"));
+
+ //but still contains the value
+ Assert.assertTrue(table1.containsKey("value"));
+
+ table1.remove("value");
+ //but after a remove it doesn't
+ Assert.assertFalse(table1.containsKey("value"));
+
+ // Table should now have zero size for encoding
+ checkEmpty(table1);
//Looking up an invalid value returns null
- Assert.assertTrue(table1.getBytes("Rubbish") == null);
+ Assert.assertEquals(null, table1.getLong("Rubbish"));
}
- // Failed Lookups
- public void testFailedBooleanLookup()
+ /**
+ * Set a double and check that we can only get it back as a double
+ * Check that attempting to lookup a non existent value returns null
+ */
+ public void testBytes()
{
- PropertyFieldTable table1 = new PropertyFieldTable();
- Assert.assertEquals(null, table1.getBoolean("int"));
- }
+ byte[] bytes = {99, 98, 97, 96, 95};
- public void testFailedByteLookup()
- {
PropertyFieldTable table1 = new PropertyFieldTable();
- Assert.assertEquals(null, table1.getByte("int"));
- }
+ table1.setBytes("value", bytes);
+ Assert.assertTrue(table1.propertyExists("value"));
- public void testFailedBytesLookup()
- {
- PropertyFieldTable table1 = new PropertyFieldTable();
- Assert.assertEquals(null, table1.getBytes("int"));
- }
+ //Tets lookups we shouldn't get anything back for other gets
+ //we should get right value back for this type ....
+ Assert.assertEquals(null, table1.getBoolean("value"));
+ Assert.assertEquals(null, table1.getByte("value"));
+ Assert.assertEquals(null, table1.getShort("value"));
+ Assert.assertEquals(null, table1.getCharacter("value"));
+ Assert.assertEquals(null, table1.getDouble("value"));
+ Assert.assertEquals(null, table1.getFloat("value"));
+ Assert.assertEquals(null, table1.getInteger("value"));
+ Assert.assertEquals(null, table1.getLong("value"));
+ assertBytesEqual(bytes, table1.getBytes("value"));
- public void testFailedCharLookup()
- {
- PropertyFieldTable table1 = new PropertyFieldTable();
- Assert.assertEquals(null, table1.getCharacter("int"));
- }
+ //... and a the string value of it is null
+ Assert.assertEquals(null, table1.getString("value"));
- public void testFailedDoubleLookup()
- {
- PropertyFieldTable table1 = new PropertyFieldTable();
- Assert.assertEquals(null, table1.getDouble("int"));
- }
+ //Try setting a null value and read it back
+ table1.put(PropertyFieldTable.Prefix.AMQP_BINARY_PROPERTY_PREFIX, "value", null);
- public void testFailedFloatLookup()
- {
- PropertyFieldTable table1 = new PropertyFieldTable();
- Assert.assertEquals(null, table1.getFloat("int"));
- }
+ Assert.assertEquals(null, table1.getBytes("value"));
- public void testFailedIntLookup()
- {
- PropertyFieldTable table1 = new PropertyFieldTable();
- Assert.assertEquals(null, table1.getInteger("int"));
+ //but still contains the value
+ Assert.assertTrue(table1.containsKey("value"));
+
+ table1.remove("value");
+ //but after a remove it doesn't
+ Assert.assertFalse(table1.containsKey("value"));
+
+ // Table should now have zero size for encoding
+ checkEmpty(table1);
+
+ //Looking up an invalid value returns null
+ Assert.assertEquals(null, table1.getBytes("Rubbish"));
}
- public void testFailedLongLookup()
+ /**
+ * Calls all methods that can be used to check the table is empty
+ * - getEncodedSize
+ * - isEmpty
+ * - size
+ *
+ * @param table to check is empty
+ */
+ private void checkEmpty(PropertyFieldTable table)
{
- PropertyFieldTable table1 = new PropertyFieldTable();
- Assert.assertEquals(null, table1.getLong("int"));
+ Assert.assertEquals(0, table.getEncodedSize());
+ Assert.assertTrue(table.isEmpty());
+ Assert.assertEquals(0, table.size());
+
+ Assert.assertEquals(0, table.keySet().size());
+ Assert.assertEquals(0, table.values().size());
+ Assert.assertEquals(0, table.entrySet().size());
}
- public void testFailedShortLookup()
+
+ /**
+ * Set a String and check that we can only get it back as a String
+ * Check that attempting to lookup a non existent value returns null
+ */
+ public void testString()
{
PropertyFieldTable table1 = new PropertyFieldTable();
- Assert.assertEquals(null, table1.getShort("int"));
+ table1.setString("value", "Hello");
+ Assert.assertTrue(table1.propertyExists("value"));
+
+ //Tets lookups we shouldn't get anything back for other gets
+ //we should get right value back for this type ....
+ Assert.assertEquals(null, table1.getBoolean("value"));
+ Assert.assertEquals(null, table1.getByte("value"));
+ Assert.assertEquals(null, table1.getShort("value"));
+ Assert.assertEquals(null, table1.getCharacter("value"));
+ Assert.assertEquals(null, table1.getDouble("value"));
+ Assert.assertEquals(null, table1.getFloat("value"));
+ Assert.assertEquals(null, table1.getInteger("value"));
+ Assert.assertEquals(null, table1.getLong("value"));
+ Assert.assertEquals(null, table1.getBytes("value"));
+ Assert.assertEquals("Hello", table1.getString("value"));
+
+ //Try setting a null value and read it back
+ table1.setString("value", null);
+
+ Assert.assertEquals(null, table1.getString("value"));
+
+ //but still contains the value
+ Assert.assertTrue(table1.containsKey("value"));
+
+ table1.remove("value");
+ //but after a remove it doesn't
+ Assert.assertFalse(table1.containsKey("value"));
+
+ checkEmpty(table1);
+
+ //Looking up an invalid value returns null
+ Assert.assertEquals(null, table1.getString("Rubbish"));
+
+ //Additional Test that haven't been covered for string
+ table1.setObject("value", "Hello");
+ //Check that it was set correctly
+ Assert.assertEquals("Hello", table1.getString("value"));
}
- public void testXML()
+
+ /**
+ * Test that the generated XML can be used to create a field table with the same values.
+ */
+ public void testValidXML()
{
PropertyFieldTable table1 = new PropertyFieldTable();
table1.setBoolean("bool", true);
@@ -249,6 +578,8 @@ public class PropertyFieldTableTest extends TestCase
table1.setInteger("int", Integer.MAX_VALUE);
table1.setLong("long", Long.MAX_VALUE);
table1.setShort("short", Short.MAX_VALUE);
+ table1.setString("string", "Hello");
+ table1.setString("null-string", null);
table1.setObject("object-bool", true);
table1.setObject("object-byte", Byte.MAX_VALUE);
@@ -259,14 +590,48 @@ public class PropertyFieldTableTest extends TestCase
table1.setObject("object-int", Integer.MAX_VALUE);
table1.setObject("object-long", Long.MAX_VALUE);
table1.setObject("object-short", Short.MAX_VALUE);
+ table1.setObject("object-string", "Hello");
+
+ Assert.assertEquals(21, table1.size());
String table1XML = table1.toString();
PropertyFieldTable table2 = new PropertyFieldTable(table1XML);
Assert.assertEquals(table1XML, table2.toString());
+
+ //Check that when bytes is written out as a string with no new line between items that it is read in ok.
+
+ }
+
+ /**
+ * Test that invalid input throws the correct Exception
+ */
+ public void testInvalidXML()
+ {
+ try
+ {
+ _logger.warn("Testing Invalid XML expecting IllegalArgumentException");
+ new PropertyFieldTable("Rubbish");
+ fail("IllegalArgumentException expected");
+ }
+ catch (IllegalArgumentException iae)
+ {
+ //normal path
+ }
+ try
+ {
+ _logger.warn("Testing Invalid XML expecting IllegalArgumentException");
+ new PropertyFieldTable("");
+ fail("IllegalArgumentException expected");
+ }
+ catch (IllegalArgumentException iae)
+ {
+ //normal path
+ }
}
+
public void testKeyEnumeration()
{
PropertyFieldTable table = new PropertyFieldTable();
@@ -298,6 +663,8 @@ public class PropertyFieldTableTest extends TestCase
table.setInteger("int", Integer.MAX_VALUE);
table.setLong("long", Long.MAX_VALUE);
table.setShort("short", Short.MAX_VALUE);
+ table.setString("string", "Hello");
+ table.setString("null-string", null);
table.setObject("object-bool", true);
table.setObject("object-byte", Byte.MAX_VALUE);
@@ -308,6 +675,7 @@ public class PropertyFieldTableTest extends TestCase
table.setObject("object-int", Integer.MAX_VALUE);
table.setObject("object-long", Long.MAX_VALUE);
table.setObject("object-short", Short.MAX_VALUE);
+ table.setObject("object-string", "Hello");
Assert.assertEquals((Boolean) true, table.getBoolean("bool"));
@@ -319,6 +687,8 @@ public class PropertyFieldTableTest extends TestCase
Assert.assertEquals((Integer) Integer.MAX_VALUE, table.getInteger("int"));
Assert.assertEquals((Long) Long.MAX_VALUE, table.getLong("long"));
Assert.assertEquals((Short) Short.MAX_VALUE, table.getShort("short"));
+ Assert.assertEquals("Hello", table.getString("string"));
+ Assert.assertEquals(null, table.getString("null-string"));
Assert.assertEquals(true, table.getObject("object-bool"));
Assert.assertEquals(Byte.MAX_VALUE, table.getObject("object-byte"));
@@ -329,6 +699,7 @@ public class PropertyFieldTableTest extends TestCase
Assert.assertEquals(Integer.MAX_VALUE, table.getObject("object-int"));
Assert.assertEquals(Long.MAX_VALUE, table.getObject("object-long"));
Assert.assertEquals(Short.MAX_VALUE, table.getObject("object-short"));
+ Assert.assertEquals("Hello", table.getObject("object-string"));
}
@@ -347,6 +718,8 @@ public class PropertyFieldTableTest extends TestCase
table.setInteger("int", Integer.MAX_VALUE);
table.setLong("long", Long.MAX_VALUE);
table.setShort("short", Short.MAX_VALUE);
+ table.setString("string", "hello");
+ table.setString("null-string", null);
final ByteBuffer buffer = ByteBuffer.allocate((int) table.getEncodedSize()); // FIXME XXX: Is cast a problem?
@@ -370,6 +743,9 @@ public class PropertyFieldTableTest extends TestCase
Assert.assertEquals((Integer) Integer.MAX_VALUE, table2.getInteger("int"));
Assert.assertEquals((Long) Long.MAX_VALUE, table2.getLong("long"));
Assert.assertEquals((Short) Short.MAX_VALUE, table2.getShort("short"));
+ Assert.assertEquals("hello", table2.getString("string"));
+ Assert.assertEquals(null, table2.getString("null-string"));
+
}
catch (AMQFrameDecodingException e)
{
@@ -380,7 +756,7 @@ public class PropertyFieldTableTest extends TestCase
public void testEncodingSize()
{
- FieldTable result = FieldTableFactory.newFieldTable();
+ PropertyFieldTable result = new PropertyFieldTable();
int size = 0;
result.setBoolean("boolean", true);
@@ -468,63 +844,296 @@ public class PropertyFieldTableTest extends TestCase
}
- public void testEncodingSize1()
+// public void testEncodingSize1()
+// {
+// PropertyFieldTable table = new PropertyFieldTable();
+// int size = 0;
+// result.put("one", 1L);
+// size = EncodingUtils.encodedShortStringLength("one");
+// size += 1 + EncodingUtils.encodedLongLength();
+// assertEquals(size, result.getEncodedSize());
+//
+// result.put("two", 2L);
+// size += EncodingUtils.encodedShortStringLength("two");
+// size += 1 + EncodingUtils.encodedLongLength();
+// assertEquals(size, result.getEncodedSize());
+//
+// result.put("three", 3L);
+// size += EncodingUtils.encodedShortStringLength("three");
+// size += 1 + EncodingUtils.encodedLongLength();
+// assertEquals(size, result.getEncodedSize());
+//
+// result.put("four", 4L);
+// size += EncodingUtils.encodedShortStringLength("four");
+// size += 1 + EncodingUtils.encodedLongLength();
+// assertEquals(size, result.getEncodedSize());
+//
+// result.put("five", 5L);
+// size += EncodingUtils.encodedShortStringLength("five");
+// size += 1 + EncodingUtils.encodedLongLength();
+// assertEquals(size, result.getEncodedSize());
+//
+// //fixme should perhaps be expanded to incorporate all types.
+//
+// final ByteBuffer buffer = ByteBuffer.allocate((int) result.getEncodedSize()); // FIXME XXX: Is cast a problem?
+//
+// result.writeToBuffer(buffer);
+//
+// buffer.flip();
+//
+// long length = buffer.getUnsignedInt();
+//
+// try
+// {
+// PropertyFieldTable table2 = new PropertyFieldTable(buffer, length);
+//
+// Assert.assertEquals((Long) 1L, table2.getLong("one"));
+// Assert.assertEquals((Long) 2L, table2.getLong("two"));
+// Assert.assertEquals((Long) 3L, table2.getLong("three"));
+// Assert.assertEquals((Long) 4L, table2.getLong("four"));
+// Assert.assertEquals((Long) 5L, table2.getLong("five"));
+// }
+// catch (AMQFrameDecodingException e)
+// {
+// e.printStackTrace();
+// fail("PFT should be instantiated from bytes." + e.getCause());
+// }
+//
+// }
+
+
+ /**
+ * Additional test for setObject
+ */
+ public void testSetObject()
{
- FieldTable result = FieldTableFactory.newFieldTable();
- int size = 0;
- result.put("one", 1L);
- size = EncodingUtils.encodedShortStringLength("one");
- size += 1 + EncodingUtils.encodedLongLength();
- assertEquals(size, result.getEncodedSize());
+ PropertyFieldTable table = new PropertyFieldTable();
+
+ //Try setting a non primative object
+
+ try
+ {
+ table.setObject("value", this);
+ fail("Only primative values allowed in setObject");
+ }
+ catch (AMQPInvalidClassException iae)
+ {
+ //normal path
+ }
+ // so size should be zero
+ Assert.assertEquals(0, table.getEncodedSize());
+ }
- result.put("two", 2L);
- size += EncodingUtils.encodedShortStringLength("two");
- size += 1 + EncodingUtils.encodedLongLength();
- assertEquals(size, result.getEncodedSize());
+ /**
+ * Additional test checkPropertyName doesn't accept Null
+ */
+ public void testCheckPropertyNameasNull()
+ {
+ PropertyFieldTable table = new PropertyFieldTable();
- result.put("three", 3L);
- size += EncodingUtils.encodedShortStringLength("three");
- size += 1 + EncodingUtils.encodedLongLength();
- assertEquals(size, result.getEncodedSize());
+ try
+ {
+ table.setObject(null, "String");
+ fail("Null property name is not allowed");
+ }
+ catch (IllegalArgumentException iae)
+ {
+ //normal path
+ }
+ // so size should be zero
+ Assert.assertEquals(0, table.getEncodedSize());
+ }
- result.put("four", 4L);
- size += EncodingUtils.encodedShortStringLength("four");
- size += 1 + EncodingUtils.encodedLongLength();
- assertEquals(size, result.getEncodedSize());
- result.put("five", 5L);
- size += EncodingUtils.encodedShortStringLength("five");
- size += 1 + EncodingUtils.encodedLongLength();
- assertEquals(size, result.getEncodedSize());
+ /**
+ * Additional test checkPropertyName doesn't accept an empty String
+ */
+ public void testCheckPropertyNameasEmptyString()
+ {
+ PropertyFieldTable table = new PropertyFieldTable();
- //fixme should perhaps be expanded to incorporate all types.
+ try
+ {
+ table.setObject("", "String");
+ fail("empty property name is not allowed");
+ }
+ catch (IllegalArgumentException iae)
+ {
+ //normal path
+ }
+ // so size should be zero
+ Assert.assertEquals(0, table.getEncodedSize());
+ }
- final ByteBuffer buffer = ByteBuffer.allocate((int) result.getEncodedSize()); // FIXME XXX: Is cast a problem?
- result.writeToBuffer(buffer);
+ /**
+ * Additional test checkPropertyName doesn't accept an empty String
+ */
+ public void testCheckPropertyNamehasMaxLength()
+ {
+ PropertyFieldTable table = new PropertyFieldTable();
- buffer.flip();
+ StringBuffer longPropertyName = new StringBuffer(129);
- long length = buffer.getUnsignedInt();
+ for (int i = 0; i < 129; i++)
+ {
+ longPropertyName.append("x");
+ }
try
{
- PropertyFieldTable table2 = new PropertyFieldTable(buffer, length);
+ table.setObject(longPropertyName.toString(), "String");
+ fail("property name must be < 128 characters");
+ }
+ catch (IllegalArgumentException iae)
+ {
+ //normal path
+ }
+ // so size should be zero
+ Assert.assertEquals(0, table.getEncodedSize());
+ }
+
- Assert.assertEquals((Long) 1L, table2.getLong("one"));
- Assert.assertEquals((Long) 2L, table2.getLong("two"));
- Assert.assertEquals((Long) 3L, table2.getLong("three"));
- Assert.assertEquals((Long) 4L, table2.getLong("four"));
- Assert.assertEquals((Long) 5L, table2.getLong("five"));
+ /**
+ * Additional test checkPropertyName starts with a letter
+ */
+ public void testCheckPropertyNameStartCharacterIsLetter()
+ {
+ PropertyFieldTable table = new PropertyFieldTable();
+
+ //Try a name that starts with a number
+ try
+ {
+ table.setObject("1", "String");
+ fail("property name must start with a letter");
}
- catch (AMQFrameDecodingException e)
+ catch (IllegalArgumentException iae)
{
- e.printStackTrace();
- fail("PFT should be instantiated from bytes." + e.getCause());
+ //normal path
}
+ // so size should be zero
+ Assert.assertEquals(0, table.getEncodedSize());
+ }
+
+
+ /**
+ * Additional test checkPropertyName starts with a hash or a dollar
+ */
+ public void testCheckPropertyNameStartCharacterIsHashorDollar()
+ {
+ PropertyFieldTable table = new PropertyFieldTable();
+ //Try a name that starts with a number
+ try
+ {
+ table.setObject("#", "String");
+ table.setObject("$", "String");
+ }
+ catch (IllegalArgumentException iae)
+ {
+ fail("property name are allowed to start with # and $s");
+ }
}
+
+ /**
+ * Additional test to test the contents of the table
+ */
+ public void testContents()
+ {
+ PropertyFieldTable table = new PropertyFieldTable();
+
+ table.put("StringProperty", "String");
+
+ Assert.assertTrue(table.containsValue("String"));
+
+ Assert.assertEquals("String", table.get("StringProperty"));
+
+ //Test Clear
+
+ table.clear();
+
+ checkEmpty(table);
+ }
+
+ /**
+ * Test the contents of the sets
+ */
+ public void testSets()
+ {
+
+ PropertyFieldTable table = new PropertyFieldTable();
+
+ table.put("n1", "1");
+ table.put("n2", "2");
+ table.put("n3", "3");
+
+ Iterator iterator = table.keySet().iterator();
+ Assert.assertEquals("n1", iterator.next());
+ Assert.assertEquals("n2", iterator.next());
+ Assert.assertEquals("n3", iterator.next());
+ Assert.assertFalse(iterator.hasNext());
+
+
+ iterator = table.values().iterator();
+ Assert.assertEquals("1", iterator.next());
+ Assert.assertEquals("2", iterator.next());
+ Assert.assertEquals("3", iterator.next());
+ Assert.assertFalse(iterator.hasNext());
+
+
+ iterator = table.entrySet().iterator();
+ Map.Entry entry = (Map.Entry) iterator.next();
+ Assert.assertEquals("n1", entry.getKey());
+ Assert.assertEquals("1", entry.getValue());
+ entry = (Map.Entry) iterator.next();
+ Assert.assertEquals("n2", entry.getKey());
+ Assert.assertEquals("2", entry.getValue());
+ entry = (Map.Entry) iterator.next();
+ Assert.assertEquals("n3", entry.getKey());
+ Assert.assertEquals("3", entry.getValue());
+ Assert.assertFalse(iterator.hasNext());
+
+
+ }
+
+
+ /**
+ * Test that all the values are preserved after a putAll
+ */
+ public void testPutAll()
+ {
+ Map map = new HashMap();
+
+ map.put("char", 'c');
+ map.put("double", Double.MAX_VALUE);
+ map.put("float", Float.MAX_VALUE);
+ map.put("int", Integer.MAX_VALUE);
+ map.put("long", Long.MAX_VALUE);
+ map.put("short", Short.MAX_VALUE);
+
+ PropertyFieldTable table = new PropertyFieldTable();
+
+ table.putAll(map);
+
+ Assert.assertEquals(6, table.size());
+
+ Assert.assertTrue(table.containsKey("char"));
+ Assert.assertEquals('c', (char) table.getCharacter("char"));
+ Assert.assertTrue(table.containsKey("double"));
+ Assert.assertEquals(Double.MAX_VALUE, table.getDouble("double"));
+ Assert.assertTrue(table.containsKey("float"));
+ Assert.assertEquals(Float.MAX_VALUE, table.getFloat("float"));
+ Assert.assertTrue(table.containsKey("int"));
+ Assert.assertEquals(Integer.MAX_VALUE, (int) table.getInteger("int"));
+ Assert.assertTrue(table.containsKey("long"));
+ Assert.assertEquals(Long.MAX_VALUE, (long) table.getLong("long"));
+ Assert.assertTrue(table.containsKey("short"));
+ Assert.assertEquals(Short.MAX_VALUE, (short) table.getShort("short"));
+ Assert.assertEquals(Short.MAX_VALUE, (short) table.getShort("short"));
+ }
+
+
private void assertBytesEqual(byte[] expected, byte[] actual)
{
Assert.assertEquals(expected.length, actual.length);
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Activator.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Activator.java
index 61b6cfaa59..5eab267c28 100644
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Activator.java
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Activator.java
@@ -26,6 +26,7 @@ import org.osgi.framework.BundleContext;
/**
* The activator class controls the plug-in life cycle
+ * @author Bhupendra Bhardwaj
*/
public class Activator extends AbstractUIPlugin
{
@@ -44,7 +45,6 @@ public class Activator extends AbstractUIPlugin
}
/*
- * (non-Javadoc)
* @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
*/
public void start(BundleContext context) throws Exception
@@ -53,7 +53,6 @@ public class Activator extends AbstractUIPlugin
}
/*
- * (non-Javadoc)
* @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
*/
public void stop(BundleContext context) throws Exception
@@ -67,18 +66,19 @@ public class Activator extends AbstractUIPlugin
*
* @return the shared instance
*/
- public static Activator getDefault() {
+ public static Activator getDefault()
+ {
return plugin;
}
/**
- * Returns an image descriptor for the image file at the given
- * plug-in relative path
+ * Returns an image descriptor for the image file at the given plug-in relative path
*
* @param path the path
* @return the image descriptor
*/
- public static ImageDescriptor getImageDescriptor(String path) {
+ public static ImageDescriptor getImageDescriptor(String path)
+ {
return imageDescriptorFromPlugin(PLUGIN_ID, path);
}
}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Application.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Application.java
index 3d014e6968..a1c4b7ddb0 100644
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Application.java
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Application.java
@@ -34,8 +34,8 @@ public class Application implements IPlatformRunnable
static Shell shell = null;
/*
- * (non-Javadoc)
- *
+ * The call to createAndRunWorkbench will not return until the workbench is closed.
+ * The SWT event loop and other low-level logistics are handled inside this method.
* @see org.eclipse.core.runtime.IPlatformRunnable#run(java.lang.Object)
*/
public Object run(Object args) throws Exception
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java
index 175130aea9..38a4d4561f 100644
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java
@@ -33,6 +33,10 @@ import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.PlatformUI;
+/**
+ * Main Application Registry, which contains shared resources and map to all connected servers.
+ * @author Bhupendra Bhardwaj
+ */
public abstract class ApplicationRegistry
{
private static ImageRegistry imageRegistry = new ImageRegistry();
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchWindowAdvisor.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchWindowAdvisor.java
index 472d003657..3d163fb111 100644
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchWindowAdvisor.java
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchWindowAdvisor.java
@@ -28,6 +28,10 @@ import org.eclipse.ui.application.IActionBarConfigurer;
import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
import org.eclipse.ui.application.WorkbenchWindowAdvisor;
+/**
+ *
+ * @author Bhupendra Bhardwaj
+ */
public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor
{
public ApplicationWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer)
@@ -49,7 +53,7 @@ public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor
configurer.setShowCoolBar(true);
configurer.setShowStatusLine(false);
- configurer.setTitle("Qpid Management Console");
+ configurer.setTitle(Constants.APPLICATION_NAME);
}
public void postWindowCreate()
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Constants.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Constants.java
index 1678cbac62..e7cd7f4671 100644
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Constants.java
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Constants.java
@@ -20,6 +20,11 @@
*/
package org.apache.qpid.management.ui;
+/**
+ * Contains constants for the application
+ * @author Bhupendra Bhardwaj
+ *
+ */
public class Constants
{
public final static String APPLICATION_NAME = "Qpid Management Console";
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedBean.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedBean.java
index 767fd8b721..7da5621345 100644
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedBean.java
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedBean.java
@@ -22,6 +22,11 @@ package org.apache.qpid.management.ui;
import java.util.HashMap;
+/**
+ * Class representing a managed bean on the managed server
+ * @author Bhupendra Bhardwaj
+ *
+ */
public abstract class ManagedBean extends ManagedObject
{
private String _uniqueName = "";
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedObject.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedObject.java
index 2ed463bdf8..96e0fa46c6 100644
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedObject.java
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedObject.java
@@ -20,6 +20,10 @@
*/
package org.apache.qpid.management.ui;
+/**
+ * Abstract class representing a managed object
+ * @author Bhupendra Bhardwaj
+ */
public abstract class ManagedObject
{
private String _name;
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedServer.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedServer.java
index 44f933a5d1..e3699bb1ee 100644
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedServer.java
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedServer.java
@@ -20,6 +20,10 @@
*/
package org.apache.qpid.management.ui;
+/**
+ * Class representing a server being managed eg. MBeanServer
+ * @author Bhupendra Bhardwaj
+ */
public class ManagedServer extends ManagedObject
{
private String host;
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Perspective.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Perspective.java
index 03477cb117..da49d70b88 100644
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Perspective.java
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Perspective.java
@@ -25,6 +25,10 @@ import org.apache.qpid.management.ui.views.NavigationView;
import org.eclipse.ui.IPageLayout;
import org.eclipse.ui.IPerspectiveFactory;
+/**
+ *
+ * @author Bhupendra Bhardwaj
+ */
public class Perspective implements IPerspectiveFactory
{
public void createInitialLayout(IPageLayout layout)
@@ -32,20 +36,9 @@ public class Perspective implements IPerspectiveFactory
String editorArea = layout.getEditorArea();
layout.setEditorAreaVisible(false);
- // standalone view meaning it can't be docked or stacked with other views,
- // and it doesn't have a title bar.
-
- layout.addStandaloneView(NavigationView.ID,
- true,
- IPageLayout.LEFT,
- 0.25f,
- editorArea);
-
- layout.addStandaloneView(MBeanView.ID,
- true,
- IPageLayout.RIGHT,
- 0.75f,
- editorArea);
+ // standalone view meaning it can't be docked or stacked with other views, and it doesn't have a title bar.
+ layout.addStandaloneView(NavigationView.ID, true, IPageLayout.LEFT, 0.25f, editorArea);
+ layout.addStandaloneView(MBeanView.ID, true, IPageLayout.RIGHT, 0.75f, editorArea);
layout.getViewLayout(NavigationView.ID).setCloseable(false);
layout.getViewLayout(MBeanView.ID).setCloseable(false);
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/exceptions/ManagementConsoleException.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/exceptions/ManagementConsoleException.java
new file mode 100644
index 0000000000..ba6167591e
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/exceptions/ManagementConsoleException.java
@@ -0,0 +1,10 @@
+package org.apache.qpid.management.ui.exceptions;
+
+@SuppressWarnings("serial")
+public class ManagementConsoleException extends Exception
+{
+ public ManagementConsoleException(String message)
+ {
+ super(message);
+ }
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/MBeanUtility.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/MBeanUtility.java
index 800a5b6ce3..923fd4a12a 100644
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/MBeanUtility.java
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/MBeanUtility.java
@@ -41,6 +41,7 @@ import javax.management.ReflectionException;
import org.apache.qpid.management.ui.ApplicationRegistry;
import org.apache.qpid.management.ui.ManagedBean;
import org.apache.qpid.management.ui.ManagedServer;
+import org.apache.qpid.management.ui.exceptions.ManagementConsoleException;
import org.apache.qpid.management.ui.model.AttributeData;
import org.apache.qpid.management.ui.model.ManagedAttributeModel;
import org.apache.qpid.management.ui.model.NotificationInfoModel;
@@ -49,31 +50,47 @@ import org.apache.qpid.management.ui.model.OperationDataModel;
import org.apache.qpid.management.ui.model.ParameterData;
import org.apache.qpid.management.ui.views.ViewUtility;
-
+/**
+ * Utility class for all mbeanserver related operations. Keeps all JMX code out from view and model classes
+ * @author Bhupendra Bhardwaj
+ */
public class MBeanUtility
{
-
- public static MBeanInfo getMBeanInfo(ManagedBean mbean)
- throws IOException, JMException
+ /**
+ * Retrieves the MBeanInfo from MBeanServer and stores in the application registry
+ * @param mbean managed bean
+ * @return MBeanInfo
+ * @throws Exception, if server connection is null or if server throws Exception
+ */
+ public static MBeanInfo getMBeanInfo(ManagedBean mbean) throws Exception
{
ManagedServer server = mbean.getServer();
JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(server);
MBeanServerConnection mbsc = serverRegistry.getServerConnection();
if (mbsc == null)
- System.out.println("MBeanServerConnection does not exist in the Application registry.");
+ {
+ throw new ManagementConsoleException("Server connection is broken");
+ }
JMXManagedObject jmxbean = (JMXManagedObject)mbean;
MBeanInfo mbeanInfo = mbsc.getMBeanInfo(jmxbean.getObjectName());
serverRegistry.putMBeanInfo(mbean, mbeanInfo);
+ // populate the server registry with attribute and operation info
getAttributes(mbean);
getOperations(mbean);
return mbeanInfo;
}
-
+ /**
+ * executes the MBean operation
+ * @param mbean
+ * @param opData
+ * @return MBean operation return value
+ * @throws Exception if server connection is broken or if operation execution fails on the mbean server
+ */
public static Object execute(ManagedBean mbean, OperationData opData) throws Exception
{
String opName = opData.getName();
@@ -89,7 +106,6 @@ public class MBeanUtility
{
signature[i] = params.get(i).getType();
values[i] = params.get(i).getValue();
- System.out.println(params.get(i).getName() + " : " + params.get(i).getValue());
}
}
@@ -99,48 +115,27 @@ public class MBeanUtility
MBeanServerConnection mbsc = serverRegistry.getServerConnection();
if (mbsc == null)
{
- System.out.println("MBeanServerConnection doesn't exist in the Application registry.");
+ throw new ManagementConsoleException("Server connection is broken");
// TODO
- // throw exception to check if the server is added
- // Or try and get the connection again if it was disconnected
- return null;
+ // try and get the connection again if it was disconnected
}
JMXManagedObject jmxbean = (JMXManagedObject)mbean;
return mbsc.invoke(jmxbean.getObjectName(), opName, values, signature);
-
- /*
- try
- {
-
- }
- catch(MBeanException ex)
- {
- ex.printStackTrace();
-
- }
- catch(OperationsException ex)
- {
- ex.printStackTrace();
-
- }
- catch(JMException ex)
- {
- ex.printStackTrace();
- ViewUtility.popupError(new Exception(ex), "Operation failed");
- }
- catch(IOException ex)
- {
- ex.printStackTrace();
- ViewUtility.popupError(new Exception(ex), "Operation failed");
- }
- */
}
+ /**
+ * @see MBeanUtility#handleException(ManagedBean, Exception)
+ */
public static void handleException(Exception ex)
{
handleException(null, ex);
}
+ /**
+ * handels the exception received. Shows the exception to the user in best suitable way
+ * @param mbean managed bean
+ * @param ex Exception
+ */
public static void handleException(ManagedBean mbean, Exception ex)
{
if (mbean == null)
@@ -161,17 +156,35 @@ public class MBeanUtility
}
else if (ex instanceof MBeanException)
{
- ViewUtility.popupInfoMessage(mbean.getName(), ex.getMessage());
+ String cause = ((MBeanException)ex).getTargetException().getMessage();
+ if (cause == null)
+ cause = ex.getMessage();
+ ViewUtility.popupInfoMessage(mbean.getName(), cause);
}
- else
+ else if (ex instanceof JMException)
+ {
+ ViewUtility.popupErrorMessage(mbean.getName(), ex.getMessage());
+ }
+ else if (ex instanceof ManagementConsoleException)
+ {
+ ViewUtility.popupErrorMessage(mbean.getName(), ex.getMessage());
+ }
+ else
{
ViewUtility.popupError(mbean.getName(), "Error occured", ex);
}
- ex.printStackTrace();
+ //ex.printStackTrace();
}
+ /**
+ * Registers the notification listener with the MBeanServer
+ * @param mbean managed bean
+ * @param name notification name
+ * @param type notification type
+ * @throws Exception if server connection is broken or if listener could not be created
+ */
public static void createNotificationlistener(ManagedBean mbean, String name, String type)
- throws IOException, Exception
+ throws Exception
{
JMXManagedObject jmxbean = (JMXManagedObject)mbean;
JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
@@ -180,23 +193,15 @@ public class MBeanUtility
if (mbsc == null)
{
- throw new Exception("MBeanServer connection is broken");
+ throw new ManagementConsoleException("Server connection is broken");
}
mbsc.addNotificationListener(jmxbean.getObjectName(), serverRegistry.getNotificationListener(), null, null);
- System.out.println("Listener created : " + jmxbean.getObjectName());
}
public static void removeNotificationListener(ManagedBean mbean, String name, String type) throws Exception
{
- //JMXManagedObject jmxbean = (JMXManagedObject)mbean;
JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
serverRegistry.removeNotificationListener(mbean, name, type);
- //MBeanServerConnection mbsc = serverRegistry.getServerConnection();
-
- //if (mbsc != null)
- //{
- // mbsc.removeNotificationListener(jmxbean.getObjectName(), serverRegistry.getNotificationListener());
- //}
}
public static int refreshAttribute(ManagedBean mbean, String attribute) throws Exception
@@ -205,7 +210,9 @@ public class MBeanUtility
MBeanServerConnection mbsc = serverRegistry.getServerConnection();
if (mbsc == null)
- throw new Exception("Server connection is not available for " + mbean.getUniqueName());
+ {
+ throw new ManagementConsoleException("Server connection is broken");
+ }
Object value = mbsc.getAttribute(((JMXManagedObject)mbean).getObjectName(), attribute);
@@ -214,7 +221,13 @@ public class MBeanUtility
return Integer.parseInt(String.valueOf(value));
}
- public static ManagedAttributeModel getAttributes(ManagedBean mbean)
+ /**
+ * Retrieves the attribute values from MBeanSever and stores in the server registry.
+ * @param mbean
+ * @return the attribute model
+ * @throws Exception if attributes can not be retrieved from MBeanServer
+ */
+ public static ManagedAttributeModel getAttributes(ManagedBean mbean) throws Exception
{
ObjectName objName = ((JMXManagedObject)mbean).getObjectName();
String[] attributes = null;
@@ -243,29 +256,28 @@ public class MBeanUtility
attributes = attributeModel.getAttributeNames().toArray(new String[0]);
}
- try
+ if (attributes.length != 0)
{
- if (attributes.length != 0)
+ list = mbsc.getAttributes(objName, attributes);
+ for (Iterator itr = list.iterator(); itr.hasNext();)
{
- list = mbsc.getAttributes(objName, attributes);
- for (Iterator itr = list.iterator(); itr.hasNext();)
- {
- Attribute attrib = (Attribute)itr.next();
- attributeModel.setAttributeValue(attrib.getName(), attrib.getValue());
- }
+ Attribute attrib = (Attribute)itr.next();
+ attributeModel.setAttributeValue(attrib.getName(), attrib.getValue());
}
- }
- catch (Exception ex)
- {
- ex.printStackTrace();
}
- serverRegistry.setAttributeModel(mbean, attributeModel);
-
+ serverRegistry.setAttributeModel(mbean, attributeModel);
return attributeModel;
}
- public static void updateAttribute(ManagedBean mbean, AttributeData attribute, String value)
+ /**
+ * Updates the attribute value of an MBean
+ * @param mbean
+ * @param attribute
+ * @param value
+ * @throws Exception if MBeanServer throws exception in updating the attribute value
+ */
+ public static void updateAttribute(ManagedBean mbean, AttributeData attribute, String value) throws Exception
{
JMXManagedObject jmxbean = (JMXManagedObject)mbean;
JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
@@ -273,11 +285,7 @@ public class MBeanUtility
MBeanServerConnection mbsc = serverRegistry.getServerConnection();
Object newValue = value;
- if (attribute.getDataType().equals(String.class.getName()))
- {
-
- }
- else if (attribute.getDataType().equals(Long.class.getName()))
+ if (attribute.getDataType().equals(Long.class.getName()))
{
newValue = new Long(Long.parseLong(value));
}
@@ -286,24 +294,20 @@ public class MBeanUtility
newValue = new Integer(Integer.parseInt(value));
}
- try
- {
- mbsc.setAttribute(jmxbean.getObjectName(), new Attribute(attribute.getName(), newValue));
-
- // Update the value in the registry, to avoid refreshing from mbsc
- ManagedAttributeModel attributeModel = serverRegistry.getAttributeModel(mbean);
- attributeModel.setAttributeValue(attribute.getName(), newValue);
- }
- catch(Exception ex)
- {
- ex.printStackTrace();
- }
+ mbsc.setAttribute(jmxbean.getObjectName(), new Attribute(attribute.getName(), newValue));
+ // Update the value in the registry, to avoid refreshing from mbsc
+ ManagedAttributeModel attributeModel = serverRegistry.getAttributeModel(mbean);
+ attributeModel.setAttributeValue(attribute.getName(), newValue);
}
+ /**
+ * populates the operation data model in server registry for given mbean
+ * @param mbean
+ * @return operation data model
+ */
public static OperationDataModel getOperations(ManagedBean mbean)
{
JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
-
OperationDataModel dataModel = serverRegistry.getOperationModel(mbean);
if (dataModel == null)
{
@@ -322,6 +326,11 @@ public class MBeanUtility
return dataModel;
}
+ /**
+ * populates the notification in the server registry for given mbean
+ * @param mbean
+ * @return notification info model
+ */
public static NotificationInfoModel[] getNotificationInfo(ManagedBean mbean)
{
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/AttributesTabControl.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/AttributesTabControl.java
index b5c044e7be..04890e4e63 100644
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/AttributesTabControl.java
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/AttributesTabControl.java
@@ -277,8 +277,16 @@ public class AttributesTabControl extends TabControl
{
public void widgetSelected(SelectionEvent e)
{
- // refresh the attributes list
- refresh(_mbean);
+ try
+ {
+ // refresh the attributes list
+ refresh(_mbean);
+ }
+ catch (Exception ex)
+ {
+ MBeanUtility.handleException(_mbean, ex);
+ }
+
}
});
}
@@ -582,12 +590,19 @@ public class AttributesTabControl extends TabControl
{
public void widgetSelected(SelectionEvent event)
{
- Button button = (Button)event.widget;
- Text text = (Text)button.getData();
- AttributeData data = (AttributeData)button.getParent().getData();
- MBeanUtility.updateAttribute(_mbean, data, text.getText());
- button.getShell().close();
- refresh();
+ try
+ {
+ Button button = (Button)event.widget;
+ Text text = (Text)button.getData();
+ AttributeData data = (AttributeData)button.getParent().getData();
+ MBeanUtility.updateAttribute(_mbean, data, text.getText());
+ button.getShell().close();
+ refresh();
+ }
+ catch (Exception ex)
+ {
+ MBeanUtility.handleException(_mbean, ex);
+ }
}
});
@@ -612,7 +627,15 @@ public class AttributesTabControl extends TabControl
_tableViewer.setInput(null);
return;
}
- ManagedAttributeModel attributesList = MBeanUtility.getAttributes(mbean);
+ ManagedAttributeModel attributesList = null;
+ try
+ {
+ attributesList = MBeanUtility.getAttributes(mbean);
+ }
+ catch(Exception ex)
+ {
+ MBeanUtility.handleException(_mbean, ex);
+ }
_tableViewer.setInput(attributesList);
_table.setItemCount(attributesList.getCount());
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/OperationTabControl.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/OperationTabControl.java
index 8563bdb882..c62f90353d 100644
--- a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/OperationTabControl.java
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/OperationTabControl.java
@@ -595,15 +595,6 @@ public class OperationTabControl extends TabControl
else
{
ViewUtility.disposeChildren(_resultsComposite);
- /*
- if (_resultsComposite == null || _resultsComposite.isDisposed())
- {
- _resultsComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
- GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true);
- layoutData.verticalIndent = 20;
- _resultsComposite.setLayoutData(layoutData);
- _resultsComposite.setLayout(new GridLayout());
- }*/
populateResults(result, _resultsComposite);
_resultsComposite.layout();
_form.layout();