summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Ritchie <ritchiem@apache.org>2006-12-06 10:59:27 +0000
committerMartin Ritchie <ritchiem@apache.org>2006-12-06 10:59:27 +0000
commitec6ce6e243209bdab29e130ef1c13233c07ff975 (patch)
treedf6c49f592c524ddf4e5ffd672f91ea0a9e63291
parent16d818e749462daf5e0e43079b2e48991646c619 (diff)
downloadqpid-python-ec6ce6e243209bdab29e130ef1c13233c07ff975.tar.gz
Moved Selector work to a branch
git-svn-id: https://svn.apache.org/repos/asf/incubator/qpid/branches/jmsselectors@483025 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--java/NOTICE.txt4
-rw-r--r--java/broker/pom.xml24
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java6
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/exchange/HeadersExchange.java3
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java2
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/protocol/AMQMinaProtocolSession.java5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessage.java76
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/AMQQueue.java29
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/Subscription.java5
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionFactory.java4
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionImpl.java39
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionSet.java77
-rw-r--r--java/broker/src/main/java/org/apache/qpid/server/security/auth/amqplain/AmqPlainSaslServer.java3
-rw-r--r--java/client/pom.xml2
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/AMQSession.java58
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java3
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/AbstractJMSMessage.java333
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/message/JMSMapMessage.java6
-rw-r--r--java/client/src/main/java/org/apache/qpid/client/security/amqplain/AmqPlainSaslClient.java3
-rw-r--r--java/client/src/test/java/org/apache/qpid/framing/FieldTableTest.java39
-rw-r--r--java/client/src/test/java/org/apache/qpid/headers/MessageFactory.java5
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableKeyEnumeratorTest.java25
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableMessageTest.java13
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTablePropertyTest.java65
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/basic/MapMessageTest.java62
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/basic/PropertyValueTest.java264
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/basic/SessionStartTest.java6
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/basic/TextMessageTest.java12
-rw-r--r--java/client/src/test/java/org/apache/qpid/test/unit/client/AMQSessionTest.java1
-rw-r--r--java/client/src/test/java/org/apache/qpid/topic/Listener.java23
-rw-r--r--java/client/src/test/java/org/apache/qpid/topic/MessageFactory.java17
-rw-r--r--java/client/src/test/java/org/apache/qpid/topic/Publisher.java38
-rw-r--r--java/cluster/src/main/java/org/apache/qpid/server/queue/RemoteSubscriptionImpl.java12
-rw-r--r--java/common/pom.xml24
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/BasicContentHeaderProperties.java11
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/EncodingUtils.java14
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/FieldTable.java398
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/FieldTableFactory.java41
-rw-r--r--java/common/src/main/java/org/apache/qpid/framing/PropertyFieldTable.java698
-rw-r--r--java/common/src/main/java/org/apache/qpid/url/URLHelper.java8
-rw-r--r--java/common/src/main/java/org/apache/qpid/url/URLSyntaxException.java4
-rw-r--r--java/common/src/main/xsl/java.xsl2
-rw-r--r--java/common/src/test/java/org/apache/qpid/framing/PropertyFieldTableTest.java117
-rw-r--r--java/distribution/pom.xml187
-rw-r--r--java/distribution/src/main/assembly/client-bin.xml89
-rw-r--r--java/management/eclipse-plugin/META-INF/MANIFEST.MF11
-rw-r--r--java/management/eclipse-plugin/README.txt7
-rw-r--r--java/management/eclipse-plugin/bin/qpidmc.bat55
-rwxr-xr-xjava/management/eclipse-plugin/bin/qpidmc.sh21
-rw-r--r--java/management/eclipse-plugin/build.properties8
-rw-r--r--java/management/eclipse-plugin/build.xml215
-rw-r--r--java/management/eclipse-plugin/configuration/config.ini25
-rw-r--r--java/management/eclipse-plugin/configuration/org.eclipse.osgi/bundles/16/1/.cp/swt-win32-3232.dllbin0 -> 323584 bytes
-rw-r--r--java/management/eclipse-plugin/icons/Thumbs.dbbin0 -> 97280 bytes
-rw-r--r--java/management/eclipse-plugin/icons/add.gifbin0 -> 318 bytes
-rw-r--r--java/management/eclipse-plugin/icons/delete.gifbin0 -> 143 bytes
-rw-r--r--java/management/eclipse-plugin/icons/icon_ClosedFolder.gifbin0 -> 160 bytes
-rw-r--r--java/management/eclipse-plugin/icons/icon_OpenFolder.gifbin0 -> 152 bytes
-rw-r--r--java/management/eclipse-plugin/icons/mbean_view.pngbin0 -> 2046 bytes
-rw-r--r--java/management/eclipse-plugin/icons/notifications.gifbin0 -> 104 bytes
-rw-r--r--java/management/eclipse-plugin/icons/qpidConnections.gifbin0 -> 168 bytes
-rw-r--r--java/management/eclipse-plugin/icons/qpidmc.gifbin0 -> 1225 bytes
-rw-r--r--java/management/eclipse-plugin/icons/qpidmc32.bmpbin0 -> 1139 bytes
-rw-r--r--java/management/eclipse-plugin/icons/qpidmc32.gifbin0 -> 1139 bytes
-rw-r--r--java/management/eclipse-plugin/icons/reconnect.gifbin0 -> 327 bytes
-rw-r--r--java/management/eclipse-plugin/icons/refresh.gifbin0 -> 182 bytes
-rw-r--r--java/management/eclipse-plugin/icons/stop.gifbin0 -> 215 bytes
-rw-r--r--java/management/eclipse-plugin/plugin.properties20
-rw-r--r--java/management/eclipse-plugin/plugin.xml222
-rw-r--r--java/management/eclipse-plugin/plugins/com.ibm.icu_3.4.4.1.jarbin0 -> 3255246 bytes
-rw-r--r--java/management/eclipse-plugin/plugins/license.eclipse.txt88
-rw-r--r--java/management/eclipse-plugin/plugins/org.eclipse.core.commands_3.2.0.jarbin0 -> 89522 bytes
-rw-r--r--java/management/eclipse-plugin/plugins/org.eclipse.core.contenttype_3.2.0.jarbin0 -> 76141 bytes
-rw-r--r--java/management/eclipse-plugin/plugins/org.eclipse.core.expressions_3.2.0.jarbin0 -> 66037 bytes
-rw-r--r--java/management/eclipse-plugin/plugins/org.eclipse.core.jobs_3.2.0.jarbin0 -> 74797 bytes
-rw-r--r--java/management/eclipse-plugin/plugins/org.eclipse.core.runtime.compatibility.auth_3.2.0.jarbin0 -> 18733 bytes
-rw-r--r--java/management/eclipse-plugin/plugins/org.eclipse.core.runtime.compatibility.registry_3.2.0/META-INF/MANIFEST.MF12
-rw-r--r--java/management/eclipse-plugin/plugins/org.eclipse.core.runtime.compatibility.registry_3.2.0/runtime_registry_compatibility.jarbin0 -> 7584 bytes
-rw-r--r--java/management/eclipse-plugin/plugins/org.eclipse.core.runtime_3.2.0.jarbin0 -> 76627 bytes
-rw-r--r--java/management/eclipse-plugin/plugins/org.eclipse.equinox.common_3.2.0.jarbin0 -> 79780 bytes
-rw-r--r--java/management/eclipse-plugin/plugins/org.eclipse.equinox.preferences_3.2.0.jarbin0 -> 91661 bytes
-rw-r--r--java/management/eclipse-plugin/plugins/org.eclipse.equinox.registry_3.2.0.jarbin0 -> 143841 bytes
-rw-r--r--java/management/eclipse-plugin/plugins/org.eclipse.help_3.2.0.jarbin0 -> 115438 bytes
-rw-r--r--java/management/eclipse-plugin/plugins/org.eclipse.jface_3.2.0.jarbin0 -> 813596 bytes
-rw-r--r--java/management/eclipse-plugin/plugins/org.eclipse.osgi_3.2.0.jarbin0 -> 846716 bytes
-rw-r--r--java/management/eclipse-plugin/plugins/org.eclipse.swt.win32.win32.x86_3.2.0.jarbin0 -> 1553408 bytes
-rw-r--r--java/management/eclipse-plugin/plugins/org.eclipse.swt_3.2.0.jarbin0 -> 11003 bytes
-rw-r--r--java/management/eclipse-plugin/plugins/org.eclipse.ui.forms_3.2.0.jarbin0 -> 235371 bytes
-rw-r--r--java/management/eclipse-plugin/plugins/org.eclipse.ui.workbench.compatibility_3.2.0/META-INF/MANIFEST.MF12
-rw-r--r--java/management/eclipse-plugin/plugins/org.eclipse.ui.workbench.compatibility_3.2.0/compatibility.jarbin0 -> 4080 bytes
-rw-r--r--java/management/eclipse-plugin/plugins/org.eclipse.ui.workbench_3.2.0.jarbin0 -> 3070253 bytes
-rw-r--r--java/management/eclipse-plugin/plugins/org.eclipse.ui_3.2.0.jarbin0 -> 124307 bytes
-rw-r--r--java/management/eclipse-plugin/splash.bmpbin0 -> 207078 bytes
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Activator.java84
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Application.java63
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationActionBarAdvisor.java96
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java129
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchAdvisor.java46
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchWindowAdvisor.java61
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Constants.java79
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ICommandIds.java36
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedBean.java80
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedObject.java (renamed from java/common/src/main/java/org/apache/qpid/framing/FieldTableKeyEnumeration.java)25
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedServer.java75
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Perspective.java53
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ServerRegistry.java79
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AddServer.java282
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/CloseConnection.java93
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/EditAttribute.java87
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/ReconnectServer.java92
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/Refresh.java77
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/RemoveServer.java92
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/exceptions/InfoRequiredException.java36
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientListener.java77
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientNotificationListener.java42
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXManagedObject.java50
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXServerRegistry.java336
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/MBeanUtility.java349
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/AttributeData.java95
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/ManagedAttributeModel.java113
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationInfoModel.java51
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationObject.java88
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationData.java84
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationDataModel.java73
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/ParameterData.java79
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/AttributesTabControl.java937
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/INotificationViewer.java32
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanView.java431
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NavigationView.java787
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NotificationsTabControl.java708
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/OperationTabControl.java718
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TabControl.java57
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TreeObject.java125
-rw-r--r--java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/ViewUtility.java512
-rw-r--r--java/management/eclipse-plugin/startup.jarbin0 -> 33049 bytes
-rw-r--r--java/pom.xml2
-rw-r--r--java/systests/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTest.java27
-rw-r--r--java/systests/src/test/java/org/apache/qpid/server/queue/SendPerfTest.java7
-rw-r--r--java/systests/src/test/java/org/apache/qpid/server/queue/TestSubscription.java10
-rw-r--r--specs/amqp-8.0.xml23
140 files changed, 10040 insertions, 991 deletions
diff --git a/java/NOTICE.txt b/java/NOTICE.txt
index bc35c48fe6..876a136521 100644
--- a/java/NOTICE.txt
+++ b/java/NOTICE.txt
@@ -32,5 +32,9 @@ includes (binary only):
Copyright 1999 (C) Exoffice Technologies Inc. All Rights Reserved.
JMS CTS is available from http://www.exolab.org/
+ - Software from the Eclipse project. The binaries from this project are
+ distributed under the Eclipse Public License and can be donwloaded
+ from http://www.eclipse.org/
+
diff --git a/java/broker/pom.xml b/java/broker/pom.xml
index 5a2c699cc1..f6dd171214 100644
--- a/java/broker/pom.xml
+++ b/java/broker/pom.xml
@@ -53,6 +53,10 @@
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-jms_1.1_spec</artifactId>
+ </dependency>
<dependency>
<groupId>org.apache.mina</groupId>
<artifactId>mina-filter-ssl</artifactId>
@@ -81,6 +85,26 @@
<build>
<plugins>
+
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>javacc-maven-plugin</artifactId>
+ <version>2.0</version>
+ <executions>
+ <execution>
+ <phase>generate-sources</phase>
+ <configuration>
+ <sourceDirectory>${basedir}/src/main/grammar</sourceDirectory>
+ <outputDirectory>${basedir}/target/generated</outputDirectory>
+ <packageName>org.apache.qpid.server.filter.jms.selector</packageName>
+ </configuration>
+ <goals>
+ <goal>javacc</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
diff --git a/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java b/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
index a6cb4523cf..4fe71c117c 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/AMQChannel.java
@@ -26,6 +26,7 @@ import org.apache.qpid.framing.AMQDataBlock;
import org.apache.qpid.framing.BasicPublishBody;
import org.apache.qpid.framing.ContentBody;
import org.apache.qpid.framing.ContentHeaderBody;
+import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.server.ack.TxAck;
import org.apache.qpid.server.ack.UnacknowledgedMessage;
import org.apache.qpid.server.ack.UnacknowledgedMessageMap;
@@ -290,7 +291,7 @@ public class AMQChannel
* @throws ConsumerTagNotUniqueException if the tag is not unique
* @throws AMQException if something goes wrong
*/
- public String subscribeToQueue(String tag, AMQQueue queue, AMQProtocolSession session, boolean acks) throws AMQException, ConsumerTagNotUniqueException
+ public String subscribeToQueue(String tag, AMQQueue queue, AMQProtocolSession session, boolean acks, FieldTable fitler) throws AMQException, ConsumerTagNotUniqueException
{
if (tag == null)
{
@@ -301,7 +302,8 @@ public class AMQChannel
throw new ConsumerTagNotUniqueException();
}
- queue.registerProtocolSession(session, _channelId, tag, acks);
+
+ queue.registerProtocolSession(session, _channelId, tag, acks,fitler);
_consumerTag2QueueMap.put(tag, queue);
return tag;
}
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 586d6b8796..ccb2211a55 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
@@ -25,6 +25,7 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.framing.FieldTableFactory;
import org.apache.qpid.server.management.MBeanConstructor;
import org.apache.qpid.server.management.MBeanDescription;
import org.apache.qpid.server.queue.AMQMessage;
@@ -154,7 +155,7 @@ public class HeadersExchange extends AbstractExchange
}
String[] bindings = binding.split(",");
- FieldTable fieldTable = new FieldTable();
+ FieldTable fieldTable = FieldTableFactory.newFieldTable();
for (int i = 0; i < bindings.length; i++)
{
String[] keyAndValue = bindings[i].split("=");
diff --git a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java
index d4c94061a0..c4c995540d 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/handler/BasicConsumeMethodHandler.java
@@ -74,7 +74,7 @@ public class BasicConsumeMethodHandler implements StateAwareMethodListener<Basic
}
try
{
- String consumerTag = channel.subscribeToQueue(body.consumerTag, queue, session, !body.noAck);
+ String consumerTag = channel.subscribeToQueue(body.consumerTag, queue, session, !body.noAck, body.filter);
if(!body.nowait)
{
session.writeFrame(BasicConsumeOkBody.createAMQFrame(channelId, consumerTag));
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 be8d2c4c82..1aa62dbfa4 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
@@ -367,6 +367,11 @@ public class AMQMinaProtocolSession implements AMQProtocolSession,
int i = pv.length - 1;
_minaProtocolSession.write(new ProtocolInitiation(pv[i][PROTOCOL_MAJOR], pv[i][PROTOCOL_MINOR]));
// TODO: Close connection (but how to wait until message is sent?)
+ // ritchiem 2006-12-04 will this not do?
+// WriteFuture future = _minaProtocolSession.write(new ProtocolInitiation(pv[i][PROTOCOL_MAJOR], pv[i][PROTOCOL_MINOR]));
+// future.join();
+// close connection
+
}
}
else
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessage.java b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessage.java
index 8b6db5b53f..69b03c9cd2 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessage.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/AMQMessage.java
@@ -25,6 +25,8 @@ import org.apache.qpid.framing.*;
import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.server.store.MessageStore;
import org.apache.qpid.server.txn.TxnBuffer;
+import org.apache.qpid.server.message.MessageDecorator;
+import org.apache.qpid.server.message.jms.JMSMessage;
import org.apache.qpid.AMQException;
import java.util.ArrayList;
@@ -33,17 +35,20 @@ import java.util.LinkedList;
import java.util.Set;
import java.util.HashSet;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.ConcurrentHashMap;
/**
* Combines the information that make up a deliverable message into a more manageable form.
*/
public class AMQMessage
{
+ public static final String JMS_MESSAGE = "jms.message";
+
private final Set<Object> _tokens = new HashSet<Object>();
private AMQProtocolSession _publisher;
- private final BasicPublishBody _publishBody;
+ private final BasicPublishBody _publishBody;
private ContentHeaderBody _contentHeaderBody;
@@ -83,6 +88,7 @@ public class AMQMessage
* messages published with the 'immediate' flag.
*/
private boolean _deliveredToConsumer;
+ private ConcurrentHashMap<String, MessageDecorator> _decodedMessages;
public AMQMessage(MessageStore messageStore, BasicPublishBody publishBody)
@@ -96,17 +102,19 @@ public class AMQMessage
_publishBody = publishBody;
_store = messageStore;
_contentBodies = new LinkedList<ContentBody>();
+ _decodedMessages = new ConcurrentHashMap<String, MessageDecorator>();
_storeWhenComplete = storeWhenComplete;
}
public AMQMessage(MessageStore store, long messageId, BasicPublishBody publishBody,
ContentHeaderBody contentHeaderBody, List<ContentBody> contentBodies)
throws AMQException
-
+
{
_publishBody = publishBody;
_contentHeaderBody = contentHeaderBody;
_contentBodies = contentBodies;
+ _decodedMessages = new ConcurrentHashMap<String, MessageDecorator>();
_messageId = messageId;
_store = store;
storeMessage();
@@ -116,7 +124,7 @@ public class AMQMessage
ContentHeaderBody contentHeaderBody, List<ContentBody> contentBodies)
throws AMQException
{
- this(store, store.getNewMessageId(), publishBody, contentHeaderBody, contentBodies);
+ this(store, store.getNewMessageId(), publishBody, contentHeaderBody, contentBodies);
}
protected AMQMessage(AMQMessage msg) throws AMQException
@@ -270,7 +278,7 @@ public class AMQMessage
{
_store.removeMessage(_messageId);
}
- catch(AMQException e)
+ catch (AMQException e)
{
//to maintain consistency, we revert the count
incrementReference();
@@ -291,7 +299,7 @@ public class AMQMessage
public boolean checkToken(Object token)
{
- if(_tokens.contains(token))
+ if (_tokens.contains(token))
{
return true;
}
@@ -307,7 +315,7 @@ public class AMQMessage
//if the message is not persistent or the queue is not durable
//we will not need to recover the association and so do not
//need to record it
- if(isPersistent() && queue.isDurable())
+ if (isPersistent() && queue.isDurable())
{
_store.enqueueMessage(queue.getName(), _messageId);
}
@@ -317,7 +325,7 @@ public class AMQMessage
{
//only record associations where both queue and message will survive
//a restart, so only need to remove association if this is the case
- if(isPersistent() && queue.isDurable())
+ if (isPersistent() && queue.isDurable())
{
_store.dequeueMessage(queue.getName(), _messageId);
}
@@ -325,14 +333,14 @@ public class AMQMessage
public boolean isPersistent() throws AMQException
{
- if(_contentHeaderBody == null)
+ if (_contentHeaderBody == null)
{
throw new AMQException("Cannot determine delivery mode of message. Content header not found.");
}
//todo remove literal values to a constant file such as AMQConstants in common
return _contentHeaderBody.properties instanceof BasicContentHeaderProperties
- &&((BasicContentHeaderProperties) _contentHeaderBody.properties).getDeliveryMode() == 2;
+ && ((BasicContentHeaderProperties) _contentHeaderBody.properties).getDeliveryMode() == 2;
}
public void setTxnBuffer(TxnBuffer buffer)
@@ -346,13 +354,15 @@ public class AMQMessage
}
/**
- * Called to enforce the 'immediate' flag.
+ * Called to enforce the 'immediate' flag.
+ *
* @throws NoConsumersException if the message is marked for
- * immediate delivery but has not been marked as delivered to a
- * consumer
+ * immediate delivery but has not been marked as delivered to a
+ * consumer
*/
- public void checkDeliveredToConsumer() throws NoConsumersException{
- if(isImmediate() && !_deliveredToConsumer)
+ public void checkDeliveredToConsumer() throws NoConsumersException
+ {
+ if (isImmediate() && !_deliveredToConsumer)
{
throw new NoConsumersException(_publishBody, _contentHeaderBody, _contentBodies);
}
@@ -362,7 +372,43 @@ public class AMQMessage
* Called when this message is delivered to a consumer. (used to
* implement the 'immediate' flag functionality).
*/
- public void setDeliveredToConsumer(){
+ public void setDeliveredToConsumer()
+ {
_deliveredToConsumer = true;
}
+
+
+ public MessageDecorator getDecodedMessage(String type)
+ {
+ MessageDecorator msgtype = null;
+
+ if (_decodedMessages != null)
+ {
+ msgtype = _decodedMessages.get(type);
+
+ if (msgtype == null)
+ {
+ msgtype = decorateMessage(type);
+ }
+ }
+
+ return msgtype;
+ }
+
+ private MessageDecorator decorateMessage(String type)
+ {
+ MessageDecorator msgdec = null;
+
+ if (type.equals(JMS_MESSAGE))
+ {
+ msgdec = new JMSMessage(this);
+ }
+
+ if (msgdec != null)
+ {
+ _decodedMessages.put(type, msgdec);
+ }
+
+ return msgdec;
+ }
}
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 353a2007c0..f734edcc7b 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
@@ -26,6 +26,7 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.framing.ContentBody;
import org.apache.qpid.framing.ContentHeaderBody;
+import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.server.exchange.Exchange;
import org.apache.qpid.server.management.AMQManagedObject;
import org.apache.qpid.server.management.MBeanConstructor;
@@ -141,8 +142,8 @@ public class AMQQueue implements Managable, Comparable
// OpenMBean data types for viewMessageContent method
private CompositeType _msgContentType = null;
- private String[] _msgContentAttributes = {"Message Id", "MimeType", "Encoding", "Content"};
- private OpenType[] _msgContentAttributeTypes = new OpenType[4];
+ 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
@@ -162,14 +163,14 @@ public class AMQQueue implements Managable, Comparable
_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);
+ _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);
+ _messageDataType = new CompositeType("Message", "AMQ Message", _msgAttributeNames, _msgAttributeNames, _msgAttributeTypes);
_messagelistDataType = new TabularType("Messages", "List of messages", _messageDataType, _msgAttributeIndex);
}
@@ -265,7 +266,7 @@ public class AMQQueue implements Managable, Comparable
{
queueDepth = queueDepth + getMessageSize(message);
}
- return (long)Math.round(queueDepth / 1000);
+ return (long) Math.round(queueDepth / 1000);
}
/**
@@ -314,7 +315,7 @@ public class AMQQueue implements Managable, Comparable
private void notifyClients(String notificationMsg)
{
Notification n = new Notification(MonitorNotification.THRESHOLD_VALUE_EXCEEDED, this,
- ++_notificationSequenceNumber, System.currentTimeMillis(), notificationMsg);
+ ++_notificationSequenceNumber, System.currentTimeMillis(), notificationMsg);
_broadcaster.sendNotification(n);
}
@@ -361,7 +362,7 @@ public class AMQQueue implements Managable, Comparable
if (msg == null)
{
- throw new JMException("AMQMessage with message id = " + msgId + " is not in the " + _queueName );
+ throw new JMException("AMQMessage with message id = " + msgId + " is not in the " + _queueName);
}
// get message content
List<ContentBody> cBodies = msg.getContentBodies();
@@ -379,7 +380,7 @@ public class AMQQueue implements Managable, Comparable
}
// Create header attributes list
- BasicContentHeaderProperties headerProperties = (BasicContentHeaderProperties)msg.getContentHeaderBody().properties;
+ 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])};
@@ -402,12 +403,12 @@ public class AMQQueue implements Managable, Comparable
TabularDataSupport _messageList = new TabularDataSupport(_messagelistDataType);
// Create the tabular list of message header contents
- for (int i = beginIndex; i <= endIndex && i <= list.size(); i++)
+ for (int i = beginIndex; i <= endIndex && i <= list.size(); i++)
{
AMQMessage msg = list.get(i - 1);
- ContentHeaderBody headerBody = msg.getContentHeaderBody();
+ ContentHeaderBody headerBody = msg.getContentHeaderBody();
// Create header attributes list
- BasicContentHeaderProperties headerProperties = (BasicContentHeaderProperties)headerBody.properties;
+ BasicContentHeaderProperties headerProperties = (BasicContentHeaderProperties) headerBody.properties;
List<String> headerAttribsList = new ArrayList<String>();
headerAttribsList.add("App Id=" + headerProperties.getAppId());
headerAttribsList.add("MimeType=" + headerProperties.getContentType());
@@ -430,7 +431,7 @@ public class AMQQueue implements Managable, Comparable
@Override
public MBeanNotificationInfo[] getNotificationInfo()
{
- String[] notificationTypes = new String[] {MonitorNotification.THRESHOLD_VALUE_EXCEEDED};
+ 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);
@@ -581,12 +582,12 @@ public class AMQQueue implements Managable, Comparable
_bindings.addBinding(routingKey, exchange);
}
- public void registerProtocolSession(AMQProtocolSession ps, int channel, String consumerTag, boolean acks)
+ public void registerProtocolSession(AMQProtocolSession ps, int channel, String consumerTag, boolean acks, FieldTable filters)
throws AMQException
{
debug("Registering protocol session {0} with channel {1} and consumer tag {2} with {3}", ps, channel, consumerTag, this);
- Subscription subscription = _subscriptionFactory.createSubscription(channel, ps, consumerTag, acks);
+ Subscription subscription = _subscriptionFactory.createSubscription(channel, ps, consumerTag, acks, filters);
_subscribers.addSubscriber(subscription);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/Subscription.java b/java/broker/src/main/java/org/apache/qpid/server/queue/Subscription.java
index dfc16a7c71..35ac9a13ac 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/Subscription.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/Subscription.java
@@ -21,6 +21,7 @@
package org.apache.qpid.server.queue;
import org.apache.qpid.AMQException;
+import org.apache.qpid.server.filter.MessageFilter;
public interface Subscription
{
@@ -29,4 +30,8 @@ public interface Subscription
boolean isSuspended();
void queueDeleted(AMQQueue queue);
+
+ boolean hasFilters();
+
+ boolean hasInterest(AMQMessage msg);
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionFactory.java b/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionFactory.java
index 0fd44e4fbc..f464384562 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionFactory.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionFactory.java
@@ -22,6 +22,7 @@ package org.apache.qpid.server.queue;
import org.apache.qpid.server.protocol.AMQProtocolSession;
import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.FieldTable;
/**
* Allows the customisation of the creation of a subscription. This is typically done within an AMQQueue. This
@@ -32,6 +33,9 @@ import org.apache.qpid.AMQException;
*/
public interface SubscriptionFactory
{
+ Subscription createSubscription(int channel, AMQProtocolSession protocolSession, String consumerTag, boolean acks, FieldTable filters)
+ throws AMQException;
+
Subscription createSubscription(int channel, AMQProtocolSession protocolSession, String consumerTag, boolean acks)
throws AMQException;
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionImpl.java b/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionImpl.java
index 5cad28b80d..a0d86deb19 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionImpl.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionImpl.java
@@ -26,7 +26,10 @@ import org.apache.qpid.AMQException;
import org.apache.qpid.framing.AMQDataBlock;
import org.apache.qpid.framing.AMQFrame;
import org.apache.qpid.framing.BasicDeliverBody;
+import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.server.AMQChannel;
+import org.apache.qpid.server.filter.FilterManager;
+import org.apache.qpid.server.filter.FilterManagerFactory;
import org.apache.qpid.server.protocol.AMQProtocolSession;
/**
@@ -52,19 +55,25 @@ public class SubscriptionImpl implements Subscription
* True if messages need to be acknowledged
*/
private final boolean _acks;
+ private FilterManager _filters;
public static class Factory implements SubscriptionFactory
{
+ public Subscription createSubscription(int channel, AMQProtocolSession protocolSession, String consumerTag, boolean acks, FieldTable filters) throws AMQException
+ {
+ return new SubscriptionImpl(channel, protocolSession, consumerTag, acks, filters);
+ }
+
public SubscriptionImpl createSubscription(int channel, AMQProtocolSession protocolSession, String consumerTag, boolean acks)
throws AMQException
{
- return new SubscriptionImpl(channel, protocolSession, consumerTag, acks);
+ return new SubscriptionImpl(channel, protocolSession, consumerTag, acks, null);
}
public SubscriptionImpl createSubscription(int channel, AMQProtocolSession protocolSession, String consumerTag)
throws AMQException
{
- return new SubscriptionImpl(channel, protocolSession, consumerTag);
+ return new SubscriptionImpl(channel, protocolSession, consumerTag, false, null);
}
}
@@ -72,6 +81,13 @@ public class SubscriptionImpl implements Subscription
String consumerTag, boolean acks)
throws AMQException
{
+ this(channelId, protocolSession, consumerTag, acks, null);
+ }
+
+ public SubscriptionImpl(int channelId, AMQProtocolSession protocolSession,
+ String consumerTag, boolean acks, FieldTable filters)
+ throws AMQException
+ {
AMQChannel channel = protocolSession.getChannel(channelId);
if (channel == null)
{
@@ -83,14 +99,9 @@ public class SubscriptionImpl implements Subscription
this.consumerTag = consumerTag;
sessionKey = protocolSession.getKey();
_acks = acks;
+ _filters = FilterManagerFactory.createManager(filters);
}
- public SubscriptionImpl(int channel, AMQProtocolSession protocolSession,
- String consumerTag)
- throws AMQException
- {
- this(channel, protocolSession, consumerTag, false);
- }
public boolean equals(Object o)
{
@@ -131,7 +142,7 @@ public class SubscriptionImpl implements Subscription
{
// if we do not need to wait for client acknowledgements
// we can decrement the reference count immediately.
-
+
// By doing this _before_ the send we ensure that it
// doesn't get sent if it can't be dequeued, preventing
// duplicate delivery on recovery.
@@ -178,6 +189,16 @@ public class SubscriptionImpl implements Subscription
channel.queueDeleted(queue);
}
+ public boolean hasFilters()
+ {
+ return _filters != null;
+ }
+
+ public boolean hasInterest(AMQMessage msg)
+ {
+ return _filters.allAllow(msg);
+ }
+
private ByteBuffer createEncodedDeliverFrame(long deliveryTag, String routingKey, String exchange)
{
AMQFrame deliverFrame = BasicDeliverBody.createAMQFrame(channel.getChannelId(), consumerTag,
diff --git a/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionSet.java b/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionSet.java
index 7cc3f5f719..a8f778244e 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionSet.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/queue/SubscriptionSet.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
@@ -21,6 +21,8 @@
package org.apache.qpid.server.queue;
import org.apache.log4j.Logger;
+import org.apache.qpid.AMQException;
+
import java.util.List;
import java.util.ListIterator;
import java.util.concurrent.CopyOnWriteArrayList;
@@ -58,6 +60,7 @@ class SubscriptionSet implements WeightedSubscriptionManager
/**
* Remove the subscription, returning it if it was found
+ *
* @param subscription
* @return null if no match was found
*/
@@ -90,7 +93,7 @@ class SubscriptionSet implements WeightedSubscriptionManager
/**
* Return the next unsuspended subscription or null if not found.
- *
+ * <p/>
* Performance note:
* This method can scan all items twice when looking for a subscription that is not
* suspended. The worst case occcurs when all subscriptions are suspended. However, it is does this
@@ -105,29 +108,59 @@ class SubscriptionSet implements WeightedSubscriptionManager
return null;
}
- try {
- final Subscription result = nextSubscriber();
- if (result == null) {
+ try
+ {
+ final Subscription result = nextSubscriberImpl(msg);
+ if (result == null)
+ {
_currentSubscriber = 0;
- return nextSubscriber();
- } else {
+ return nextSubscriberImpl(msg);
+ }
+ else
+ {
return result;
}
- } catch (IndexOutOfBoundsException e) {
+ }
+ catch (IndexOutOfBoundsException e)
+ {
_currentSubscriber = 0;
- return nextSubscriber();
+ return nextSubscriber(msg);
}
}
- private Subscription nextSubscriber()
+ private Subscription nextSubscriberImpl(AMQMessage msg)
{
final ListIterator<Subscription> iterator = _subscriptions.listIterator(_currentSubscriber);
- while (iterator.hasNext()) {
+ while (iterator.hasNext())
+ {
Subscription subscription = iterator.next();
++_currentSubscriber;
subscriberScanned();
- if (!subscription.isSuspended()) {
- return subscription;
+
+ if (!subscription.isSuspended())
+ {
+
+ if ((!subscription.hasFilters()) || (subscription.hasFilters() && subscription.hasInterest(msg)))
+ {
+ return subscription;
+ }
+ // 2006-12-04 : It is fairer to simply skip the person who isn't interested.
+ // Although it does need to be looked at again.
+
+// else
+// {
+// //Don't take penalise a subscriber for not wanting this message.
+// // This would introduce unfairness sticking with the current subscriber
+// // will allow the next message to match.. although could lead to unfairness if:
+// // subscribers: a(bin) b(text) c(text)
+// // msgs : 1(text) 2(text) 3(bin)
+// // subscriber c won't get any messages. as the first two text msgs will go to b and then a will get
+// // the bin msg.
+// // Never said this was fair round-robin-ing.
+// //FIXME - Make a fair round robin.
+//
+// --_currentSubscriber;
+// }
}
}
return null;
@@ -149,7 +182,10 @@ class SubscriptionSet implements WeightedSubscriptionManager
{
for (Subscription s : _subscriptions)
{
- if (!s.isSuspended()) return true;
+ if (!s.isSuspended())
+ {
+ return true;
+ }
}
return false;
}
@@ -159,7 +195,10 @@ class SubscriptionSet implements WeightedSubscriptionManager
int count = 0;
for (Subscription s : _subscriptions)
{
- if (!s.isSuspended()) count++;
+ if (!s.isSuspended())
+ {
+ count++;
+ }
}
return count;
}
@@ -167,9 +206,10 @@ class SubscriptionSet implements WeightedSubscriptionManager
/**
* Notification that a queue has been deleted. This is called so that the subscription can inform the
* channel, which in turn can update its list of unacknowledged messages.
+ *
* @param queue
*/
- public void queueDeleted(AMQQueue queue)
+ public void queueDeleted(AMQQueue queue) throws AMQException
{
for (Subscription s : _subscriptions)
{
@@ -177,7 +217,8 @@ class SubscriptionSet implements WeightedSubscriptionManager
}
}
- int size() {
+ int size()
+ {
return _subscriptions.size();
}
}
diff --git a/java/broker/src/main/java/org/apache/qpid/server/security/auth/amqplain/AmqPlainSaslServer.java b/java/broker/src/main/java/org/apache/qpid/server/security/auth/amqplain/AmqPlainSaslServer.java
index 3ad74ce180..c364ca1d8d 100644
--- a/java/broker/src/main/java/org/apache/qpid/server/security/auth/amqplain/AmqPlainSaslServer.java
+++ b/java/broker/src/main/java/org/apache/qpid/server/security/auth/amqplain/AmqPlainSaslServer.java
@@ -22,6 +22,7 @@ package org.apache.qpid.server.security.auth.amqplain;
import org.apache.qpid.framing.FieldTable;
import org.apache.qpid.framing.AMQFrameDecodingException;
+import org.apache.qpid.framing.FieldTableFactory;
import org.apache.mina.common.ByteBuffer;
import javax.security.sasl.SaslServer;
@@ -54,7 +55,7 @@ public class AmqPlainSaslServer implements SaslServer
{
try
{
- final FieldTable ft = new FieldTable(ByteBuffer.wrap(response), response.length);
+ final FieldTable ft = FieldTableFactory.newFieldTable(ByteBuffer.wrap(response), response.length);
String username = (String) ft.get("LOGIN");
// we do not care about the prompt but it throws if null
NameCallback nameCb = new NameCallback("prompt", username);
diff --git a/java/client/pom.xml b/java/client/pom.xml
index 25372772af..6beb5146d4 100644
--- a/java/client/pom.xml
+++ b/java/client/pom.xml
@@ -122,7 +122,9 @@
</includes>
<excludes>
<exclude>**/JNDIReferenceableTest.java</exclude>
+ <exclude>**/DurableSubscriptionTest.java</exclude>
</excludes>
+
</configuration>
</plugin>
</plugins>
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 57b941a060..885f7647bc 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
@@ -829,14 +829,16 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
AMQDestination amqd = (AMQDestination) destination;
final AMQProtocolHandler protocolHandler = _connection.getProtocolHandler();
- // TODO: construct the rawSelector from the selector string if rawSelector == null
- final FieldTable ft = new FieldTable();
- //if (rawSelector != null)
- // ft.put("headers", rawSelector.getDataAsBytes());
+
+ final FieldTable ft = FieldTableFactory.newFieldTable();
+
+ // Add headers for headers exchange
if (rawSelector != null)
{
ft.putAll(rawSelector);
}
+
+
BasicMessageConsumer consumer = new BasicMessageConsumer(_channelId, _connection, amqd, selector, noLocal,
_messageFactoryRegistry, AMQSession.this,
protocolHandler, ft, prefetchHigh, prefetchLow, exclusive,
@@ -915,6 +917,18 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
protocolHandler.writeFrame(queueBind);
}
+// /**
+// * Register to consume from the queue.
+// *
+// * @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
+// {
+// return consumeFromQueue(queueName, protocolHandler, prefetchHigh, prefetchLow, noLocal, exclusive, acknowledgeMode, null);
+// }
+
/**
* Register to consume from the queue.
*
@@ -922,16 +936,25 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
* @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
+ boolean noLocal, boolean exclusive, int acknowledgeMode, String messageSelector) 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++);
+ FieldTable ft = new FieldTable();
+
+ if (messageSelector != null)
+ {
+ //fixme move literal value to a common class.
+ ft.put("x-filter-jms-selector", messageSelector);
+ }
+
AMQFrame jmsConsume = BasicConsumeBody.createAMQFrame(_channelId, 0,
queueName, tag, noLocal,
acknowledgeMode == Session.NO_ACKNOWLEDGE,
- exclusive, true);
+ exclusive, true, ft);
+
protocolHandler.writeFrame(jmsConsume);
return tag;
@@ -992,7 +1015,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
public QueueSender createSender(Queue queue) throws JMSException
{
//return (QueueSender) createProducer(queue);
- return new QueueSenderAdapter(createProducer(queue),queue);
+ return new QueueSenderAdapter(createProducer(queue), queue);
}
public Topic createTopic(String topicName) throws JMSException
@@ -1072,7 +1095,7 @@ public class AMQSession extends Closeable implements Session, QueueSession, Topi
public TopicPublisher createPublisher(Topic topic) throws JMSException
{
//return (TopicPublisher) createProducer(topic);
- return new TopicPublisherAdapter(createProducer(topic), topic);
+ return new TopicPublisherAdapter(createProducer(topic), topic);
}
public QueueBrowser createBrowser(Queue queue) throws JMSException
@@ -1218,11 +1241,22 @@ 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());
+ String consumerTag = null;
+ try
+ {
+ consumerTag = consumeFromQueue(queueName, protocolHandler, consumer.getPrefetchHigh(), consumer.getPrefetchLow(),
+ consumer.isNoLocal(), consumer.isExclusive(), consumer.getAcknowledgeMode(),
+ consumer.getMessageSelector());
+
+ consumer.setConsumerTag(consumerTag);
+ _consumers.put(consumerTag, consumer);
+ }
+ catch (JMSException e)
+ {
+ // getMessageSelector throws JMSEx but it is simply a string return so won't happen.
+ }
+
- consumer.setConsumerTag(consumerTag);
- _consumers.put(consumerTag, consumer);
}
/**
diff --git a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java
index caef9a3f44..9333df3fe4 100644
--- a/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java
+++ b/java/client/src/main/java/org/apache/qpid/client/handler/ConnectionStartMethodHandler.java
@@ -32,6 +32,7 @@ import org.apache.qpid.client.state.StateAwareMethodListener;
import org.apache.qpid.framing.ConnectionStartBody;
import org.apache.qpid.framing.ConnectionStartOkBody;
import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.framing.FieldTableFactory;
import javax.security.sasl.Sasl;
import javax.security.sasl.SaslClient;
@@ -117,7 +118,7 @@ public class ConnectionStartMethodHandler implements StateAwareMethodListener
}
stateManager.changeState(AMQState.CONNECTION_NOT_TUNED);
- FieldTable clientProperties = new FieldTable();
+ FieldTable clientProperties = FieldTableFactory.newFieldTable();
clientProperties.put("instance", ps.getClientID());
clientProperties.put("product", "Qpid");
clientProperties.put("version", "1.0");
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 a5b135da2d..aaf0320afb 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
@@ -28,9 +28,8 @@ import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQTopic;
import org.apache.qpid.client.JmsNotImplementedException;
import org.apache.qpid.framing.BasicContentHeaderProperties;
-import org.apache.qpid.framing.FieldTableKeyEnumeration;
import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.framing.PropertyFieldTable;
+import org.apache.qpid.framing.FieldTableFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
@@ -45,20 +44,6 @@ public abstract class AbstractJMSMessage extends AMQMessage implements javax.jms
{
private static final Map _destinationCache = Collections.synchronizedMap(new ReferenceMap());
-
- //todo Remove these and Change _headers to use a subclass of PropertyFieldTable that limits
- // the properties that can be added... or suitably handles the values that cannot be added to the
- // AMQP header field table.
- public static final char BOOLEAN_PROPERTY_PREFIX = PropertyFieldTable.BOOLEAN_PROPERTY_PREFIX;
- public static final char BYTE_PROPERTY_PREFIX = PropertyFieldTable.BYTE_PROPERTY_PREFIX;
- public static final char SHORT_PROPERTY_PREFIX = PropertyFieldTable.SHORT_PROPERTY_PREFIX;
- public static final char INT_PROPERTY_PREFIX = PropertyFieldTable.INT_PROPERTY_PREFIX;
- public static final char LONG_PROPERTY_PREFIX = PropertyFieldTable.LONG_PROPERTY_PREFIX;
- public static final char FLOAT_PROPERTY_PREFIX = PropertyFieldTable.FLOAT_PROPERTY_PREFIX;
- public static final char DOUBLE_PROPERTY_PREFIX = PropertyFieldTable.DOUBLE_PROPERTY_PREFIX;
- public static final char STRING_PROPERTY_PREFIX = PropertyFieldTable.STRING_PROPERTY_PREFIX;
-
-
protected boolean _redelivered;
protected ByteBuffer _data;
@@ -73,7 +58,8 @@ public abstract class AbstractJMSMessage extends AMQMessage implements javax.jms
{
_data.acquire();
}
- _readableProperties = (_contentHeaderProperties != null);
+ // ContentHeaderProperties are just created and so are empty
+ //_readableProperties = (_contentHeaderProperties != null);
_readableMessage = (data != null);
}
@@ -86,13 +72,13 @@ public abstract class AbstractJMSMessage extends AMQMessage implements javax.jms
_data.acquire();
}
- _readableProperties = (_contentHeaderProperties != null);
_readableMessage = data != null;
}
protected AbstractJMSMessage(BasicContentHeaderProperties contentHeader, long deliveryTag)
{
super(contentHeader, deliveryTag);
+ _readableProperties = (_contentHeaderProperties != null);
}
public String getJMSMessageID() throws JMSException
@@ -221,11 +207,12 @@ public abstract class AbstractJMSMessage extends AMQMessage implements javax.jms
public String getJMSType() throws JMSException
{
+ //fixme wrong QPID-152
return getMimeType();
}
public void setJMSType(String string) throws JMSException
- {
+ {
//throw new JMSException("Cannot set JMS Type - it is implicitly defined based on message type");
// this is not spec comliant, should not throw the message
}
@@ -252,10 +239,7 @@ public abstract class AbstractJMSMessage extends AMQMessage implements javax.jms
public void clearProperties() throws JMSException
{
- if (getJmsContentHeaderProperties().getHeaders() != null)
- {
- getJmsContentHeaderProperties().getHeaders().clear();
- }
+ getJmsContentHeaderProperties().getHeaders().clear();
_readableProperties = false;
}
@@ -270,281 +254,136 @@ public abstract class AbstractJMSMessage extends AMQMessage implements javax.jms
public boolean propertyExists(String propertyName) throws JMSException
{
checkPropertyName(propertyName);
- if (getJmsContentHeaderProperties().getHeaders() == null)
- {
- return false;
- }
- else
- {
- Iterator keys = getJmsContentHeaderProperties().getHeaders().keySet().iterator();
-
- while (keys.hasNext())
- {
- String key = (String) keys.next();
-
- if (key.endsWith(propertyName))
- {
- return true;
- }
- }
- return false;
- }
+ return getJmsContentHeaderProperties().getHeaders().propertyExists(propertyName);
}
public boolean getBooleanProperty(String propertyName) throws JMSException
{
checkPropertyName(propertyName);
- if (getJmsContentHeaderProperties().getHeaders() == null)
+
+ if (getJmsContentHeaderProperties() == null)
{
- return Boolean.valueOf(null).booleanValue();
+ System.out.println("HEADERS ARE NULL");
}
- else
- {
- // store as integer as temporary workaround
- //Boolean b = (Boolean) getJmsContentHeaderProperties().headers.get(BOOLEAN_PROPERTY_PREFIX + propertyName);
- Long b = (Long) getJmsContentHeaderProperties().getHeaders().get(BOOLEAN_PROPERTY_PREFIX + propertyName);
- if (b == null)
- {
- return Boolean.valueOf(null).booleanValue();
- }
- else
- {
- return b.longValue() != 0;
- }
- }
+
+ return getJmsContentHeaderProperties().getHeaders().getBoolean(propertyName);
}
public byte getByteProperty(String propertyName) throws JMSException
{
checkPropertyName(propertyName);
- if (getJmsContentHeaderProperties().getHeaders() == null)
- {
- return Byte.valueOf(null).byteValue();
- }
- else
- {
- Byte b = (Byte) getJmsContentHeaderProperties().getHeaders().get(BYTE_PROPERTY_PREFIX + propertyName);
- if (b == null)
- {
- return Byte.valueOf(null).byteValue();
- }
- else
- {
- return b.byteValue();
- }
- }
+ return getJmsContentHeaderProperties().getHeaders().getByte(propertyName);
}
public short getShortProperty(String propertyName) throws JMSException
{
checkPropertyName(propertyName);
- if (getJmsContentHeaderProperties().getHeaders() == null)
- {
- return Short.valueOf(null).shortValue();
- }
- else
- {
- Short s = (Short) getJmsContentHeaderProperties().getHeaders().get(SHORT_PROPERTY_PREFIX + propertyName);
- if (s == null)
- {
- return Short.valueOf(null).shortValue();
- }
- else
- {
- return s.shortValue();
- }
- }
+ return getJmsContentHeaderProperties().getHeaders().getShort(propertyName);
}
public int getIntProperty(String propertyName) throws JMSException
{
checkPropertyName(propertyName);
- if (getJmsContentHeaderProperties().getHeaders() == null)
- {
- return Integer.valueOf(null).intValue();
- }
- else
- {
- Integer i = (Integer) getJmsContentHeaderProperties().getHeaders().get(INT_PROPERTY_PREFIX + propertyName);
- if (i == null)
- {
- return Integer.valueOf(null).intValue();
- }
- else
- {
- return i.intValue();
- }
- }
+ return getJmsContentHeaderProperties().getHeaders().getInteger(propertyName);
}
public long getLongProperty(String propertyName) throws JMSException
{
checkPropertyName(propertyName);
- if (getJmsContentHeaderProperties().getHeaders() == null)
- {
- return Long.valueOf(null).longValue();
- }
- else
- {
- Long l = (Long) getJmsContentHeaderProperties().getHeaders().get(LONG_PROPERTY_PREFIX + propertyName);
- if (l == null)
- {
- // temp - the spec says do this but this throws a NumberFormatException
- //return Long.valueOf(null).longValue();
- return 0;
- }
- else
- {
- return l.longValue();
- }
- }
+ return getJmsContentHeaderProperties().getHeaders().getLong(propertyName);
}
public float getFloatProperty(String propertyName) throws JMSException
{
checkPropertyName(propertyName);
- if (getJmsContentHeaderProperties().getHeaders() == null)
- {
- return Float.valueOf(null).floatValue();
- }
- else
- {
- final Float f = (Float) getJmsContentHeaderProperties().getHeaders().get(FLOAT_PROPERTY_PREFIX + propertyName);
- if (f == null)
- {
- return Float.valueOf(null).floatValue();
- }
- else
- {
- return f.floatValue();
- }
- }
+ return getJmsContentHeaderProperties().getHeaders().getFloat(propertyName);
}
public double getDoubleProperty(String propertyName) throws JMSException
{
checkPropertyName(propertyName);
- if (getJmsContentHeaderProperties().getHeaders() == null)
- {
- return Double.valueOf(null).doubleValue();
- }
- else
- {
- final Double d = (Double) getJmsContentHeaderProperties().getHeaders().get(DOUBLE_PROPERTY_PREFIX + propertyName);
- if (d == null)
- {
- return Double.valueOf(null).doubleValue();
- }
- else
- {
- return d.shortValue();
- }
- }
+ return getJmsContentHeaderProperties().getHeaders().getDouble(propertyName);
}
public String getStringProperty(String propertyName) throws JMSException
{
checkPropertyName(propertyName);
- if (getJmsContentHeaderProperties().getHeaders() == null)
- {
- return null;
- }
- else
- {
- return (String) getJmsContentHeaderProperties().getHeaders().get(STRING_PROPERTY_PREFIX + propertyName);
- }
+ return getJmsContentHeaderProperties().getHeaders().getString(propertyName);
}
public Object getObjectProperty(String propertyName) throws JMSException
{
checkPropertyName(propertyName);
- throw new JmsNotImplementedException();
+ return getJmsContentHeaderProperties().getHeaders().getObject(propertyName);
}
public Enumeration getPropertyNames() throws JMSException
{
- return new FieldTableKeyEnumeration(getJmsContentHeaderProperties().getHeaders())
- {
- public Object nextElement()
- {
- String propName = (String) _iterator.next();
-
- //The propertyName has a single Char prefix. Skip this.
- return propName.substring(1);
- }
- };
+ return getJmsContentHeaderProperties().getHeaders().getPropertyNames();
}
public void setBooleanProperty(String propertyName, boolean b) throws JMSException
{
checkWritableProperties();
checkPropertyName(propertyName);
- //getJmsContentHeaderProperties().headers.put(BOOLEAN_PROPERTY_PREFIX + propertyName, Boolean.valueOf(b));
- getJmsContentHeaderProperties().getHeaders().put(BOOLEAN_PROPERTY_PREFIX + propertyName, b ? new Long(1) : new Long(0));
+ getJmsContentHeaderProperties().getHeaders().setBoolean(propertyName, b);
}
public void setByteProperty(String propertyName, byte b) throws JMSException
{
checkWritableProperties();
checkPropertyName(propertyName);
- getJmsContentHeaderProperties().getHeaders().put(BYTE_PROPERTY_PREFIX + propertyName, new Byte(b));
+ getJmsContentHeaderProperties().getHeaders().setByte(propertyName, new Byte(b));
}
public void setShortProperty(String propertyName, short i) throws JMSException
{
checkWritableProperties();
checkPropertyName(propertyName);
- getJmsContentHeaderProperties().getHeaders().put(SHORT_PROPERTY_PREFIX + propertyName, new Short(i));
+ getJmsContentHeaderProperties().getHeaders().setShort(propertyName, new Short(i));
}
public void setIntProperty(String propertyName, int i) throws JMSException
{
checkWritableProperties();
checkPropertyName(propertyName);
- getJmsContentHeaderProperties().getHeaders().put(INT_PROPERTY_PREFIX + propertyName, new Integer(i));
+ getJmsContentHeaderProperties().getHeaders().setInteger(propertyName, new Integer(i));
}
public void setLongProperty(String propertyName, long l) throws JMSException
{
checkWritableProperties();
checkPropertyName(propertyName);
- getJmsContentHeaderProperties().getHeaders().put(LONG_PROPERTY_PREFIX + propertyName, new Long(l));
+ getJmsContentHeaderProperties().getHeaders().setLong(propertyName, new Long(l));
}
public void setFloatProperty(String propertyName, float f) throws JMSException
{
checkWritableProperties();
checkPropertyName(propertyName);
- getJmsContentHeaderProperties().getHeaders().put(FLOAT_PROPERTY_PREFIX + propertyName, new Float(f));
+ getJmsContentHeaderProperties().getHeaders().setFloat(propertyName, new Float(f));
}
public void setDoubleProperty(String propertyName, double v) throws JMSException
{
checkWritableProperties();
checkPropertyName(propertyName);
- getJmsContentHeaderProperties().getHeaders().put(DOUBLE_PROPERTY_PREFIX + propertyName, new Double(v));
+ getJmsContentHeaderProperties().getHeaders().setDouble(propertyName, new Double(v));
}
public void setStringProperty(String propertyName, String value) throws JMSException
{
checkWritableProperties();
checkPropertyName(propertyName);
- getJmsContentHeaderProperties().getHeaders().put(STRING_PROPERTY_PREFIX + propertyName, value);
- }
-
- private void createPropertyMapIfRequired()
- {
- if (getJmsContentHeaderProperties().getHeaders() == null)
- {
- getJmsContentHeaderProperties().setHeaders(new FieldTable());
- }
+ getJmsContentHeaderProperties().getHeaders().setString(propertyName, value);
}
- public void setObjectProperty(String string, Object object) throws JMSException
+ public void setObjectProperty(String propertyName, Object object) throws JMSException
{
- //todo this should be changed to something else.. the Header doesn't support objects.
- throw new RuntimeException("Not Implemented");
+ checkWritableProperties();
+ checkPropertyName(propertyName);
+ getJmsContentHeaderProperties().getHeaders().setObject(propertyName, object);
}
public void acknowledge() throws JMSException
@@ -586,61 +425,23 @@ public abstract class AbstractJMSMessage extends AMQMessage implements javax.jms
buf.append("\nJMS priority: ").append(getJMSPriority());
buf.append("\nJMS delivery mode: ").append(getJMSDeliveryMode());
buf.append("\nJMS reply to: ").append(String.valueOf(getJMSReplyTo()));
+ buf.append("\nJMS Type: ").append(String.valueOf(getJMSType()));
+ buf.append("\nJMS CorrelationID: ").append(String.valueOf(getJMSCorrelationID()));
+ buf.append("\nJMS Destination: NOT IMPLEMENTED");//.append(String.valueOf(getJMSDestination()));
+ buf.append("\nJMS MessageID: ").append(String.valueOf(getJMSMessageID()));
+ buf.append("\nJMS Redelivered: ").append(String.valueOf(getJMSRedelivered()));
+ buf.append("\nProperty Names: ").append(String.valueOf(getPropertyNames()));
+
buf.append("\nAMQ message number: ").append(_deliveryTag);
+
buf.append("\nProperties:");
- if (getJmsContentHeaderProperties().getHeaders() == null)
+ if (getJmsContentHeaderProperties().getHeaders().isEmpty())
{
buf.append("<NONE>");
}
else
{
- final Iterator it = getJmsContentHeaderProperties().getHeaders().entrySet().iterator();
- while (it.hasNext())
- {
- 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').append(propertyName.substring(1));
-
- char typeIdentifier = propertyName.charAt(0);
- switch (typeIdentifier)
- {
- case org.apache.qpid.client.message.AbstractJMSMessage.BOOLEAN_PROPERTY_PREFIX:
- buf.append("<boolean> ");
- break;
- case org.apache.qpid.client.message.AbstractJMSMessage.BYTE_PROPERTY_PREFIX:
- buf.append("<byte> ");
- break;
- case org.apache.qpid.client.message.AbstractJMSMessage.SHORT_PROPERTY_PREFIX:
- buf.append("<short> ");
- break;
- case org.apache.qpid.client.message.AbstractJMSMessage.INT_PROPERTY_PREFIX:
- buf.append("<int> ");
- break;
- case org.apache.qpid.client.message.AbstractJMSMessage.LONG_PROPERTY_PREFIX:
- buf.append("<long> ");
- break;
- case org.apache.qpid.client.message.AbstractJMSMessage.FLOAT_PROPERTY_PREFIX:
- buf.append("<float> ");
- break;
- case org.apache.qpid.client.message.AbstractJMSMessage.DOUBLE_PROPERTY_PREFIX:
- buf.append("<double> ");
- break;
- case org.apache.qpid.client.message.AbstractJMSMessage.STRING_PROPERTY_PREFIX:
- buf.append("<string> ");
- break;
- default:
- buf.append("<unknown type (identifier " +
- typeIdentifier + ") ");
- }
- buf.append(String.valueOf(entry.getValue()));
- }
- }
+ buf.append('\n').append(getJmsContentHeaderProperties().getHeaders());
}
return buf.toString();
}
@@ -662,7 +463,6 @@ public abstract class AbstractJMSMessage extends AMQMessage implements javax.jms
private void checkPropertyName(String propertyName)
{
-
if (propertyName == null)
{
throw new IllegalArgumentException("Property name must not be null");
@@ -672,38 +472,33 @@ public abstract class AbstractJMSMessage extends AMQMessage implements javax.jms
throw new IllegalArgumentException("Property name must not be the empty string");
}
- createPropertyMapIfRequired();
+ // Call to ensure that the it has been set.
+ getJmsContentHeaderProperties().getHeaders();
}
public FieldTable populateHeadersFromMessageProperties()
{
- if (getJmsContentHeaderProperties().getHeaders() == null)
- {
- return null;
- }
- else
- {
- //
- // We need to convert every property into a String representation
- // Note that type information is preserved in the property name
- //
- final FieldTable table = new FieldTable();
- final Iterator entries = getJmsContentHeaderProperties().getHeaders().entrySet().iterator();
- while (entries.hasNext())
+ //
+ // We need to convert every property into a String representation
+ // Note that type information is preserved in the property name
+ //
+ final FieldTable table = FieldTableFactory.newFieldTable();
+ final Iterator entries = getJmsContentHeaderProperties().getHeaders().entrySet().iterator();
+ while (entries.hasNext())
+ {
+ final Map.Entry entry = (Map.Entry) entries.next();
+ final String propertyName = (String) entry.getKey();
+ if (propertyName == null)
{
- final Map.Entry entry = (Map.Entry) entries.next();
- final String propertyName = (String) entry.getKey();
- if (propertyName == null)
- {
- continue;
- }
- else
- {
- table.put(propertyName, entry.getValue().toString());
- }
+ continue;
+ }
+ else
+ {
+ table.put(propertyName, entry.getValue().toString());
}
- return table;
}
+ return table;
+
}
public BasicContentHeaderProperties getJmsContentHeaderProperties()
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 233f05244f..5282dce4c9 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
@@ -23,10 +23,10 @@ package org.apache.qpid.client.message;
import org.apache.mina.common.ByteBuffer;
import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.framing.PropertyFieldTable;
+import org.apache.qpid.framing.FieldTableFactory;
import org.apache.qpid.AMQException;
import javax.jms.JMSException;
-import javax.jms.MessageFormatException;
import java.util.Enumeration;
public class JMSMapMessage extends JMSTextMessage implements javax.jms.MapMessage
@@ -58,7 +58,7 @@ public class JMSMapMessage extends JMSTextMessage implements javax.jms.MapMessag
try
{
- _map = new PropertyFieldTable(getText());
+ _map = FieldTableFactory.newFieldTable(getText());
}
catch (JMSException e)
{
@@ -74,7 +74,7 @@ public class JMSMapMessage extends JMSTextMessage implements javax.jms.MapMessag
{
_data.release();
}
- _data = null;
+ _data = null;
}
public String toBodyString() throws JMSException
diff --git a/java/client/src/main/java/org/apache/qpid/client/security/amqplain/AmqPlainSaslClient.java b/java/client/src/main/java/org/apache/qpid/client/security/amqplain/AmqPlainSaslClient.java
index 81d3fb76d5..4291cb3259 100644
--- a/java/client/src/main/java/org/apache/qpid/client/security/amqplain/AmqPlainSaslClient.java
+++ b/java/client/src/main/java/org/apache/qpid/client/security/amqplain/AmqPlainSaslClient.java
@@ -21,6 +21,7 @@
package org.apache.qpid.client.security.amqplain;
import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.framing.FieldTableFactory;
import javax.security.sasl.SaslClient;
import javax.security.sasl.SaslException;
@@ -71,7 +72,7 @@ public class AmqPlainSaslClient implements SaslClient
{
throw new SaslException("Error handling SASL callbacks: " + e, e);
}
- FieldTable table = new FieldTable();
+ FieldTable table = FieldTableFactory.newFieldTable();
table.put("LOGIN", nameCallback.getName());
table.put("PASSWORD", pwdCallback.getPassword());
return table.getDataAsBytes();
diff --git a/java/client/src/test/java/org/apache/qpid/framing/FieldTableTest.java b/java/client/src/test/java/org/apache/qpid/framing/FieldTableTest.java
index 49e1630f15..2a7cb8be30 100644
--- a/java/client/src/test/java/org/apache/qpid/framing/FieldTableTest.java
+++ b/java/client/src/test/java/org/apache/qpid/framing/FieldTableTest.java
@@ -33,6 +33,33 @@ import junit.framework.TestCase;
public class FieldTableTest extends TestCase
{
+
+ public void testEncoding()
+ {
+ FieldTable table = FieldTableFactory.newFieldTable();
+
+ String key = "String";
+ String value = "Hello";
+ table.put(key, value);
+
+ //Add one for the type encoding
+ int size = EncodingUtils.encodedShortStringLength(key) + 1 +
+ EncodingUtils.encodedLongStringLength(value);
+
+ assertEquals(table.getEncodedSize(), size);
+
+ key = "Integer";
+ Integer number = new Integer(60);
+ table.put(key, number);
+
+ //Add one for the type encoding
+ size += EncodingUtils.encodedShortStringLength(key) + 1 + 4;
+
+
+ assertEquals(table.getEncodedSize(), size);
+ }
+
+
public void testDataDump() throws IOException, AMQFrameDecodingException
{
byte[] data = readBase64("content.txt");
@@ -46,7 +73,7 @@ public class FieldTableTest extends TestCase
ByteBuffer buffer = ByteBuffer.allocate(data.length);
buffer.put(data);
buffer.flip();
- FieldTable table = new FieldTable(buffer, size);
+ FieldTable table = FieldTableFactory.newFieldTable(buffer, size);
}
/*
@@ -107,7 +134,7 @@ public class FieldTableTest extends TestCase
FieldTable load(String name) throws IOException
{
- return populate(new FieldTable(), read(name));
+ return populate(FieldTableFactory.newFieldTable(), read(name));
}
Properties read(String name) throws IOException
@@ -123,11 +150,12 @@ public class FieldTableTest extends TestCase
{
String key = (String) i.nextElement();
String value = properties.getProperty(key);
- try{
+ try
+ {
int ival = Integer.parseInt(value);
table.put(key, (long) ival);
}
- catch(NumberFormatException e)
+ catch (NumberFormatException e)
{
table.put(key, value);
}
@@ -144,7 +172,8 @@ public class FieldTableTest extends TestCase
{
StringBuffer buffer = new StringBuffer();
String line = in.readLine();
- while (line != null){
+ while (line != null)
+ {
buffer.append(line).append(" ");
line = in.readLine();
}
diff --git a/java/client/src/test/java/org/apache/qpid/headers/MessageFactory.java b/java/client/src/test/java/org/apache/qpid/headers/MessageFactory.java
index f1f310c6e5..6f538d068c 100644
--- a/java/client/src/test/java/org/apache/qpid/headers/MessageFactory.java
+++ b/java/client/src/test/java/org/apache/qpid/headers/MessageFactory.java
@@ -22,6 +22,7 @@ package org.apache.qpid.headers;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.framing.FieldTableFactory;
import javax.jms.BytesMessage;
import javax.jms.Destination;
@@ -127,14 +128,14 @@ class MessageFactory
FieldTable getConsumerBinding()
{
- FieldTable binding = new FieldTable();
+ FieldTable binding = FieldTableFactory.newFieldTable();
binding.put("SF0000", "value");
return binding;
}
FieldTable getControllerBinding()
{
- FieldTable binding = new FieldTable();
+ FieldTable binding = FieldTableFactory.newFieldTable();
binding.put("SCONTROL", "value");
return binding;
}
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableKeyEnumeratorTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableKeyEnumeratorTest.java
index 079def81d0..ad180e3a89 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableKeyEnumeratorTest.java
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTableKeyEnumeratorTest.java
@@ -21,10 +21,13 @@
package org.apache.qpid.test.unit.basic;
import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.framing.FieldTableFactory;
import org.apache.qpid.client.message.JMSTextMessage;
import org.apache.qpid.client.message.TestMessageHelper;
import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
import javax.jms.JMSException;
@@ -34,20 +37,28 @@ public class FieldTableKeyEnumeratorTest extends TestCase
{
public void testKeyEnumeration()
{
- FieldTable result = new FieldTable();
+ FieldTable result = FieldTableFactory.newFieldTable();
result.put("one", 1L);
result.put("two", 2L);
result.put("three", 3L);
result.put("four", 4L);
result.put("five", 5L);
- Enumeration e = result.keys();
+ Iterator iterator = result.keySet().iterator();
+
+ try
+ {
+ assertTrue("one".equals(iterator.next()));
+ assertTrue("two".equals(iterator.next()));
+ assertTrue("three".equals(iterator.next()));
+ assertTrue("four".equals(iterator.next()));
+ assertTrue("five".equals(iterator.next()));
+ }
+ catch (NoSuchElementException e)
+ {
+ fail("All elements should be found.");
+ }
- assertTrue("one".equals(e.nextElement()));
- assertTrue("two".equals(e.nextElement()));
- assertTrue("three".equals(e.nextElement()));
- assertTrue("four".equals(e.nextElement()));
- assertTrue("five".equals(e.nextElement()));
}
public void testPropertEnu()
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 67b7f49565..c1ecef6b57 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,10 +26,12 @@ 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.FieldTable;
import org.apache.qpid.framing.FieldTableTest;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.framing.FieldTableFactory;
import org.apache.qpid.test.VMBrokerSetup;
import org.apache.mina.common.ByteBuffer;
+import org.apache.log4j.Logger;
import java.io.IOException;
import java.util.ArrayList;
@@ -39,6 +41,9 @@ import junit.framework.TestCase;
public class FieldTableMessageTest extends TestCase implements MessageListener
{
+
+ private static final Logger _logger = Logger.getLogger(FieldTableMessageTest.class);
+
private AMQConnection _connection;
private AMQDestination _destination;
private AMQSession _session;
@@ -50,7 +55,7 @@ public class FieldTableMessageTest extends TestCase implements MessageListener
protected void setUp() throws Exception
{
super.setUp();
- init(new AMQConnection(_connectionString, "guest", "guest", randomize("Client"), "/test_path"));
+ init(new AMQConnection(_connectionString, "guest", "guest", randomize("Client"), "/test_path"));
}
protected void tearDown() throws Exception
@@ -80,7 +85,7 @@ public class FieldTableMessageTest extends TestCase implements MessageListener
private FieldTable load() throws IOException
{
- FieldTable result = new FieldTable();
+ FieldTable result = FieldTableFactory.newFieldTable();
result.put("one", 1L);
result.put("two", 2L);
result.put("three", 3L);
@@ -128,7 +133,7 @@ public class FieldTableMessageTest extends TestCase implements MessageListener
for (Object m : received)
{
ByteBuffer buffer = ((JMSBytesMessage) m).getData();
- FieldTable actual = new FieldTable(buffer, buffer.remaining());
+ FieldTable actual = FieldTableFactory.newFieldTable(buffer, buffer.remaining());
new FieldTableTest().assertEquivalent(_expected, actual);
}
}
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTablePropertyTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTablePropertyTest.java
new file mode 100644
index 0000000000..92b4831d93
--- /dev/null
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/basic/FieldTablePropertyTest.java
@@ -0,0 +1,65 @@
+/*
+ *
+ * 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 org.apache.qpid.framing.PropertyFieldTable;
+import org.apache.qpid.framing.FieldTable;
+import org.apache.qpid.client.message.JMSTextMessage;
+import org.apache.qpid.client.message.TestMessageHelper;
+
+import java.util.Enumeration;
+import java.util.NoSuchElementException;
+
+import javax.jms.JMSException;
+
+import junit.framework.TestCase;
+
+public class FieldTablePropertyTest extends TestCase
+{
+ public void testPropertyNames()
+ {
+ try
+ {
+ JMSTextMessage text = TestMessageHelper.newJMSTextMessage();
+
+ text.setBooleanProperty("Boolean1", true);
+ text.setBooleanProperty("Boolean2", true);
+ text.setIntProperty("Int", 2);
+ text.setLongProperty("Long", 2);
+
+ Enumeration e = text.getPropertyNames();
+
+ assertEquals("Boolean1", e.nextElement());
+ assertTrue("Boolean2".equals(e.nextElement()));
+ assertTrue("Int".equals(e.nextElement()));
+ assertTrue("Long".equals(e.nextElement()));
+ }
+ catch (JMSException e)
+ {
+
+ }
+ }
+
+ public static junit.framework.Test suite()
+ {
+ return new junit.framework.TestSuite(FieldTablePropertyTest.class);
+ }
+}
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 a685e75a29..5353a19d13 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
@@ -47,6 +47,7 @@ public class MapMessageTest extends TestCase implements MessageListener
private final List<String> messages = new ArrayList<String>();
private int _count = 100;
public String _connectionString = "vm://:1";
+ private byte[] _bytes = {99, 98, 97, 96, 95};
protected void setUp() throws Exception
{
@@ -104,9 +105,31 @@ public class MapMessageTest extends TestCase implements MessageListener
MapMessage message = _session.createMapMessage();
message.setBoolean("odd", i / 2 == 0);
+ message.setByte("byte", (byte) Byte.MAX_VALUE);
+
+ message.setBytes("bytes", _bytes);
+ message.setChar("char", (char) 'c');
+ message.setDouble("double", (double) Double.MAX_VALUE);
+ message.setFloat("float", (float) Float.MAX_VALUE);
+
message.setInt("messageNumber", i);
+ message.setInt("int", (int) Integer.MAX_VALUE);
+
+ message.setLong("long", (long) Long.MAX_VALUE);
+ message.setShort("short", (short) Short.MAX_VALUE);
message.setString("message", text);
+
+ message.setObject("object-bool", true);
+ message.setObject("object-byte", Byte.MAX_VALUE);
+ message.setObject("object-bytes", _bytes);
+ message.setObject("object-char", 'c');
+ message.setObject("object-double", Double.MAX_VALUE);
+ message.setObject("object-float", Float.MAX_VALUE);
+ message.setObject("object-int", Integer.MAX_VALUE);
+ message.setObject("object-long", Long.MAX_VALUE);
+ message.setObject("object-short", Short.MAX_VALUE);
+
producer.send(message);
}
}
@@ -130,7 +153,31 @@ public class MapMessageTest extends TestCase implements MessageListener
{
actual.add(m.getString("message"));
assertEqual(m.getInt("messageNumber"), count);
- assertEqual(m.getBoolean("odd"), count / 2 == 0);
+
+
+ assertEqual(count / 2 == 0, m.getBoolean("odd"));
+ assertEqual((byte) Byte.MAX_VALUE, m.getByte("byte"));
+
+ assertBytesEqual(_bytes, m.getBytes("bytes"));
+ assertEqual((char) 'c', m.getChar("char"));
+ assertEqual((double) Double.MAX_VALUE, m.getDouble("double"));
+ assertEqual((float) Float.MAX_VALUE, m.getFloat("float"));
+
+ assertEqual(count, m.getInt("messageNumber"));
+ assertEqual((int) Integer.MAX_VALUE, m.getInt("int"));
+ assertEqual((long) Long.MAX_VALUE, m.getLong("long"));
+ assertEqual((short) Short.MAX_VALUE, m.getShort("short"));
+
+ assertEqual(true, m.getObject("object-bool"));
+ assertEqual(Byte.MAX_VALUE, m.getObject("object-byte"));
+ assertBytesEqual(_bytes, (byte[]) m.getObject("object-bytes"));
+ assertEqual('c', m.getObject("object-char"));
+ assertEqual(Double.MAX_VALUE, m.getObject("object-double"));
+ assertEqual(Float.MAX_VALUE, m.getObject("object-float"));
+ assertEqual(Integer.MAX_VALUE, m.getObject("object-int"));
+ assertEqual(Long.MAX_VALUE, m.getObject("object-long"));
+ assertEqual(Short.MAX_VALUE, m.getObject("object-short"));
+
try
{
@@ -153,7 +200,7 @@ public class MapMessageTest extends TestCase implements MessageListener
Assert.fail("Message should be writeable");
}
- //Check property write status
+ //Check property write status
try
{
m.setStringProperty("test", "test");
@@ -181,6 +228,17 @@ public class MapMessageTest extends TestCase implements MessageListener
assertEqual(messages.iterator(), actual.iterator());
}
+ private void assertBytesEqual(byte[] expected, byte[] actual)
+ {
+ Assert.assertEquals(expected.length, actual.length);
+
+ for (int index = 0; index < expected.length; index++)
+ {
+ Assert.assertEquals(expected[index], actual[index]);
+ }
+ }
+
+
private static void assertEqual(Iterator expected, Iterator actual)
{
List<String> errors = new ArrayList<String>();
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/PropertyValueTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/basic/PropertyValueTest.java
new file mode 100644
index 0000000000..02f371e81b
--- /dev/null
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/basic/PropertyValueTest.java
@@ -0,0 +1,264 @@
+/*
+ *
+ * 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.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.JMSTextMessage;
+import org.apache.qpid.test.VMBrokerSetup;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageListener;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+public class PropertyValueTest extends TestCase implements MessageListener
+{
+
+ private static final Logger _logger = Logger.getLogger(PropertyValueTest.class);
+
+ private int count = 0;
+ private AMQConnection _connection;
+ private Destination _destination;
+ private AMQSession _session;
+ private final List<JMSTextMessage> received = new ArrayList<JMSTextMessage>();
+ private final List<String> messages = new ArrayList<String>();
+ private int _count = 100;
+ public String _connectionString = "vm://:1";
+
+ protected void setUp() throws Exception
+ {
+ super.setUp();
+ try
+ {
+ init(new AMQConnection(_connectionString, "guest", "guest", randomize("Client"), "/test_path"));
+ }
+ catch (Exception e)
+ {
+ fail("Unable to initialilse connection: " + e);
+ }
+ }
+
+ protected void tearDown() throws Exception
+ {
+ super.tearDown();
+ }
+
+ private void init(AMQConnection connection) throws Exception
+ {
+ Destination destination = new AMQQueue(randomize("PropertyValueTest"), true);
+ init(connection, destination);
+ }
+
+ private void init(AMQConnection connection, Destination destination) throws Exception
+ {
+ _connection = connection;
+ _destination = destination;
+ _session = (AMQSession) connection.createSession(false, AMQSession.AUTO_ACKNOWLEDGE);
+
+ //set up a slow consumer
+ _session.createConsumer(destination).setMessageListener(this);
+ connection.start();
+ }
+
+ public void test() throws Exception
+ {
+ int count = _count;
+ send(count);
+ waitFor(count);
+ check();
+ System.out.println("Completed without failure");
+ _connection.close();
+ }
+
+ void send(int count) throws JMSException
+ {
+ //create a publisher
+ MessageProducer producer = _session.createProducer(_destination);
+ for (int i = 0; i < count; i++)
+ {
+ String text = "Message " + i;
+ messages.add(text);
+ Message m = _session.createTextMessage(text);
+
+ m.setBooleanProperty("Bool", true);
+
+ m.setByteProperty("Byte", (byte) Byte.MAX_VALUE);
+ m.setDoubleProperty("Double", (double) Double.MAX_VALUE);
+ m.setFloatProperty("Float", (float) Float.MAX_VALUE);
+ m.setIntProperty("Int", (int) Integer.MAX_VALUE);
+
+ m.setJMSCorrelationID("Correlation");
+ m.setJMSPriority(100);
+
+ // Queue
+ Queue q = //_session.createTemporaryQueue();
+ q = new AMQQueue("TestReply");
+ m.setJMSReplyTo(q);
+ m.setStringProperty("TempQueue", q.toString());
+
+ _logger.info("Message:" + m);
+
+ Assert.assertEquals("Check temp queue has been set correctly",
+ m.getJMSReplyTo().toString(), m.getStringProperty("TempQueue"));
+
+ m.setJMSType("Test");
+ m.setLongProperty("UnsignedInt", (long) 4294967295L);
+ m.setLongProperty("Long", (long) Long.MAX_VALUE);
+
+ m.setShortProperty("Short", (short) Short.MAX_VALUE);
+ m.setStringProperty("String", "Test");
+
+ _logger.info("Sending Msg:" + m);
+ producer.send(m);
+ }
+ }
+
+ void waitFor(int count) throws InterruptedException
+ {
+ synchronized(received)
+ {
+ while (received.size() < count)
+ {
+ received.wait();
+ }
+ }
+ }
+
+ void check() throws JMSException
+ {
+ List<String> actual = new ArrayList<String>();
+ for (JMSTextMessage m : received)
+ {
+ actual.add(m.getText());
+
+ //Check Properties
+
+ Assert.assertEquals("Check Boolean properties are correctly transported",
+ true, m.getBooleanProperty("Bool"));
+ Assert.assertEquals("Check Byte properties are correctly transported",
+ (byte) Byte.MAX_VALUE, m.getByteProperty("Byte"));
+ Assert.assertEquals("Check Double properties are correctly transported",
+ (double) Double.MAX_VALUE, m.getDoubleProperty("Double"));
+ Assert.assertEquals("Check Float properties are correctly transported",
+ (float) Float.MAX_VALUE, m.getFloatProperty("Float"));
+ Assert.assertEquals("Check Int properties are correctly transported",
+ (int) Integer.MAX_VALUE, m.getIntProperty("Int"));
+ Assert.assertEquals("Check CorrelationID properties are correctly transported",
+ "Correlation", m.getJMSCorrelationID());
+// Assert.assertEquals("Check Priority properties are correctly transported",
+// 100, m.getJMSPriority());
+
+ // Queue
+ Assert.assertEquals("Check ReplyTo properties are correctly transported",
+ m.getStringProperty("TempQueue"), m.getJMSReplyTo().toString());
+
+// Assert.assertEquals("Check Type properties are correctly transported",
+// "Test", m.getJMSType());
+ Assert.assertEquals("Check Short properties are correctly transported",
+ (short) Short.MAX_VALUE, m.getShortProperty("Short"));
+ Assert.assertEquals("Check UnsignedInt properties are correctly transported",
+ (long) 4294967295L, m.getLongProperty("UnsignedInt"));
+ Assert.assertEquals("Check Long properties are correctly transported",
+ (long) Long.MAX_VALUE, m.getLongProperty("Long"));
+ Assert.assertEquals("Check String properties are correctly transported",
+ "Test", m.getStringProperty("String"));
+ }
+
+ assertEqual(messages.iterator(), actual.iterator());
+ }
+
+ private static void assertEqual(Iterator expected, Iterator actual)
+ {
+ List<String> errors = new ArrayList<String>();
+ while (expected.hasNext() && actual.hasNext())
+ {
+ try
+ {
+ assertEqual(expected.next(), actual.next());
+ }
+ catch (Exception e)
+ {
+ errors.add(e.getMessage());
+ }
+ }
+ while (expected.hasNext())
+ {
+ errors.add("Expected " + expected.next() + " but no more actual values.");
+ }
+ while (actual.hasNext())
+ {
+ errors.add("Found " + actual.next() + " but no more expected values.");
+ }
+ if (!errors.isEmpty())
+ {
+ throw new RuntimeException(errors.toString());
+ }
+ }
+
+ private static void assertEqual(Object expected, Object actual)
+ {
+ if (!expected.equals(actual))
+ {
+ throw new RuntimeException("Expected '" + expected + "' found '" + actual + "'");
+ }
+ }
+
+ public void onMessage(Message message)
+ {
+ synchronized(received)
+ {
+ received.add((JMSTextMessage) message);
+ received.notify();
+ }
+ }
+
+ private static String randomize(String in)
+ {
+ return in + System.currentTimeMillis();
+ }
+
+ public static void main(String[] argv) throws Exception
+ {
+ PropertyValueTest test = new PropertyValueTest();
+ test._connectionString = argv.length == 0 ? "vm://:1" : argv[0];
+ test.setUp();
+ if (argv.length > 1)
+ {
+ test._count = Integer.parseInt(argv[1]);
+ }
+ test.test();
+ }
+
+ public static junit.framework.Test suite()
+ {
+ return new VMBrokerSetup(new junit.framework.TestSuite(PropertyValueTest.class));
+ }
+}
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/basic/SessionStartTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/basic/SessionStartTest.java
index 6fa8ab95bf..387238cbf1 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/basic/SessionStartTest.java
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/basic/SessionStartTest.java
@@ -24,8 +24,6 @@ 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.transport.TransportConnection;
-import org.apache.qpid.client.vmbroker.AMQVMBrokerCreationException;
import org.apache.qpid.test.VMBrokerSetup;
import javax.jms.JMSException;
@@ -104,7 +102,7 @@ public class SessionStartTest extends TestCase implements MessageListener
public static void main(String[] argv) throws Exception
{
- SessionStartTest test = new SessionStartTest();
+ SelectorTest test = new SelectorTest();
test._connectionString = argv.length == 0 ? "localhost:5672" : argv[0];
test.setUp();
test.test();
@@ -112,6 +110,6 @@ public class SessionStartTest extends TestCase implements MessageListener
public static junit.framework.Test suite()
{
- return new VMBrokerSetup(new junit.framework.TestSuite(SessionStartTest.class));
+ return new VMBrokerSetup(new junit.framework.TestSuite(SelectorTest.class));
}
}
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 dfbec81549..d46463dbb2 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,13 +21,11 @@
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.test.VMBrokerSetup;
+import org.apache.log4j.Logger;
import java.util.ArrayList;
import java.util.Iterator;
@@ -39,6 +37,8 @@ import junit.framework.Assert;
public class TextMessageTest extends TestCase implements MessageListener
{
+ private static final Logger _logger = Logger.getLogger(TextMessageTest.class);
+
private AMQConnection _connection;
private Destination _destination;
private AMQSession _session;
@@ -100,7 +100,11 @@ public class TextMessageTest extends TestCase implements MessageListener
{
String text = "Message " + i;
messages.add(text);
- producer.send(_session.createTextMessage(text));
+ Message m = _session.createTextMessage(text);
+ m.setStringProperty("String", "hello");
+
+ _logger.info("Sending Msg:" + m);
+ producer.send(m);
}
}
diff --git a/java/client/src/test/java/org/apache/qpid/test/unit/client/AMQSessionTest.java b/java/client/src/test/java/org/apache/qpid/test/unit/client/AMQSessionTest.java
index af4673856e..bdfe7d4df0 100644
--- a/java/client/src/test/java/org/apache/qpid/test/unit/client/AMQSessionTest.java
+++ b/java/client/src/test/java/org/apache/qpid/test/unit/client/AMQSessionTest.java
@@ -50,6 +50,7 @@ public class AMQSessionTest extends TestCase
protected void setUp() throws Exception
{
super.setUp();
+ TransportConnection.createVMBroker(1);
_connection = new AMQConnection("vm://:1", "guest", "guest", "fred", "/test");
_topic = new AMQTopic("mytopic");
_queue = new AMQQueue("myqueue");
diff --git a/java/client/src/test/java/org/apache/qpid/topic/Listener.java b/java/client/src/test/java/org/apache/qpid/topic/Listener.java
index 47c608cfe4..d6d2be7298 100644
--- a/java/client/src/test/java/org/apache/qpid/topic/Listener.java
+++ b/java/client/src/test/java/org/apache/qpid/topic/Listener.java
@@ -45,10 +45,10 @@ public class Listener implements MessageListener
{
_connection = connection;
_session = connection.createSession(false, ackMode);
- _factory = new MessageFactory(_session);
+ _factory = new MessageFactory(_session, "topictest.messages.#", 256);
//register for events
- if(name == null)
+ if (name == null)
{
_factory.createTopicConsumer().setMessageListener(this);
}
@@ -61,9 +61,10 @@ public class Listener implements MessageListener
_controller = _factory.createControlPublisher();
System.out.println("Waiting for messages " +
- Config.getAckModeDescription(ackMode)
- + (name == null ? "" : " (subscribed with name " + name + " and client id " + connection.getClientID() + ")")
- + "...");
+ Config.getAckModeDescription(ackMode)
+ + (name == null ? "" : " (subscribed with name " + name + " and client id " + connection.getClientID() + ")")
+ + " with Messages on Topic: " + _factory.getTopic()
+ + "...");
}
@@ -75,7 +76,7 @@ public class Listener implements MessageListener
_connection.stop();
_connection.close();
}
- catch(Exception e)
+ catch (Exception e)
{
e.printStackTrace(System.out);
}
@@ -89,7 +90,7 @@ public class Listener implements MessageListener
_controller.send(_factory.createReportResponseMessage(msg));
System.out.println("Sent report: " + msg);
}
- catch(Exception e)
+ catch (Exception e)
{
e.printStackTrace(System.out);
}
@@ -103,18 +104,18 @@ public class Listener implements MessageListener
public void onMessage(Message message)
{
- if(!init)
+ if (!init)
{
start = System.currentTimeMillis();
count = 0;
init = true;
}
- if(_factory.isShutdown(message))
+ if (_factory.isShutdown(message))
{
shutdown();
}
- else if(_factory.isReport(message))
+ else if (_factory.isReport(message))
{
//send a report:
report();
@@ -132,7 +133,7 @@ public class Listener implements MessageListener
config.setOptions(argv);
Connection con = config.createConnection();
- if(config.getClientId() != null)
+ if (config.getClientId() != null)
{
con.setClientID(config.getClientId());
}
diff --git a/java/client/src/test/java/org/apache/qpid/topic/MessageFactory.java b/java/client/src/test/java/org/apache/qpid/topic/MessageFactory.java
index 1520f18408..7b5b451424 100644
--- a/java/client/src/test/java/org/apache/qpid/topic/MessageFactory.java
+++ b/java/client/src/test/java/org/apache/qpid/topic/MessageFactory.java
@@ -23,6 +23,7 @@ package org.apache.qpid.topic;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.AMQTopic;
+
import javax.jms.*;
/**
@@ -42,22 +43,28 @@ class MessageFactory
this(session, 256);
}
- MessageFactory(Session session, int size) throws JMSException
+ public MessageFactory(Session session, int size) throws JMSException
+ {
+ this(session, "topictest.messages", size);
+ }
+
+
+ MessageFactory(Session session, String topicMessages, int size) throws JMSException
{
_session = session;
- if(session instanceof AMQSession)
+ if (session instanceof AMQSession)
{
- _topic = new AMQTopic("topictest.messages");
+ _topic = new AMQTopic(topicMessages);
_control = new AMQTopic("topictest.control");
}
else
{
- _topic = session.createTopic("topictest.messages");
+ _topic = session.createTopic(topicMessages);
_control = session.createTopic("topictest.control");
}
_payload = new byte[size];
- for(int i = 0; i < size; i++)
+ for (int i = 0; i < size; i++)
{
_payload[i] = (byte) DATA[i % DATA.length];
}
diff --git a/java/client/src/test/java/org/apache/qpid/topic/Publisher.java b/java/client/src/test/java/org/apache/qpid/topic/Publisher.java
index d788029ee9..6899215a09 100644
--- a/java/client/src/test/java/org/apache/qpid/topic/Publisher.java
+++ b/java/client/src/test/java/org/apache/qpid/topic/Publisher.java
@@ -51,7 +51,7 @@ public class Publisher implements MessageListener
_factory.createControlConsumer().setMessageListener(this);
_connection.start();
- if(warmup > 0)
+ if (warmup > 0)
{
System.out.println("Runing warmup (" + warmup + " msgs)");
long time = batch(warmup, consumerCount);
@@ -59,11 +59,14 @@ public class Publisher implements MessageListener
}
long[] times = new long[batches];
- for(int i = 0; i < batches; i++)
+ for (int i = 0; i < batches; i++)
{
- if(i > 0) Thread.sleep(delay*1000);
+ if (i > 0)
+ {
+ Thread.sleep(delay * 1000);
+ }
times[i] = batch(msgCount, consumerCount);
- System.out.println("Batch " + (i+1) + " of " + batches + " completed in " + times[i] + " ms.");
+ System.out.println("Batch " + (i + 1) + " of " + batches + " completed in " + times[i] + " ms.");
}
long min = min(times);
@@ -106,7 +109,7 @@ public class Publisher implements MessageListener
private void waitForCompletion(int consumers) throws Exception
{
System.out.println("Waiting for completion...");
- synchronized (_lock)
+ synchronized(_lock)
{
while (_count > 0)
{
@@ -121,7 +124,7 @@ public class Publisher implements MessageListener
System.out.println("Received report " + _factory.getReport(message) + " " + --_count + " remaining");
if (_count == 0)
{
- synchronized (_lock)
+ synchronized(_lock)
{
_lock.notify();
}
@@ -131,7 +134,7 @@ public class Publisher implements MessageListener
static long min(long[] times)
{
long min = times.length > 0 ? times[0] : 0;
- for(int i = 0; i < times.length; i++)
+ for (int i = 0; i < times.length; i++)
{
min = Math.min(min, times[i]);
}
@@ -141,7 +144,7 @@ public class Publisher implements MessageListener
static long max(long[] times)
{
long max = times.length > 0 ? times[0] : 0;
- for(int i = 0; i < times.length; i++)
+ for (int i = 0; i < times.length; i++)
{
max = Math.max(max, times[i]);
}
@@ -151,14 +154,25 @@ public class Publisher implements MessageListener
static long avg(long[] times, long min, long max)
{
long sum = 0;
- for(int i = 0; i < times.length; i++)
+ for (int i = 0; i < times.length; i++)
{
sum += times[i];
}
- sum -= min;
- sum -= max;
- return (sum / (times.length - 2));
+ int divisor = times.length;
+ //remove max and min from averages
+ if (times.length > 2)
+ {
+ sum -= min;
+ sum -= max;
+ divisor -= 2;
+ }
+ else
+ {
+ System.out.println("More batches are required to generate a meaninful average.");
+ }
+
+ return (sum / divisor);
}
public static void main(String[] argv) throws Exception
diff --git a/java/cluster/src/main/java/org/apache/qpid/server/queue/RemoteSubscriptionImpl.java b/java/cluster/src/main/java/org/apache/qpid/server/queue/RemoteSubscriptionImpl.java
index 0268ff2171..1394e7e20b 100644
--- a/java/cluster/src/main/java/org/apache/qpid/server/queue/RemoteSubscriptionImpl.java
+++ b/java/cluster/src/main/java/org/apache/qpid/server/queue/RemoteSubscriptionImpl.java
@@ -88,9 +88,19 @@ class RemoteSubscriptionImpl implements Subscription, WeightedSubscriptionManage
public void queueDeleted(AMQQueue queue)
{
- if(queue instanceof ClusteredQueue)
+ if (queue instanceof ClusteredQueue)
{
((ClusteredQueue) queue).removeAllRemoteSubscriber(_peer);
}
}
+
+ public boolean hasFilters()
+ {
+ return false;
+ }
+
+ public boolean hasInterest(AMQMessage msg)
+ {
+ return true;
+ }
}
diff --git a/java/common/pom.xml b/java/common/pom.xml
index e655054453..0d48a24646 100644
--- a/java/common/pom.xml
+++ b/java/common/pom.xml
@@ -46,7 +46,7 @@
</properties>
<build>
- <plugins>
+ <plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
@@ -77,6 +77,19 @@
</plugins>
</build>
+ <repositories>
+ <repository>
+ <snapshots>
+ <enabled>true</enabled>
+ </snapshots>
+ <id>java.net repository</id>
+ <name>Maven 1.x Repository</name>
+ <url>httsp://maven-repository.dev.java.net/nonav/repository/</url>
+ <layout>legacy</layout>
+ </repository>
+
+
+ </repositories>
<dependencies>
<dependency>
<groupId>log4j</groupId>
@@ -86,7 +99,16 @@
<groupId>org.apache.mina</groupId>
<artifactId>mina-core</artifactId>
</dependency>
+ <!-- dependency>
+ <groupId>grizzly</groupId>
+ <artifactId>grizzly</artifactId>
+ <version>1.0.4</version>
+ </dependency -->
<dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-jms_1.1_spec</artifactId>
+ </dependency>
+ <dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
</dependency>
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 3c7e656053..a908c76286 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
@@ -241,7 +241,7 @@ public class BasicContentHeaderProperties implements ContentHeaderProperties
}
}
}
-
+
public void populatePropertiesFromBuffer(ByteBuffer buffer, int propertyFlags, int size)
throws AMQFrameDecodingException
{
@@ -402,6 +402,7 @@ public class BasicContentHeaderProperties implements ContentHeaderProperties
decodeUpToContentType();
}
}
+
public String getContentType()
{
decodeContentTypeIfNecessary();
@@ -431,6 +432,12 @@ public class BasicContentHeaderProperties implements ContentHeaderProperties
public FieldTable getHeaders()
{
decodeHeadersIfNecessary();
+
+ if (_headers == null)
+ {
+ setHeaders(FieldTableFactory.newFieldTable());
+ }
+
return _headers;
}
@@ -587,6 +594,6 @@ public class BasicContentHeaderProperties implements ContentHeaderProperties
public String toString()
{
- return "reply-to = " + _replyTo + " propertyFlags = " + _propertyFlags;
+ return "reply-to = " + _replyTo + " propertyFlags = " + _propertyFlags;
}
}
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 3a683b8e90..97fb434e1c 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
@@ -286,7 +286,7 @@ public class EncodingUtils
}
else
{
- return new FieldTable(buffer, length);
+ return FieldTableFactory.newFieldTable(buffer, length);
}
}
@@ -330,9 +330,9 @@ public class EncodingUtils
// than constructing one from a char array.
// this approach here is valid since we know that all the chars are
// ASCII (0-127)
- byte[] stringBytes = new byte[(int)length];
- buffer.get(stringBytes, 0, (int)length);
- char[] stringChars = new char[(int)length];
+ byte[] stringBytes = new byte[(int) length];
+ buffer.get(stringBytes, 0, (int) length);
+ char[] stringChars = new char[(int) length];
for (int i = 0; i < stringChars.length; i++)
{
stringChars[i] = (char) stringBytes[i];
@@ -350,7 +350,7 @@ public class EncodingUtils
}
else
{
- byte[] result = new byte[(int)length];
+ byte[] result = new byte[(int) length];
buffer.get(result);
return result;
}
@@ -388,7 +388,7 @@ public class EncodingUtils
// TODO: Doesn't support embedded quotes properly.
String[] expressions = selector.split(" +");
- FieldTable result = new FieldTable();
+ FieldTable result = FieldTableFactory.newFieldTable();
for (int i = 0; i < expressions.length; i++)
{
@@ -481,7 +481,7 @@ public class EncodingUtils
public static char[] convertToHexCharArray(byte[] from)
{
int length = from.length;
- char[] result_buff = new char[length * 2 + 2];
+ char[] result_buff = new char[length * 2 + 2];
result_buff[0] = '0';
result_buff[1] = 'x';
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 be456c8754..44d0268561 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
@@ -1,322 +1,96 @@
/*
+ * 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
*
- * 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.
+ * 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.log4j.Logger;
import org.apache.mina.common.ByteBuffer;
-import java.util.*;
-
-/**
- * From the protocol document:
- * field-table = short-integer *field-value-pair
- * field-value-pair = field-name field-value
- * field-name = short-string
- * field-value = 'S' long-string
- * / 'I' long-integer
- * / 'D' decimal-value
- * / 'T' long-integer
- * decimal-value = decimals long-integer
- * decimals = OCTET
- */
-public class FieldTable extends LinkedHashMap
+import java.util.Map;
+import java.util.Enumeration;
+
+public interface FieldTable extends Map
{
- private static final Logger _logger = Logger.getLogger(FieldTable.class);
- private long _encodedSize = 0;
-
- public FieldTable()
- {
- super();
- }
-
- /**
- * Construct a new field table.
- *
- * @param buffer the buffer from which to read data. The length byte must be read already
- * @param length the length of the field table. Must be > 0.
- * @throws AMQFrameDecodingException if there is an error decoding the table
- */
- public FieldTable(ByteBuffer buffer, long length) throws AMQFrameDecodingException
- {
- super();
- final boolean debug = _logger.isDebugEnabled();
- assert length > 0;
- _encodedSize = length;
- int sizeRead = 0;
- while (sizeRead < _encodedSize)
- {
- 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;
- switch (type)
- {
- case 'S':
- value = EncodingUtils.readLongString(buffer);
- break;
- case 'I':
- value = new Long(buffer.getUnsignedInt());
- break;
- default:
- String msg = "Field '" + key + "' - unsupported field table type: " + type;
- //some extra debug information...
- msg += " (" + iType + "), length=" + length + ", sizeRead=" + sizeRead + ", sizeRemaining=" + sizeRemaining;
- throw new AMQFrameDecodingException(msg);
- }
- sizeRead += (sizeRemaining - buffer.remaining());
-
- if (debug)
- {
- _logger.debug("FieldTable::FieldTable(buffer," + length + "): Read type '" + type + "', key '" + key + "', value '" + value + "' (now read " + sizeRead + " of " + length + " encoded bytes)...");
- }
-
- // we deliberately want to call put in the parent class since we do
- // not need to do the size calculations
- super.put(key, value);
- }
-
- if (debug)
- {
- _logger.debug("FieldTable::FieldTable(buffer," + length + "): Done.");
- }
- }
-
- public void writeToBuffer(ByteBuffer buffer)
- {
- final boolean debug = _logger.isDebugEnabled();
-
- if (debug)
- {
- _logger.debug("FieldTable::writeToBuffer: Writing encoded size of " + _encodedSize + "...");
- }
-
- // write out the total length, which we have kept up to date as data is added
- EncodingUtils.writeUnsignedInteger(buffer, _encodedSize);
- final Iterator it = this.entrySet().iterator();
- while (it.hasNext())
- {
- Map.Entry me = (Map.Entry) it.next();
- String key = (String) me.getKey();
-
- EncodingUtils.writeShortStringBytes(buffer, key);
- Object value = me.getValue();
-
- if (debug)
- {
- _logger.debug("FieldTable::writeToBuffer: Writing key '" + key + "' of type " + value.getClass() + ", value '" + value + "'...");
- }
-
- if (value instanceof byte[])
- {
- buffer.put((byte) 'S');
- EncodingUtils.writeLongstr(buffer, (byte[]) value);
- }
- else if (value instanceof String)
- {
- // TODO: look at using proper charset encoder
- buffer.put((byte) 'S');
- EncodingUtils.writeLongStringBytes(buffer, (String) value);
- }
- else if (value instanceof Long)
- {
- // TODO: look at using proper charset encoder
- buffer.put((byte) 'I');
- EncodingUtils.writeUnsignedInteger(buffer, ((Long) value).longValue());
- }
- else
- {
- // Should never get here
- throw new IllegalArgumentException("Key '" + key + "': Unsupported type in field table, type: " + ((value == null) ? "null-object" : value.getClass()));
- }
- }
-
- if (debug)
- {
- _logger.debug("FieldTable::writeToBuffer: Done.");
- }
- }
-
- public byte[] getDataAsBytes()
- {
- final ByteBuffer buffer = ByteBuffer.allocate((int) _encodedSize); // XXX: Is cast a problem?
- final Iterator it = this.entrySet().iterator();
- while (it.hasNext())
- {
- Map.Entry me = (Map.Entry) it.next();
- String key = (String) me.getKey();
- EncodingUtils.writeShortStringBytes(buffer, key);
- Object value = me.getValue();
- if (value instanceof byte[])
- {
- buffer.put((byte) 'S');
- EncodingUtils.writeLongstr(buffer, (byte[]) value);
- }
- else if (value instanceof String)
- {
- // TODO: look at using proper charset encoder
- buffer.put((byte) 'S');
- EncodingUtils.writeLongStringBytes(buffer, (String) value);
- }
- else if (value instanceof char[])
- {
- // TODO: look at using proper charset encoder
- buffer.put((byte) 'S');
- EncodingUtils.writeLongStringBytes(buffer, (char[]) value);
- }
- else if (value instanceof Long || value instanceof Integer)
- {
- // TODO: look at using proper charset encoder
- buffer.put((byte) 'I');
- EncodingUtils.writeUnsignedInteger(buffer, ((Long) value).longValue());
- }
- else
- {
- // Should never get here
- assert false;
- }
- }
- final byte[] result = new byte[(int) _encodedSize];
- buffer.flip();
- buffer.get(result);
- buffer.release();
- return result;
- }
-
- public Object put(Object key, Object value)
- {
- final boolean debug = _logger.isDebugEnabled();
-
- if (key == null)
- {
- throw new IllegalArgumentException("All keys must be Strings - was passed: null");
- }
- else if (!(key instanceof String))
- {
- throw new IllegalArgumentException("All keys must be Strings - was passed: " + key.getClass());
- }
-
- Object existing;
-
- if ((existing = super.remove(key)) != null)
- {
- if (debug)
- {
- _logger.debug("Found duplicate of key '" + key + "', previous value '" + existing + "' (" + existing.getClass() + "), to be replaced by '" + value + "', (" + value.getClass() + ") - stack trace of source of duplicate follows...", new Throwable().fillInStackTrace());
- }
-
- // 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 (value == null)
- {
- _encodedSize -= EncodingUtils.encodedShortStringLength((String) key);
- }
-
- // 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(existing);
- }
- else
- {
- if (value != null)
- {
- _encodedSize += EncodingUtils.encodedShortStringLength((String) key);
- }
- }
-
- // 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.
- if (value != null)
- {
- _encodedSize += getEncodingSize(value);
- }
-
- return super.put(key, value);
- }
-
- public Object remove(Object key)
- {
- if (super.containsKey(key))
- {
- final Object value = super.remove(key);
- _encodedSize -= EncodingUtils.encodedShortStringLength((String) key);
-
- // This check is, for now, unnecessary (we don't store null values).
- if (value != null)
- {
- _encodedSize -= getEncodingSize(value);
- }
-
- return value;
- }
- else
- {
- return null;
- }
- }
-
- /**
- * @return unsigned integer
- */
- public long getEncodedSize()
- {
- return _encodedSize;
- }
-
- /**
- * @return integer
- */
- private static int getEncodingSize(Object value)
- {
- int encodingSize;
-
- // the extra byte if for the type indicator that is written out
- if (value instanceof String)
- {
- encodingSize = 1 + EncodingUtils.encodedLongStringLength((String) value);
- }
- else if (value instanceof char[])
- {
- encodingSize = 1 + EncodingUtils.encodedLongStringLength((char[]) value);
- }
- else if (value instanceof Integer)
- {
- encodingSize = 1 + 4;
- }
- else if (value instanceof Long)
- {
- encodingSize = 1 + 4;
- }
- else
- {
- throw new IllegalArgumentException("Unsupported type in field table: " + value.getClass());
- }
-
- return encodingSize;
- }
-
- public Enumeration keys()
- {
- return new FieldTableKeyEnumeration(this);
- }
+ void writeToBuffer(ByteBuffer buffer);
+
+ void setFromBuffer(ByteBuffer buffer, long length) throws AMQFrameDecodingException;
+
+ byte[] getDataAsBytes();
+
+ public long getEncodedSize();
+
+ Object put(Object key, Object value);
+
+ Object remove(Object key);
+
+
+ public Enumeration getPropertyNames();
+
+ public boolean propertyExists(String propertyName);
+
+ //Getters
+
+ public Boolean getBoolean(String string);
+
+ public Byte getByte(String string);
+
+ public Short getShort(String string);
+
+ public Integer getInteger(String string);
+
+ public Long getLong(String string);
+
+ public Float getFloat(String string);
+
+ public Double getDouble(String string);
+
+ public String getString(String string);
+
+ public Character getCharacter(String string);
+
+ public byte[] getBytes(String string);
+
+ public Object getObject(String string);
+
+ // Setters
+ public Object setBoolean(String string, boolean b);
+
+ public Object setByte(String string, byte b);
+
+ public Object setShort(String string, short i);
+
+ public Object setInteger(String string, int i);
+
+ public Object setLong(String string, long l);
+
+ public Object setFloat(String string, float v);
+
+ public Object setDouble(String string, double v);
+
+ public Object setString(String string, String string1);
+
+ public Object setChar(String string, char c);
+
+ public Object setBytes(String string, byte[] bytes);
+
+ public Object setBytes(String string, byte[] bytes, int start, int length);
+
+ public Object setObject(String string, Object object);
+
}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/FieldTableFactory.java b/java/common/src/main/java/org/apache/qpid/framing/FieldTableFactory.java
new file mode 100644
index 0000000000..1ec57da35b
--- /dev/null
+++ b/java/common/src/main/java/org/apache/qpid/framing/FieldTableFactory.java
@@ -0,0 +1,41 @@
+/*
+ * 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;
+
+public class FieldTableFactory
+{
+ public static FieldTable newFieldTable()
+ {
+ return new PropertyFieldTable();
+ }
+
+ public static FieldTable newFieldTable(ByteBuffer byteBuffer, long length) throws AMQFrameDecodingException
+ {
+ return new PropertyFieldTable(byteBuffer, length);
+ }
+
+ public static PropertyFieldTable newFieldTable(String text)
+ {
+ return new PropertyFieldTable(text);
+ }
+}
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 96360e4aaa..36558011ac 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
@@ -21,20 +21,28 @@
package org.apache.qpid.framing;
import org.apache.log4j.Logger;
+import org.apache.mina.common.ByteBuffer;
+import java.util.Collection;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
+import java.util.Set;
import java.util.StringTokenizer;
import java.util.Vector;
//extends FieldTable
-public class PropertyFieldTable
+public class PropertyFieldTable implements FieldTable, Map
{
-
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 BOOLEAN_PROPERTY_PREFIX = 'B';
public static final char BYTE_PROPERTY_PREFIX = 'b';
public static final char SHORT_PROPERTY_PREFIX = 's';
@@ -42,10 +50,12 @@ public class PropertyFieldTable
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 STRING_PROPERTY_PREFIX = 'S';
+ public static final char STRING_PROPERTY_PREFIX = AMQP_STRING_PROPERTY_PREFIX;
public static final char CHAR_PROPERTY_PREFIX = 'c';
public static final char BYTES_PROPERTY_PREFIX = 'y';
+ //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";
@@ -66,7 +76,7 @@ public class PropertyFieldTable
private LinkedHashMap<String, Object> _properties;
private LinkedHashMap<String, String> _propertyNamesTypeMap;
-
+ private long _encodedSize = 0;
public PropertyFieldTable()
{
@@ -84,73 +94,167 @@ public class PropertyFieldTable
}
catch (Exception e)
{
- System.out.println(textFormat);
- e.printStackTrace();
+ _logger.error("Unable to decode PropertyFieldTable format:" + textFormat, e);
}
+ }
+ /**
+ * Construct a new field table.
+ *
+ * @param buffer the buffer from which to read data. The length byte must be read already
+ * @param length the length of the field table. Must be > 0.
+ * @throws AMQFrameDecodingException if there is an error decoding the table
+ */
+ public PropertyFieldTable(ByteBuffer buffer, long length) throws AMQFrameDecodingException
+ {
+ this();
+ setFromBuffer(buffer, length);
}
// ************ Getters
+ private Object get(String propertyName, char prefix)
+ {
+ String type = _propertyNamesTypeMap.get(propertyName);
+
+ if (type == null)
+ {
+ return null;
+ }
+
+ if (type.equals("" + prefix))
+ {
+ return _properties.get(propertyName);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
public Boolean getBoolean(String string)
{
- return (Boolean) _properties.get(BOOLEAN_PROPERTY_PREFIX + string);
+ Object o = get(string, BOOLEAN_PROPERTY_PREFIX);
+ if (o != null)
+ {
+ return (Boolean) o;
+ }
+ else
+ {
+ return null;
+ }
}
public Byte getByte(String string)
{
- return (Byte) _properties.get(BYTE_PROPERTY_PREFIX + string);
+ Object o = get(string, BYTE_PROPERTY_PREFIX);
+ if (o != null)
+ {
+ return (Byte) o;
+ }
+ else
+ {
+ return null;
+ }
}
public Short getShort(String string)
{
- return (Short) _properties.get(SHORT_PROPERTY_PREFIX + string);
+ Object o = get(string, SHORT_PROPERTY_PREFIX);
+ if (o != null)
+ {
+ return (Short) o;
+ }
+ else
+ {
+ return null;
+ }
}
public Integer getInteger(String string)
{
- return (Integer) _properties.get(INT_PROPERTY_PREFIX + string);
+ Object o = get(string, INT_PROPERTY_PREFIX);
+ if (o != null)
+ {
+ return (Integer) o;
+ }
+ else
+ {
+ return null;
+ }
}
public Long getLong(String string)
{
- return (Long) _properties.get(LONG_PROPERTY_PREFIX + string);
+ Object o = get(string, LONG_PROPERTY_PREFIX);
+ if (o != null)
+ {
+ return (Long) o;
+ }
+ else
+ {
+ return null;
+ }
}
public Float getFloat(String string)
{
- return (Float) _properties.get(FLOAT_PROPERTY_PREFIX + string);
+ Object o = get(string, FLOAT_PROPERTY_PREFIX);
+ if (o != null)
+ {
+ return (Float) o;
+ }
+ else
+ {
+ return null;
+ }
}
public Double getDouble(String string)
{
- return (Double) _properties.get(DOUBLE_PROPERTY_PREFIX + string);
+ Object o = get(string, DOUBLE_PROPERTY_PREFIX);
+ if (o != null)
+ {
+ return (Double) o;
+ }
+ else
+ {
+ return null;
+ }
}
public String getString(String string)
{
- return (String) _properties.get(STRING_PROPERTY_PREFIX + string);
+ Object o = get(string, STRING_PROPERTY_PREFIX);
+ if (o != null)
+ {
+ return (String) o;
+ }
+ else
+ {
+ return null;
+ }
}
public Character getCharacter(String string)
{
- return (Character) _properties.get(CHAR_PROPERTY_PREFIX + string);
+ Object o = get(string, CHAR_PROPERTY_PREFIX);
+ if (o != null)
+ {
+ return (Character) o;
+ }
+ else
+ {
+ return null;
+ }
}
public byte[] getBytes(String string)
{
- return (byte[]) _properties.get(BYTES_PROPERTY_PREFIX + string);
- }
-
- public Object getObject(String string)
- {
- String typestring = _propertyNamesTypeMap.get(string);
-
- if (typestring != null && !typestring.equals(""))
+ Object o = get(string, BYTES_PROPERTY_PREFIX);
+ if (o != null)
{
- char type = typestring.charAt(0);
-
- return _properties.get(type + string);
+ return (byte[]) o;
}
else
{
@@ -158,91 +262,66 @@ public class PropertyFieldTable
}
}
- // ************ Setters
-
-
- public void setBoolean(String string, boolean b)
+ public Object getObject(String string)
{
- checkPropertyName(string, BOOLEAN_PROPERTY_PREFIX);
+ return _properties.get(string);
+ }
+ // ************ Setters
- _propertyNamesTypeMap.put(string, "" + BOOLEAN_PROPERTY_PREFIX);
- _properties.put(BOOLEAN_PROPERTY_PREFIX + string, b);// ? new Long(1) : new Long(0));
+ public Object setBoolean(String string, boolean b)
+ {
+ return put(BOOLEAN_PROPERTY_PREFIX + string, b);
}
- public void setByte(String string, byte b)
+ public Object setByte(String string, byte b)
{
- checkPropertyName(string, BYTE_PROPERTY_PREFIX);
-
-
- _properties.put(BYTE_PROPERTY_PREFIX + string, b);
+ return put(BYTE_PROPERTY_PREFIX + string, b);
}
- public void setShort(String string, short i)
+ public Object setShort(String string, short i)
{
- checkPropertyName(string, SHORT_PROPERTY_PREFIX);
-
-
- _properties.put(SHORT_PROPERTY_PREFIX + string, i);
+ return put(SHORT_PROPERTY_PREFIX + string, i);
}
- public void setInteger(String string, int i)
+ public Object setInteger(String string, int i)
{
- checkPropertyName(string, INT_PROPERTY_PREFIX);
-
-
- _properties.put(INT_PROPERTY_PREFIX + string, i);
+ return put(INT_PROPERTY_PREFIX + string, i);
}
- public void setLong(String string, long l)
+ public Object setLong(String string, long l)
{
- checkPropertyName(string, LONG_PROPERTY_PREFIX);
-
-
- _properties.put(LONG_PROPERTY_PREFIX + string, l);
+ return put(LONG_PROPERTY_PREFIX + string, l);
}
- public void setFloat(String string, float v)
+ public Object setFloat(String string, float v)
{
- checkPropertyName(string, FLOAT_PROPERTY_PREFIX);
-
-
- _properties.put(FLOAT_PROPERTY_PREFIX + string, v);
+ return put(FLOAT_PROPERTY_PREFIX + string, v);
}
- public void setDouble(String string, double v)
+ public Object setDouble(String string, double v)
{
- checkPropertyName(string, DOUBLE_PROPERTY_PREFIX);
-
-
- _properties.put(DOUBLE_PROPERTY_PREFIX + string, v);
+ return put(DOUBLE_PROPERTY_PREFIX + string, v);
}
- public void setString(String string, String string1)
+ public Object setString(String string, String string1)
{
- checkPropertyName(string, STRING_PROPERTY_PREFIX);
-
-
- _properties.put(STRING_PROPERTY_PREFIX + string, string1);
+ return put(STRING_PROPERTY_PREFIX + string, string1);
}
- public void setChar(String string, char c)
+ public Object setChar(String string, char c)
{
- checkPropertyName(string, CHAR_PROPERTY_PREFIX);
-
- _properties.put(CHAR_PROPERTY_PREFIX + string, c);
+ return put(CHAR_PROPERTY_PREFIX + string, c);
}
- public void setBytes(String string, byte[] bytes)
+ public Object setBytes(String string, byte[] bytes)
{
- setBytes(string, bytes, 0, bytes.length);
+ return setBytes(string, bytes, 0, bytes.length);
}
- public void setBytes(String string, byte[] bytes, int start, int length)
+ public Object setBytes(String string, byte[] bytes, int start, int length)
{
- checkPropertyName(string, BYTES_PROPERTY_PREFIX);
-
- _properties.put(BYTES_PROPERTY_PREFIX + string, sizeByteArray(bytes, start, length));
+ return put(BYTES_PROPERTY_PREFIX + string, sizeByteArray(bytes, start, length));
}
private byte[] sizeByteArray(byte[] bytes, int start, int length)
@@ -259,65 +338,65 @@ public class PropertyFieldTable
}
- public void setObject(String string, Object object)
+ public Object setObject(String string, Object object)
{
if (object instanceof Boolean)
{
- setBoolean(string, (Boolean) object);
+ return setBoolean(string, (Boolean) object);
}
else
{
if (object instanceof Byte)
{
- setByte(string, (Byte) object);
+ return setByte(string, (Byte) object);
}
else
{
if (object instanceof Short)
{
- setShort(string, (Short) object);
+ return setShort(string, (Short) object);
}
else
{
if (object instanceof Integer)
{
- setInteger(string, (Integer) object);
+ return setInteger(string, (Integer) object);
}
else
{
if (object instanceof Long)
{
- setLong(string, (Long) object);
+ return setLong(string, (Long) object);
}
else
{
if (object instanceof Float)
{
- setFloat(string, (Float) object);
+ return setFloat(string, (Float) object);
}
else
{
if (object instanceof Double)
{
- setDouble(string, (Double) object);
+ return setDouble(string, (Double) object);
}
else
{
if (object instanceof String)
{
- setString(string, (String) object);
+ return setString(string, (String) object);
}
else
{
if (object instanceof Character)
{
- setChar(string, (Character) object);
+ return setChar(string, (Character) object);
}
else
{
if (object instanceof byte[])
{
- setBytes(string, (byte[]) object);
+ return setBytes(string, (byte[]) object);
}
}
}
@@ -328,8 +407,7 @@ public class PropertyFieldTable
}
}
}
-
-
+ return null;
}
// ***** Methods
@@ -344,12 +422,16 @@ public class PropertyFieldTable
{
String key = (String) keys.next();
- names.add(key.substring(1));
+ names.add(key);
}
return names.elements();
}
+ public boolean propertyExists(String propertyName)
+ {
+ return _propertyNamesTypeMap.containsKey(propertyName);
+ }
public boolean itemExists(String string)
{
@@ -367,7 +449,6 @@ public class PropertyFieldTable
return false;
}
-
public String toString()
{
return valueOf(this);
@@ -390,35 +471,55 @@ public class PropertyFieldTable
else
{
buf.append('\n');
- buf.append(propertyXML(propertyName, true));
- if (propertyName.charAt(0) == BYTES_PROPERTY_PREFIX)
- {
- //remove '>'
- buf.deleteCharAt(buf.length() - 1);
+ buf.append(valueAsXML(table._propertyNamesTypeMap.get(propertyName) + propertyName, entry.getValue()));
+ }
+ }
+ buf.append("\n");
+ buf.append(PROPERTY_FIELD_TABLE_CLOSE_XML);
- byte[] bytes = (byte[]) entry.getValue();
- buf.append(" length='").append(bytes.length).append("'>");
+ return buf.toString();
+ }
- buf.append(byteArrayToXML(propertyName.substring(1), bytes));
- }
- else
- {
+ private static String valueAsXML(String name, Object value)
+ {
+ char propertyPrefix = name.charAt(0);
+ String propertyName = name.substring(1);
- buf.append(String.valueOf(entry.getValue()));
- }
- buf.append(propertyXML(propertyName, false));
- }
+ StringBuffer buf = new StringBuffer();
+ // Start Tag
+ buf.append(propertyXML(name, true));
+
+ // Value
+ if (propertyPrefix == BYTES_PROPERTY_PREFIX)
+ {
+ //remove '>'
+ buf.deleteCharAt(buf.length() - 1);
+
+ byte[] bytes = (byte[]) value;
+ buf.append(" length='").append(bytes.length).append("'>");
+
+ buf.append(byteArrayToXML(propertyName, bytes));
+ }
+ else
+ {
+ buf.append(String.valueOf(value));
}
- buf.append("\n");
- buf.append(PROPERTY_FIELD_TABLE_CLOSE_XML);
+
+ //End Tag
+ buf.append(propertyXML(name, false));
return buf.toString();
}
- private void checkPropertyName(String propertyName, char propertyPrefix)
+ private Object checkPropertyName(String name)
{
+ 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");
@@ -432,15 +533,29 @@ public class PropertyFieldTable
if (currentValue != null)
{
- _properties.remove(currentValue + propertyName);
+ 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);
}
_propertyNamesTypeMap.put(propertyName, "" + propertyPrefix);
+
+ return previous;
}
- private static String propertyXML(String propertyName, boolean start)
+ private static String propertyXML(String name, boolean start)
{
- char typeIdentifier = propertyName.charAt(0);
+ char propertyPrefix = name.charAt(0);
+ String propertyName = name.substring(1);
StringBuffer buf = new StringBuffer();
@@ -453,8 +568,7 @@ public class PropertyFieldTable
buf.append("</");
}
-
- switch (typeIdentifier)
+ switch (propertyPrefix)
{
case BOOLEAN_PROPERTY_PREFIX:
buf.append(BOOLEAN);
@@ -487,14 +601,13 @@ public class PropertyFieldTable
buf.append(CHAR);
break;
default:
- buf.append(UNKNOWN + " (identifier ").append(typeIdentifier).append(")");
+ buf.append(UNKNOWN + " (identifier ").append(propertyPrefix).append(")");
break;
}
-
if (start)
{
- buf.append(" name='").append(propertyName.substring(1)).append("'");
+ buf.append(" name='").append(propertyName).append("'");
}
buf.append(">");
@@ -519,8 +632,6 @@ public class PropertyFieldTable
private void processBytesXMLLine(String xmlline)
{
- String type = xmlline.substring(1, xmlline.indexOf(" "));
-
String propertyName = xmlline.substring(xmlline.indexOf('\'') + 1,
xmlline.indexOf('\'', xmlline.indexOf('\'') + 1));
String value = xmlline.substring(xmlline.indexOf(">") + 1,
@@ -545,7 +656,6 @@ public class PropertyFieldTable
{
String token = tokenizer.nextToken();
-
if (token.equals(PROPERTY_FIELD_TABLE_CLOSE_XML)
|| token.equals(BYTES_CLOSE_XML))
{
@@ -555,7 +665,6 @@ public class PropertyFieldTable
if (token.equals(BYTES_CLOSE_XML))
{
processing_bytes = false;
-
}
if (processing)
@@ -578,11 +687,9 @@ public class PropertyFieldTable
{
processing = true;
}
-
}
}
-
private void processXMLLine(String xmlline)
{
// <<type> name='<property>'><value></<type>>
@@ -611,11 +718,39 @@ public class PropertyFieldTable
}
if (type.equals(BYTES))
{
- Integer length = Integer.parseInt(xmlline.substring(
- xmlline.lastIndexOf("=") + 2
- , xmlline.lastIndexOf("'")));
+ int headerEnd = xmlline.indexOf('>');
+ String bytesHeader = xmlline.substring(0, headerEnd);
+
+ //Extract length value
+ Integer length = Integer.parseInt(bytesHeader.substring(
+ bytesHeader.lastIndexOf("=") + 2
+ , bytesHeader.lastIndexOf("'")));
+
+
byte[] bytes = new byte[length];
setBytes(propertyName, bytes);
+
+ //Check if the line contains all the byte values
+ // This is needed as the XMLLine sent across the wire is the bytes value
+
+ int byteStart = xmlline.indexOf('<', headerEnd);
+
+ if (byteStart > 0)
+ {
+ while (!xmlline.startsWith(BYTES_CLOSE_XML, byteStart))
+ {
+ //This should be the next byte line
+ int bytePrefixEnd = xmlline.indexOf('>', byteStart) + 1;
+ int byteEnd = xmlline.indexOf('>', bytePrefixEnd) + 1;
+
+ String byteline = xmlline.substring(byteStart, byteEnd);
+
+ processBytesXMLLine(byteline);
+
+ byteStart = xmlline.indexOf('<', byteEnd);
+ }
+ }
+
}
if (type.equals(SHORT))
{
@@ -651,6 +786,311 @@ public class PropertyFieldTable
}
}
+ // ************************* Byte Buffer Processing
-}
+ public void writeToBuffer(ByteBuffer buffer)
+ {
+ final boolean debug = _logger.isDebugEnabled();
+
+ if (debug)
+ {
+ _logger.debug("FieldTable::writeToBuffer: Writing encoded size of " + _encodedSize + "...");
+ }
+
+ EncodingUtils.writeUnsignedInteger(buffer, _encodedSize);
+
+ putDataInBuffer(buffer);
+ }
+
+ public byte[] getDataAsBytes()
+ {
+ final ByteBuffer buffer = ByteBuffer.allocate((int) _encodedSize); // FIXME XXX: Is cast a problem?
+
+ putDataInBuffer(buffer);
+
+ final byte[] result = new byte[(int) _encodedSize];
+ buffer.flip();
+ buffer.get(result);
+ buffer.release();
+ return result;
+ }
+
+ public int size()
+ {
+ return _properties.size();
+ }
+
+ public boolean isEmpty()
+ {
+ return _properties.isEmpty();
+ }
+
+ public boolean containsKey(Object key)
+ {
+ return _properties.containsKey(key);
+ }
+
+ public boolean containsValue(Object value)
+ {
+ return _properties.containsValue(value);
+ }
+
+ public Object get(Object key)
+ {
+ return _properties.get(key);
+ }
+
+
+ public Object put(Object key, Object value)
+ {
+ return setObject(key.toString(), value);
+ }
+
+ protected Object put(String key, Object value)
+ {
+ Object previous = checkPropertyName(key);
+
+
+ String propertyName = key.substring(1);
+ char propertyPrefix = _propertyNamesTypeMap.get(propertyName).charAt(0);
+
+ 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 content
+ _encodedSize += getEncodingSize(key, value);
+ }
+
+ _properties.put((String) propertyName, value);
+
+ return previous;
+ }
+
+ public Object remove(Object key)
+ {
+ if (key instanceof String)
+ {
+ throw new IllegalArgumentException("Property key be a string");
+ }
+
+ char propertyPrefix = ((String) key).charAt(0);
+
+ if (_properties.containsKey(key))
+ {
+ final Object value = _properties.remove(key);
+ // plus one for the type
+ _encodedSize -= EncodingUtils.encodedShortStringLength(((String) key));
+
+ // This check is, for now, unnecessary (we don't store null values).
+ if (value != null)
+ {
+ _encodedSize -= getEncodingSize(propertyPrefix + (String) key, value);
+ }
+
+ return value;
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ public void putAll(Map t)
+ {
+ Iterator it = t.keySet().iterator();
+
+ while (it.hasNext())
+ {
+ Object key = it.next();
+ put(key, t.get(key));
+ }
+ }
+
+ public void clear()
+ {
+ _properties.clear();
+ _propertyNamesTypeMap.clear();
+ }
+
+ public Set keySet()
+ {
+ return _properties.keySet();
+ }
+
+ public Collection values()
+ {
+ return _properties.values();
+ }
+
+ public Set entrySet()
+ {
+ return _properties.entrySet();
+ }
+
+ public long getEncodedSize()
+ {
+ return _encodedSize;
+ }
+
+
+ private void putDataInBuffer(ByteBuffer buffer)
+ {
+ final Iterator it = _properties.entrySet().iterator();
+
+ //If there are values then write out the encoded Size... could check _encodedSize != 0
+ // write out the total length, which we have kept up to date as data is added
+
+
+ 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);
+ //The actual param name skipping type
+
+ EncodingUtils.writeShortStringBytes(buffer, propertyName);
+ Object value = me.getValue();
+
+ switch (propertyPrefix)
+ {
+
+ case STRING_PROPERTY_PREFIX:
+ // TODO: look at using proper charset encoder
+ buffer.put((byte) STRING_PROPERTY_PREFIX);
+ EncodingUtils.writeLongStringBytes(buffer, (String) value);
+ break;
+
+ case AMQP_UNSIGNEDINT_PROPERTY_PREFIX:
+ case LONG_PROPERTY_PREFIX:
+ case INT_PROPERTY_PREFIX:
+ case BOOLEAN_PROPERTY_PREFIX:
+ case BYTE_PROPERTY_PREFIX:
+ case SHORT_PROPERTY_PREFIX:
+ case FLOAT_PROPERTY_PREFIX:
+ case DOUBLE_PROPERTY_PREFIX:
+ case CHAR_PROPERTY_PREFIX:
+ case BYTES_PROPERTY_PREFIX:
+ 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
+ throw new IllegalArgumentException("Key '" + propertyName + "': Unsupported type in field table, type: " + ((value == null) ? "null-object" : value.getClass()));
+ }
+ }
+ }
+ }
+
+
+ public void setFromBuffer(ByteBuffer buffer, long length) throws AMQFrameDecodingException
+ {
+ final boolean debug = _logger.isDebugEnabled();
+
+ 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;
+
+ switch (type)
+ {
+ case STRING_PROPERTY_PREFIX:
+ value = EncodingUtils.readLongString(buffer);
+ break;
+ case LONG_PROPERTY_PREFIX:
+ case INT_PROPERTY_PREFIX:
+ case BOOLEAN_PROPERTY_PREFIX:
+ case BYTE_PROPERTY_PREFIX:
+ case SHORT_PROPERTY_PREFIX:
+ case FLOAT_PROPERTY_PREFIX:
+ case DOUBLE_PROPERTY_PREFIX:
+ case CHAR_PROPERTY_PREFIX:
+ case BYTES_PROPERTY_PREFIX:
+ 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;
+ throw new AMQFrameDecodingException(msg);
+ }
+
+ sizeRead += (sizeRemaining - buffer.remaining());
+
+ if (debug)
+ {
+ _logger.debug("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 (debug)
+ {
+ _logger.debug("FieldTable::FieldTable(buffer," + length + "): Done.");
+ }
+ }
+
+
+ /**
+ * @param name the property name with type prefix
+ * @param value the property value
+ * @return integer
+ */
+ private static int getEncodingSize(String name, Object value)
+ {
+ int encodingSize;
+
+ char propertyPrefix = name.charAt(0);
+
+ switch (propertyPrefix)
+ {
+ // the extra byte if for the type indicator that is written out
+ case STRING_PROPERTY_PREFIX:
+ encodingSize = 1 + EncodingUtils.encodedLongStringLength((String) value);
+ break;
+ case LONG_PROPERTY_PREFIX:
+ case INT_PROPERTY_PREFIX:
+ case BOOLEAN_PROPERTY_PREFIX:
+ case BYTE_PROPERTY_PREFIX:
+ case SHORT_PROPERTY_PREFIX:
+ case FLOAT_PROPERTY_PREFIX:
+ case DOUBLE_PROPERTY_PREFIX:
+ case CHAR_PROPERTY_PREFIX:
+ case BYTES_PROPERTY_PREFIX:
+ case XML_PROPERTY_PREFIX:
+ encodingSize = 1 + EncodingUtils.encodedLongStringLength(valueAsXML(name, value));
+ break;
+ default:
+ //encodingSize = 1 + EncodingUtils.encodedLongStringLength(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
+ return encodingSize;
+ }
+
+
+}
diff --git a/java/common/src/main/java/org/apache/qpid/url/URLHelper.java b/java/common/src/main/java/org/apache/qpid/url/URLHelper.java
index 2121346c02..f8c621e413 100644
--- a/java/common/src/main/java/org/apache/qpid/url/URLHelper.java
+++ b/java/common/src/main/java/org/apache/qpid/url/URLHelper.java
@@ -64,9 +64,9 @@ public class URLHelper
if (valueIndex + 1 < options.length())
{
if (options.charAt(valueIndex + 1) == DEFAULT_OPTION_SEPERATOR ||
- options.charAt(valueIndex + 1) == ALTERNATIVE_OPTION_SEPARATOR ||
- options.charAt(valueIndex + 1) == BROKER_SEPARATOR ||
- options.charAt(valueIndex + 1) == '\'')
+ options.charAt(valueIndex + 1) == ALTERNATIVE_OPTION_SEPARATOR ||
+ options.charAt(valueIndex + 1) == BROKER_SEPARATOR ||
+ options.charAt(valueIndex + 1) == '\'')
{
nestedQuotes--;
// System.out.println(
@@ -119,7 +119,7 @@ public class URLHelper
else
{
parseError(sepIndex, "Unterminated option. Possible illegal option separator:'" +
- options.charAt(sepIndex) + "'", options);
+ options.charAt(sepIndex) + "'", options);
}
}
diff --git a/java/common/src/main/java/org/apache/qpid/url/URLSyntaxException.java b/java/common/src/main/java/org/apache/qpid/url/URLSyntaxException.java
index 3ff7195794..5cac2505a8 100644
--- a/java/common/src/main/java/org/apache/qpid/url/URLSyntaxException.java
+++ b/java/common/src/main/java/org/apache/qpid/url/URLSyntaxException.java
@@ -62,12 +62,12 @@ public class URLSyntaxException extends URISyntaxException
if (getIndex() > -1)
{
- if (_length != -1)
+ if (_length > 1)
{
sb.append(" between indicies ");
sb.append(getIndex());
sb.append(" and ");
- sb.append(_length);
+ sb.append(getIndex() + _length);
}
else
{
diff --git a/java/common/src/main/xsl/java.xsl b/java/common/src/main/xsl/java.xsl
index 685a9a27ed..e98370fd7b 100644
--- a/java/common/src/main/xsl/java.xsl
+++ b/java/common/src/main/xsl/java.xsl
@@ -69,7 +69,7 @@ import org.apache.qpid.framing.EncodableAMQDataBlock;
import org.apache.qpid.framing.EncodingUtils;
import org.apache.qpid.framing.FieldTable;
-/**
+ /**
* This class is autogenerated, do not modify. [From <xsl:value-of select="$f/parent::frames/@protocol"/>]
*/
public class <xsl:value-of select="$f/@name"/> extends AMQMethodBody implements EncodableAMQDataBlock
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 5070b6ecb1..0b6820b8a9 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
@@ -25,6 +25,10 @@ import junit.framework.TestCase;
import java.util.Enumeration;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.ByteBufferProxy;
+import org.apache.mina.common.support.BaseByteBuffer;
+
public class PropertyFieldTableTest extends TestCase
{
@@ -206,7 +210,7 @@ public class PropertyFieldTableTest extends TestCase
PropertyFieldTable table2 = new PropertyFieldTable(table1XML);
- Assert.assertEquals(table1XML, table2.toString());
+ Assert.assertEquals(table1XML, table2.toString());
}
public void testKeyEnumeration()
@@ -273,6 +277,117 @@ public class PropertyFieldTableTest extends TestCase
Assert.assertEquals(Short.MAX_VALUE, table.getObject("object-short"));
}
+
+ public void testwriteBuffer()
+ {
+ byte[] bytes = {99, 98, 97, 96, 95};
+
+ PropertyFieldTable table = new PropertyFieldTable();
+ table.setBoolean("bool", true);
+ table.setByte("byte", Byte.MAX_VALUE);
+
+ table.setBytes("bytes", bytes);
+ table.setChar("char", 'c');
+ 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);
+
+
+ final ByteBuffer buffer = ByteBuffer.allocate((int) table.getEncodedSize()); // FIXME XXX: Is cast a problem?
+
+ table.writeToBuffer(buffer);
+
+ buffer.flip();
+
+ long length = buffer.getUnsignedInt();
+
+ try
+ {
+ PropertyFieldTable table2 = new PropertyFieldTable(buffer, length);
+
+ Assert.assertEquals((Boolean) true, table2.getBoolean("bool"));
+ Assert.assertEquals((Byte) Byte.MAX_VALUE, table2.getByte("byte"));
+ assertBytesEqual(bytes, table2.getBytes("bytes"));
+ Assert.assertEquals((Character) 'c', table2.getCharacter("char"));
+ Assert.assertEquals(Double.MAX_VALUE, table2.getDouble("double"));
+ Assert.assertEquals(Float.MAX_VALUE, table2.getFloat("float"));
+ 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"));
+ }
+ catch (AMQFrameDecodingException e)
+ {
+ e.printStackTrace();
+ fail("PFT should be instantiated from bytes." + e.getCause());
+ }
+ }
+
+ public void testEncodingSize()
+ {
+ FieldTable result = FieldTableFactory.newFieldTable();
+ int size = 0;
+ result.put("one", 1L);
+ // size is 1(size) + bytes for short string
+ size = 1 + 3; // 1 + key length
+ // or size is 1(the type) + number of bytes (4bytes worth) + bytes
+ size += 1 + 4; // 1 + 4 + value length
+ size += "<long name='one'>1</long>".length(); // this is the xml encoding for a long.
+ assertEquals(size, result.getEncodedSize());
+
+ result.put("two", 2L);
+ size += 1 + 3; // 1 + key length
+ size += 1 + 4; // 1 + 4 + value length
+ size += "<long name='two'>2</long>".length(); // this is the xml encoding for a long.
+ assertEquals(size, result.getEncodedSize());
+
+ result.put("three", 3L);
+ size += 1 + 5; // 1 + key length
+ size += 1 + 4; // 1 + 4 + value length
+ size += "<long name='three'>3</long>".length(); // this is the xml encoding for a long.
+ assertEquals(size, result.getEncodedSize());
+
+ result.put("four", 4L);
+ size += 1 + 4; // 1 + key length
+ size += 1 + 4; // 1 + 4 + value length
+ size += "<long name='four'>4</long>".length(); // this is the xml encoding for a long.
+ assertEquals(size, result.getEncodedSize());
+
+ result.put("five", 5L);
+ size += 1 + 4; // 1 + key length
+ size += 1 + 4; // 1 + 4 + value length
+ size += "<long name='five'>5</long>".length(); // this is the xml encoding for a long.
+ 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());
+ }
+
+ }
+
private void assertBytesEqual(byte[] expected, byte[] actual)
{
Assert.assertEquals(expected.length, actual.length);
diff --git a/java/distribution/pom.xml b/java/distribution/pom.xml
index f0eb3ab06a..65e5cb7aa1 100644
--- a/java/distribution/pom.xml
+++ b/java/distribution/pom.xml
@@ -17,94 +17,111 @@
under the License.
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
- <modelVersion>4.0.0</modelVersion>
- <groupId>org.apache.qpid</groupId>
- <artifactId>qpid-distribution</artifactId>
- <packaging>jar</packaging>
- <name>Qpid Distribution</name>
- <version>1.0-incubating-M2-SNAPSHOT</version>
-
- <parent>
+ <modelVersion>4.0.0</modelVersion>
<groupId>org.apache.qpid</groupId>
- <artifactId>qpid</artifactId>
+ <artifactId>qpid-distribution</artifactId>
+ <packaging>jar</packaging>
+ <name>Qpid Distribution</name>
<version>1.0-incubating-M2-SNAPSHOT</version>
- </parent>
- <properties>
- <topDirectoryLocation>..</topDirectoryLocation>
- <java.source.version>1.5</java.source.version>
- <qpid.version>${pom.version}</qpid.version>
- </properties>
+ <parent>
+ <groupId>org.apache.qpid</groupId>
+ <artifactId>qpid</artifactId>
+ <version>1.0-incubating-M2-SNAPSHOT</version>
+ </parent>
+
+ <properties>
+ <topDirectoryLocation>..</topDirectoryLocation>
+ <java.source.version>1.5</java.source.version>
+ <qpid.version>${pom.version}</qpid.version>
+ <qpid.targetDir>${project.build.directory}</qpid.targetDir>
+ </properties>
- <dependencies>
- <dependency>
- <groupId>${pom.groupId}</groupId>
- <artifactId>qpid-common</artifactId>
- <version>${pom.version}</version>
- </dependency>
- <dependency>
- <groupId>${pom.groupId}</groupId>
- <artifactId>qpid-broker</artifactId>
- <version>${pom.version}</version>
- </dependency>
- <dependency>
- <groupId>${pom.groupId}</groupId>
- <artifactId>qpid-client</artifactId>
- <version>${pom.version}</version>
- </dependency>
- </dependencies>
+ <dependencies>
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>qpid-common</artifactId>
+ <version>${pom.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>qpid-broker</artifactId>
+ <version>${pom.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${pom.groupId}</groupId>
+ <artifactId>qpid-client</artifactId>
+ <version>${pom.version}</version>
+ </dependency>
+ </dependencies>
- <build>
- <resources>
- <resource>
- <directory>src/main/java</directory>
- <includes>
- <include>**/*</include>
- </includes>
- </resource>
- </resources>
- <plugins>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-compiler-plugin</artifactId>
- <configuration>
- <source>${java.source.version}</source>
- <target>${java.source.version}</target>
- </configuration>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-assembly-plugin</artifactId>
- <version>${assembly.version}</version>
- <executions>
- <execution>
- <id>distribution-package</id>
- <phase>package</phase>
- <goals>
- <goal>single</goal>
- </goals>
- <configuration>
- <descriptors>
- <descriptor>src/main/assembly/bin.xml</descriptor>
- <descriptor>src/main/assembly/src.xml</descriptor>
- </descriptors>
- <finalName>qpid-${pom.version}</finalName>
- </configuration>
- </execution>
- </executions>
- </plugin>
- <plugin>
- <groupId>org.apache.maven.plugins</groupId>
- <artifactId>maven-jar-plugin</artifactId>
- <configuration>
- <finalName>qpid-incubating</finalName>
- <archive>
- <manifest>
- <addClasspath>true</addClasspath>
- </manifest>
- </archive>
- </configuration>
- </plugin>
- </plugins>
- </build>
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <source>${java.source.version}</source>
+ <target>${java.source.version}</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <version>${assembly.version}</version>
+ <configuration>
+ <descriptors>
+ <descriptor>src/main/assembly/bin.xml</descriptor>
+ </descriptors>
+ <finalName>qpid-${pom.version}</finalName>
+ <outputDirectory>${qpid.targetDir}</outputDirectory>
+ <tarLongFileMode>gnu</tarLongFileMode>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-jar-plugin</artifactId>
+ <configuration>
+ <finalName>qpid-incubating</finalName>
+ <archive>
+ <manifest>
+ <addClasspath>true</addClasspath>
+ </manifest>
+ </archive>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ <resources>
+ <resource>
+ <directory>src/main/java</directory>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <artifactId>maven-assembly-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>distribution-package</id>
+ <phase>package</phase>
+ <goals>
+ <goal>single</goal>
+ </goals>
+ <configuration>
+ <descriptors>
+ <descriptor>src/main/assembly/bin.xml</descriptor>
+ <descriptor>src/main/assembly/client-bin.xml</descriptor>
+ <descriptor>src/main/assembly/src.xml</descriptor>
+ </descriptors>
+ <finalName>qpid-${pom.version}</finalName>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
</project>
diff --git a/java/distribution/src/main/assembly/client-bin.xml b/java/distribution/src/main/assembly/client-bin.xml
new file mode 100644
index 0000000000..fe3daf176b
--- /dev/null
+++ b/java/distribution/src/main/assembly/client-bin.xml
@@ -0,0 +1,89 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ * 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.
+-->
+<assembly>
+ <id>java-client-bin</id>
+ <includeBaseDirectory>false</includeBaseDirectory>
+ <formats>
+ <format>tar.gz</format>
+ <format>zip</format>
+ </formats>
+
+ <moduleSets>
+ <moduleSet>
+ <includes>
+ <include>org.apache.qpid:client</include>
+ </includes>
+ <binaries>
+ <includeDependencies>true</includeDependencies>
+ <unpack>false</unpack>
+ </binaries>
+ </moduleSet>
+ </moduleSets>
+
+ <fileSets>
+ <fileSet>
+ <directory>src/main/release</directory>
+ <outputDirectory>qpid-${qpid.version}</outputDirectory>
+ <includes>
+ <include>DISCLAIMER</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>..</directory>
+ <outputDirectory>qpid-${qpid.version}</outputDirectory>
+ <includes>
+ <include>*.txt</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>src/main/release/etc</directory>
+ <outputDirectory>qpid-${qpid.version}/etc</outputDirectory>
+ <includes>
+ <include>logging.properties</include>
+ <include>log4j.properties</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>src/main/release/docs</directory>
+ <outputDirectory>qpid-${qpid.version}/docs</outputDirectory>
+ <includes>
+ <include>RELEASE_NOTES.txt</include>
+ </includes>
+ </fileSet>
+ <fileSet>
+ <directory>target</directory>
+ <outputDirectory>qpid-${qpid.version}/lib</outputDirectory>
+ <includes>
+ <include>qpid-incubating.jar</include>
+ </includes>
+ </fileSet>
+ </fileSets>
+
+ <dependencySets>
+ <dependencySet>
+ <outputDirectory>qpid-${qpid.version}/lib</outputDirectory>
+ <unpack>false</unpack>
+ <excludes>
+ <exclude>org.apache.qpid:qpid-distribution</exclude>
+ </excludes>
+ <scope>runtime</scope>
+ </dependencySet>
+ </dependencySets>
+</assembly>
diff --git a/java/management/eclipse-plugin/META-INF/MANIFEST.MF b/java/management/eclipse-plugin/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..e1859bbf1a
--- /dev/null
+++ b/java/management/eclipse-plugin/META-INF/MANIFEST.MF
@@ -0,0 +1,11 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-Name: Qpid Management Console Plug-in
+Bundle-SymbolicName: org.apache.qpid.management.ui; singleton:=true
+Bundle-Version: 0.1.0
+Bundle-Activator: org.apache.qpid.management.ui.Activator
+Bundle-Localization: plugin
+Require-Bundle: org.eclipse.ui,
+ org.eclipse.core.runtime,
+ org.eclipse.ui.forms
+Eclipse-LazyStart: true
diff --git a/java/management/eclipse-plugin/README.txt b/java/management/eclipse-plugin/README.txt
new file mode 100644
index 0000000000..284cf8e8d9
--- /dev/null
+++ b/java/management/eclipse-plugin/README.txt
@@ -0,0 +1,7 @@
+
+Running the Qpid Management Console (eclipse-plugin)
+----------------------------------------------------
+
+To run the management console, set the QPIDMC_HOME environment variable to
+management eclipse-plugin directory and add $QPIDMC_HOME/bin to your PATH.
+Then run the qpidmc.bat batch file to launch the management console.
diff --git a/java/management/eclipse-plugin/bin/qpidmc.bat b/java/management/eclipse-plugin/bin/qpidmc.bat
new file mode 100644
index 0000000000..4ddb88d22c
--- /dev/null
+++ b/java/management/eclipse-plugin/bin/qpidmc.bat
@@ -0,0 +1,55 @@
+@REM
+@REM Licensed to the Apache Software Foundation (ASF) under one
+@REM or more contributor license agreements. See the NOTICE file
+@REM distributed with this work for additional information
+@REM regarding copyright ownership. The ASF licenses this file
+@REM to you under the Apache License, Version 2.0 (the
+@REM "License"); you may not use this file except in compliance
+@REM with the License. You may obtain a copy of the License at
+@REM
+@REM http://www.apache.org/licenses/LICENSE-2.0
+@REM
+@REM Unless required by applicable law or agreed to in writing,
+@REM software distributed under the License is distributed on an
+@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+@REM KIND, either express or implied. See the License for the
+@REM specific language governing permissions and limitations
+@REM under the License.
+@REM
+
+@echo off
+REM Script to run the Qpid Management Console
+
+rem Guess QPIDMC_HOME if not defined
+set CURRENT_DIR=%cd%
+if not "%QPIDMC_HOME%" == "" goto gotHome
+set QPIDMC_HOME=%CURRENT_DIR%
+echo %QPIDMC_HOME%
+if exist "%QPIDMC_HOME%\bin\qpidmc.bat" goto okHome
+cd ..
+set QPIDMC_HOME=%cd%
+cd %CURRENT_DIR%
+:gotHome
+if exist "%QPIDMC_HOME%\bin\qpidmc.bat" goto okHome
+echo The QPIDMC_HOME environment variable is not defined correctly
+echo This environment variable is needed to run this program
+goto end
+:okHome
+
+if not "%JAVA_HOME%" == "" goto gotJavaHome
+echo The JAVA_HOME environment variable is not defined
+echo This environment variable is needed to run this program
+goto exit
+:gotJavaHome
+if not exist "%JAVA_HOME%\bin\java.exe" goto noJavaHome
+goto okJavaHome
+:noJavaHome
+echo The JAVA_HOME environment variable is not defined correctly
+echo This environment variable is needed to run this program.
+goto exit
+:okJavaHome
+
+rem Slurp the command line arguments. This loop allows for an unlimited number
+rem of agruments (up to the command line limit, anyway).
+
+"%JAVA_HOME%\bin\java" -Xms40m -Xmx256m -Declipse.consoleLog=true -jar %QPIDMC_HOME%\startup.jar org.eclipse.core.launcher.Main -name "Qpid Management Console" -nosplash -application org.apache.qpid.management.ui.application -data %QPIDMC_HOME%\data -configuration "file:%QPIDMC_HOME%/configuration" -os win32 -ws win32 -arch x86
diff --git a/java/management/eclipse-plugin/bin/qpidmc.sh b/java/management/eclipse-plugin/bin/qpidmc.sh
new file mode 100755
index 0000000000..9d2d075a5e
--- /dev/null
+++ b/java/management/eclipse-plugin/bin/qpidmc.sh
@@ -0,0 +1,21 @@
+#!/bin/bash
+#
+# 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.
+#
+
+"$JAVA_HOME/bin/java" -Xms40m -Xmx256m -Declipse.consoleLog=true -jar $QPIDMC_HOME/startup.jar org.eclipse.core.launcher.Main -name "Qpid Management Console" -showsplash 600 -application org.apache.qpid.management.ui.application -data $QPIDMC_HOME/data -configuration "file:$QPIDMC_HOME/configuration" \ No newline at end of file
diff --git a/java/management/eclipse-plugin/build.properties b/java/management/eclipse-plugin/build.properties
new file mode 100644
index 0000000000..d9eefdc502
--- /dev/null
+++ b/java/management/eclipse-plugin/build.properties
@@ -0,0 +1,8 @@
+source.. = src/main/java/
+output.. = target/classes/
+bin.includes = plugin.xml,\
+ META-INF/,\
+ .,\
+ icons/,\
+ plugin.properties,\
+ splash.bmp
diff --git a/java/management/eclipse-plugin/build.xml b/java/management/eclipse-plugin/build.xml
new file mode 100644
index 0000000000..407381b03f
--- /dev/null
+++ b/java/management/eclipse-plugin/build.xml
@@ -0,0 +1,215 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ 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.
+-->
+<project name="org.apache.qpid.management.ui" default="build.update.jar" basedir=".">
+
+ <property name="basews" value="${ws}"/>
+ <property name="baseos" value="${os}"/>
+ <property name="basearch" value="${arch}"/>
+ <property name="basenl" value="${nl}"/>
+
+ <!-- Compiler settings. -->
+ <property name="javacFailOnError" value="false"/>
+ <property name="javacDebugInfo" value="on"/>
+ <property name="javacVerbose" value="false"/>
+ <property name="logExtension" value=".log"/>
+ <property name="compilerArg" value=""/>
+ <property name="javacSource" value="1.5"/>
+ <property name="javacTarget" value="1.5"/>
+ <path id="path_bootclasspath">
+ <fileset dir="${java.home}/lib">
+ <include name="*.jar"/>
+ </fileset>
+ </path>
+ <property name="bootclasspath" refid="path_bootclasspath"/>
+ <property name="bundleJavacSource" value="${javacSource}"/>
+ <property name="bundleJavacTarget" value="${javacTarget}"/>
+ <property name="bundleBootClasspath" value="${bootclasspath}"/>
+ <property name="pluginName" value="org.apache.qpid.management.ui"/>
+ <property name="distName" value="qpidmc"/>
+ <property name="version" value="0.1.0"/>
+
+ <target name="init" depends="properties">
+ <condition property="pluginTemp" value="${buildTempFolder}/plugins">
+ <isset property="buildTempFolder"/>
+ </condition>
+ <property name="pluginTemp" value="${basedir}"/>
+ <condition property="build.result.folder" value="${pluginTemp}/eclipse-plugin">
+ <isset property="buildTempFolder"/>
+ </condition>
+ <property name="build.result.folder" value="${basedir}"/>
+ <property name="temp.folder" value="${basedir}/temp.folder"/>
+ <property name="plugin.destination" value="${basedir}"/>
+ <property name="target.folder" value="${basedir}/target"/>
+ <property name="compile.folder" value="${target.folder}/classes"/>
+ <property name="plugins.folder" value="${basedir}/plugins"/>
+ </target>
+
+ <target name="properties" if="eclipse.running">
+ <property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>
+
+ </target>
+
+ <target name="build.update.jar" depends="init" description="Build the plug-in: org.apache.qpid.management.ui for an update site.">
+ <delete dir="${temp.folder}"/>
+ <mkdir dir="${temp.folder}"/>
+ <antcall target="build.jars"/>
+ <antcall target="gather.bin.parts">
+ <param name="destination.temp.folder" value="${temp.folder}/"/>
+ </antcall>
+ <zip destfile="${plugins.folder}/${pluginName}_${version}.jar" basedir="${temp.folder}/${pluginName}" filesonly="false" whenempty="skip" update="false"/>
+ <delete dir="${temp.folder}"/>
+ </target>
+
+ <target name="compile" depends="init" unless="compile" description="Create jar: org.apache.qpid.management.ui compile.">
+ <delete dir="${temp.folder}/compile.bin"/>
+ <mkdir dir="${temp.folder}/compile.bin"/>
+ <path id="compile.classpath">
+ <pathelement path="plugins/org.eclipse.ui_3.2.0.jar"/>
+ <pathelement path="plugins/org.eclipse.core.runtime_3.2.0.jar"/>
+ <pathelement path="plugins/org.eclipse.osgi_3.2.0.jar"/>
+ <pathelement path="plugins/org.eclipse.equinox.common_3.2.0.jar"/>
+ <pathelement path="plugins/org.eclipse.core.jobs_3.2.0.jar"/>
+ <pathelement path="plugins/org.eclipse.core.runtime.compatibility.registry_3.2.0/runtime_registry_compatibility.jar"/>
+ <pathelement path="plugins/org.eclipse.equinox.registry_3.2.0.jar"/>
+ <pathelement path="plugins/org.eclipse.equinox.preferences_3.2.0.jar"/>
+ <pathelement path="plugins/org.eclipse.core.contenttype_3.2.0.jar"/>
+ <pathelement path="plugins/org.eclipse.core.runtime.compatibility.auth_3.2.0.jar"/>
+ <pathelement path="plugins/org.eclipse.swt_3.2.0.jar"/>
+ <pathelement path="plugins/org.eclipse.swt.win32.win32.x86_3.2.0.jar"/>
+ <pathelement path="plugins/org.eclipse.jface_3.2.0.jar"/>
+ <pathelement path="plugins/org.eclipse.core.commands_3.2.0.jar"/>
+ <pathelement path="plugins/org.eclipse.ui.workbench_3.2.0.jar"/>
+ <pathelement path="plugins/org.eclipse.ui.workbench.compatibility_3.2.0/compatibility.jar"/>
+ <pathelement path="plugins/com.ibm.icu_3.4.4.1.jar"/>
+ <pathelement path="plugins/org.eclipse.help_3.2.0.jar"/>
+ <pathelement path="plugins/org.eclipse.core.expressions_3.2.0.jar"/>
+ <pathelement path="plugins/org.eclipse.ui.forms_3.2.0.jar"/>
+ </path>
+ <!-- compile the source code -->
+ <javac destdir="${temp.folder}/compile.bin" failonerror="${javacFailOnError}" verbose="${javacVerbose}" debug="${javacDebugInfo}" includeAntRuntime="no" bootclasspath="${bundleBootClasspath}" source="${bundleJavacSource}" target="${bundleJavacTarget}" >
+ <compilerarg line="${compilerArg}" compiler="${build.compiler}"/>
+ <classpath refid="compile.classpath" />
+ <src path="src/main/java/" />
+ <!--compilerarg value="@${basedir}/javaCompiler...args" compiler="org.eclipse.jdt.core.JDTCompilerAdapter" -->
+ <compilerarg line="-log '${temp.folder}/compile.bin${logExtension}'" compiler="org.eclipse.jdt.core.JDTCompilerAdapter"/>
+ </javac>
+ <!-- Copy necessary resources -->
+ <copy todir="${temp.folder}/compile.bin" failonerror="true" overwrite="false">
+ <fileset dir="src/main/java/" excludes="**/*.java, **/package.htm*" />
+ </copy>
+ <mkdir dir="${build.result.folder}"/>
+ <copy todir="${target.folder}/classes" failonerror="true" overwrite="false">
+ <fileset dir="${temp.folder}/compile.bin" />
+ </copy>
+ <delete dir="${temp.folder}/compile.bin"/>
+ </target>
+
+ <target name="src.zip" depends="init" unless="src.zip">
+ <mkdir dir="${build.result.folder}"/>
+ <zip destfile="${build.result.folder}/src.zip" filesonly="false" whenempty="skip" update="false">
+ <fileset dir="src/main/java/" includes="**/*.java" />
+ </zip>
+ </target>
+
+ <target name="build.jars" depends="init" description="Build all the jars for the plug-in: org.apache.qpid.management.ui.">
+ <available property="compile" file="${target.folder}/classes"/>
+ <antcall target="compile"/>
+ </target>
+
+ <target name="build.sources" depends="init">
+ <available property="src.zip" file="${build.result.folder}/src.zip"/>
+ <antcall target="src.zip"/>
+ </target>
+
+ <target name="gather.bin.parts" depends="init" if="destination.temp.folder">
+ <mkdir dir="${destination.temp.folder}/${pluginName}"/>
+ <copy todir="${destination.temp.folder}/${pluginName}" failonerror="true" overwrite="false">
+ <fileset dir="${target.folder}/classes" includes="**"/>
+ </copy>
+ <copy todir="${destination.temp.folder}/${pluginName}" failonerror="true" overwrite="false">
+ <fileset dir="${basedir}" includes="plugin.xml,META-INF/,icons/,plugin.properties,splash.bmp"/>
+ </copy>
+ </target>
+
+ <target name="gather.sources" depends="init" if="destination.temp.folder">
+ <mkdir dir="${destination.temp.folder}"/>
+ <copy file="${build.result.folder}/src.zip" todir="${destination.temp.folder}" failonerror="false" overwrite="false"/>
+ </target>
+
+ <target name="gather.logs" depends="init" if="destination.temp.folder">
+ <mkdir dir="${destination.temp.folder}/${pluginName}_${version}"/>
+ <copy file="${temp.folder}/compile.bin${logExtension}" todir="${destination.temp.folder}/${pluginName}_${version}" failonerror="false" overwrite="false"/>
+ </target>
+
+ <target name="clean" depends="init" description="Clean the plug-in: org.apache.qpid.management.ui of all the zips, jars and logs created.">
+ <delete dir="${target.folder}/classes"/>
+ <delete file="${build.result.folder}/src.zip"/>
+ <delete file="${plugins.folder}/${pluginName}_${version}.jar"/>
+ <delete file="${target.folder}/${pluginName}_${version}.zip"/>
+ <delete file="${target.folder}/${distName}_${version}.zip"/>
+ <delete dir="${temp.folder}"/>
+ </target>
+
+ <target name="build.zip" depends="init" description="Create a zip containing all the elements for the plug-in: org.apache.qpid.management.ui.">
+ <delete dir="${temp.folder}"/>
+ <mkdir dir="${temp.folder}"/>
+ <antcall target="build.update.jar"/>
+ <antcall target="build.sources"/>
+ <antcall target="gather.sources">
+ <param name="destination.temp.folder" value="${temp.folder}/plugins/${pluginName}_${version}/"/>
+ </antcall>
+ <delete>
+ <fileset dir="${temp.folder}" includes="**/*.bin${logExtension}"/>
+ </delete>
+ <copy todir="${temp.folder}/plugins" failonerror="true" overwrite="false">
+ <fileset dir="${plugins.folder}" includes="${pluginName}_${version}.jar"/>
+ </copy>
+ <zip destfile="${target.folder}/${pluginName}_${version}.zip" basedir="${temp.folder}" filesonly="true" whenempty="skip" update="false"/>
+ <delete dir="${temp.folder}"/>
+ </target>
+
+ <target name="dist" depends="init" description="Create a zip containing all the elements for deploying the plug-in: org.apache.qpid.management.ui.">
+ <antcall target="clean"/>
+ <antcall target="build.update.jar"/>
+ <antcall target="build.sources"/>
+ <antcall target="gather.sources">
+ <param name="destination.temp.folder" value="${temp.folder}/${distName}"/>
+ </antcall>
+ <copy todir="${temp.folder}/${distName}/plugins" failonerror="true" overwrite="false">
+ <fileset dir="${plugins.folder}" includes="**" />
+ </copy>
+ <copy todir="${temp.folder}/${distName}/bin" failonerror="true" overwrite="false">
+ <fileset dir="${basedir}/bin" includes="**" />
+ </copy>
+ <copy todir="${temp.folder}/${distName}" failonerror="true" overwrite="false">
+ <fileset dir="${basedir}" includes="startup.jar,plugin.xml,META-INF/,icons/,plugin.properties,splash.bmp"/>
+ </copy>
+ <copy todir="${temp.folder}/${distName}/configuration" failonerror="true" overwrite="false">
+ <fileset dir="${basedir}/configuration" includes="**"/>
+ </copy>
+
+ <delete>
+ <fileset dir="${temp.folder}" includes="**/*.bin${logExtension}"/>
+ </delete>
+ <zip destfile="${target.folder}/${distName}_${version}.zip" basedir="${temp.folder}" filesonly="true" whenempty="skip" update="false"/>
+ <delete dir="${temp.folder}"/>
+ </target>
+
+</project>
diff --git a/java/management/eclipse-plugin/configuration/config.ini b/java/management/eclipse-plugin/configuration/config.ini
new file mode 100644
index 0000000000..a0c5d002b0
--- /dev/null
+++ b/java/management/eclipse-plugin/configuration/config.ini
@@ -0,0 +1,25 @@
+###############################################################################
+# 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.
+###############################################################################
+
+#Product Runtime Configuration File
+
+osgi.splashPath=platform:/base/plugins/org.apache.qpid.management.ui
+eclipse.product=org.apache.qpid.management.ui.product
+osgi.bundles=org.eclipse.equinox.common@2:start,org.eclipse.core.runtime@start,com.ibm.icu,org.apache.qpid.management.ui,org.eclipse.core.commands,org.eclipse.core.contenttype,org.eclipse.core.expressions,org.eclipse.core.jobs,org.eclipse.core.runtime.compatibility.auth,org.eclipse.core.runtime.compatibility.registry,org.eclipse.equinox.preferences,org.eclipse.equinox.registry,org.eclipse.help,org.eclipse.jface,org.eclipse.swt,org.eclipse.swt.win32.win32.x86,org.eclipse.ui,org.eclipse.ui.forms,org.eclipse.ui.workbench
+osgi.bundles.defaultStartLevel=4
diff --git a/java/management/eclipse-plugin/configuration/org.eclipse.osgi/bundles/16/1/.cp/swt-win32-3232.dll b/java/management/eclipse-plugin/configuration/org.eclipse.osgi/bundles/16/1/.cp/swt-win32-3232.dll
new file mode 100644
index 0000000000..f028cec28d
--- /dev/null
+++ b/java/management/eclipse-plugin/configuration/org.eclipse.osgi/bundles/16/1/.cp/swt-win32-3232.dll
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/Thumbs.db b/java/management/eclipse-plugin/icons/Thumbs.db
new file mode 100644
index 0000000000..306bfb2eda
--- /dev/null
+++ b/java/management/eclipse-plugin/icons/Thumbs.db
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/add.gif b/java/management/eclipse-plugin/icons/add.gif
new file mode 100644
index 0000000000..252d7ebcb8
--- /dev/null
+++ b/java/management/eclipse-plugin/icons/add.gif
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/delete.gif b/java/management/eclipse-plugin/icons/delete.gif
new file mode 100644
index 0000000000..6f647666d3
--- /dev/null
+++ b/java/management/eclipse-plugin/icons/delete.gif
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/icon_ClosedFolder.gif b/java/management/eclipse-plugin/icons/icon_ClosedFolder.gif
new file mode 100644
index 0000000000..beb6ed134c
--- /dev/null
+++ b/java/management/eclipse-plugin/icons/icon_ClosedFolder.gif
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/icon_OpenFolder.gif b/java/management/eclipse-plugin/icons/icon_OpenFolder.gif
new file mode 100644
index 0000000000..a9c777343c
--- /dev/null
+++ b/java/management/eclipse-plugin/icons/icon_OpenFolder.gif
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/mbean_view.png b/java/management/eclipse-plugin/icons/mbean_view.png
new file mode 100644
index 0000000000..9871b72bb8
--- /dev/null
+++ b/java/management/eclipse-plugin/icons/mbean_view.png
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/notifications.gif b/java/management/eclipse-plugin/icons/notifications.gif
new file mode 100644
index 0000000000..f1e585bdf7
--- /dev/null
+++ b/java/management/eclipse-plugin/icons/notifications.gif
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/qpidConnections.gif b/java/management/eclipse-plugin/icons/qpidConnections.gif
new file mode 100644
index 0000000000..89489f11f2
--- /dev/null
+++ b/java/management/eclipse-plugin/icons/qpidConnections.gif
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/qpidmc.gif b/java/management/eclipse-plugin/icons/qpidmc.gif
new file mode 100644
index 0000000000..baf929fbc5
--- /dev/null
+++ b/java/management/eclipse-plugin/icons/qpidmc.gif
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/qpidmc32.bmp b/java/management/eclipse-plugin/icons/qpidmc32.bmp
new file mode 100644
index 0000000000..e42ce01dff
--- /dev/null
+++ b/java/management/eclipse-plugin/icons/qpidmc32.bmp
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/qpidmc32.gif b/java/management/eclipse-plugin/icons/qpidmc32.gif
new file mode 100644
index 0000000000..e42ce01dff
--- /dev/null
+++ b/java/management/eclipse-plugin/icons/qpidmc32.gif
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/reconnect.gif b/java/management/eclipse-plugin/icons/reconnect.gif
new file mode 100644
index 0000000000..e2f8c3e1fe
--- /dev/null
+++ b/java/management/eclipse-plugin/icons/reconnect.gif
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/refresh.gif b/java/management/eclipse-plugin/icons/refresh.gif
new file mode 100644
index 0000000000..a063c230ac
--- /dev/null
+++ b/java/management/eclipse-plugin/icons/refresh.gif
Binary files differ
diff --git a/java/management/eclipse-plugin/icons/stop.gif b/java/management/eclipse-plugin/icons/stop.gif
new file mode 100644
index 0000000000..dc47edf069
--- /dev/null
+++ b/java/management/eclipse-plugin/icons/stop.gif
Binary files differ
diff --git a/java/management/eclipse-plugin/plugin.properties b/java/management/eclipse-plugin/plugin.properties
new file mode 100644
index 0000000000..8507441886
--- /dev/null
+++ b/java/management/eclipse-plugin/plugin.properties
@@ -0,0 +1,20 @@
+###############################################################################
+# 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.
+###############################################################################
+pluginName = Qpid Management Console Plug-in
+providerName = Apache Software Foundation \ No newline at end of file
diff --git a/java/management/eclipse-plugin/plugin.xml b/java/management/eclipse-plugin/plugin.xml
new file mode 100644
index 0000000000..ed30d73532
--- /dev/null
+++ b/java/management/eclipse-plugin/plugin.xml
@@ -0,0 +1,222 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<?eclipse version="3.2"?>
+<!--
+ 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.
+-->
+<plugin>
+
+ <extension
+ id="application"
+ point="org.eclipse.core.runtime.applications">
+ <application>
+ <run
+ class="org.apache.qpid.management.ui.Application">
+ </run>
+ </application>
+ </extension>
+ <extension
+ point="org.eclipse.ui.perspectives">
+ <perspective
+ name="qpid.management.perspective"
+ class="org.apache.qpid.management.ui.Perspective"
+ id="org.apache.qpid.management.ui.perspective">
+ </perspective>
+ </extension>
+ <extension
+ point="org.eclipse.ui.views">
+ <category
+ id="org.apache.qpid.management.ui.viewcategory"
+ name="Qpid Management Console"/>
+ <view
+ allowMultiple="false"
+ category="org.apache.qpid.management.ui.viewcategory"
+ class="org.apache.qpid.management.ui.views.NavigationView"
+ icon="icons/qpidConnections.gif"
+ id="org.apache.qpid.management.ui.navigationView"
+ name="Qpid Connections">
+ </view>
+ <view
+ allowMultiple="false"
+ category="org.apache.qpid.management.ui.viewcategory"
+ class="org.apache.qpid.management.ui.views.MBeanView"
+ icon="icons/mbean_view.png"
+ id="org.apache.qpid.management.ui.mbeanView"
+ name="Qpid Management">
+ </view>
+ </extension>
+ <extension
+ point="org.eclipse.ui.commands">
+ <category
+ name="qpid.manager.commands"
+ id="org.apache.qpid.management.ui.category">
+ </category>
+ <command
+ name="New Connection"
+ description="Created a new Qpid server connection"
+ categoryId="org.apache.qpid.management.ui.category"
+ id="org.apache.qpid.management.ui.actions.cmd_add">
+ </command>
+ <command
+ categoryId="org.apache.qpid.management.ui.category"
+ description="Reconnect the Qpid server connection"
+ id="org.apache.qpid.management.ui.actions.cmd_reconnect"
+ name="Reconnect"/>
+ <command
+ categoryId="org.apache.qpid.management.ui.category"
+ description="Disconnects the Qpid server connection"
+ id="org.apache.qpid.management.ui.actions.cmd_disconnect"
+ name="Disconnect"/>
+ <command
+ categoryId="org.apache.qpid.management.ui.category"
+ description="Removes the server from management console"
+ id="org.apache.qpid.management.ui.actions.cmd_remove"
+ name="Remove Connection"/>
+ <command
+ categoryId="org.apache.qpid.management.ui.category"
+ description="refreshes the views"
+ id="org.apache.qpid.management.ui.actions.cmd_refresh"
+ name="Refresh"/>
+ <command
+ categoryId="org.apache.qpid.management.ui.category"
+ description="pops up the window for editing selected attribute"
+ id="org.apache.qpid.management.ui.actions.cmd_editAttribute"
+ name="Edit Attribute"/>
+ </extension>
+ <extension
+ point="org.eclipse.ui.bindings">
+ <key
+ commandId="org.apache.qpid.management.ui.actions.cmd_add"
+ schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
+ sequence="CTRL+Alt+N">
+ </key>
+ <key
+ commandId="org.apache.qpid.management.ui.actions.cmd_reconnect"
+ schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
+ sequence="CTRL+Alt+C"/>
+ <key
+ commandId="org.apache.qpid.management.ui.actions.cmd_disconnect"
+ schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
+ sequence="CTRL+Alt+D">
+ </key>
+ <key
+ commandId="org.apache.qpid.management.ui.actions.cmd_remove"
+ schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
+ sequence="CTRL+Alt+R"/>
+ <key
+ commandId="org.apache.qpid.management.ui.actions.cmd_refresh"
+ schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
+ sequence="CTRL+Alt+F5"/>
+ <key
+ commandId="org.apache.qpid.management.ui.actions.cmd_editAttribute"
+ schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
+ sequence="CTRL+Alt+E"/>
+ <key
+ commandId="org.eclipse.ui.file.exit"
+ schemeId="org.eclipse.ui.defaultAcceleratorConfiguration"
+ sequence="CTRL+Alt+X">
+ </key>
+ </extension>
+
+ <extension
+ id="product"
+ point="org.eclipse.core.runtime.products">
+ <product
+ application="org.apache.qpid.management.ui.application"
+ name="Qpid Management Console">
+ <property
+ name="about Qpid Management Console"
+ value="version 0.1.0">
+ </property>
+ <property
+ name="windowImages"
+ value="icons/qpidmc32.gif">
+ </property>
+ <property
+ name="aboutText"
+ value="Qpid Management Console&#x0A;version 0.1.0"/>
+ </product>
+ </extension>
+ <extension
+ point="org.eclipse.ui.actionSets">
+ <actionSet
+ id="org.apache.qpid.management.ui.actionSet"
+ label="Qpid Action Set"
+ visible="true">
+ <menu
+ id="qpidmanager"
+ label="&amp;Qpid Manager">
+ <separator name="qpidActionsGroup"/>
+ </menu>
+ <action
+ class="org.apache.qpid.management.ui.actions.EditAttribute"
+ definitionId="org.apache.qpid.management.ui.actions.cmd_editAttribute"
+ id="org.apache.qpid.management.ui.actions.editAttribute"
+ label="Edit Attribute"
+ menubarPath="qpidmanager/mbeanactions"
+ style="push"
+ tooltip="Edit Attribute"/>
+ <action
+ class="org.apache.qpid.management.ui.actions.Refresh"
+ definitionId="org.apache.qpid.management.ui.actions.cmd_refresh"
+ icon="icons/refresh.gif"
+ id="org.apache.qpid.management.ui.actions.refresh"
+ label="Refresh"
+ menubarPath="qpidmanager/additions"
+ style="push"
+ toolbarPath="qpidActionsGroup"
+ tooltip="Refresh"/>
+ <action
+ class="org.apache.qpid.management.ui.actions.RemoveServer"
+ definitionId="org.apache.qpid.management.ui.actions.cmd_remove"
+ icon="icons/delete.gif"
+ id="org.apache.qpid.management.ui.actions.remove"
+ label="Remove Connection"
+ menubarPath="qpidmanager/additions"
+ style="push"
+ toolbarPath="qpidActionsGroup"/>
+ <action
+ class="org.apache.qpid.management.ui.actions.CloseConnection"
+ definitionId="org.apache.qpid.management.ui.actions.cmd_disconnect"
+ icon="icons/stop.gif"
+ id="org.apache.qpid.management.ui.disconnect"
+ label="Disconnect"
+ menubarPath="qpidmanager/additions"
+ toolbarPath="qpidActionsGroup"
+ tooltip="Disconnect"/>
+ <action
+ class="org.apache.qpid.management.ui.actions.ReconnectServer"
+ definitionId="org.apache.qpid.management.ui.actions.cmd_reconnect"
+ icon="icons/reconnect.gif"
+ id="org.apache.qpid.management.ui.reconnect"
+ label="Reconnect"
+ menubarPath="qpidmanager/additions"
+ toolbarPath="qpidActionsGroup"
+ tooltip="Reconnect"/>
+ <action
+ class="org.apache.qpid.management.ui.actions.AddServer"
+ definitionId="org.apache.qpid.management.ui.actions.cmd_add"
+ icon="icons/add.gif"
+ id="org.apache.qpid.management.ui.add"
+ label="New Connection"
+ menubarPath="qpidmanager/additions"
+ toolbarPath="qpidActionsGroup"
+ tooltip="New Connection"/>
+ </actionSet>
+ </extension>
+
+</plugin>
diff --git a/java/management/eclipse-plugin/plugins/com.ibm.icu_3.4.4.1.jar b/java/management/eclipse-plugin/plugins/com.ibm.icu_3.4.4.1.jar
new file mode 100644
index 0000000000..c33f004a95
--- /dev/null
+++ b/java/management/eclipse-plugin/plugins/com.ibm.icu_3.4.4.1.jar
Binary files differ
diff --git a/java/management/eclipse-plugin/plugins/license.eclipse.txt b/java/management/eclipse-plugin/plugins/license.eclipse.txt
new file mode 100644
index 0000000000..da433e89f9
--- /dev/null
+++ b/java/management/eclipse-plugin/plugins/license.eclipse.txt
@@ -0,0 +1,88 @@
+Eclipse Public License - v 1.0
+
+THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
+
+1. DEFINITIONS
+
+"Contribution" means:
+
+a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and
+b) in the case of each subsequent Contributor:
+
+i) changes to the Program, and
+
+ii) additions to the Program;
+
+where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program.
+
+"Contributor" means any person or entity that distributes the Program.
+
+"Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program.
+
+"Program" means the Contributions distributed in accordance with this Agreement.
+
+"Recipient" means anyone who receives the Program under this Agreement, including all Contributors.
+
+2. GRANT OF RIGHTS
+
+a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form.
+
+b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder.
+
+c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program.
+
+d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement.
+
+3. REQUIREMENTS
+
+A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that:
+
+a) it complies with the terms and conditions of this Agreement; and
+
+b) its license agreement:
+
+i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose;
+
+ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits;
+
+iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and
+
+iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange.
+
+When the Program is made available in source code form:
+
+a) it must be made available under this Agreement; and
+
+b) a copy of this Agreement must be included with each copy of the Program.
+
+Contributors may not remove or alter any copyright notices contained within the Program.
+
+Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution.
+
+4. COMMERCIAL DISTRIBUTION
+
+Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense.
+
+For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages.
+
+5. NO WARRANTY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement , including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations.
+
+6. DISCLAIMER OF LIABILITY
+
+EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+7. GENERAL
+
+If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
+
+If Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed.
+
+All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive.
+
+Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. The Eclipse Foundation is the initial Agreement Steward. The Eclipse Foundation may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved.
+
+This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation.
+
+
diff --git a/java/management/eclipse-plugin/plugins/org.eclipse.core.commands_3.2.0.jar b/java/management/eclipse-plugin/plugins/org.eclipse.core.commands_3.2.0.jar
new file mode 100644
index 0000000000..215f09bf12
--- /dev/null
+++ b/java/management/eclipse-plugin/plugins/org.eclipse.core.commands_3.2.0.jar
Binary files differ
diff --git a/java/management/eclipse-plugin/plugins/org.eclipse.core.contenttype_3.2.0.jar b/java/management/eclipse-plugin/plugins/org.eclipse.core.contenttype_3.2.0.jar
new file mode 100644
index 0000000000..f7f8e93d22
--- /dev/null
+++ b/java/management/eclipse-plugin/plugins/org.eclipse.core.contenttype_3.2.0.jar
Binary files differ
diff --git a/java/management/eclipse-plugin/plugins/org.eclipse.core.expressions_3.2.0.jar b/java/management/eclipse-plugin/plugins/org.eclipse.core.expressions_3.2.0.jar
new file mode 100644
index 0000000000..9672474250
--- /dev/null
+++ b/java/management/eclipse-plugin/plugins/org.eclipse.core.expressions_3.2.0.jar
Binary files differ
diff --git a/java/management/eclipse-plugin/plugins/org.eclipse.core.jobs_3.2.0.jar b/java/management/eclipse-plugin/plugins/org.eclipse.core.jobs_3.2.0.jar
new file mode 100644
index 0000000000..63ae34b87b
--- /dev/null
+++ b/java/management/eclipse-plugin/plugins/org.eclipse.core.jobs_3.2.0.jar
Binary files differ
diff --git a/java/management/eclipse-plugin/plugins/org.eclipse.core.runtime.compatibility.auth_3.2.0.jar b/java/management/eclipse-plugin/plugins/org.eclipse.core.runtime.compatibility.auth_3.2.0.jar
new file mode 100644
index 0000000000..9e1a33cfa9
--- /dev/null
+++ b/java/management/eclipse-plugin/plugins/org.eclipse.core.runtime.compatibility.auth_3.2.0.jar
Binary files differ
diff --git a/java/management/eclipse-plugin/plugins/org.eclipse.core.runtime.compatibility.registry_3.2.0/META-INF/MANIFEST.MF b/java/management/eclipse-plugin/plugins/org.eclipse.core.runtime.compatibility.registry_3.2.0/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..0e8c61f1b7
--- /dev/null
+++ b/java/management/eclipse-plugin/plugins/org.eclipse.core.runtime.compatibility.registry_3.2.0/META-INF/MANIFEST.MF
@@ -0,0 +1,12 @@
+Manifest-Version: 1.0
+Bundle-Name: %fragmentName
+Bundle-ClassPath: runtime_registry_compatibility.jar
+Bundle-RequiredExecutionEnvironment: CDC-1.0/Foundation-1.0,J2SE-1.3
+Eclipse-PatchFragment: true
+Bundle-Vendor: %providerName
+Bundle-ManifestVersion: 2
+Fragment-Host: org.eclipse.equinox.registry
+Bundle-Localization: fragment
+Bundle-SymbolicName: org.eclipse.core.runtime.compatibility.registry
+Bundle-Version: 3.2.0.v20060603
+
diff --git a/java/management/eclipse-plugin/plugins/org.eclipse.core.runtime.compatibility.registry_3.2.0/runtime_registry_compatibility.jar b/java/management/eclipse-plugin/plugins/org.eclipse.core.runtime.compatibility.registry_3.2.0/runtime_registry_compatibility.jar
new file mode 100644
index 0000000000..aae3e74ad7
--- /dev/null
+++ b/java/management/eclipse-plugin/plugins/org.eclipse.core.runtime.compatibility.registry_3.2.0/runtime_registry_compatibility.jar
Binary files differ
diff --git a/java/management/eclipse-plugin/plugins/org.eclipse.core.runtime_3.2.0.jar b/java/management/eclipse-plugin/plugins/org.eclipse.core.runtime_3.2.0.jar
new file mode 100644
index 0000000000..3834c9802c
--- /dev/null
+++ b/java/management/eclipse-plugin/plugins/org.eclipse.core.runtime_3.2.0.jar
Binary files differ
diff --git a/java/management/eclipse-plugin/plugins/org.eclipse.equinox.common_3.2.0.jar b/java/management/eclipse-plugin/plugins/org.eclipse.equinox.common_3.2.0.jar
new file mode 100644
index 0000000000..ee0e7865c2
--- /dev/null
+++ b/java/management/eclipse-plugin/plugins/org.eclipse.equinox.common_3.2.0.jar
Binary files differ
diff --git a/java/management/eclipse-plugin/plugins/org.eclipse.equinox.preferences_3.2.0.jar b/java/management/eclipse-plugin/plugins/org.eclipse.equinox.preferences_3.2.0.jar
new file mode 100644
index 0000000000..32f8e048dc
--- /dev/null
+++ b/java/management/eclipse-plugin/plugins/org.eclipse.equinox.preferences_3.2.0.jar
Binary files differ
diff --git a/java/management/eclipse-plugin/plugins/org.eclipse.equinox.registry_3.2.0.jar b/java/management/eclipse-plugin/plugins/org.eclipse.equinox.registry_3.2.0.jar
new file mode 100644
index 0000000000..1fe65676d5
--- /dev/null
+++ b/java/management/eclipse-plugin/plugins/org.eclipse.equinox.registry_3.2.0.jar
Binary files differ
diff --git a/java/management/eclipse-plugin/plugins/org.eclipse.help_3.2.0.jar b/java/management/eclipse-plugin/plugins/org.eclipse.help_3.2.0.jar
new file mode 100644
index 0000000000..809be21af0
--- /dev/null
+++ b/java/management/eclipse-plugin/plugins/org.eclipse.help_3.2.0.jar
Binary files differ
diff --git a/java/management/eclipse-plugin/plugins/org.eclipse.jface_3.2.0.jar b/java/management/eclipse-plugin/plugins/org.eclipse.jface_3.2.0.jar
new file mode 100644
index 0000000000..5c7509b07e
--- /dev/null
+++ b/java/management/eclipse-plugin/plugins/org.eclipse.jface_3.2.0.jar
Binary files differ
diff --git a/java/management/eclipse-plugin/plugins/org.eclipse.osgi_3.2.0.jar b/java/management/eclipse-plugin/plugins/org.eclipse.osgi_3.2.0.jar
new file mode 100644
index 0000000000..5f86e420d6
--- /dev/null
+++ b/java/management/eclipse-plugin/plugins/org.eclipse.osgi_3.2.0.jar
Binary files differ
diff --git a/java/management/eclipse-plugin/plugins/org.eclipse.swt.win32.win32.x86_3.2.0.jar b/java/management/eclipse-plugin/plugins/org.eclipse.swt.win32.win32.x86_3.2.0.jar
new file mode 100644
index 0000000000..392713689c
--- /dev/null
+++ b/java/management/eclipse-plugin/plugins/org.eclipse.swt.win32.win32.x86_3.2.0.jar
Binary files differ
diff --git a/java/management/eclipse-plugin/plugins/org.eclipse.swt_3.2.0.jar b/java/management/eclipse-plugin/plugins/org.eclipse.swt_3.2.0.jar
new file mode 100644
index 0000000000..7e1dbb85da
--- /dev/null
+++ b/java/management/eclipse-plugin/plugins/org.eclipse.swt_3.2.0.jar
Binary files differ
diff --git a/java/management/eclipse-plugin/plugins/org.eclipse.ui.forms_3.2.0.jar b/java/management/eclipse-plugin/plugins/org.eclipse.ui.forms_3.2.0.jar
new file mode 100644
index 0000000000..9c1bee69f4
--- /dev/null
+++ b/java/management/eclipse-plugin/plugins/org.eclipse.ui.forms_3.2.0.jar
Binary files differ
diff --git a/java/management/eclipse-plugin/plugins/org.eclipse.ui.workbench.compatibility_3.2.0/META-INF/MANIFEST.MF b/java/management/eclipse-plugin/plugins/org.eclipse.ui.workbench.compatibility_3.2.0/META-INF/MANIFEST.MF
new file mode 100644
index 0000000000..04a1db7c85
--- /dev/null
+++ b/java/management/eclipse-plugin/plugins/org.eclipse.ui.workbench.compatibility_3.2.0/META-INF/MANIFEST.MF
@@ -0,0 +1,12 @@
+Manifest-Version: 1.0
+Bundle-Name: %fragmentName
+Bundle-RequiredExecutionEnvironment: J2SE-1.4
+Bundle-Vendor: %providerName
+Bundle-ManifestVersion: 2
+Fragment-Host: org.eclipse.ui.workbench;bundle-version="[3.0.0,4.0.0)"
+Bundle-Localization: fragment-compatibility
+Bundle-SymbolicName: org.eclipse.ui.workbench.compatibility
+Require-Bundle: org.eclipse.core.resources;bundle-version="[3.2.0,4.0.
+ 0)"
+Bundle-Version: 3.2.0.I20060605-1400
+
diff --git a/java/management/eclipse-plugin/plugins/org.eclipse.ui.workbench.compatibility_3.2.0/compatibility.jar b/java/management/eclipse-plugin/plugins/org.eclipse.ui.workbench.compatibility_3.2.0/compatibility.jar
new file mode 100644
index 0000000000..13682c5d36
--- /dev/null
+++ b/java/management/eclipse-plugin/plugins/org.eclipse.ui.workbench.compatibility_3.2.0/compatibility.jar
Binary files differ
diff --git a/java/management/eclipse-plugin/plugins/org.eclipse.ui.workbench_3.2.0.jar b/java/management/eclipse-plugin/plugins/org.eclipse.ui.workbench_3.2.0.jar
new file mode 100644
index 0000000000..40e7d55f58
--- /dev/null
+++ b/java/management/eclipse-plugin/plugins/org.eclipse.ui.workbench_3.2.0.jar
Binary files differ
diff --git a/java/management/eclipse-plugin/plugins/org.eclipse.ui_3.2.0.jar b/java/management/eclipse-plugin/plugins/org.eclipse.ui_3.2.0.jar
new file mode 100644
index 0000000000..5821d85bac
--- /dev/null
+++ b/java/management/eclipse-plugin/plugins/org.eclipse.ui_3.2.0.jar
Binary files differ
diff --git a/java/management/eclipse-plugin/splash.bmp b/java/management/eclipse-plugin/splash.bmp
new file mode 100644
index 0000000000..b528a508c5
--- /dev/null
+++ b/java/management/eclipse-plugin/splash.bmp
Binary files differ
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
new file mode 100644
index 0000000000..61b6cfaa59
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Activator.java
@@ -0,0 +1,84 @@
+/*
+ *
+ * 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.management.ui;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+/**
+ * The activator class controls the plug-in life cycle
+ */
+public class Activator extends AbstractUIPlugin
+{
+ // The plug-in ID
+ public static final String PLUGIN_ID = "org.apache.qpid.management.ui";
+
+ // The shared instance
+ private static Activator plugin;
+
+ /**
+ * The constructor
+ */
+ public Activator()
+ {
+ plugin = this;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception
+ {
+ super.start(context);
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception
+ {
+ plugin = null;
+ super.stop(context);
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static Activator getDefault() {
+ return plugin;
+ }
+
+ /**
+ * 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) {
+ 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
new file mode 100644
index 0000000000..3d014e6968
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Application.java
@@ -0,0 +1,63 @@
+/*
+ *
+ * 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.management.ui;
+
+import org.eclipse.core.runtime.IPlatformRunnable;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.PlatformUI;
+
+/**
+ * This class controls all aspects of the application's execution
+ * @author Bhupendra Bhardwaj
+ */
+public class Application implements IPlatformRunnable
+{
+ static Shell shell = null;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.eclipse.core.runtime.IPlatformRunnable#run(java.lang.Object)
+ */
+ public Object run(Object args) throws Exception
+ {
+ Display display = PlatformUI.createDisplay();
+ try
+ {
+ int returnCode = PlatformUI.createAndRunWorkbench(display,
+ new ApplicationWorkbenchAdvisor());
+ if (returnCode == PlatformUI.RETURN_RESTART)
+ {
+ return IPlatformRunnable.EXIT_RESTART;
+ }
+ return IPlatformRunnable.EXIT_OK;
+ } finally
+ {
+ display.dispose();
+ }
+ }
+
+ static Shell getActiveShell()
+ {
+ return shell;
+ }
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationActionBarAdvisor.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationActionBarAdvisor.java
new file mode 100644
index 0000000000..9015b74f3f
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationActionBarAdvisor.java
@@ -0,0 +1,96 @@
+/*
+ *
+ * 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.management.ui;
+
+import org.eclipse.jface.action.GroupMarker;
+import org.eclipse.jface.action.ICoolBarManager;
+import org.eclipse.jface.action.IMenuManager;
+import org.eclipse.jface.action.MenuManager;
+import org.eclipse.jface.action.Separator;
+import org.eclipse.ui.IWorkbenchActionConstants;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.actions.ActionFactory;
+import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
+import org.eclipse.ui.application.ActionBarAdvisor;
+import org.eclipse.ui.application.IActionBarConfigurer;
+
+/**
+ * An action bar advisor is responsible for creating, adding, and disposing of the
+ * actions added to a workbench window. Each window will be populated with
+ * new actions.
+ */
+public class ApplicationActionBarAdvisor extends ActionBarAdvisor
+{
+
+ // Actions - important to allocate these only in makeActions, and then use them
+ // in the fill methods. This ensures that the actions aren't recreated
+ // when fillActionBars is called with FILL_PROXY.
+ private IWorkbenchAction exitAction;
+ private IWorkbenchAction aboutAction;
+
+
+ public ApplicationActionBarAdvisor(IActionBarConfigurer configurer)
+ {
+ super(configurer);
+ }
+
+ protected void makeActions(final IWorkbenchWindow window)
+ {
+ // Creates the actions and registers them.
+ // Registering is needed to ensure that key bindings work.
+ // The corresponding commands keybindings are defined in the plugin.xml file.
+ // Registering also provides automatic disposal of the actions when
+ // the window is closed.
+
+ exitAction = ActionFactory.QUIT.create(window);
+ register(exitAction);
+
+ aboutAction = ActionFactory.ABOUT.create(window);
+ register(aboutAction);
+ }
+
+
+ protected void fillMenuBar(IMenuManager menuBar)
+ {
+ MenuManager fileMenu = new MenuManager("&Qpid Manager", "qpidmanager");
+ MenuManager helpMenu = new MenuManager("&Help", IWorkbenchActionConstants.M_HELP);
+
+ menuBar.add(fileMenu);
+ // Add a group marker indicating where action set menus will appear.
+ menuBar.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
+ menuBar.add(helpMenu);
+
+ fileMenu.add(new GroupMarker(IWorkbenchActionConstants.MB_ADDITIONS));
+ fileMenu.add(new Separator());
+ fileMenu.add(new GroupMarker("mbeanactions"));
+ fileMenu.add(new Separator());
+ fileMenu.add(exitAction);
+
+ // Help
+ //aboutAction.setText("about Qpid Management Console");
+ helpMenu.add(aboutAction);
+ }
+
+ protected void fillCoolBar(ICoolBarManager coolBar)
+ {
+
+ }
+}
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
new file mode 100644
index 0000000000..175130aea9
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java
@@ -0,0 +1,129 @@
+/*
+ *
+ * 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.management.ui;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import org.eclipse.jface.resource.FontRegistry;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.FontData;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.ui.ISharedImages;
+import org.eclipse.ui.PlatformUI;
+
+public abstract class ApplicationRegistry
+{
+ private static ImageRegistry imageRegistry = new ImageRegistry();
+ private static FontRegistry fontRegistry = new FontRegistry();
+
+ static
+ {
+ imageRegistry.put(Constants.CONSOLE_IMAGE,
+ org.apache.qpid.management.ui.Activator.getImageDescriptor("/icons/qpidmc.gif"));
+ imageRegistry.put(Constants.CLOSED_FOLDER_IMAGE,
+ org.apache.qpid.management.ui.Activator.getImageDescriptor("/icons/icon_ClosedFolder.gif"));
+ imageRegistry.put(Constants.OPEN_FOLDER_IMAGE,
+ PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_FOLDER));
+ imageRegistry.put(Constants.MBEAN_IMAGE,
+ PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_ELEMENT));
+ imageRegistry.put(Constants.NOTIFICATION_IMAGE,
+ org.apache.qpid.management.ui.Activator.getImageDescriptor("/icons/notifications.gif"));
+ }
+
+ static
+ {
+ fontRegistry.put(Constants.FONT_BUTTON, new FontData[]{new FontData("Arial", 8, SWT.BOLD)} );
+ fontRegistry.put(Constants.FONT_BOLD, new FontData[]{new FontData("Bold", 9, SWT.BOLD)} );
+ fontRegistry.put(Constants.FONT_ITALIC, new FontData[]{new FontData("Italic", 9, SWT.ITALIC)} );
+ fontRegistry.put(Constants.FONT_TABLE_CELL, new FontData[]{new FontData("Tablecell", 8, SWT.NORMAL)} );
+ fontRegistry.put(Constants.FONT_NORMAL, new FontData[]{new FontData("Normal", 9, SWT.NORMAL)} );
+ }
+
+ /*
+ * This maps all the managed servers to the respective server registry.
+ * Server can be JMX MBeanServer or a C++ server
+ */
+ private static HashMap<ManagedServer, ServerRegistry> _serverRegistryMap = new HashMap<ManagedServer, ServerRegistry>();
+
+ // This map gets updated when a server connection closes.
+ private static List<ManagedServer> _closedServerList = new CopyOnWriteArrayList<ManagedServer>();
+
+ public static Image getImage(String key)
+ {
+ return imageRegistry.get(key);
+ }
+
+ public static Font getFont(String key)
+ {
+ return fontRegistry.get(key);
+ }
+
+ public static void addServer(ManagedServer server, ServerRegistry registry)
+ {
+ _serverRegistryMap.put(server, registry);
+ }
+
+ public static void removeServer(ManagedServer server)
+ {
+ _serverRegistryMap.remove(server);
+ }
+
+ public static ServerRegistry getServerRegistry(ManagedServer server)
+ {
+ return _serverRegistryMap.get(server);
+ }
+
+ public static ServerRegistry getServerRegistry(ManagedBean mbean)
+ {
+ ManagedServer server = mbean.getServer();
+ return _serverRegistryMap.get(server);
+ }
+
+ public static boolean isServerConnected(ManagedServer server)
+ {
+ return _serverRegistryMap.containsKey(server);
+ }
+
+ // remove the server from the registry
+ public static void serverConnectionClosed(ManagedServer server)
+ {
+ _closedServerList.add(server);
+ _serverRegistryMap.remove(server);
+ }
+
+ /*
+ * Returns the lis of closed servers. The Thread in GUI, which keeps checking for closed connection
+ * will check this and will remove the server links from the GUI.
+ */
+ public static List<ManagedServer> getClosedServers()
+ {
+ if (_closedServerList.isEmpty())
+ return null;
+
+ List<ManagedServer> list = new CopyOnWriteArrayList<ManagedServer>(_closedServerList);
+ _closedServerList.clear();
+ return list;
+ }
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchAdvisor.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchAdvisor.java
new file mode 100644
index 0000000000..a46fa870e4
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchAdvisor.java
@@ -0,0 +1,46 @@
+/*
+ *
+ * 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.management.ui;
+
+import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
+import org.eclipse.ui.application.WorkbenchAdvisor;
+import org.eclipse.ui.application.WorkbenchWindowAdvisor;
+
+/**
+ * This workbench advisor creates the window advisor, and specifies
+ * the perspective id for the initial window.
+ */
+public class ApplicationWorkbenchAdvisor extends WorkbenchAdvisor
+{
+ public static final String PERSPECTIVE_ID = "org.apache.qpid.management.ui.perspective";
+
+ public WorkbenchWindowAdvisor createWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer)
+ {
+ return new ApplicationWorkbenchWindowAdvisor(configurer);
+ }
+
+
+ public String getInitialWindowPerspectiveId()
+ {
+ return PERSPECTIVE_ID;
+ }
+
+}
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
new file mode 100644
index 0000000000..472d003657
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchWindowAdvisor.java
@@ -0,0 +1,61 @@
+/*
+ *
+ * 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.management.ui;
+
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.ui.application.ActionBarAdvisor;
+import org.eclipse.ui.application.IActionBarConfigurer;
+import org.eclipse.ui.application.IWorkbenchWindowConfigurer;
+import org.eclipse.ui.application.WorkbenchWindowAdvisor;
+
+public class ApplicationWorkbenchWindowAdvisor extends WorkbenchWindowAdvisor
+{
+ public ApplicationWorkbenchWindowAdvisor(IWorkbenchWindowConfigurer configurer)
+ {
+ super(configurer);
+ }
+
+ public ActionBarAdvisor createActionBarAdvisor(IActionBarConfigurer configurer)
+ {
+ return new ApplicationActionBarAdvisor(configurer);
+ }
+
+ public void preWindowOpen()
+ {
+ IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
+ int x = Display.getDefault().getBounds().width;
+ int y = Display.getDefault().getBounds().height;
+ configurer.setInitialSize(new Point(4*x/5, 3*y/4));
+ configurer.setShowCoolBar(true);
+ configurer.setShowStatusLine(false);
+
+ configurer.setTitle("Qpid Management Console");
+ }
+
+ public void postWindowCreate()
+ {
+ IWorkbenchWindowConfigurer configurer = getWindowConfigurer();
+ Shell shell = configurer.getWindow().getShell();
+ shell.setImage(ApplicationRegistry.getImage(Constants.CONSOLE_IMAGE));
+ }
+} \ No newline at end of file
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
new file mode 100644
index 0000000000..1678cbac62
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Constants.java
@@ -0,0 +1,79 @@
+/*
+ *
+ * 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.management.ui;
+
+public class Constants
+{
+ public final static String APPLICATION_NAME = "Qpid Management Console";
+ public final static String ITEM_VALUE = "value";
+ public final static String ITEM_TYPE = "type";
+ public final static String SERVER = "server";
+ public final static String DOMAIN = "domain";
+ public final static String TYPE = "mbeantype";
+ public final static String MBEAN = "mbean";
+ public final static String ATTRIBUTES = "Attributes";
+ public final static String NOTIFICATION = "Notifications";
+
+ public final static String ALL = "All";
+
+ public final static String NAVIGATION_ROOT = "Qpid Connections";
+ public final static String DESCRIPTION = " Description : ";
+
+ public final static String BROKER_MANAGER = "Broker_Manager";
+ public final static String QUEUE = "Queue";
+ public final static String EXCHANGE = "Exchange";
+ public final static String EXCHANGE_TYPE = "ExchangeType";
+ public final static String[] EXCHANGE_TYPE_VALUES = {"direct", "topic", "headers"};
+ public final static String CONNECTION ="Connection";
+
+ public final static String ACTION_ADDSERVER = "New Connection";
+
+
+ public final static String SUBSCRIBE_BUTTON = "Subscribe";
+ public final static String UNSUBSCRIBE_BUTTON = "Unsubscribe";
+
+ public final static String CONSOLE_IMAGE = "ConsoelImage";
+ public final static String CLOSED_FOLDER_IMAGE = "ClosedFolderImage";
+ public final static String OPEN_FOLDER_IMAGE = "OpenFolderImage";
+ public final static String MBEAN_IMAGE = "MBeanImage";
+ public final static String NOTIFICATION_IMAGE = "NotificationImage";
+
+ public final static String FONT_BUTTON = "ButtonFont";
+ public final static String FONT_BOLD = "BoldFont";
+ public final static String FONT_ITALIC = "ItalicFont";
+ public final static String FONT_TABLE_CELL = "TableCellFont";
+ public final static String FONT_NORMAL = "Normal";
+
+ public final static String BUTTON_DETAILS = "Details";
+ public final static String BUTTON_EDIT_ATTRIBUTE = "Edit Attribute";
+ public final static String BUTTON_REFRESH = "Refresh";
+ public final static String BUTTON_GRAPH = "Graph";
+ public final static int TIMER_INTERVAL = 5000;
+ public final static String BUTTON_EXECUTE = "Execute";
+ public final static String BUTTON_CLEAR = "Clear";
+ public final static String BUTTON_CONNECT = "Connect";
+ public final static String BUTTON_CANCEL = "Cancel";
+
+ public final static int OPERATION_IMPACT_INFO = 0;
+ public final static int OPERATION_IMPACT_ACTION = 1;
+ public final static int OPERATION_IMPACT_ACTIONINFO = 2;
+ public final static int OPERATION_IMPACT_UNKNOWN = 3;
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ICommandIds.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ICommandIds.java
new file mode 100644
index 0000000000..12dea649c6
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ICommandIds.java
@@ -0,0 +1,36 @@
+/*
+ *
+ * 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.management.ui;
+
+/**
+ * Interface defining the application's command IDs.
+ * Key bindings can be defined for specific commands.
+ * To associate an action with a command, use IAction.setActionDefinitionId(commandId).
+ *
+ * @see org.eclipse.jface.action.IAction#setActionDefinitionId(String)
+ */
+public interface ICommandIds
+{
+ //public static final String CMD_ADD_SERVER = "org.apache.qpid.management.ui.add";
+ //public static final String CMD_RECONNECT_SERVER = "org.apache.qpid.management.ui.reconnect";
+ //public static final String CMD_DISCONNECT_SERVER = "org.apache.qpid.management.ui.disconnect";
+ //public static final String CMD_REFRESH = "org.apache.qpid.management.ui.actions.refresh";
+}
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
new file mode 100644
index 0000000000..767fd8b721
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedBean.java
@@ -0,0 +1,80 @@
+/*
+ *
+ * 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.management.ui;
+
+import java.util.HashMap;
+
+public abstract class ManagedBean extends ManagedObject
+{
+ private String _uniqueName = "";
+ private String _domain = "";
+ private String _type = "";
+ private ManagedServer _server = null;
+ private HashMap _properties = null;
+
+ public String getProperty(String key)
+ {
+ return (String)_properties.get(key);
+ }
+
+ public HashMap getProperties()
+ {
+ return _properties;
+ }
+ public void setProperties(HashMap properties)
+ {
+ this._properties = properties;
+ }
+ public String getDomain()
+ {
+ return _domain;
+ }
+ public void setDomain(String domain)
+ {
+ this._domain = domain;
+ }
+
+ public ManagedServer getServer()
+ {
+ return _server;
+ }
+ public void setServer(ManagedServer server)
+ {
+ this._server = server;
+ }
+ public String getType()
+ {
+ return _type;
+ }
+ public void setType(String type)
+ {
+ this._type = type;
+ }
+ public String getUniqueName()
+ {
+ return _uniqueName;
+ }
+ public void setUniqueName(String uniqueName)
+ {
+ this._uniqueName = uniqueName;
+ }
+
+}
diff --git a/java/common/src/main/java/org/apache/qpid/framing/FieldTableKeyEnumeration.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedObject.java
index e3ba9080c7..2ed463bdf8 100644
--- a/java/common/src/main/java/org/apache/qpid/framing/FieldTableKeyEnumeration.java
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedObject.java
@@ -18,30 +18,19 @@
* under the License.
*
*/
-package org.apache.qpid.framing;
+package org.apache.qpid.management.ui;
-import java.util.Enumeration;
-import java.util.Iterator;
-
-
-public class FieldTableKeyEnumeration implements Enumeration
+public abstract class ManagedObject
{
- protected FieldTable _table;
- protected Iterator _iterator;
-
- public FieldTableKeyEnumeration(FieldTable ft)
- {
- _table = ft;
- _iterator = ft.keySet().iterator();
- }
+ private String _name;
- public boolean hasMoreElements()
+ public String getName()
{
- return _iterator.hasNext();
+ return _name;
}
- public Object nextElement()
+ public void setName(String name)
{
- return _iterator.next();
+ this._name = 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
new file mode 100644
index 0000000000..44f933a5d1
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedServer.java
@@ -0,0 +1,75 @@
+/*
+ *
+ * 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.management.ui;
+
+public class ManagedServer extends ManagedObject
+{
+ private String host;
+ private String port;
+ private String url;
+ private String domain;
+
+ public ManagedServer(String host, String port, String domain)
+ {
+ this.host = host;
+ this.port = port;
+ this.domain = domain;
+ setName(host + ":" + port);
+ }
+
+ public ManagedServer(String url, String domain)
+ {
+ this.url = url;
+ this.domain = domain;
+ }
+
+ public String getDomain()
+ {
+ return domain;
+ }
+
+ public String getHost()
+ {
+ return host;
+ }
+
+ public String getPort()
+ {
+ return port;
+ }
+
+ public String getUrl()
+ {
+ return url;
+ }
+
+ public void setHostAndPort(String host, String port)
+ {
+ this.host = host;
+ this.port = port;
+ setName(host + ":" + port);
+ }
+
+ public void setUrl(String url)
+ {
+ this.url = url;
+ }
+}
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
new file mode 100644
index 0000000000..03477cb117
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Perspective.java
@@ -0,0 +1,53 @@
+/*
+ *
+ * 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.management.ui;
+
+import org.apache.qpid.management.ui.views.MBeanView;
+import org.apache.qpid.management.ui.views.NavigationView;
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.IPerspectiveFactory;
+
+public class Perspective implements IPerspectiveFactory
+{
+ public void createInitialLayout(IPageLayout layout)
+ {
+ 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);
+
+ 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/ServerRegistry.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ServerRegistry.java
new file mode 100644
index 0000000000..0beeda84dd
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ServerRegistry.java
@@ -0,0 +1,79 @@
+/*
+ *
+ * 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.management.ui;
+
+
+import java.util.List;
+
+import org.apache.qpid.management.ui.jmx.ClientListener;
+import org.apache.qpid.management.ui.model.NotificationObject;
+import org.apache.qpid.management.ui.model.OperationDataModel;
+
+public abstract class ServerRegistry
+{
+ private ManagedServer _managedServer = null;
+
+ public ServerRegistry()
+ {
+
+ }
+
+ public ServerRegistry(ManagedServer server)
+ {
+ _managedServer = server;
+ }
+
+ public ManagedServer getManagedServer()
+ {
+ return _managedServer;
+ }
+
+ public void setManagedServer(ManagedServer server)
+ {
+ _managedServer = server;
+ }
+
+ public abstract Object getServerConnection();
+
+ public abstract void closeServerConnection() throws Exception;
+
+ public abstract OperationDataModel getOperationModel(ManagedBean mbean);
+
+ public abstract String[] getQueueNames();
+
+ public abstract String[] getExchangeNames();
+
+ public abstract List<NotificationObject> getNotifications(ManagedBean mbean);
+
+ public abstract boolean hasSubscribedForNotifications(ManagedBean mbean, String name, String type);
+
+ public abstract void clearNotifications(ManagedBean mbean);
+
+ public ClientListener getNotificationListener()
+ {
+ return null;
+ }
+
+ public ClientListener getClientListener()
+ {
+ return null;
+ }
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AddServer.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AddServer.java
new file mode 100644
index 0000000000..14c214ad5f
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AddServer.java
@@ -0,0 +1,282 @@
+/*
+ *
+ * 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.management.ui.actions;
+
+import org.apache.qpid.management.ui.ApplicationRegistry;
+import org.apache.qpid.management.ui.ApplicationWorkbenchAdvisor;
+import org.apache.qpid.management.ui.Constants;
+import org.apache.qpid.management.ui.exceptions.InfoRequiredException;
+import org.apache.qpid.management.ui.views.NavigationView;
+import org.apache.qpid.management.ui.views.ViewUtility;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+public class AddServer/* extends Action*/ implements IWorkbenchWindowActionDelegate
+{
+ private IWorkbenchWindow _window;
+ private static final String[] _connectionTypes ={"RMI"};
+ private static final String[] _domains ={"org.apache.qpid"};
+
+ public AddServer()
+ {
+
+ }
+
+ /*
+ public AddServer(IWorkbenchWindow window)//, String label)
+ {
+ _window = window;
+ //setText(label);
+ // The id is used to refer to the action in a menu or toolbar
+ setId(ICommandIds.CMD_ADD_SERVER);
+ // Associate the action with a pre-defined command, to allow key bindings.
+ setActionDefinitionId(ICommandIds.CMD_ADD_SERVER);
+ //setImageDescriptor(org.apache.qpid.management.ui.Activator.getImageDescriptor("/icons/add.gif"));
+ }
+ */
+
+ public void run(IAction action)
+ {
+ if(_window != null)
+ {
+ try
+ {
+ // TODO
+ //_window.getActivePage().showView(NavigationView.ID, Integer.toString(0), IWorkbenchPage.VIEW_ACTIVATE);
+ //_window.getActivePage().showView(MBeanView.ID, Integer.toString(0), IWorkbenchPage.VIEW_ACTIVATE);
+ }
+ catch (Exception ex)
+ {
+
+ }
+ createWidgets();
+ }
+ }
+
+ /**
+ * Selection in the workbench has been changed. We
+ * can change the state of the 'real' action here
+ * if we want, but this can only happen after
+ * the delegate has been created.
+ * @see IWorkbenchWindowActionDelegate#selectionChanged
+ */
+ public void selectionChanged(IAction action, ISelection selection) {
+ }
+
+ /**
+ * We can use this method to dispose of any system
+ * resources we previously allocated.
+ * @see IWorkbenchWindowActionDelegate#dispose
+ */
+ public void dispose() {
+ }
+
+ /**
+ * We will cache window object in order to
+ * be able to provide parent shell for the message dialog.
+ * @see IWorkbenchWindowActionDelegate#init
+ */
+ public void init(IWorkbenchWindow window) {
+ this._window = window;
+ }
+
+
+ /*
+ public void run()
+ {
+ if(_window != null)
+ {
+ createWidgets();
+ }
+ }
+ */
+ private void createWidgets()
+ {
+ Display display = Display.getCurrent();
+ final Shell shell = new Shell(display, SWT.BORDER | SWT.CLOSE);
+ shell.setText(Constants.ACTION_ADDSERVER);
+ shell.setLayout(new GridLayout());
+
+ int x = display.getBounds().width;
+ int y = display.getBounds().height;
+ shell.setBounds(x/4, y/4, 425, 250);
+
+ Composite composite = new Composite(shell, SWT.NONE);
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ GridLayout layout = new GridLayout(2, false);
+ layout.horizontalSpacing = 10;
+ layout.verticalSpacing = 10;
+ layout.marginHeight = 20;
+ layout.marginWidth = 20;
+ composite.setLayout(layout);
+
+ Label name = new Label(composite, SWT.NONE);
+ name.setText("Connection Type");
+ GridData layoutData = new GridData(SWT.TRAIL, SWT.TOP, false, false);
+ name.setLayoutData(layoutData);
+
+ final Combo comboTransport = new Combo(composite, SWT.READ_ONLY);
+ comboTransport.setItems(_connectionTypes);
+ comboTransport.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ comboTransport.select(0);
+
+ Label host = new Label(composite, SWT.NONE);
+ host.setText("Host");
+ host.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, false, false));
+
+ final Text textHost = new Text(composite, SWT.BORDER);
+ textHost.setText("");
+ textHost.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ textHost.setFocus();
+ textHost.addVerifyListener(new VerifyListener(){
+ public void verifyText(VerifyEvent event)
+ {
+ if (!(Character.isLetterOrDigit(event.character) ||
+ (event.character == '.') ||
+ (event.character == '\b') ))
+ {
+ event.doit = false;
+ }
+ }
+ });
+
+
+ Label port = new Label(composite, SWT.NONE);
+ port.setText("Port");
+ port.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, false, false));
+
+ final Text textPort = new Text(composite, SWT.BORDER);
+ textPort.setText("");
+ textPort.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ textPort.addVerifyListener(new VerifyListener(){
+ public void verifyText(VerifyEvent event)
+ {
+ if (textPort.getText().length() == 4)
+ event.doit = false;
+ else if (!(Character.isDigit(event.character) ||
+ (event.character == '\b')))
+ {
+ event.doit = false;
+ }
+ }
+ });
+
+
+ Label domain = new Label(composite, SWT.NONE);
+ domain.setText("Domain");
+ domain.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, false, false));
+
+ final Combo comboDomain = new Combo(composite, SWT.DROP_DOWN | SWT.READ_ONLY);
+ comboDomain.setItems(_domains);
+ comboDomain.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ comboDomain.select(0);
+
+ Composite buttonsComposite = new Composite(composite, SWT.NONE);
+ buttonsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1));
+ buttonsComposite.setLayout(new GridLayout(2, true));
+
+
+ final Button connectButton = new Button(buttonsComposite, SWT.PUSH | SWT.CENTER);
+ connectButton.setText(Constants.BUTTON_CONNECT);
+ GridData gridData = new GridData (SWT.TRAIL, SWT.BOTTOM, true, true);
+ gridData.widthHint = 100;
+ connectButton.setLayoutData(gridData);
+ connectButton.setFont(ApplicationRegistry.getFont(Constants.FONT_BUTTON));
+ connectButton.addSelectionListener(new SelectionAdapter(){
+ public void widgetSelected(SelectionEvent event)
+ {
+ String transport = comboTransport.getText();
+ String host = textHost.getText();
+ String port = textPort.getText();
+ String domain = comboDomain.getText();
+
+ NavigationView view = (NavigationView)_window.getActivePage().findView(NavigationView.ID);
+ try
+ {
+ view.addNewServer(transport, host, port, domain);
+
+ if (!connectButton.getShell().isDisposed())
+ connectButton.getShell().dispose();
+ }
+ catch(InfoRequiredException ex)
+ {
+ ViewUtility.popupInfoMessage("New connection", ex.getMessage());
+ }
+ catch(Exception ex)
+ {
+ IStatus status = new Status(IStatus.ERROR, ApplicationWorkbenchAdvisor.PERSPECTIVE_ID,
+ IStatus.OK, ex.getMessage(), ex.getCause());
+ ErrorDialog.openError(shell, "Error", "Server could not be added", status);
+ }
+ }
+ });
+
+ final Button cancelButton = new Button(buttonsComposite, SWT.PUSH);
+ cancelButton.setText(Constants.BUTTON_CANCEL);
+ gridData = new GridData (SWT.LEAD, SWT.BOTTOM, true, true);
+ gridData.widthHint = 100;
+ cancelButton.setLayoutData(gridData);
+ cancelButton.setFont(ApplicationRegistry.getFont(Constants.FONT_BUTTON));
+ cancelButton.addSelectionListener(new SelectionAdapter(){
+ public void widgetSelected(SelectionEvent event)
+ {
+ shell.dispose();
+ }
+ });
+
+ shell.open();
+ _window.getShell().setEnabled(false);
+ while (!shell.isDisposed())
+ {
+ if (!display.readAndDispatch())
+ {
+ display.sleep();
+ }
+ }
+
+ //If you create it, you dispose it.
+ shell.dispose();
+
+ // enable the main shell
+ _window.getShell().setEnabled(true);
+ _window.getShell().open();
+ }
+
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/CloseConnection.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/CloseConnection.java
new file mode 100644
index 0000000000..3f44274a92
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/CloseConnection.java
@@ -0,0 +1,93 @@
+/*
+ *
+ * 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.management.ui.actions;
+
+import org.apache.qpid.management.ui.ApplicationWorkbenchAdvisor;
+import org.apache.qpid.management.ui.exceptions.InfoRequiredException;
+import org.apache.qpid.management.ui.views.NavigationView;
+import org.apache.qpid.management.ui.views.ViewUtility;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+public class CloseConnection implements IWorkbenchWindowActionDelegate
+{
+ private IWorkbenchWindow _window;
+
+ public CloseConnection()
+ {
+
+ }
+
+ public void run(IAction action)
+ {
+ if(_window != null)
+ {
+ NavigationView view = (NavigationView)_window.getActivePage().findView(NavigationView.ID);
+ try
+ {
+ view.disconnect();
+ }
+ catch(InfoRequiredException ex)
+ {
+ ViewUtility.popupInfoMessage("Close connection", ex.getMessage());
+ }
+ catch(Exception ex)
+ {
+ IStatus status = new Status(IStatus.ERROR, ApplicationWorkbenchAdvisor.PERSPECTIVE_ID,
+ IStatus.OK, ex.getMessage(), ex.getCause());
+ ErrorDialog.openError(_window.getShell(), "Error", "Server could not be removed", status);
+ }
+ }
+ }
+
+ /**
+ * Selection in the workbench has been changed. We
+ * can change the state of the 'real' action here
+ * if we want, but this can only happen after
+ * the delegate has been created.
+ * @see IWorkbenchWindowActionDelegate#selectionChanged
+ */
+ public void selectionChanged(IAction action, ISelection selection) {
+ }
+
+ /**
+ * We can use this method to dispose of any system
+ * resources we previously allocated.
+ * @see IWorkbenchWindowActionDelegate#dispose
+ */
+ public void dispose() {
+ }
+
+ /**
+ * We will cache window object in order to
+ * be able to provide parent shell for the message dialog.
+ * @see IWorkbenchWindowActionDelegate#init
+ */
+ public void init(IWorkbenchWindow window) {
+ this._window = window;
+ }
+
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/EditAttribute.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/EditAttribute.java
new file mode 100644
index 0000000000..0030330b06
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/EditAttribute.java
@@ -0,0 +1,87 @@
+/*
+ *
+ * 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.management.ui.actions;
+
+import org.apache.qpid.management.ui.ApplicationWorkbenchAdvisor;
+import org.apache.qpid.management.ui.exceptions.InfoRequiredException;
+import org.apache.qpid.management.ui.views.MBeanView;
+import org.apache.qpid.management.ui.views.ViewUtility;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+public class EditAttribute implements IWorkbenchWindowActionDelegate
+{
+ private IWorkbenchWindow _window;
+
+ public void run(IAction action)
+ {
+ if(_window != null)
+ {
+ MBeanView view = (MBeanView)_window.getActivePage().findView(MBeanView.ID);
+ try
+ {
+ view.editAttribute();
+ }
+ catch(InfoRequiredException ex)
+ {
+ ViewUtility.popupInfoMessage("Edit Attribute", ex.getMessage());
+ }
+ catch(Exception ex)
+ {
+ IStatus status = new Status(IStatus.ERROR, ApplicationWorkbenchAdvisor.PERSPECTIVE_ID,
+ IStatus.OK, ex.getMessage(), ex.getCause());
+ ErrorDialog.openError(_window.getShell(), "Error", "Attribute could not be edited", status);
+ }
+ }
+ }
+
+ /**
+ * Selection in the workbench has been changed. We
+ * can change the state of the 'real' action here
+ * if we want, but this can only happen after
+ * the delegate has been created.
+ * @see IWorkbenchWindowActionDelegate#selectionChanged
+ */
+ public void selectionChanged(IAction action, ISelection selection) {
+ }
+
+ /**
+ * We can use this method to dispose of any system
+ * resources we previously allocated.
+ * @see IWorkbenchWindowActionDelegate#dispose
+ */
+ public void dispose() {
+ }
+
+ /**
+ * We will cache window object in order to
+ * be able to provide parent shell for the message dialog.
+ * @see IWorkbenchWindowActionDelegate#init
+ */
+ public void init(IWorkbenchWindow window) {
+ this._window = window;
+ }
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/ReconnectServer.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/ReconnectServer.java
new file mode 100644
index 0000000000..25337f3fbe
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/ReconnectServer.java
@@ -0,0 +1,92 @@
+/*
+ *
+ * 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.management.ui.actions;
+
+import org.apache.qpid.management.ui.ApplicationWorkbenchAdvisor;
+import org.apache.qpid.management.ui.exceptions.InfoRequiredException;
+import org.apache.qpid.management.ui.views.NavigationView;
+import org.apache.qpid.management.ui.views.ViewUtility;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+public class ReconnectServer implements IWorkbenchWindowActionDelegate
+{
+ private IWorkbenchWindow _window;
+
+ /**
+ * Selection in the workbench has been changed. We
+ * can change the state of the 'real' action here
+ * if we want, but this can only happen after
+ * the delegate has been created.
+ * @see IWorkbenchWindowActionDelegate#selectionChanged
+ */
+ public void selectionChanged(IAction action, ISelection selection)
+ {
+
+ }
+
+ /**
+ * We can use this method to dispose of any system
+ * resources we previously allocated.
+ * @see IWorkbenchWindowActionDelegate#dispose
+ */
+ public void dispose()
+ {
+
+ }
+
+ /**
+ * We will cache window object in order to
+ * be able to provide parent shell for the message dialog.
+ * @see IWorkbenchWindowActionDelegate#init
+ */
+ public void init(IWorkbenchWindow window)
+ {
+ this._window = window;
+ }
+
+ public void run(IAction action)
+ {
+ if(_window != null)
+ {
+ NavigationView view = (NavigationView)_window.getActivePage().findView(NavigationView.ID);
+ try
+ {
+ view.reconnect();
+ }
+ catch(InfoRequiredException ex)
+ {
+ ViewUtility.popupInfoMessage("Reconnect Qpid server", ex.getMessage());
+ }
+ catch(Exception ex)
+ {
+ IStatus status = new Status(IStatus.ERROR, ApplicationWorkbenchAdvisor.PERSPECTIVE_ID,
+ IStatus.OK, ex.getMessage(), ex.getCause());
+ ErrorDialog.openError(_window.getShell(), "Error", "Server could not be connected", status);
+ }
+ }
+ }
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/Refresh.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/Refresh.java
new file mode 100644
index 0000000000..85b312cf99
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/Refresh.java
@@ -0,0 +1,77 @@
+/*
+ *
+ * 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.management.ui.actions;
+
+import org.apache.qpid.management.ui.views.MBeanView;
+import org.apache.qpid.management.ui.views.NavigationView;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+public class Refresh implements IWorkbenchWindowActionDelegate
+{
+ private IWorkbenchWindow _window;
+
+ /**
+ * Selection in the workbench has been changed. We
+ * can change the state of the 'real' action here
+ * if we want, but this can only happen after
+ * the delegate has been created.
+ * @see IWorkbenchWindowActionDelegate#selectionChanged
+ */
+ public void selectionChanged(IAction action, ISelection selection)
+ {
+
+ }
+
+ /**
+ * We can use this method to dispose of any system
+ * resources we previously allocated.
+ * @see IWorkbenchWindowActionDelegate#dispose
+ */
+ public void dispose()
+ {
+
+ }
+
+ /**
+ * We will cache window object in order to
+ * be able to provide parent shell for the message dialog.
+ * @see IWorkbenchWindowActionDelegate#init
+ */
+ public void init(IWorkbenchWindow window)
+ {
+ this._window = window;
+ }
+
+ public void run(IAction action)
+ {
+ if(_window != null)
+ {
+ NavigationView view = (NavigationView)_window.getActivePage().findView(NavigationView.ID);
+ view.refresh();
+
+ MBeanView mbeanview = (MBeanView)_window.getActivePage().findView(MBeanView.ID);
+ mbeanview.refreshMBeanView();
+ }
+ }
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/RemoveServer.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/RemoveServer.java
new file mode 100644
index 0000000000..189f0f811b
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/RemoveServer.java
@@ -0,0 +1,92 @@
+/*
+ *
+ * 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.management.ui.actions;
+
+import org.apache.qpid.management.ui.ApplicationWorkbenchAdvisor;
+import org.apache.qpid.management.ui.exceptions.InfoRequiredException;
+import org.apache.qpid.management.ui.views.NavigationView;
+import org.apache.qpid.management.ui.views.ViewUtility;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+public class RemoveServer implements IWorkbenchWindowActionDelegate
+{
+ private IWorkbenchWindow _window;
+
+ /**
+ * Selection in the workbench has been changed. We
+ * can change the state of the 'real' action here
+ * if we want, but this can only happen after
+ * the delegate has been created.
+ * @see IWorkbenchWindowActionDelegate#selectionChanged
+ */
+ public void selectionChanged(IAction action, ISelection selection)
+ {
+
+ }
+
+ /**
+ * We can use this method to dispose of any system
+ * resources we previously allocated.
+ * @see IWorkbenchWindowActionDelegate#dispose
+ */
+ public void dispose()
+ {
+
+ }
+
+ /**
+ * We will cache window object in order to
+ * be able to provide parent shell for the message dialog.
+ * @see IWorkbenchWindowActionDelegate#init
+ */
+ public void init(IWorkbenchWindow window)
+ {
+ this._window = window;
+ }
+
+ public void run(IAction action)
+ {
+ if(_window != null)
+ {
+ NavigationView view = (NavigationView)_window.getActivePage().findView(NavigationView.ID);
+ try
+ {
+ view.removeServer();
+ }
+ catch(InfoRequiredException ex)
+ {
+ ViewUtility.popupInfoMessage("Remove Qpid server", ex.getMessage());
+ }
+ catch(Exception ex)
+ {
+ IStatus status = new Status(IStatus.ERROR, ApplicationWorkbenchAdvisor.PERSPECTIVE_ID,
+ IStatus.OK, ex.getMessage(), ex.getCause());
+ ErrorDialog.openError(_window.getShell(), "Error", "Server could not be removed", status);
+ }
+ }
+ }
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/exceptions/InfoRequiredException.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/exceptions/InfoRequiredException.java
new file mode 100644
index 0000000000..672426a59d
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/exceptions/InfoRequiredException.java
@@ -0,0 +1,36 @@
+/*
+ *
+ * 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.management.ui.exceptions;
+
+public class InfoRequiredException extends Exception
+{
+ private static final long serialVersionUID = 1L;
+
+ public InfoRequiredException(String message)
+ {
+ super(message);
+ }
+
+ public InfoRequiredException(String msg, Throwable t)
+ {
+ super(msg, t);
+ }
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientListener.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientListener.java
new file mode 100644
index 0000000000..00a9ae7653
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientListener.java
@@ -0,0 +1,77 @@
+
+/*
+ *
+ * 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.management.ui.jmx;
+
+import javax.management.MBeanServerNotification;
+import javax.management.Notification;
+import javax.management.NotificationListener;
+import javax.management.ObjectName;
+import javax.management.remote.JMXConnectionNotification;
+
+import org.apache.qpid.management.ui.ApplicationRegistry;
+import org.apache.qpid.management.ui.ManagedServer;
+
+
+public class ClientListener implements NotificationListener
+{
+ protected ManagedServer server = null;
+ protected JMXServerRegistry serverRegistry = null;
+
+ public ClientListener(ManagedServer server)
+ {
+ this.server = server;
+ serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(server);
+ }
+
+ public void handleNotification(Notification notification, Object handback)
+ {
+ System.out.println("\nReceived server notification: " + notification);
+
+ ObjectName objName = null;
+ String type = notification.getType();
+ if (MBeanServerNotification.REGISTRATION_NOTIFICATION.equals(type))
+ {
+ objName = ((MBeanServerNotification)notification).getMBeanName();
+ getServerRegistry().registerManagedObject(objName);
+ }
+ else if (MBeanServerNotification.UNREGISTRATION_NOTIFICATION.equals(type))
+ {
+ objName = ((MBeanServerNotification)notification).getMBeanName();
+ getServerRegistry().unregisterManagedObject(objName);
+ }
+ else if (JMXConnectionNotification.FAILED.equals(type))
+ {
+ ApplicationRegistry.serverConnectionClosed(server);
+ }
+ }
+
+ protected JMXServerRegistry getServerRegistry()
+ {
+ if (serverRegistry == null)
+ serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(server);
+
+ return serverRegistry;
+ }
+ public ManagedServer getServer()
+ {
+ return server;
+ }
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientNotificationListener.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientNotificationListener.java
new file mode 100644
index 0000000000..31b761fcf3
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientNotificationListener.java
@@ -0,0 +1,42 @@
+/*
+ *
+ * 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.management.ui.jmx;
+
+import javax.management.Notification;
+import javax.management.ObjectName;
+
+import org.apache.qpid.management.ui.ManagedServer;
+
+public class ClientNotificationListener extends ClientListener
+{
+ public ClientNotificationListener(ManagedServer server)
+ {
+ super(server);
+ }
+
+ public void handleNotification(Notification notification, Object handback)
+ {
+ System.out.println("\nReceived mbean notification: " + notification);
+ ObjectName objName = (ObjectName)notification.getSource();
+ //String type = notification.getType();
+ getServerRegistry().addNotification(objName, notification);
+ }
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXManagedObject.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXManagedObject.java
new file mode 100644
index 0000000000..dd665eabb3
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXManagedObject.java
@@ -0,0 +1,50 @@
+/*
+ *
+ * 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.management.ui.jmx;
+
+import java.util.HashMap;
+
+import javax.management.ObjectName;
+
+import org.apache.qpid.management.ui.ManagedBean;
+
+
+public class JMXManagedObject extends ManagedBean
+{
+ private ObjectName _objName;
+
+ @SuppressWarnings("unchecked")
+ public JMXManagedObject(ObjectName objName)
+ {
+ super();
+ this._objName = objName;
+ setName(_objName.getKeyProperty("name"));
+ setType(_objName.getKeyProperty("type"));
+ setUniqueName(_objName.toString());
+ setDomain(_objName.getDomain());
+ super.setProperties(new HashMap(_objName.getKeyPropertyList()));
+ }
+
+ public ObjectName getObjectName()
+ {
+ return _objName;
+ }
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXServerRegistry.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXServerRegistry.java
new file mode 100644
index 0000000000..9bc3ea1b0f
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXServerRegistry.java
@@ -0,0 +1,336 @@
+/*
+ *
+ * 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.management.ui.jmx;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import javax.management.MBeanInfo;
+import javax.management.MBeanServerConnection;
+import javax.management.Notification;
+import javax.management.ObjectName;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXServiceURL;
+
+import org.apache.qpid.management.ui.Constants;
+import org.apache.qpid.management.ui.ManagedBean;
+import org.apache.qpid.management.ui.ManagedServer;
+import org.apache.qpid.management.ui.ServerRegistry;
+import org.apache.qpid.management.ui.model.ManagedAttributeModel;
+import org.apache.qpid.management.ui.model.NotificationInfoModel;
+import org.apache.qpid.management.ui.model.NotificationObject;
+import org.apache.qpid.management.ui.model.OperationDataModel;
+
+
+public class JMXServerRegistry extends ServerRegistry
+{
+ private ObjectName _serverObjectName = null;
+ private JMXConnector _jmxc = null;
+ private MBeanServerConnection _mbsc = null;
+
+ private List<ManagedBean> _mbeansToBeAdded = new ArrayList<ManagedBean>();
+ private List<ManagedBean> _mbeansToBeRemoved = new ArrayList<ManagedBean>();
+
+ private List<String> _queues = new ArrayList<String>();
+ private List<String> _exchanges = new ArrayList<String>();
+
+ private HashMap<String, ManagedBean> _mbeansMap = new HashMap<String, ManagedBean>();
+ private HashMap<String, MBeanInfo> _mbeanInfoMap = new HashMap<String, MBeanInfo>();
+ private HashMap<String, ManagedAttributeModel> _attributeModelMap = new HashMap<String, ManagedAttributeModel>();
+ private HashMap<String, OperationDataModel> _operationModelMap = new HashMap<String, OperationDataModel>();
+ private HashMap<String, List<NotificationInfoModel>> _notificationInfoMap = new HashMap<String, List<NotificationInfoModel>>();
+ private HashMap<String, List<NotificationObject>> _notificationsMap = new HashMap<String, List<NotificationObject>>();
+ private HashMap<String, HashMap<String, List<String>>> _subscribedNotificationMap = new HashMap<String, HashMap<String, List<String>>>();
+
+ private ClientNotificationListener _notificationListener = null;
+ private ClientListener _clientListener = null;
+
+ public JMXServerRegistry(ManagedServer server) throws Exception
+ {
+ super(server);
+ JMXServiceURL jmxUrl = new JMXServiceURL(server.getUrl());
+ _jmxc = JMXConnectorFactory.connect(jmxUrl, null);
+ _mbsc = _jmxc.getMBeanServerConnection();
+
+ _clientListener = new ClientListener(server);
+ _notificationListener = new ClientNotificationListener(server);
+
+ _jmxc.addConnectionNotificationListener(_clientListener, null, null);
+ _serverObjectName = new ObjectName("JMImplementation:type=MBeanServerDelegate");
+ _mbsc.addNotificationListener(_serverObjectName, _clientListener, null, null);
+ }
+
+ public MBeanServerConnection getServerConnection()
+ {
+ return _mbsc;
+ }
+
+ /**
+ * removes all listeners from the mbean server. This is required when user
+ * disconnects the Qpid server connection
+ */
+ public void closeServerConnection() throws Exception
+ {
+ if (_jmxc != null)
+ _jmxc.removeConnectionNotificationListener(_clientListener);
+
+ if (_mbsc != null)
+ _mbsc.removeNotificationListener(_serverObjectName, _clientListener);
+
+ // remove mbean notification listeners
+ for (String mbeanName : _subscribedNotificationMap.keySet())
+ {
+ _mbsc.removeNotificationListener(new ObjectName(mbeanName), _notificationListener);
+ }
+ }
+
+ public ManagedBean getManagedObject(String uniqueName)
+ {
+ return _mbeansMap.get(uniqueName);
+ }
+
+ public void addManagedObject(ManagedBean key)
+ {
+ if (Constants.QUEUE.equals(key.getType()))
+ _queues.add(key.getName());
+ else if (Constants.EXCHANGE.equals(key.getType()))
+ _exchanges.add(key.getName());
+
+ _mbeansMap.put(key.getUniqueName(), key);
+ }
+
+ public void removeManagedObject(ManagedBean mbean)
+ {
+ if (Constants.QUEUE.equals(mbean.getType()))
+ _queues.remove(mbean.getName());
+ else if (Constants.EXCHANGE.equals(mbean.getType()))
+ _exchanges.remove(mbean.getName());
+
+ _mbeansMap.remove(mbean.getUniqueName());
+ }
+
+ public void putMBeanInfo(ManagedBean mbean, MBeanInfo mbeanInfo)
+ {
+ _mbeanInfoMap.put(mbean.getUniqueName(), mbeanInfo);
+ }
+ public MBeanInfo getMBeanInfo(ManagedBean mbean)
+ {
+ return _mbeanInfoMap.get(mbean.getUniqueName());
+ }
+
+ public void setNotificationInfo(ManagedBean mbean, List<NotificationInfoModel>value)
+ {
+ _notificationInfoMap.put(mbean.getUniqueName(), value);
+ }
+
+ public List<NotificationInfoModel> getNotificationInfo(ManagedBean mbean)
+ {
+ return _notificationInfoMap.get(mbean.getUniqueName());
+ }
+
+ public void addNotification(ObjectName objName, Notification notification)
+ {
+ List<NotificationObject> list = _notificationsMap.get(objName.toString());
+ NotificationObject obj = new NotificationObject(notification.getSequenceNumber(),
+ new Date(notification.getTimeStamp()),
+ notification.getMessage(),
+ notification.getSource(),
+ notification.getType());
+
+ if (list == null)
+ {
+ list = new ArrayList<NotificationObject>();
+ _notificationsMap.put(objName.toString(), list);
+ }
+
+ list.add(obj);
+ }
+
+ public List<NotificationObject> getNotifications(ManagedBean mbean)
+ {
+ return _notificationsMap.get(mbean.getUniqueName());
+ }
+
+ public void clearNotifications(ManagedBean mbean)
+ {
+ if (_notificationsMap.containsKey(mbean.getUniqueName()))
+ _notificationsMap.get(mbean.getUniqueName()).clear();
+ }
+
+ public void addNotificationListener(ManagedBean mbean, String name, String type)
+ {
+ HashMap<String, List<String>> map = _subscribedNotificationMap.get(mbean.getUniqueName());
+ if (map == null)
+ {
+ map = new HashMap<String, List<String>>();
+ _subscribedNotificationMap.put(mbean.getUniqueName(),map);
+ }
+
+ List<String> list = map.get(name);
+ if (list == null)
+ {
+ list = new ArrayList<String>();
+ map.put(name, list);
+ }
+ if (Constants.ALL.equals(type))
+ {
+ List<NotificationInfoModel> infoList = _notificationInfoMap.get(mbean.getUniqueName());
+ for (NotificationInfoModel model : infoList)
+ {
+ if (model.getName().equals(name))
+ {
+ String[] types = model.getTypes();
+ for (int i = 0; i < types.length; i++)
+ {
+ list.add(types[i]);
+ }
+ }
+ }
+ }
+ else
+ {
+ list.add(type);
+ }
+
+ System.out.println("Subscribed for notification :" + mbean.getUniqueName());
+ }
+
+ public boolean hasSubscribedForNotifications(ManagedBean mbean, String name, String type)
+ {
+ if (_subscribedNotificationMap.containsKey(mbean.getUniqueName()))
+ {
+ HashMap<String, List<String>> map = _subscribedNotificationMap.get(mbean.getUniqueName());
+ if (map.containsKey(name))
+ {
+ if (map.get(name).contains(type))
+ {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public void removeNotificationListener(ManagedBean mbean, String name, String type) throws Exception
+ {
+ System.out.println("Removed notification listener :" + mbean.getUniqueName() + name +type);
+ if (_subscribedNotificationMap.containsKey(mbean.getUniqueName()))
+ {
+ HashMap<String, List<String>> map = _subscribedNotificationMap.get(mbean.getUniqueName());
+ if (map.containsKey(name))
+ {
+ if (Constants.ALL.equals(type))
+ {
+ map.remove(name);
+ }
+ else if (type != null)
+ {
+ map.get(name).remove(type);
+ }
+ }
+
+ JMXManagedObject jmxbean = (JMXManagedObject)mbean;
+ _mbsc.removeNotificationListener(jmxbean.getObjectName(), _notificationListener);
+ }
+ }
+
+ public void registerManagedObject(ObjectName objName)
+ {
+ JMXManagedObject managedObject = new JMXManagedObject(objName);
+ managedObject.setServer(getManagedServer());
+ _mbeansToBeAdded.add(managedObject);
+ }
+
+ public void unregisterManagedObject(ObjectName objName)
+ {
+ JMXManagedObject managedObject = new JMXManagedObject(objName);
+ managedObject.setServer(getManagedServer());
+ _mbeansToBeRemoved.add(managedObject);
+ }
+
+ public List<ManagedBean> getObjectsToBeAdded()
+ {
+ if (_mbeansToBeAdded.isEmpty())
+ return null;
+ else
+ {
+ List<ManagedBean> list = _mbeansToBeAdded;
+ _mbeansToBeAdded = new ArrayList<ManagedBean>();
+ return list;
+ }
+ }
+
+ public List<ManagedBean> getObjectsToBeRemoved()
+ {
+ if (_mbeansToBeRemoved.isEmpty())
+ return null;
+ else
+ {
+ List<ManagedBean> list = new CopyOnWriteArrayList<ManagedBean>(_mbeansToBeRemoved);
+ _mbeansToBeRemoved.clear();
+ return list;
+ }
+ }
+
+ public void setAttributeModel(ManagedBean mbean, ManagedAttributeModel value)
+ {
+ _attributeModelMap.put(mbean.getUniqueName(), value);
+ }
+
+ public ManagedAttributeModel getAttributeModel(ManagedBean mbean)
+ {
+ return _attributeModelMap.get(mbean.getUniqueName());
+ }
+
+ public void setOperationModel(ManagedBean mbean, OperationDataModel value)
+ {
+ _operationModelMap.put(mbean.getUniqueName(), value);
+ }
+
+ public OperationDataModel getOperationModel(ManagedBean mbean)
+ {
+ return _operationModelMap.get(mbean.getUniqueName());
+ }
+
+ public String[] getQueueNames()
+ {
+ return _queues.toArray(new String[0]);
+ }
+
+ public String[] getExchangeNames()
+ {
+ return _exchanges.toArray(new String[0]);
+ }
+
+ public ClientNotificationListener getNotificationListener()
+ {
+ return _notificationListener;
+ }
+
+ public ClientListener getClientListener()
+ {
+ return _clientListener;
+ }
+}
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
new file mode 100644
index 0000000000..800a5b6ce3
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/MBeanUtility.java
@@ -0,0 +1,349 @@
+/*
+ *
+ * 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.management.ui.jmx;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.management.Attribute;
+import javax.management.AttributeList;
+import javax.management.InstanceNotFoundException;
+import javax.management.JMException;
+import javax.management.MBeanAttributeInfo;
+import javax.management.MBeanException;
+import javax.management.MBeanInfo;
+import javax.management.MBeanNotificationInfo;
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectName;
+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.model.AttributeData;
+import org.apache.qpid.management.ui.model.ManagedAttributeModel;
+import org.apache.qpid.management.ui.model.NotificationInfoModel;
+import org.apache.qpid.management.ui.model.OperationData;
+import org.apache.qpid.management.ui.model.OperationDataModel;
+import org.apache.qpid.management.ui.model.ParameterData;
+import org.apache.qpid.management.ui.views.ViewUtility;
+
+
+public class MBeanUtility
+{
+
+ public static MBeanInfo getMBeanInfo(ManagedBean mbean)
+ throws IOException, JMException
+ {
+ 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.");
+
+ JMXManagedObject jmxbean = (JMXManagedObject)mbean;
+ MBeanInfo mbeanInfo = mbsc.getMBeanInfo(jmxbean.getObjectName());
+ serverRegistry.putMBeanInfo(mbean, mbeanInfo);
+
+ getAttributes(mbean);
+ getOperations(mbean);
+
+ return mbeanInfo;
+ }
+
+
+ public static Object execute(ManagedBean mbean, OperationData opData) throws Exception
+ {
+ String opName = opData.getName();
+ Object[] values = null;
+ String[] signature = null;
+
+ List<ParameterData> params = opData.getParameters();
+ if (params != null && !params.isEmpty())
+ {
+ signature = new String[params.size()];;
+ values = new Object[params.size()];
+ for (int i = 0; i < params.size(); i++)
+ {
+ signature[i] = params.get(i).getType();
+ values[i] = params.get(i).getValue();
+ System.out.println(params.get(i).getName() + " : " + params.get(i).getValue());
+ }
+ }
+
+ ManagedServer server = mbean.getServer();
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(server);
+
+ MBeanServerConnection mbsc = serverRegistry.getServerConnection();
+ if (mbsc == null)
+ {
+ System.out.println("MBeanServerConnection doesn't exist in the Application registry.");
+ // TODO
+ // throw exception to check if the server is added
+ // Or try and get the connection again if it was disconnected
+ return null;
+ }
+ 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");
+ }
+ */
+ }
+
+ public static void handleException(Exception ex)
+ {
+ handleException(null, ex);
+ }
+
+ public static void handleException(ManagedBean mbean, Exception ex)
+ {
+ if (mbean == null)
+ {
+ ViewUtility.popupErrorMessage("Error", ex.getMessage());
+ }
+ else if (ex instanceof IOException)
+ {
+ ViewUtility.popupErrorMessage(mbean.getName(), ex.getMessage());
+ }
+ else if (ex instanceof ReflectionException)
+ {
+ ViewUtility.popupErrorMessage(mbean.getName(), ex.getMessage());
+ }
+ else if (ex instanceof InstanceNotFoundException)
+ {
+ ViewUtility.popupErrorMessage(mbean.getName(), ex.getMessage());
+ }
+ else if (ex instanceof MBeanException)
+ {
+ ViewUtility.popupInfoMessage(mbean.getName(), ex.getMessage());
+ }
+ else
+ {
+ ViewUtility.popupError(mbean.getName(), "Error occured", ex);
+ }
+ ex.printStackTrace();
+ }
+
+ public static void createNotificationlistener(ManagedBean mbean, String name, String type)
+ throws IOException, Exception
+ {
+ JMXManagedObject jmxbean = (JMXManagedObject)mbean;
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
+ serverRegistry.addNotificationListener(mbean, name, type);
+ MBeanServerConnection mbsc = serverRegistry.getServerConnection();
+
+ if (mbsc == null)
+ {
+ throw new Exception("MBeanServer 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
+ {
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
+ MBeanServerConnection mbsc = serverRegistry.getServerConnection();
+
+ if (mbsc == null)
+ throw new Exception("Server connection is not available for " + mbean.getUniqueName());
+
+ Object value = mbsc.getAttribute(((JMXManagedObject)mbean).getObjectName(), attribute);
+
+ ManagedAttributeModel attributeModel = serverRegistry.getAttributeModel(mbean);
+ attributeModel.setAttributeValue(attribute, value);
+ return Integer.parseInt(String.valueOf(value));
+ }
+
+ public static ManagedAttributeModel getAttributes(ManagedBean mbean)
+ {
+ ObjectName objName = ((JMXManagedObject)mbean).getObjectName();
+ String[] attributes = null;
+ AttributeList list = null;
+
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
+ MBeanServerConnection mbsc = serverRegistry.getServerConnection();
+ MBeanAttributeInfo[] attributesInfo = null;
+ ManagedAttributeModel attributeModel = serverRegistry.getAttributeModel(mbean);
+ // If retrieving attributeInfo for the first time.
+ if (attributeModel == null)
+ {
+ attributeModel = new ManagedAttributeModel();
+ attributesInfo = serverRegistry.getMBeanInfo(mbean).getAttributes();
+ attributes = new String[attributesInfo.length];
+ for (int i = 0; i< attributesInfo.length ; i++)
+ {
+ attributes[i] = attributesInfo[i].getName();
+ attributeModel.setAttributeDescription(attributes[i], attributesInfo[i].getDescription());
+ attributeModel.setAttributeWritable(attributes[i], attributesInfo[i].isWritable());
+ attributeModel.setAttributeReadable(attributes[i], attributesInfo[i].isReadable());
+ }
+ }
+ else
+ {
+ attributes = attributeModel.getAttributeNames().toArray(new String[0]);
+ }
+
+ try
+ {
+ if (attributes.length != 0)
+ {
+ list = mbsc.getAttributes(objName, attributes);
+ for (Iterator itr = list.iterator(); itr.hasNext();)
+ {
+ Attribute attrib = (Attribute)itr.next();
+ attributeModel.setAttributeValue(attrib.getName(), attrib.getValue());
+ }
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+
+ serverRegistry.setAttributeModel(mbean, attributeModel);
+
+ return attributeModel;
+ }
+
+ public static void updateAttribute(ManagedBean mbean, AttributeData attribute, String value)
+ {
+ JMXManagedObject jmxbean = (JMXManagedObject)mbean;
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
+
+ MBeanServerConnection mbsc = serverRegistry.getServerConnection();
+
+ Object newValue = value;
+ if (attribute.getDataType().equals(String.class.getName()))
+ {
+
+ }
+ else if (attribute.getDataType().equals(Long.class.getName()))
+ {
+ newValue = new Long(Long.parseLong(value));
+ }
+ else if (attribute.getDataType().equals(Integer.class.getName()))
+ {
+ 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();
+ }
+ }
+
+ public static OperationDataModel getOperations(ManagedBean mbean)
+ {
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
+
+ OperationDataModel dataModel = serverRegistry.getOperationModel(mbean);
+ if (dataModel == null)
+ {
+ MBeanInfo mbeanInfo = serverRegistry.getMBeanInfo(mbean);
+ MBeanOperationInfo[] operationsInfo = mbeanInfo.getOperations();
+ dataModel = new OperationDataModel();
+
+ for (int i = 0; i < operationsInfo.length; i++)
+ {
+ dataModel.addOperation(operationsInfo[i]);
+ }
+
+ serverRegistry.setOperationModel(mbean, dataModel);
+ }
+
+ return dataModel;
+ }
+
+ public static NotificationInfoModel[] getNotificationInfo(ManagedBean mbean)
+ {
+
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
+ MBeanNotificationInfo[] info = serverRegistry.getMBeanInfo(mbean).getNotifications();
+
+ if (info == null || info.length == 0)
+ return null;
+
+ List<NotificationInfoModel> list = serverRegistry.getNotificationInfo(mbean);
+
+ if (list != null)
+ return list.toArray(new NotificationInfoModel[0]);
+ else
+ list = new ArrayList<NotificationInfoModel>();
+
+ for (int i = 0; i < info.length; i++)
+ {
+ list.add(new NotificationInfoModel(info[i].getName(), info[i].getDescription(), info[i].getNotifTypes()));
+ }
+ serverRegistry.setNotificationInfo(mbean, list);
+
+ return list.toArray(new NotificationInfoModel[0]);
+ }
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/AttributeData.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/AttributeData.java
new file mode 100644
index 0000000000..601f499a0c
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/AttributeData.java
@@ -0,0 +1,95 @@
+/*
+ *
+ * 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.management.ui.model;
+
+public class AttributeData
+{
+ String name = "";
+ String description = "";
+ String dataType = "";
+ Object value = null;
+ boolean readable = true;
+ boolean writable = false;
+
+
+ public String getDataType()
+ {
+ return dataType;
+ }
+ public void setDataType(String dataType)
+ {
+ this.dataType = dataType;
+ }
+
+ public String getDescription()
+ {
+ return description;
+ }
+ public void setDescription(String description)
+ {
+ this.description = description;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+ public void setName(String name)
+ {
+ this.name = name;
+ }
+
+ public Object getValue()
+ {
+ return value;
+ }
+ public void setValue(Object value)
+ {
+ this.value = value;
+ }
+ public boolean isReadable()
+ {
+ return readable;
+ }
+ public void setReadable(boolean readable)
+ {
+ this.readable = readable;
+ }
+ public boolean isWritable()
+ {
+ return writable;
+ }
+ public void setWritable(boolean writable)
+ {
+ this.writable = writable;
+ }
+
+ public boolean isNumber()
+ {
+ if ("int".equals(dataType) || "java.lang.Integer".equals(dataType) ||
+ "long".equals(dataType) || "java.lang.Long".equals(dataType) )
+ {
+ return true;
+ }
+ else
+ return false;
+ }
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/ManagedAttributeModel.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/ManagedAttributeModel.java
new file mode 100644
index 0000000000..692e72fc5a
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/ManagedAttributeModel.java
@@ -0,0 +1,113 @@
+/*
+ *
+ * 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.management.ui.model;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+public class ManagedAttributeModel
+{
+ HashMap<String, AttributeData> _attributeMap = new HashMap<String, AttributeData>();
+
+ public void setAttributeValue(String name, Object value)
+ {
+ if (value == null)
+ return;
+
+ AttributeData data = null;
+ String dataType = value.getClass().getName();
+ if (_attributeMap.containsKey(name))
+ {
+ data = _attributeMap.get(name);
+ data.setValue(value);
+ }
+ else
+ {
+ data = new AttributeData();
+ data.setName(name);
+ data.setValue(value);
+ _attributeMap.put(name, data);
+ }
+ data.setDataType(dataType);
+ }
+
+
+ public void setAttributeDescription(String name, String value)
+ {
+ if (_attributeMap.containsKey(name))
+ {
+ _attributeMap.get(name).setDescription(value);
+ }
+ else
+ {
+ AttributeData data = new AttributeData();
+ data.setName(name);
+ data.setDescription(value);
+ _attributeMap.put(name, data);
+ }
+ }
+
+ public void setAttributeReadable(String name, boolean readable)
+ {
+ if (_attributeMap.containsKey(name))
+ {
+ _attributeMap.get(name).setReadable(readable);
+ }
+ else
+ {
+ AttributeData data = new AttributeData();
+ data.setName(name);
+ data.setReadable(readable);
+ _attributeMap.put(name, data);
+ }
+ }
+
+ public void setAttributeWritable(String name, boolean writable)
+ {
+ if (_attributeMap.containsKey(name))
+ {
+ _attributeMap.get(name).setWritable(writable);
+ }
+ else
+ {
+ AttributeData data = new AttributeData();
+ data.setName(name);
+ data.setWritable(writable);
+ _attributeMap.put(name, data);
+ }
+ }
+
+ public List<String> getAttributeNames()
+ {
+ return new ArrayList<String>(_attributeMap.keySet());
+ }
+
+ public AttributeData[] getAttributes()
+ {
+ return _attributeMap.values().toArray(new AttributeData[0]);
+ }
+
+ public int getCount()
+ {
+ return _attributeMap.size();
+ }
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationInfoModel.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationInfoModel.java
new file mode 100644
index 0000000000..6d4160889e
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationInfoModel.java
@@ -0,0 +1,51 @@
+/*
+ *
+ * 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.management.ui.model;
+
+public class NotificationInfoModel
+{
+ String name;
+ String description;
+ String[] types;
+
+ public NotificationInfoModel(String name, String desc, String[] types)
+ {
+ this.name = name;
+ this.description = desc;
+ this.types = types;
+ }
+
+ public String getDescription()
+ {
+ return description;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public String[] getTypes()
+ {
+ return types;
+ }
+
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationObject.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationObject.java
new file mode 100644
index 0000000000..8ba74b3ce8
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationObject.java
@@ -0,0 +1,88 @@
+/*
+ *
+ * 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.management.ui.model;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.TimeZone;
+
+public class NotificationObject
+{
+
+ private long _sequenceNo;
+ private Date _timeStamp;
+ private String _message;
+ private Object _source;
+ private String _type; // INFO, WARN, etc
+ private static final SimpleDateFormat dateFormat = new SimpleDateFormat("hh:mm:ss dd/MM/yy z");
+
+ public NotificationObject(long seqNo, Date timeStamp, String message, Object source, String type)
+ {
+ this._sequenceNo = seqNo;
+ this._message = message;
+ this._source = source;
+ this._type = type;
+ this._timeStamp = timeStamp;
+ dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
+ }
+
+ public Object getSource()
+ {
+ return _source;
+ }
+ public void setSource(Object _source)
+ {
+ this._source = _source;
+ }
+ public String getMessage()
+ {
+ return _message;
+ }
+ public void setMessage(String _message)
+ {
+ this._message = _message;
+ }
+ public long getSequenceNo()
+ {
+ return _sequenceNo;
+ }
+ public void setSequenceNo(long no)
+ {
+ _sequenceNo = no;
+ }
+ public String getTimeStamp()
+ {
+ return dateFormat.format(_timeStamp);
+ }
+ public void setTimeStamp(Date stamp)
+ {
+ _timeStamp = stamp;
+ }
+ public String getType()
+ {
+ return _type;
+ }
+ public void setType(String _type)
+ {
+ this._type = _type;
+ }
+
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationData.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationData.java
new file mode 100644
index 0000000000..9b6750c21a
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationData.java
@@ -0,0 +1,84 @@
+/*
+ *
+ * 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.management.ui.model;
+
+import java.util.List;
+
+public class OperationData
+{
+ private String _name;
+ private String _description;
+ private String _returnType;
+ private int _impact;
+ private List<ParameterData> _parameters;
+
+ public OperationData(String value)
+ {
+ this._name = value;
+ }
+
+ public String getName()
+ {
+ return _name;
+ }
+
+ public String getDescription()
+ {
+ return _description;
+ }
+
+ public void setDescription(String description)
+ {
+ this._description = description;
+ }
+
+ public List<ParameterData> getParameters()
+ {
+ return _parameters;
+ }
+
+ public void setParameters(List<ParameterData> parameters)
+ {
+ this._parameters = parameters;
+ }
+
+ public int getImpact()
+ {
+ return _impact;
+ }
+
+ public void setImpact(int impact)
+ {
+ this._impact = impact;
+ }
+
+ public String getReturnType()
+ {
+ return _returnType;
+ }
+
+ public void setReturnType(String returnType)
+ {
+ this._returnType = returnType;
+ }
+
+
+} \ No newline at end of file
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationDataModel.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationDataModel.java
new file mode 100644
index 0000000000..2df36ee8c6
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationDataModel.java
@@ -0,0 +1,73 @@
+/*
+ *
+ * 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.management.ui.model;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+
+import javax.management.MBeanOperationInfo;
+import javax.management.MBeanParameterInfo;
+
+public class OperationDataModel
+{
+ HashMap<String, OperationData> _operationMap = new HashMap<String, OperationData>();
+
+ public void addOperation(MBeanOperationInfo opInfo)
+ {
+ OperationData opData = new OperationData(opInfo.getName());
+ opData.setDescription(opInfo.getDescription());
+ opData.setImpact(opInfo.getImpact());
+ opData.setReturnType(opInfo.getReturnType());
+
+ int parametersCount = opInfo.getSignature().length;
+ if (parametersCount != 0)
+ {
+ List<ParameterData> paramList = new ArrayList<ParameterData>();
+ for (int i = 0; i < parametersCount; i++)
+ {
+ MBeanParameterInfo paramInfo = opInfo.getSignature()[i];
+ ParameterData param = new ParameterData(paramInfo.getName());
+ param.setDescription(paramInfo.getDescription());
+ param.setType(paramInfo.getType());
+ paramList.add(param);
+ }
+ opData.setParameters(paramList);
+ }
+
+ _operationMap.put(opInfo.getName(), opData);
+ }
+
+ public OperationData getOperation(String name)
+ {
+ return _operationMap.get(name);
+ }
+
+ public List<OperationData> getOperations()
+ {
+ return new ArrayList<OperationData>(_operationMap.values());
+ }
+
+ public int getCount()
+ {
+ return _operationMap.size();
+ }
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/ParameterData.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/ParameterData.java
new file mode 100644
index 0000000000..4ca47c88ea
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/ParameterData.java
@@ -0,0 +1,79 @@
+/*
+ *
+ * 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.management.ui.model;
+
+public class ParameterData
+{
+ private String name;
+ private String description;
+ private String type;
+ private Object value;
+
+ ParameterData(String value)
+ {
+ this.name = value;
+ }
+
+ public String getDescription()
+ {
+ return description;
+ }
+ public void setDescription(String description)
+ {
+ this.description = description;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public String getType()
+ {
+ return type;
+ }
+ public void setType(String type)
+ {
+ this.type = type;
+ }
+
+ public Object getValue()
+ {
+ return value;
+ }
+
+ public void setValueFromString(String strValue)
+ {
+ if ("int".equals(type))
+ value = Integer.parseInt(strValue);
+ else if ("boolean".equals(type))
+ value = Boolean.valueOf(strValue);
+ else if ("long".equals(type))
+ value = Long.parseLong(strValue);
+ else
+ value = strValue;
+ }
+
+ public void setValue(Object value)
+ {
+ this.value = value;
+ }
+}
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
new file mode 100644
index 0000000000..b5c044e7be
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/AttributesTabControl.java
@@ -0,0 +1,937 @@
+/*
+ *
+ * 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.management.ui.views;
+
+import javax.management.openmbean.TabularDataSupport;
+
+import org.apache.qpid.management.ui.ApplicationRegistry;
+import org.apache.qpid.management.ui.Constants;
+import org.apache.qpid.management.ui.ManagedBean;
+import org.apache.qpid.management.ui.jmx.JMXServerRegistry;
+import org.apache.qpid.management.ui.jmx.MBeanUtility;
+import org.apache.qpid.management.ui.model.AttributeData;
+import org.apache.qpid.management.ui.model.ManagedAttributeModel;
+import org.eclipse.jface.viewers.IColorProvider;
+import org.eclipse.jface.viewers.IFontProvider;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.MouseMoveListener;
+import org.eclipse.swt.events.MouseTrackListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.forms.widgets.Form;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+
+public class AttributesTabControl extends TabControl
+{
+ private FormToolkit _toolkit;
+ private Form _form;
+ private Table _table = null;
+ private TableViewer _tableViewer = null;
+ private static final int[] tableWidths = new int[] {300, 300};
+ private static final String DESCRIPTION = "Description";
+ private static final String UPDATE_BUTTON = "Update";
+ private final String[] _tableTitles = {"Attribute Name", "Value"};
+
+ private DisposeListener tableDisposeListener = new DisposeListenerImpl();
+ final Image image;
+ private Button _detailsButton = null;
+ private Button _editButton = null;
+ private Button _graphButton = null;
+ private Button _refreshButton = null;
+ private boolean disableEditing = false;
+
+ private static final String MAX_VALUE = "MaxValue";
+ private static final String GRAPH_VALUES = "GraphValues";
+ private int GRAPH_WIDTH = 700;
+ private int GRAPH_HEIGHT = 450;
+ private int GRAPH_ITEM_GAP = 100;
+ private int startX = 80;
+ private int startY = 60;
+
+ static int number = 0;
+
+ public AttributesTabControl(TabFolder tabFolder)
+ {
+ super(tabFolder);
+ _toolkit = new FormToolkit(_tabFolder.getDisplay());
+ _form = _toolkit.createForm(_tabFolder);
+ GridLayout gridLayout = new GridLayout(2, false);
+ gridLayout.marginWidth = 0;
+ gridLayout.marginHeight = 0;
+ _form.getBody().setLayout(gridLayout);
+
+ image = Display.getCurrent().getSystemImage(SWT.ICON_INFORMATION);
+ createWidgets();
+ }
+
+ public Control getControl()
+ {
+ return _form;
+ }
+
+ protected void createWidgets()
+ {
+ createTable();
+ createTableViewer();
+ createButtons();
+ addTableListeners();
+ }
+
+ private void createTable()
+ {
+ _table = _toolkit.createTable(_form.getBody(), SWT.FULL_SELECTION);
+ GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false, 1, 6);
+ _table.setLayoutData(gridData);
+
+ for (int i = 0; i < _tableTitles.length; ++i)
+ {
+ final TableColumn column = new TableColumn(_table, SWT.NONE);
+ column.setText(_tableTitles[i]);
+ column.setWidth(tableWidths[i]);
+ column.setResizable(false);
+ }
+
+ _table.setLinesVisible (true);
+ _table.setHeaderVisible (true);
+ }
+
+ private void createTableViewer()
+ {
+ _tableViewer = new TableViewer(_table);
+ _tableViewer.setUseHashlookup(true);
+ //_tableViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 1, 6));
+
+ // Set the column properties that will be used in callbacks to recognize
+ // the column on which we will want to operate
+ _tableViewer.setColumnProperties(_tableTitles);
+ /*
+ // Create the cell editors
+ CellEditor[] cellEditors = new CellEditor[_tableTitles.length];
+
+
+ TextCellEditor textEditor = new TextCellEditor(_table);
+ cellEditors[0] = textEditor;
+ textEditor = new TextCellEditor(_table);
+ cellEditors[1] = textEditor;
+
+ // Assign the cell editors to the viewer
+ _tableViewer.setCellEditors(cellEditors);
+ _tableViewer.setCellModifier(new TableCellModifier());
+ */
+
+
+
+ _tableViewer.setContentProvider(new ContentProviderImpl());
+ _tableViewer.setLabelProvider(new LabelProviderImpl());
+
+ }
+
+ private void createButtons()
+ {
+ addDetailsButton();
+ addEditButton();
+ addGraphButton();
+ addRefreshButton();
+ }
+
+
+ private void addDetailsButton()
+ {
+ // Create and configure the button for attribute details
+ _detailsButton = _toolkit.createButton(_form.getBody(),
+ Constants.BUTTON_DETAILS,
+ SWT.PUSH | SWT.CENTER);
+
+ _detailsButton.setFont(ApplicationRegistry.getFont(Constants.FONT_BUTTON));
+ GridData gridData = new GridData(SWT.BEGINNING, SWT.TOP, true, false);
+ gridData.widthHint = 80;
+ _detailsButton.setLayoutData(gridData);
+ _detailsButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ disableEditing = true;
+ int index = _table.getSelectionIndex();
+ TableItem item = _table.getItem(index);
+ createDetailsPopup((AttributeData)item.getData());
+ disableEditing = false;
+ setFocus();
+ }
+ });
+ }
+
+ private void addEditButton()
+ {
+ // Create and configure the button for editing attribute
+ _editButton = _toolkit.createButton(_form.getBody(),
+ Constants.BUTTON_EDIT_ATTRIBUTE,
+ SWT.PUSH | SWT.CENTER);
+ _editButton.setFont(ApplicationRegistry.getFont(Constants.FONT_BUTTON));
+ GridData gridData = new GridData(SWT.BEGINNING, SWT.TOP, true, false);
+ gridData.widthHint = 80;
+ _editButton.setLayoutData(gridData);
+ _editButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ int index = _table.getSelectionIndex();
+ TableItem item = _table.getItem(index);
+ createDetailsPopup((AttributeData)item.getData());
+ setFocus();
+ }
+ });
+ }
+
+ private void addGraphButton()
+ {
+ _graphButton = _toolkit.createButton(_form.getBody(),
+ Constants.BUTTON_GRAPH,
+ SWT.PUSH | SWT.CENTER);
+ _graphButton.setFont(ApplicationRegistry.getFont(Constants.FONT_BUTTON));
+ GridData gridData = new GridData(SWT.BEGINNING, SWT.TOP, true, false);
+ gridData.widthHint = 80;
+ _graphButton.setLayoutData(gridData);
+ _graphButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent event)
+ {
+ int selectionIndex = _table.getSelectionIndex();
+ AttributeData data = (AttributeData)_table.getItem(selectionIndex).getData();
+ createGraph(data);
+ setFocus();
+ }
+ });
+ }
+
+ private void addRefreshButton()
+ {
+ // Create and configure the "Refresh" button
+ _refreshButton = _toolkit.createButton(_form.getBody(),
+ Constants.BUTTON_REFRESH,
+ SWT.PUSH | SWT.CENTER);
+
+ _refreshButton.setFont(ApplicationRegistry.getFont(Constants.FONT_BUTTON));
+ GridData gridData = new GridData(SWT.BEGINNING, SWT.TOP, true, false);
+ gridData.widthHint = 80;
+ _refreshButton.setLayoutData(gridData);
+ _refreshButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ // refresh the attributes list
+ refresh(_mbean);
+ }
+ });
+ }
+
+ private void addTableListeners()
+ {
+ _tableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
+ public void selectionChanged(SelectionChangedEvent evt)
+ {
+ IStructuredSelection ss = (IStructuredSelection)evt.getSelection();
+ checkForEnablingButtons((AttributeData)ss.getFirstElement());
+ }
+ });
+
+ MouseListenerImpl listener = new MouseListenerImpl();
+ _tableViewer.getTable().addMouseTrackListener(listener);
+ _tableViewer.getTable().addMouseMoveListener(listener);
+ _tableViewer.getTable().addMouseListener(listener);
+
+ _table.addDisposeListener(tableDisposeListener);
+
+ // _table is equal to _tableViewer.getControl()
+ _table.addListener(SWT.MeasureItem, new Listener() {
+ public void handleEvent(Event event)
+ {
+ event.height = event.gc.getFontMetrics().getHeight() * 3/2;
+ }
+ });
+
+ // Below to be worked on to set an image in front of each row.
+ /*
+ _table.addListener(SWT.PaintItem, new Listener() {
+ public void handleEvent(Event event)
+ {
+ int x = event.x + event.width;
+ Rectangle rect = image.getBounds();
+ int offset = Math.max(0, (event.height - rect.height) / 2);
+ event.gc.drawImage(image, event.x, event.y + offset);
+ }
+ });
+ */
+ }
+
+ private class MouseListenerImpl implements MouseTrackListener, MouseMoveListener,
+ KeyListener, MouseListener
+
+ {
+ Shell tooltipShell = null;
+ Label tooltipLabel = null;
+ public void mouseHover(MouseEvent event)
+ {
+ TableItem item = _table.getItem (new Point (event.x, event.y));
+
+ if (item != null)
+ {
+ AttributeData data = (AttributeData)item.getData();
+ if (tooltipShell != null && !tooltipShell.isDisposed ()) tooltipShell.dispose ();
+ tooltipShell = new Shell(_table.getShell(), SWT.ON_TOP | SWT.NO_FOCUS | SWT.TOOL);
+ tooltipShell.setBackground(event.display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+ FillLayout layout = new FillLayout();
+ layout.marginWidth = 2;
+ tooltipShell.setLayout(layout);
+ tooltipLabel = new Label(tooltipShell, SWT.NONE);
+ tooltipLabel.setForeground(event.display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
+ tooltipLabel.setBackground(event.display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
+ tooltipLabel.setText(data.getDescription());
+ tooltipLabel.setData("_TABLEITEM", item);
+ tooltipLabel.addListener(SWT.MouseExit, tooltipLabelListener);
+ tooltipLabel.addListener(SWT.MouseDown, tooltipLabelListener);
+ Point size = tooltipShell.computeSize(SWT.DEFAULT, SWT.DEFAULT);
+ Rectangle rect = item.getBounds(0);
+ Point pt = _table.toDisplay(rect.x, rect.y);
+ tooltipShell.setBounds(pt.x, pt.y, size.x, size.y);
+ tooltipShell.setVisible(true);
+ }
+ }
+ public void mouseEnter(MouseEvent e)
+ {
+ }
+ public void mouseExit(MouseEvent e)
+ {
+ }
+
+ // MouseMoveListener implementation
+ public void mouseMove(MouseEvent event)
+ {
+ if (tooltipShell == null)
+ return;
+
+ tooltipShell.dispose();
+ tooltipShell = null;
+ tooltipLabel = null;
+ }
+
+ // KeyListener implementation
+ public void keyPressed(KeyEvent e)
+ {
+ if (tooltipShell == null)
+ return;
+
+ tooltipShell.dispose();
+ tooltipShell = null;
+ tooltipLabel = null;
+ }
+ public void keyReleased(KeyEvent e)
+ {
+
+ }
+
+ // MouseListener implementation
+ public void mouseDoubleClick(MouseEvent event)
+ {
+ if (tooltipShell != null)
+ {
+ tooltipShell.dispose();
+ tooltipShell = null;
+ tooltipLabel = null;
+ }
+ Table table = (Table)event.getSource();
+ int selectionIndex = table.getSelectionIndex();
+ AttributeData data = (AttributeData)table.getItem(selectionIndex).getData();
+ createDetailsPopup(data);
+ }
+ public void mouseDown(MouseEvent e)
+ {
+ if (tooltipShell != null)
+ {
+ tooltipShell.dispose();
+ tooltipShell = null;
+ tooltipLabel = null;
+ }
+ }
+ public void mouseUp(MouseEvent e)
+ {
+
+ }
+ } // end of MouseListenerImpl
+
+ public void createDetailsPopup(AttributeData data)
+ {
+ int width = 500;
+ int height = 250;
+ if (data.getValue() instanceof TabularDataSupport)
+ {
+ width = 650;
+ height = 450;
+ }
+
+ Display display = Display.getCurrent();
+ Shell shell = ViewUtility.createPopupShell("Attribute", width, height);
+ createDetailsPopupContents(shell, data);
+
+ shell.open();
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch()) {
+ display.sleep();
+ }
+ }
+ shell.dispose();
+ }
+
+ final Listener tooltipLabelListener = new Listener ()
+ {
+ public void handleEvent (Event event)
+ {
+ Label label = (Label)event.widget;
+ Shell shell = label.getShell();
+ switch (event.type)
+ {
+ case SWT.MouseDown:
+ Event e = new Event();
+ e.item = (TableItem)label.getData ("_TABLEITEM");
+ _table.setSelection(new TableItem[] {(TableItem)e.item});
+ shell.dispose();
+ _table.setFocus();
+ break;
+ case SWT.MouseExit:
+ shell.dispose();
+ break;
+ }
+ }
+ };
+
+
+ private void createDetailsPopupContents(Composite shell, AttributeData attribute)
+ {
+ GridLayout layout = new GridLayout(2, false);
+ layout.horizontalSpacing = 10;
+ layout.verticalSpacing = 10;
+ layout.marginHeight = 20;
+ layout.marginWidth = 20;
+
+ Composite parent = new Composite(shell, SWT.NONE);
+ parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ parent.setLayout(layout);
+
+ // Name
+ Label label = new Label(parent, SWT.NONE);
+ label.setText(_tableTitles[0]);
+ GridData layoutData = new GridData(SWT.TRAIL, SWT.TOP, false, false);
+ label.setLayoutData(layoutData);
+ Text value = new Text(parent, SWT.BEGINNING | SWT.BORDER |SWT.READ_ONLY);
+ value.setText(attribute.getName());
+ value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+
+
+ // Description
+ label = new Label(parent, SWT.NONE);
+ label.setText(DESCRIPTION);
+ label.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, false, false));
+ value = new Text(parent, SWT.BEGINNING | SWT.BORDER | SWT.READ_ONLY);
+ value.setText(attribute.getDescription());
+ value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+
+ // value
+ label = new Label(parent, SWT.NONE);
+ label.setText(_tableTitles[1]);
+ label.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, false, false));
+
+ if (!attribute.isReadable())
+ {
+ value = new Text(parent, SWT.BEGINNING | SWT.BORDER | SWT.READ_ONLY);
+ value.setText("");
+ value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ }
+ else
+ {
+ if (attribute.getValue() instanceof TabularDataSupport)
+ {
+ Composite composite = new Composite(parent, SWT.BORDER);
+ composite.setLayout(new GridLayout());
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+ ViewUtility.createTabularDataHolder(composite,(TabularDataSupport)attribute.getValue());
+ }
+ else
+ {
+ int style = 0;
+ if (attribute.isWritable())
+ {
+ style = SWT.BEGINNING | SWT.BORDER;
+ value = new Text(parent, style);
+ value.addVerifyListener(new VerifyListener()
+ {
+ public void verifyText(VerifyEvent event)
+ {
+ String string = event.text;
+ char [] chars = new char [string.length ()];
+ string.getChars (0, chars.length, chars, 0);
+ for (int i=0; i<chars.length; i++)
+ {
+ if (!('0' <= chars [i] && chars [i] <= '9'))
+ {
+ event.doit = false;
+ return;
+ }
+ }
+ }
+ });
+
+ // set data to access in the listener
+ parent.setData(attribute);
+ }
+ else
+ {
+ style = SWT.BEGINNING | SWT.BORDER | SWT.READ_ONLY;
+ value = new Text(parent, style);
+ }
+
+ value.setText(attribute.getValue().toString());
+ value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ }
+ }
+
+
+ // Update button
+ Button updateButton = addUpdateButton(parent);
+ updateButton.setData(value);
+ if (!attribute.isWritable())
+ {
+ updateButton.setVisible(false);
+ }
+
+ if (disableEditing)
+ {
+ value.setEditable(false);
+ updateButton.setVisible(false);
+ }
+ }
+
+ private Button addUpdateButton(Composite parent)
+ {
+ final Button updateButton = new Button(parent, SWT.PUSH | SWT.CENTER);
+ // set the data to access in the listener
+ parent.setData(UPDATE_BUTTON, updateButton);
+
+ updateButton.setText(UPDATE_BUTTON);
+ GridData gridData = new GridData (SWT.CENTER, SWT.BOTTOM, true, true, 2, 1);
+ gridData.widthHint = 100;
+ updateButton.setLayoutData(gridData);
+ updateButton.addSelectionListener(new SelectionAdapter()
+ {
+ 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();
+ }
+ });
+
+ return updateButton;
+ }
+
+ // Refresh from the server registry
+ private void refresh()
+ {
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(_mbean);
+ ManagedAttributeModel attributesList = serverRegistry.getAttributeModel(_mbean);
+ _tableViewer.setInput(attributesList);
+ }
+
+ // Refreshes the attribute tab by querying the mbean server for latest values
+ @Override
+ public void refresh(ManagedBean mbean)
+ {
+ _mbean = mbean;
+ if (_mbean == null)
+ {
+ _tableViewer.setInput(null);
+ return;
+ }
+ ManagedAttributeModel attributesList = MBeanUtility.getAttributes(mbean);
+ _tableViewer.setInput(attributesList);
+ _table.setItemCount(attributesList.getCount());
+
+ // No attribtue selected when refreshing the tab
+ checkForEnablingButtons(null);
+ _form.layout();
+ }
+
+ public void setFocus()
+ {
+ _table.setFocus();
+ }
+
+ private void checkForEnablingButtons(AttributeData attribute)
+ {
+ if (attribute == null)
+ {
+ _detailsButton.setEnabled(false);
+ _editButton.setEnabled(false);
+ _graphButton.setEnabled(false);
+ _refreshButton.setEnabled(false);
+ return;
+ }
+
+ _detailsButton.setEnabled(true);
+ _refreshButton.setEnabled(true);
+ if (attribute.isWritable())
+ {
+ _editButton.setEnabled(true);
+ _graphButton.setEnabled(false);
+ }
+ else
+ {
+ _editButton.setEnabled(false);
+ if (attribute.isNumber())
+ {
+ _graphButton.setEnabled(true);
+ }
+ else
+ {
+ _graphButton.setEnabled(false);
+ }
+ }
+ }
+
+ private void createGraph(final AttributeData data)
+ {
+ Display display = Display.getCurrent();
+ Shell shell = new Shell(display, SWT.BORDER | SWT.CLOSE | SWT.MIN | SWT.MAX);
+ shell.setText(_mbean.getName());
+ int x = display.getBounds().width;
+ int y = display.getBounds().height;
+ shell.setBounds(x/4, y/4, GRAPH_WIDTH, GRAPH_HEIGHT);
+ shell.setLayout(new FillLayout());
+
+ final Canvas canvas = new Canvas(shell, SWT.NONE);
+ long currentValue = Long.parseLong(data.getValue().toString());
+ long mValue = getGraphMaxValue(currentValue);
+ canvas.setData(MAX_VALUE, mValue);
+ canvas.setData(GRAPH_VALUES, new long[] {0,0,0,0,0,currentValue});
+
+ canvas.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
+ canvas.addPaintListener(new PaintListener()
+ {
+ public void paintControl(PaintEvent event)
+ {
+ Canvas canvas = (Canvas)event.widget;
+ int maxX = canvas.getSize().x;
+ int maxY = canvas.getSize().y;
+ event.gc.fillRectangle(canvas.getBounds());
+ event.gc.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_BLACK));
+ event.gc.setLineWidth(4);
+
+ Object canvasData = canvas.getData(MAX_VALUE);
+ String str = canvasData.toString();
+ long maxValue = Long.parseLong(str);
+ // Set the graph dimensions
+ event.gc.drawText("0", startX - 40, maxY - startY - 10);
+ event.gc.drawText("" + maxValue/2, startX - 40, maxY/2);
+ event.gc.drawText("" + maxValue, startX - 40, startY);
+
+ // horizontal line
+ event.gc.drawLine(startX, maxY - startY, maxX - 60, maxY - startY);
+ // vertical line
+ event.gc.drawLine(startX, maxY - startY, startX, startY);
+ // set graph text
+ event.gc.drawText(data.getName(), startX - 40, startY - 40);
+ event.gc.drawText("25 sec", startX, maxY - startY + 10);
+ event.gc.drawText("20 sec", startX + GRAPH_ITEM_GAP, maxY - startY + 10);
+ event.gc.drawText("15 sec", startX + GRAPH_ITEM_GAP * 2, maxY - startY + 10);
+ event.gc.drawText("10 sec", startX + GRAPH_ITEM_GAP * 3, maxY - startY + 10);
+ event.gc.drawText(" 5 sec", startX + GRAPH_ITEM_GAP * 4, maxY - startY + 10);
+ event.gc.drawText(" 0 sec", startX + GRAPH_ITEM_GAP * 5, maxY - startY + 10);
+
+ // plot the graph now for values
+ event.gc.setForeground(Display.getCurrent().getSystemColor(SWT.COLOR_BLUE));
+ canvasData = canvas.getData(GRAPH_VALUES);
+ long[] graphValues = (long[]) canvasData;
+ for (int i = 0; i < graphValues.length; i++)
+ {
+ int x = startX + i * GRAPH_ITEM_GAP;
+ int yTotalLength = (maxY - 2 * startY);
+ float ratio = ((float)graphValues[i]/(float)maxValue);
+ int itemlength = (int)(yTotalLength * ratio);
+ int y = maxY - startY - itemlength;
+ event.gc.drawLine(x, maxY- startY, x, y);
+ event.gc.drawText(String.valueOf(graphValues[i]), x, y - 20);
+ }
+ }
+ });
+
+ shell.open();
+
+ // Set up the timer for the animation
+ Runnable runnable = new Runnable()
+ {
+ public void run()
+ {
+ try
+ {
+ animate(canvas, data);
+ Display.getCurrent().timerExec(Constants.TIMER_INTERVAL, this);
+ }
+ catch(Exception ex)
+ {
+ MBeanUtility.handleException(ex);
+ }
+ }
+ };
+
+ // Launch the timer
+ display.timerExec(Constants.TIMER_INTERVAL, runnable);
+
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch()) {
+ display.sleep();
+ }
+ }
+
+ // Kill the timer
+ display.timerExec(-1, runnable);
+ shell.dispose();
+ }
+
+ public AttributeData getSelectionAttribute()
+ {
+ int index = _table.getSelectionIndex();
+ if (index == -1)
+ return null;
+
+ return (AttributeData)_table.getItem(index).getData();
+ }
+
+ private void animate(Canvas canvas, AttributeData data) throws Exception
+ {
+ String attribute = data.getName();
+ int value = MBeanUtility.refreshAttribute(_mbean, attribute);
+ Object canvasData = canvas.getData(GRAPH_VALUES);
+ long[] graphValues = (long[]) canvasData;
+
+ for (int i = 0; i < graphValues.length -1; i++)
+ {
+ graphValues[i] = graphValues[i + 1];
+ }
+ graphValues[graphValues.length - 1] = value;
+
+ canvasData = canvas.getData(MAX_VALUE);
+ long maxValue = Long.parseLong(String.valueOf(canvasData));
+ if (maxValue < value)
+ {
+ maxValue = getGraphMaxValue(value);
+ canvas.setData(MAX_VALUE, maxValue);
+ }
+
+ canvas.redraw();
+ }
+
+ private long getGraphMaxValue(long maxAttributeValue)
+ {
+ long maxGraphValue = 100;
+ long temp = maxAttributeValue * 3/2;
+ if (temp > maxGraphValue)
+ {
+ long modulus = temp % 100;
+ maxGraphValue = temp + ( 100 - modulus);
+ }
+
+ return maxGraphValue;
+ }
+
+ private class ContentProviderImpl implements IStructuredContentProvider
+ {
+
+ public void inputChanged(Viewer v, Object oldInput, Object newInput)
+ {
+
+ }
+
+ public void dispose()
+ {
+
+ }
+
+ public Object[] getElements(Object parent)
+ {
+ return ((ManagedAttributeModel)parent).getAttributes();
+ }
+ }
+
+ private class LabelProviderImpl extends LabelProvider implements ITableLabelProvider,
+ IFontProvider,
+ IColorProvider
+ {
+
+ AttributeData attribute = null;
+ public String getColumnText(Object element, int columnIndex)
+ {
+ String result = "";
+ attribute = (AttributeData) element;
+
+ switch (columnIndex)
+ {
+ case 0 : // attribute name column
+ result = ViewUtility.getDisplayText(attribute.getName());
+ break;
+ case 1 : // attribute value column
+ if (attribute.getValue() != null)
+ result = String.valueOf(attribute.getValue());
+ break;
+ default :
+ result = "";
+ }
+
+ return result;
+ }
+
+ public Image getColumnImage(Object element, int columnIndex)
+ {
+ return null;
+ }
+
+ public Font getFont(Object element)
+ {
+ return ApplicationRegistry.getFont(Constants.FONT_TABLE_CELL);
+ }
+
+ public Color getForeground(Object element)
+ {
+ attribute = (AttributeData) element;
+ if (attribute.isWritable())
+ return Display.getCurrent().getSystemColor(SWT.COLOR_DARK_BLUE);
+ else
+ return Display.getCurrent().getSystemColor(SWT.COLOR_BLACK);
+ }
+ public Color getBackground(Object element)
+ {
+ return _form.getBackground();
+ }
+ }
+
+ private class DisposeListenerImpl implements DisposeListener
+ {
+ public void widgetDisposed(DisposeEvent e)
+ {
+
+ }
+ }
+
+ /*
+ class TableCellModifier implements ICellModifier
+ {
+
+ public boolean canModify(Object element, String property)
+ {
+ int columnIndex = Arrays.asList(_tableTitles).indexOf(property);
+ if (columnIndex == 0)
+ return false;
+
+ return true;
+ }
+
+ public Object getValue(Object element, String property) {
+
+ // Find the index of the column
+ int columnIndex = Arrays.asList(_tableTitles).indexOf(property);
+ Attribute attribute = (Attribute)element;
+
+
+ Object result = null;
+
+ switch (columnIndex)
+ {
+ case 0 : // attribute name column
+ result = attribute.getName();
+ break;
+ case 1 : // attribute value column
+ result = attribute.getValue();
+ break;
+ default :
+ result = "";
+ }
+
+ return result;
+ }
+
+
+ public void modify(Object element, String property, Object value)
+ {
+ // Find the index of the column
+ int columnIndex = Arrays.asList(_tableTitles).indexOf(property);
+
+ if (columnIndex == 1)
+ {
+ //TODO
+ // update the attribute value and call the MBean setAttribute method
+ // then refresh the attribute tab with new values
+ }
+ }
+ }
+ */
+
+} \ No newline at end of file
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/INotificationViewer.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/INotificationViewer.java
new file mode 100644
index 0000000000..bc560b6064
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/INotificationViewer.java
@@ -0,0 +1,32 @@
+/*
+ *
+ * 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.management.ui.views;
+
+import java.util.List;
+
+import org.apache.qpid.management.ui.model.NotificationObject;
+
+public interface INotificationViewer
+{
+ public void addNotification(NotificationObject notification);
+
+ public void addNotification(List<NotificationObject> notificationList);
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanView.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanView.java
new file mode 100644
index 0000000000..063f80fd3f
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanView.java
@@ -0,0 +1,431 @@
+/*
+ *
+ * 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.management.ui.views;
+
+import java.util.HashMap;
+
+import org.apache.qpid.management.ui.ApplicationRegistry;
+import org.apache.qpid.management.ui.Constants;
+import org.apache.qpid.management.ui.ManagedBean;
+import org.apache.qpid.management.ui.exceptions.InfoRequiredException;
+import org.apache.qpid.management.ui.jmx.JMXServerRegistry;
+import org.apache.qpid.management.ui.jmx.MBeanUtility;
+import org.apache.qpid.management.ui.model.AttributeData;
+import org.apache.qpid.management.ui.model.OperationData;
+import org.apache.qpid.management.ui.model.OperationDataModel;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.TabItem;
+import org.eclipse.ui.ISelectionListener;
+import org.eclipse.ui.IWorkbenchPart;
+import org.eclipse.ui.forms.widgets.Form;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+import org.eclipse.ui.part.ViewPart;
+
+
+public class MBeanView extends ViewPart
+{
+ public static final String ID = "org.apache.qpid.management.ui.mbeanView";
+
+ private FormToolkit _toolkit = null;
+ private Form _form = null;
+ private ManagedBean _mbean = null;
+ private HashMap<String, TabFolder> tabFolderMap = new HashMap<String, TabFolder>();
+ private ISelectionListener selectionListener = new SelectionListenerImpl();
+
+ private static final String ATTRIBUTES_CONTROL = "AttributesTabControl";
+ private static final String OPERATIONS_CONTROL = "OperationsTabControl";
+ private static final String NOTIFICATIONS_CONTROL = "NotificationsTabControl";
+
+
+ /*
+ * Listener for the selection events in the navigation view
+ */
+ private class SelectionListenerImpl implements ISelectionListener
+ {
+ public void selectionChanged(IWorkbenchPart part, ISelection sel)
+ {
+ if (!(sel instanceof IStructuredSelection))
+ return;
+
+ IStructuredSelection ss = (IStructuredSelection) sel;
+ TreeObject node = (TreeObject)ss.getFirstElement();
+ showSelectedMBean(node);
+ /*
+ _mbean = null;
+ setInvisible();
+
+ if (node == null)
+ {
+ _form.setText("Qpid Management Console");
+ return;
+ }
+
+ if (Constants.NOTIFICATION.equals(node.getType()))
+ {
+ _mbean = (ManagedBean)node.getParent().getManagedObject();
+ }
+ else if (Constants.MBEAN.equals(node.getType()))
+ {
+ _mbean = (ManagedBean)node.getManagedObject();
+ }
+ else
+ {
+ _form.setText("Qpid Management Console");
+ return;
+ }
+
+ setFocus();
+ try
+ {
+ MBeanUtility.getMBeanInfo(_mbean);
+ }
+ catch(Exception ex)
+ {
+ MBeanUtility.handleException(_mbean, ex);
+ return;
+ }
+
+ TabFolder tabFolder = tabFolderMap.get(_mbean.getType());
+ if (tabFolder == null)
+ {
+ tabFolder = createTabFolder();
+ }
+
+ String text = _mbean.getType();
+ if (_mbean.getName() != null && _mbean.getName().length() != 0)
+ {
+ text = text + ": " + _mbean.getName();
+ }
+ _form.setText(text);
+ int tabIndex = 0;
+ if (Constants.NOTIFICATION.equals(node.getType()))
+ {
+ tabIndex = tabFolder.getItemCount() -1;
+ }
+
+ TabItem tab = tabFolder.getItem(tabIndex);
+ // refreshTab(tab);
+ // If folder is being set as visible after tab refresh, then the tab
+ // doesn't have the focus.
+
+ tabFolder.setSelection(tabIndex);
+ refreshTab(tab);
+ setVisible(tabFolder);
+ _form.layout();
+
+ // Set the focus on the first attribute in attributes table
+ if (tab.getText().equals(Constants.ATTRIBUTES))
+ {
+ ((TabControl)tabFolder.getData(ATTRIBUTES_CONTROL)).setFocus();
+ }*/
+ }
+ }
+
+ public void showSelectedMBean(TreeObject node)
+ {
+ _mbean = null;
+ setInvisible();
+
+ if (node == null)
+ {
+ _form.setText("Qpid Management Console");
+ return;
+ }
+
+ if (Constants.NOTIFICATION.equals(node.getType()))
+ {
+ _mbean = (ManagedBean)node.getParent().getManagedObject();
+ }
+ else if (Constants.MBEAN.equals(node.getType()))
+ {
+ _mbean = (ManagedBean)node.getManagedObject();
+ }
+ else
+ {
+ _form.setText("Qpid Management Console");
+ return;
+ }
+
+ setFocus();
+ try
+ {
+ MBeanUtility.getMBeanInfo(_mbean);
+ }
+ catch(Exception ex)
+ {
+ MBeanUtility.handleException(_mbean, ex);
+ return;
+ }
+
+ TabFolder tabFolder = tabFolderMap.get(_mbean.getType());
+ if (tabFolder == null)
+ {
+ tabFolder = createTabFolder();
+ }
+
+ String text = _mbean.getType();
+ if (_mbean.getName() != null && _mbean.getName().length() != 0)
+ {
+ text = text + ": " + _mbean.getName();
+ }
+ _form.setText(text);
+ int tabIndex = 0;
+ if (Constants.NOTIFICATION.equals(node.getType()))
+ {
+ tabIndex = tabFolder.getItemCount() -1;
+ }
+
+ TabItem tab = tabFolder.getItem(tabIndex);
+ // refreshTab(tab);
+ // If folder is being set as visible after tab refresh, then the tab
+ // doesn't have the focus.
+
+ tabFolder.setSelection(tabIndex);
+ refreshTab(tab);
+ setVisible(tabFolder);
+ _form.layout();
+ }
+
+ public void createPartControl(Composite parent)
+ {
+ // Create the Form
+ _toolkit = new FormToolkit(parent.getDisplay());
+ _form = _toolkit.createForm(parent);
+ _form.getBody().setLayout(new FormLayout());
+ _form.setText(Constants.APPLICATION_NAME);
+
+ // Add selection listener for selection events in the Navigation view
+ getSite().getPage().addSelectionListener(NavigationView.ID, selectionListener);
+ }
+
+ public void refreshMBeanView()
+ {
+ if (_mbean == null)
+ return;
+
+ TabFolder tabFolder = tabFolderMap.get(_mbean.getType());
+ if (tabFolder == null)
+ return;
+
+ int index = tabFolder.getSelectionIndex();
+ TabItem tab = tabFolder.getItem(index);
+ if (tab == null)
+ return;
+
+ refreshTab(tab);
+ _form.layout();
+ }
+
+ private TabFolder createTabFolder()
+ {
+ TabFolder tabFolder = new TabFolder(_form.getBody(), SWT.NONE);
+ FormData layoutData = new FormData();
+ layoutData.left = new FormAttachment(0);
+ layoutData.top = new FormAttachment(0);
+ layoutData.right = new FormAttachment(100);
+ layoutData.bottom = new FormAttachment(100);
+ tabFolder.setLayoutData(layoutData);
+ tabFolder.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
+ tabFolder.setVisible(false);
+
+ createAttributesTab(tabFolder);
+ createOperationTabs(tabFolder);
+ createNotificationsTab(tabFolder);
+
+ tabFolder.addListener(SWT.Selection, new Listener()
+ {
+ public void handleEvent(Event evt)
+ {
+ TabItem tab = (TabItem)evt.item;
+ refreshTab(tab);
+ }
+ });
+
+ tabFolderMap.put(_mbean.getType(), tabFolder);
+ return tabFolder;
+ }
+
+ private void refreshTab(TabItem tab)
+ {
+ // We can avoid refreshing the attributes tab because it's control
+ // already contains the required values. But it is added for now and
+ // will remove if there is any perfornce or any such issue.
+ // The operations control should be refreshed because there is only one
+ // controller for all operations tab.
+ // The Notifications control needs to refresh with latest set of notifications
+
+ if (tab == null)
+ return;
+
+ TabFolder tabFolder = tab.getParent();
+ if (tab.getData() != null && (tab.getData() instanceof OperationData))
+ {
+ // Refresh selected operation tab
+ TabControl control = (TabControl)tabFolder.getData(OPERATIONS_CONTROL);
+ if (control == null)
+ return;
+
+ control.refresh(_mbean, (OperationData)tab.getData());
+ }
+ else if (tab.getText().equals(Constants.NOTIFICATION))
+ {
+ TabControl control = (TabControl)tabFolder.getData(NOTIFICATIONS_CONTROL);
+ if (control == null)
+ return;
+
+ control.refresh(_mbean);
+ }
+ else if (tab.getText().equals(Constants.ATTRIBUTES))
+ {
+ TabControl control = (TabControl)tabFolder.getData(ATTRIBUTES_CONTROL);
+ if (control == null)
+ return;
+
+ control.refresh(_mbean);
+ }
+
+ }
+
+ public void setFocus()
+ {
+ //_form.setFocus();
+ }
+
+ public void dispose()
+ {
+ _toolkit.dispose();
+ super.dispose();
+ }
+
+ private void createAttributesTab(TabFolder tabFolder)
+ {
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(_mbean);
+ if (serverRegistry.getAttributeModel(_mbean).getCount() == 0)
+ {
+ return;
+ }
+
+ TabItem tab = new TabItem(tabFolder, SWT.NONE);
+ tab.setText(Constants.ATTRIBUTES);
+ AttributesTabControl control = new AttributesTabControl(tabFolder);
+ tab.setControl(control.getControl());
+ tabFolder.setData(ATTRIBUTES_CONTROL, control);
+ }
+
+ private void createOperationTabs(TabFolder tabFolder)
+ {
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(_mbean);
+ int operationsCount = serverRegistry.getOperationModel(_mbean).getCount();
+ if (operationsCount == 0)
+ {
+ return;
+ }
+
+ OperationTabControl control = new OperationTabControl(tabFolder);
+ tabFolder.setData(OPERATIONS_CONTROL, control);
+
+ OperationDataModel operationModel = serverRegistry.getOperationModel(_mbean);
+ for (OperationData operationData : operationModel.getOperations())
+ {
+ TabItem operationTab = new TabItem(tabFolder, SWT.NONE);
+ operationTab.setText(ViewUtility.getDisplayText(operationData.getName()));
+ operationTab.setData(operationData);
+ operationTab.setControl(control.getControl());
+ }
+ }
+
+ private void createNotificationsTab(TabFolder tabFolder)
+ {
+ NotificationsTabControl controller = new NotificationsTabControl(tabFolder);
+ tabFolder.setData(NOTIFICATIONS_CONTROL, controller);
+
+ TabItem tab = new TabItem(tabFolder, SWT.NONE);
+ tab.setText(Constants.NOTIFICATION);
+ tab.setControl(controller.getControl());
+ }
+
+ /**
+ * For the EditAttribtue Action. Invoking this from action is same as clicking
+ * "EditAttribute" button from Attribute tab.
+ */
+ public void editAttribute() throws Exception
+ {
+ if (_mbean == null)
+ throw new InfoRequiredException("Please select the managed object and then attribute to be edited");
+
+ String name = (_mbean.getName() != null) ? _mbean.getName() : _mbean.getType();
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(_mbean);
+ if (serverRegistry.getAttributeModel(_mbean).getCount() == 0)
+ {
+ throw new InfoRequiredException("There are no attributes to be edited for " + name);
+ }
+
+ TabFolder tabFolder = tabFolderMap.get(_mbean.getType());
+ int index = tabFolder.getSelectionIndex();
+ if (index != 0)
+ {
+ tabFolder.setSelection(0);
+ throw new InfoRequiredException("Please select the attribute to be edited");
+ }
+
+ AttributesTabControl tabControl = (AttributesTabControl)tabFolder.getData(ATTRIBUTES_CONTROL);
+ AttributeData attribute = tabControl.getSelectionAttribute();
+ if (attribute == null)
+ throw new InfoRequiredException("Please select the attribute to be edited");
+
+ tabControl.createDetailsPopup(attribute);
+ }
+
+
+ /**
+ * hides other folders and makes the given one visible.
+ * @param tabFolder
+ */
+ private void setVisible(TabFolder tabFolder)
+ {
+ for (TabFolder folder : tabFolderMap.values())
+ {
+ if (folder == tabFolder)
+ folder.setVisible(true);
+ else
+ folder.setVisible(false);
+ }
+ }
+
+ private void setInvisible()
+ {
+ for (TabFolder folder : tabFolderMap.values())
+ {
+ folder.setVisible(false);
+ }
+ }
+
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NavigationView.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NavigationView.java
new file mode 100644
index 0000000000..4319a4bd10
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NavigationView.java
@@ -0,0 +1,787 @@
+/*
+ *
+ * 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.management.ui.views;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import javax.management.MBeanServerConnection;
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+
+import org.apache.qpid.management.ui.ApplicationRegistry;
+import org.apache.qpid.management.ui.Constants;
+import org.apache.qpid.management.ui.ManagedBean;
+import org.apache.qpid.management.ui.ManagedServer;
+import org.apache.qpid.management.ui.ServerRegistry;
+import org.apache.qpid.management.ui.exceptions.InfoRequiredException;
+import org.apache.qpid.management.ui.jmx.JMXManagedObject;
+import org.apache.qpid.management.ui.jmx.JMXServerRegistry;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.IFontProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.ITreeContentProvider;
+import org.eclipse.jface.viewers.ITreeViewerListener;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TreeExpansionEvent;
+import org.eclipse.jface.viewers.TreeViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.ui.part.ViewPart;
+
+
+public class NavigationView extends ViewPart
+{
+ public static final String ID = "org.apache.qpid.management.ui.navigationView";
+ public static final String INI_FILENAME = System.getProperty("user.home") + File.separator + "qpidManagementConsole.ini";
+
+ private TreeViewer _treeViewer = null;
+ private TreeObject _rootNode = null;
+ private TreeObject _serversRootNode = null;
+ // List of all server nodes (connecged or removed)
+ //private List<TreeObject> _serverNodeList = new ArrayList<TreeObject>();
+ // Map of connected servers
+ private HashMap<ManagedServer, TreeObject> _managedServerMap = new HashMap<ManagedServer, TreeObject>();
+
+ private void createTreeViewer(Composite parent)
+ {
+ _treeViewer = new TreeViewer(parent);
+ _treeViewer.setContentProvider(new ContentProviderImpl());
+ _treeViewer.setLabelProvider(new LabelProviderImpl());
+ _treeViewer.setSorter(new ViewerSorterImpl());
+
+ // layout the tree viewer below the label field, to cover the area
+ GridData layoutData = new GridData();
+ layoutData = new GridData();
+ layoutData.grabExcessHorizontalSpace = true;
+ layoutData.grabExcessVerticalSpace = true;
+ layoutData.horizontalAlignment = GridData.FILL;
+ layoutData.verticalAlignment = GridData.FILL;
+ _treeViewer.getControl().setLayoutData(layoutData);
+ _treeViewer.setUseHashlookup(true);
+
+ createListeners();
+ }
+
+ private void createListeners()
+ {
+ _treeViewer.addDoubleClickListener(new IDoubleClickListener()
+ {
+ public void doubleClick(DoubleClickEvent event)
+ {
+ IStructuredSelection ss = (IStructuredSelection)event.getSelection();
+ if (ss == null || ss.getFirstElement() == null)
+ {
+ return;
+ }
+ boolean state = _treeViewer.getExpandedState(ss.getFirstElement());
+ _treeViewer.setExpandedState(ss.getFirstElement(), !state);
+ }
+ });
+
+ _treeViewer.addTreeListener(new ITreeViewerListener()
+ {
+ public void treeExpanded(TreeExpansionEvent event)
+ {
+ _treeViewer.setExpandedState(event.getElement(), true);
+ // Following will cause the selection event to be sent, so commented
+ //_treeViewer.setSelection(new StructuredSelection(event.getElement()));
+ _treeViewer.refresh();
+ }
+
+ public void treeCollapsed(TreeExpansionEvent event)
+ {
+ _treeViewer.setExpandedState(event.getElement(), false);
+ _treeViewer.refresh();
+ }
+ });
+ }
+
+ private void createRMIServerConnection(ManagedServer server) throws Exception
+ {
+ try
+ {
+ // Currently Qpid Management Console only supports JMX MBeanServer
+ JMXServerRegistry serverRegistry = new JMXServerRegistry(server);
+ ApplicationRegistry.addServer(server, serverRegistry);
+ }
+ catch(Exception ex)
+ {
+ throw new Exception("Error in connecting to Qpid broker at " + server.getUrl(), ex);
+ }
+ }
+
+ private String getRMIURL(String host)
+ {
+ return "service:jmx:rmi:///jndi/rmi://" + host + "/jmxrmi";
+ }
+
+
+ public void addNewServer(String transportProtocol, String host, String port, String domain)
+ throws Exception
+ {
+ if ("RMI".equals(transportProtocol))
+ {
+ String serverAddress = host + ":" + port;
+ String url = getRMIURL(serverAddress);
+ List<TreeObject> list = _serversRootNode.getChildren();
+ for (TreeObject node : list)
+ {
+ if (url.equals(node.getUrl()))
+ throw new InfoRequiredException("Server " + serverAddress + " is already added");
+ }
+
+ ManagedServer managedServer = new ManagedServer(url, domain);
+ managedServer.setName(serverAddress);
+ createRMIServerConnection(managedServer);
+
+ // RMI server connection is successful. Now add the server in the tree
+ TreeObject serverNode = new TreeObject(serverAddress, Constants.SERVER);
+ serverNode.setUrl(url);
+ serverNode.setManagedObject(managedServer);
+ _serversRootNode.addChild(serverNode);
+
+ // Add server in the connected server map
+ _managedServerMap.put(managedServer, serverNode);
+ populateServer(serverNode);
+ _treeViewer.refresh();
+
+ // save server address in file
+ addServerAddressInFile(serverAddress);
+ }
+ else
+ {
+ throw new InfoRequiredException(transportProtocol + " transport is not supported");
+ }
+ }
+
+ private void addServerAddressInFile(String serverAddress)
+ {
+ File file = new File(INI_FILENAME);
+ try
+ {
+ if (!file.exists())
+ file.createNewFile();
+
+ BufferedWriter out = new BufferedWriter(new FileWriter(file, true));
+ out.write(serverAddress + "\n");
+ out.close();
+
+ }
+ catch(Exception ex)
+ {
+ System.out.println("Could not write to the file " + INI_FILENAME);
+ System.out.println(ex);
+ }
+ }
+
+
+ private void populateServer(TreeObject serverNode)
+ {
+ ManagedServer server = (ManagedServer)serverNode.getManagedObject();
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(server);
+ String domain = server.getDomain();
+ try
+ {
+ if (!domain.equals("All"))
+ {
+ TreeObject domainNode = new TreeObject(domain, Constants.DOMAIN);
+ domainNode.setParent(serverNode);
+
+ populateDomain(domainNode);
+ }
+ else
+ {
+ List<TreeObject> domainList = new ArrayList<TreeObject>();
+ MBeanServerConnection mbsc = serverRegistry.getServerConnection();
+ String[] domains = mbsc.getDomains();
+ for (int i = 0; i < domains.length; i++)
+ {
+ TreeObject domainNode = new TreeObject(domains[i], Constants.DOMAIN);
+ domainNode.setParent(serverNode);
+
+ domainList.add(domainNode);
+ populateDomain(domainNode);
+ }
+ }
+ }
+ catch(Exception ex)
+ {
+ System.out.println("\nError in connecting to Qpid broker ");
+ System.out.println("\n" + ex.toString());
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void populateDomain(TreeObject domain) throws IOException, Exception
+ {
+ ManagedServer server = (ManagedServer)domain.getParent().getManagedObject();
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(server);
+
+ String domainName = domain.getName();
+ MBeanServerConnection mbsc = serverRegistry.getServerConnection();
+
+
+ ObjectName objName = new ObjectName(domainName + ":*");
+ Set queryMBeans = mbsc.queryMBeans(objName, null);
+ final Set<ObjectInstance> objectInstances = queryMBeans;
+
+ for (Iterator<ObjectInstance> itr = objectInstances.iterator(); itr.hasNext();)
+ {
+ ObjectInstance instance = itr.next();
+ ManagedBean obj = new JMXManagedObject(instance.getObjectName());
+ obj.setServer(server);
+ addManagedBean(domain, obj);
+ }
+ }
+
+ private TreeObject getIfTypeAlreadyExists(TreeObject domain, String type)
+ {
+ List<TreeObject> types = domain.getChildren();
+
+ for (TreeObject child : types)
+ {
+ if (Constants.TYPE.equals(child.getType()) && type.equals(child.getName()))
+ return child;
+ }
+ return null;
+ }
+
+ private void addManagedBean(TreeObject domain, ManagedBean obj)
+ {
+ ManagedServer server = (ManagedServer)domain.getParent().getManagedObject();
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(server);
+ serverRegistry.addManagedObject(obj);
+
+ String type = obj.getType();
+ String name = obj.getName();
+
+ TreeObject typeChild = getIfTypeAlreadyExists(domain, type);
+ TreeObject mbeanNode = null;
+ if (typeChild != null) // if type is already added as a TreeItem
+ {
+ if (name == null)
+ {
+ System.out.println("Two mbeans can't exist without a name and with same type");
+ return;
+ }
+ mbeanNode = new TreeObject(obj);
+ mbeanNode.setParent(typeChild);
+ }
+ else
+ {
+ if (name != null) // An managedObject with type and name
+ {
+ typeChild = new TreeObject(type, Constants.TYPE);
+ typeChild.setParent(domain);
+ mbeanNode = new TreeObject(obj);
+ mbeanNode.setParent(typeChild);
+ }
+ else // An managedObject with only type
+ {
+ mbeanNode = new TreeObject(obj);
+ mbeanNode.setParent(domain);
+ }
+ }
+
+ // Add notification node
+ // TODO: show this only of the mbean sends any notification
+ TreeObject notificationNode = new TreeObject(Constants.NOTIFICATION, Constants.NOTIFICATION);
+ notificationNode.setParent(mbeanNode);
+ }
+
+ /**
+ * Removes all the child nodes of the given parent node
+ * @param parent
+ */
+ private void removeManagedObject(TreeObject parent)
+ {
+ List<TreeObject> list = parent.getChildren();
+ for (TreeObject child : list)
+ {
+ removeManagedObject(child);
+ }
+
+ list.clear();
+ }
+
+ /**
+ * Removes the mbean from the tree
+ * @param parent
+ * @param mbean
+ */
+ private void removeManagedObject(TreeObject parent, ManagedBean mbean)
+ {
+ List<TreeObject> list = parent.getChildren();
+ TreeObject objectToRemove = null;
+ for (TreeObject child : list)
+ {
+ if (Constants.MBEAN.equals(child.getType()))
+ {
+ String name = mbean.getName() != null ? mbean.getName() : mbean.getType();
+ if (child.getName().equals(name))
+ {
+ objectToRemove = child;
+ break;
+ }
+ }
+ else
+ {
+ removeManagedObject(child, mbean);
+ }
+ }
+
+ if (objectToRemove != null)
+ {
+ list.remove(objectToRemove);
+ }
+
+ }
+
+ public void disconnect() throws Exception
+ {
+ TreeObject selectedNode = getSelectedServerNode();
+ ManagedServer managedServer = (ManagedServer)selectedNode.getManagedObject();
+ if (!_managedServerMap.containsKey(managedServer))
+ return;
+
+ // Close server connection
+ ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(managedServer);
+ if (serverRegistry == null) // server connection is already closed
+ return;
+
+ serverRegistry.closeServerConnection();
+ // Add server to the closed server list and the worker thread will remove the server from required places.
+ ApplicationRegistry.serverConnectionClosed(managedServer);
+ }
+
+ /**
+ * Connects the selected server node
+ * @throws Exception
+ */
+ public void reconnect() throws Exception
+ {
+ TreeObject selectedNode = getSelectedServerNode();
+ ManagedServer managedServer = (ManagedServer)selectedNode.getManagedObject();
+ if(_managedServerMap.containsKey(managedServer))
+ {
+ throw new InfoRequiredException("Server " + managedServer.getName() + " is already connected");
+ }
+ createRMIServerConnection(managedServer);
+ _managedServerMap.put(managedServer, selectedNode);
+ populateServer(selectedNode);
+ _treeViewer.refresh();
+ }
+
+ public void removeServer() throws Exception
+ {
+ disconnect();
+
+ // Remove from the Tree
+ String serverNodeName = getSelectedServerNode().getName();
+ List<TreeObject> list = _serversRootNode.getChildren();
+ TreeObject objectToRemove = null;
+ for (TreeObject child : list)
+ {
+ if (child.getName().equals(serverNodeName))
+ {
+ objectToRemove = child;
+ break;
+ }
+ }
+
+ if (objectToRemove != null)
+ {
+ list.remove(objectToRemove);
+ }
+
+ //_serverNodeList.remove(objectToRemove);
+ _treeViewer.refresh();
+
+ // Remove from the ini file
+ List<String> serversList = getServerListFromFile();
+ serversList.remove(serverNodeName);
+
+ BufferedWriter out = new BufferedWriter(new FileWriter(INI_FILENAME));
+ for (String serverAddress : serversList)
+ {
+ out.write(serverAddress + "\n");
+ }
+ out.close();
+ }
+
+ private List<String> getServerListFromFile() throws Exception
+ {
+ BufferedReader in = new BufferedReader(new FileReader(INI_FILENAME));
+ List<String> serversList = new ArrayList<String>();
+ String str;
+ while ((str = in.readLine()) != null)
+ {
+ serversList.add(str);
+ }
+ in.close();
+
+ return serversList;
+ }
+
+ private TreeObject getSelectedServerNode() throws Exception
+ {
+ IStructuredSelection ss = (IStructuredSelection)_treeViewer.getSelection();
+ TreeObject selectedNode = (TreeObject)ss.getFirstElement();
+ if (ss.isEmpty() || selectedNode == null || (!selectedNode.getType().equals(Constants.SERVER)))
+ {
+ throw new InfoRequiredException("Please select the server");
+ }
+
+ return selectedNode;
+ }
+ /**
+ * This is a callback that will allow us to create the viewer and initialize
+ * it.
+ */
+ public void createPartControl(Composite parent)
+ {
+ Composite composite = new Composite(parent, SWT.NONE);
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.marginHeight = 2;
+ gridLayout.marginWidth = 2;
+ gridLayout.horizontalSpacing = 0;
+ gridLayout.verticalSpacing = 2;
+ composite.setLayout(gridLayout);
+
+ createTreeViewer(composite);
+ _rootNode = new TreeObject("ROOT", "ROOT");
+ _serversRootNode = new TreeObject(Constants.NAVIGATION_ROOT, "ROOT");
+ _serversRootNode.setParent(_rootNode);
+
+ _treeViewer.setInput(_rootNode);
+ // set viewer as selection event provider for MBeanView
+ getSite().setSelectionProvider(_treeViewer);
+
+ // Start worker thread to refresh tree for added or removed objects
+ (new Thread(new Worker())).start();
+
+ try
+ {
+ // load the list of servers already added from file
+ List<String> serversList = getServerListFromFile();
+ for (String serverAddress : serversList)
+ {
+ try
+ {
+ String url = getRMIURL(serverAddress);
+ ManagedServer managedServer = new ManagedServer(url, "org.apache.qpid");
+ managedServer.setName(serverAddress);
+ TreeObject serverNode = new TreeObject(serverAddress, Constants.SERVER);
+ serverNode.setUrl(url);
+ serverNode.setManagedObject(managedServer);
+ _serversRootNode.addChild(serverNode);
+ }
+ catch(Exception ex)
+ {
+ System.out.println(ex);
+ }
+ }
+ _treeViewer.refresh();
+ }
+ catch(Exception ex)
+ {
+ System.out.println(ex);
+ }
+ }
+
+ /**
+ * Passing the focus request to the viewer's control.
+ */
+ public void setFocus()
+ {
+
+ }
+
+ public void refresh()
+ {
+ _treeViewer.refresh();
+ }
+
+ private class ContentProviderImpl implements ITreeContentProvider
+ {
+ public Object[] getElements(Object parent)
+ {
+ return getChildren(parent);
+ }
+
+ public Object[] getChildren(final Object parentElement)
+ {
+ final TreeObject node = (TreeObject)parentElement;
+ return node.getChildren().toArray(new TreeObject[0]);
+ }
+
+ public Object getParent(final Object element)
+ {
+ final TreeObject node = (TreeObject)element;
+ return node.getParent();
+ }
+
+ public boolean hasChildren(final Object element)
+ {
+ final TreeObject node = (TreeObject) element;
+ return !node.getChildren().isEmpty();
+ }
+
+ public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput)
+ {
+ // Do nothing
+ }
+
+ public void dispose()
+ {
+ // Do nothing
+ }
+ }
+
+ private class LabelProviderImpl extends LabelProvider implements IFontProvider
+ {
+ public Image getImage(Object element)
+ {
+ TreeObject node = (TreeObject)element;
+ if (node.getType().equals(Constants.NOTIFICATION))
+ {
+ return ApplicationRegistry.getImage(Constants.NOTIFICATION_IMAGE);
+ }
+ else if (!node.getType().equals(Constants.MBEAN))
+ {
+ if (_treeViewer.getExpandedState(node))
+ return ApplicationRegistry.getImage(Constants.OPEN_FOLDER_IMAGE);
+ else
+ return ApplicationRegistry.getImage(Constants.CLOSED_FOLDER_IMAGE);
+
+ }
+ else
+ {
+ return ApplicationRegistry.getImage(Constants.MBEAN_IMAGE);
+ }
+ }
+
+ public String getText(Object element)
+ {
+ TreeObject node = (TreeObject)element;
+ return node.getName();
+ }
+
+ public Font getFont(Object element)
+ {
+ TreeObject node = (TreeObject)element;
+ if (node.getType().equals(Constants.SERVER))
+ {
+ if (node.getChildren().isEmpty())
+ return ApplicationRegistry.getFont(Constants.FONT_NORMAL);
+ else
+ return ApplicationRegistry.getFont(Constants.FONT_BOLD);
+ }
+ return ApplicationRegistry.getFont(Constants.FONT_NORMAL);
+ }
+
+ /*
+ public Color getForeground(Object element)
+ {
+ TreeObject node = (TreeObject)element;
+ if (node.getType().equals(Constants.SERVER))
+ {
+ if (!node.getChildren().isEmpty())
+ return Display.getCurrent().getSystemColor(SWT.COLOR_DARK_GREEN);
+ else
+ return Display.getCurrent().getSystemColor(SWT.COLOR_DARK_GRAY);
+ }
+ return Display.getCurrent().getSystemColor(SWT.COLOR_BLACK);
+ }
+ public Color getBackground(Object element)
+ {
+ return _treeViewer.getControl().getBackground();
+ }*/
+ } // End of LabelProviderImpl
+
+
+ private class ViewerSorterImpl extends ViewerSorter
+ {
+ public int category(Object element)
+ {
+ TreeObject node = (TreeObject)element;
+ if (node.getType().equals(Constants.MBEAN))
+ return 1;
+ return 2;
+ }
+ }
+
+ /**
+ * Worker thread, which keeps looking for new ManagedObjects to be added and
+ * unregistered objects to be removed from the tree.
+ * @author Bhupendra Bhardwaj
+ */
+ private class Worker implements Runnable
+ {
+ public void run()
+ {
+ while(true)
+ {
+ if (_managedServerMap.isEmpty())
+ continue;
+
+ try
+ {
+ Thread.sleep(2000);
+ }
+ catch(Exception ex)
+ {
+
+ }
+ refreshAddedObjects();
+ refreshRemovedObjects();
+ refreshClosedServerConnections();
+ }// end of while loop
+ }// end of run method.
+ }// end of Worker class
+
+
+ private void refreshAddedObjects()
+ {
+ for (ManagedServer server : _managedServerMap.keySet())
+ {
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(server);
+ if (serverRegistry == null) // server connection is closed
+ continue;
+
+ final List<ManagedBean> list = serverRegistry.getObjectsToBeAdded();
+ if (list != null)
+ {
+ Display display = getSite().getShell().getDisplay();
+ display.syncExec(new Runnable()
+ {
+ public void run()
+ {
+ for (ManagedBean obj : list)
+ {
+ System.out.println("adding " + obj.getName() + " " + obj.getType());
+ TreeObject treeServerObject = _managedServerMap.get(obj.getServer());
+ List<TreeObject> domains = treeServerObject.getChildren();
+ TreeObject domain = null;
+ for (TreeObject child : domains)
+ {
+ if (child.getName().equals(obj.getDomain()))
+ {
+ domain = child;
+ break;
+ }
+ }
+
+ addManagedBean(domain, obj);
+ }
+ _treeViewer.refresh();
+ }
+ });
+ }
+ }
+ }
+
+ private void refreshRemovedObjects()
+ {
+ for (ManagedServer server : _managedServerMap.keySet())
+ {
+ final JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(server);
+ if (serverRegistry == null) // server connection is closed
+ continue;
+
+ final List<ManagedBean> removalList = serverRegistry.getObjectsToBeRemoved();
+ if (removalList != null)
+ {
+ Display display = getSite().getShell().getDisplay();
+ display.syncExec(new Runnable()
+ {
+ public void run()
+ {
+ for (ManagedBean mbean : removalList)
+ {
+ System.out.println("removing " + mbean.getName() + " " + mbean.getType());
+ TreeObject treeServerObject = _managedServerMap.get(mbean.getServer());
+ List<TreeObject> domains = treeServerObject.getChildren();
+ TreeObject domain = null;
+ for (TreeObject child : domains)
+ {
+ if (child.getName().equals(mbean.getDomain()))
+ {
+ domain = child;
+ break;
+ }
+ }
+ removeManagedObject(domain, mbean);
+ serverRegistry.removeManagedObject(mbean);
+ }
+ _treeViewer.refresh();
+ }
+ });
+ }
+ }
+ }
+
+ /**
+ *
+ *
+ */
+ private void refreshClosedServerConnections()
+ {
+ final List<ManagedServer> closedServers = ApplicationRegistry.getClosedServers();
+ if (closedServers != null)
+ {
+ Display display = getSite().getShell().getDisplay();
+ display.syncExec(new Runnable()
+ {
+ public void run()
+ {
+ for (ManagedServer server : closedServers)
+ {
+ removeManagedObject(_managedServerMap.get(server));
+ _managedServerMap.remove(server);
+ ApplicationRegistry.removeServer(server);
+ }
+
+ _treeViewer.refresh();
+ }
+ });
+ }
+ }
+
+} \ No newline at end of file
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NotificationsTabControl.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NotificationsTabControl.java
new file mode 100644
index 0000000000..c3f42f46aa
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NotificationsTabControl.java
@@ -0,0 +1,708 @@
+/*
+ *
+ * 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.management.ui.views;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.qpid.management.ui.ApplicationRegistry;
+import org.apache.qpid.management.ui.Constants;
+import org.apache.qpid.management.ui.ManagedBean;
+import org.apache.qpid.management.ui.ServerRegistry;
+import org.apache.qpid.management.ui.jmx.MBeanUtility;
+import org.apache.qpid.management.ui.model.NotificationInfoModel;
+import org.apache.qpid.management.ui.model.NotificationObject;
+import org.eclipse.jface.viewers.DoubleClickEvent;
+import org.eclipse.jface.viewers.IDoubleClickListener;
+import org.eclipse.jface.viewers.ILabelProviderListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.forms.widgets.Form;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+/**
+ *
+ * @author Bhupendra Bhardwaj
+ *
+ */
+public class NotificationsTabControl extends TabControl
+{
+ private FormToolkit _toolkit;
+ private Form _form;
+ private Table table = null;
+ private TableViewer _tableViewer = null;
+
+ private IStructuredContentProvider contentProvider = new ContentProviderImpl();
+ private SelectionListener selectionListener = new SelectionListenerImpl();
+ private SelectionListener comboListener = new ComboSelectionListener();
+
+ private Thread worker = null;
+
+ private List<NotificationObject> _notifications = null;
+ private static final String COLUMN_SEQ = "Sequence No";
+ private static final String COLUMN_TIME = "TimeStamp";
+ private static final String COLUMN_TYPE = "Type";
+ private static final String COLUMN_MSG = "Notification Message";
+ private static final String[] _tableTitles = new String [] {
+ COLUMN_SEQ,
+ COLUMN_TIME,
+ COLUMN_TYPE,
+ COLUMN_MSG
+ };
+
+ private Combo notificationNameCombo = null;
+ private Combo typesCombo = null;
+ private Label descriptionLabel = null;
+ private Button _subscribeButton = null;
+ private Button _unsubscribeButton = null;
+ private Button _clearButton = null;
+ private Button _refreshButton = null;
+
+
+ public NotificationsTabControl(TabFolder tabFolder)
+ {
+ super(tabFolder);
+ _toolkit = new FormToolkit(_tabFolder.getDisplay());
+ _form = _toolkit.createForm(_tabFolder);
+ GridLayout gridLayout = new GridLayout();
+ gridLayout.marginWidth = 0;
+ gridLayout.marginHeight = 0;
+ _form.getBody().setLayout(gridLayout);
+
+ createWidgets();
+ worker = new Thread(new Worker());
+ worker.start();
+ }
+
+ private void createWidgets()
+ {
+ createNotificationInfoComposite();
+ //addFilterComposite();
+ addButtons();
+ createTableViewer();
+ }
+
+ public Control getControl()
+ {
+ return _form;
+ }
+
+ private void createNotificationInfoComposite()
+ {
+ Composite composite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ composite.setLayout(new FormLayout());
+
+ Label label = _toolkit.createLabel(composite, "Select the notification to subscribe or unsubscribe");
+ label.setFont(ApplicationRegistry.getFont(Constants.FONT_BOLD));
+ FormData formData = new FormData();
+ formData.top = new FormAttachment(0, 10);
+ formData.left = new FormAttachment(0, 10);
+ label.setLayoutData(formData);
+
+ notificationNameCombo = new Combo(composite, SWT.READ_ONLY | SWT.DROP_DOWN);
+ formData = new FormData();
+ formData.top = new FormAttachment(label, 10);
+ formData.left = new FormAttachment(0, 10);
+ formData.right = new FormAttachment(40);
+ notificationNameCombo.setLayoutData(formData);
+ notificationNameCombo.addSelectionListener(comboListener);
+
+ typesCombo = new Combo(composite, SWT.READ_ONLY | SWT.DROP_DOWN);
+ formData = new FormData();
+ formData.top = new FormAttachment(label, 10);
+ formData.left = new FormAttachment(notificationNameCombo, 5);
+ formData.right = new FormAttachment(65);
+ typesCombo.setLayoutData(formData);
+ typesCombo.addSelectionListener(comboListener);
+
+ _subscribeButton = new Button(composite, SWT.PUSH | SWT.CENTER);
+ _subscribeButton.setFont(ApplicationRegistry.getFont(Constants.FONT_BUTTON));
+ _subscribeButton.setText(Constants.SUBSCRIBE_BUTTON);
+ formData = new FormData();
+ formData.top = new FormAttachment(label, 10);
+ formData.left = new FormAttachment(65, 10);
+ formData.width = 80;
+ _subscribeButton.setLayoutData(formData);
+ _subscribeButton.addSelectionListener(selectionListener);
+
+ _unsubscribeButton = new Button(composite, SWT.PUSH | SWT.CENTER);
+ _unsubscribeButton.setFont(ApplicationRegistry.getFont(Constants.FONT_BUTTON));
+ _unsubscribeButton.setText(Constants.UNSUBSCRIBE_BUTTON);
+ formData = new FormData();
+ formData.top = new FormAttachment(label, 10);
+ formData.left = new FormAttachment(_subscribeButton, 10);
+ formData.width = 80;
+ _unsubscribeButton.setLayoutData(formData);
+ _unsubscribeButton.addSelectionListener(selectionListener);
+
+ Label fixedLabel = _toolkit.createLabel(composite, "");
+ formData = new FormData();
+ formData.top = new FormAttachment(notificationNameCombo, 5);
+ formData.left = new FormAttachment(0, 10);
+ fixedLabel.setLayoutData(formData);
+ fixedLabel.setText(Constants.DESCRIPTION);
+ fixedLabel.setFont(ApplicationRegistry.getFont(Constants.FONT_BOLD));
+
+ descriptionLabel = _toolkit.createLabel(composite, "");
+ formData = new FormData();
+ formData.top = new FormAttachment(notificationNameCombo, 5);
+ formData.left = new FormAttachment(fixedLabel, 10);
+ formData.right = new FormAttachment(80);
+ descriptionLabel.setLayoutData(formData);
+ descriptionLabel.setText(" ");
+ descriptionLabel.setFont(ApplicationRegistry.getFont(Constants.FONT_ITALIC));
+ }
+
+ private void addButtons()
+ {
+ Composite composite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ composite.setLayout(new GridLayout(2, true));
+
+ // Add Clear Button
+ _clearButton = _toolkit.createButton(composite, Constants.BUTTON_CLEAR, SWT.PUSH | SWT.CENTER);
+ _clearButton.setFont(ApplicationRegistry.getFont(Constants.FONT_BUTTON));
+ GridData gridData = new GridData(SWT.LEAD, SWT.TOP, true, false);
+ gridData.widthHint = 80;
+ _clearButton.setLayoutData(gridData);
+ _clearButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ if (_mbean == null)
+ return;
+
+ ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(_mbean);
+ serverRegistry.clearNotifications(_mbean);
+ refresh();
+ }
+ });
+
+ // Add Refresh Button
+ _refreshButton = _toolkit.createButton(composite, Constants.BUTTON_REFRESH, SWT.PUSH | SWT.CENTER);
+ _refreshButton.setFont(ApplicationRegistry.getFont(Constants.FONT_BUTTON));
+ gridData = new GridData(SWT.TRAIL, SWT.TOP, true, false);
+ gridData.widthHint = 80;
+ _refreshButton.setLayoutData(gridData);
+ _refreshButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ if (_mbean == null)
+ return;
+
+ refresh();
+ }
+ });
+ }
+
+ private void createTable()
+ {
+ table = _toolkit.createTable(_form.getBody(), SWT.FULL_SELECTION);
+ table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+ TableColumn column = new TableColumn(table, SWT.NONE);
+ column.setText(_tableTitles[0]);
+ column.pack(); //column.setWidth(200);
+
+ column = new TableColumn(table, SWT.NONE);
+ column.setText(_tableTitles[1]);
+ column.setWidth(150);
+
+ column = new TableColumn(table, SWT.NONE);
+ column.setText(_tableTitles[2]);
+ column.setWidth(100);
+
+ column = new TableColumn(table, SWT.NONE);
+ column.setText(_tableTitles[3]);
+ column.setWidth(500);
+
+ table.setHeaderVisible(true);
+ table.setLinesVisible(true);
+ }
+
+ protected void createTableViewer()
+ {
+ createTable();
+ _tableViewer = new TableViewer(table);
+ //_tableViewer.getControl().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ _tableViewer.setUseHashlookup(true);
+ _tableViewer.setContentProvider(contentProvider);
+ _tableViewer.setLabelProvider(new LabelProviderImpl());
+ _tableViewer.setColumnProperties(_tableTitles);
+ /*
+ CellEditor[] cellEditors = new CellEditor[_tableTitles.length];
+ TextCellEditor textEditor = new TextCellEditor(table);
+ cellEditors[0] = textEditor;
+ textEditor = new TextCellEditor(table);
+ cellEditors[1] = textEditor;
+ textEditor = new TextCellEditor(table);
+ cellEditors[2] = textEditor;
+ textEditor = new TextCellEditor(table);
+ cellEditors[3] = textEditor;
+
+ // Assign the cell editors to the viewer
+ _tableViewer.setCellEditors(cellEditors);
+ _tableViewer.setCellModifier(new TableCellModifier());
+ */
+
+ addTableListeners();
+
+ //_tableViewer.addSelectionChangedListener(new );
+
+ //_notificationDetails = new Composite(_tabControl, SWT.BORDER);
+ //_notificationDetails.setLayoutData(new GridData(GridData.FILL_BOTH));
+
+ //_tabControl.layout();
+ //viewerComposite.layout();
+ }
+
+ private void addTableListeners()
+ {
+ _tableViewer.addDoubleClickListener(new IDoubleClickListener()
+ {
+ Display display = null;
+ Shell shell = null;
+ public void doubleClick(DoubleClickEvent event)
+ {
+ System.out.println("DoubleClickEvent" + event);
+ display = Display.getCurrent();
+ shell = new Shell(display, SWT.BORDER | SWT.CLOSE | SWT.MIN |
+ SWT.MAX | SWT.RESIZE);
+ shell.setText("Notification");
+
+ int x = display.getBounds().width;
+ int y = display.getBounds().height;
+ shell.setBounds(x/4, y/4, x/2, y/3);
+ StructuredSelection selection = (StructuredSelection)event.getSelection();
+ createPopupContents((NotificationObject)selection.getFirstElement());
+ shell.open();
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch()) {
+ display.sleep();
+ }
+ }
+
+ //If you create it, you dispose it.
+ shell.dispose();
+ }
+
+ private void createPopupContents(NotificationObject obj)
+ {
+ shell.setLayout(new GridLayout());
+
+ Composite parent = new Composite(shell, SWT.NONE);
+ parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ GridLayout layout = new GridLayout(4, true);
+ parent.setLayout(layout);
+
+ Label key = new Label(parent, SWT.TRAIL);
+ key.setText(COLUMN_SEQ);
+ GridData layoutData = new GridData(SWT.TRAIL, SWT.TOP, false, false,1,1);
+ key.setLayoutData(layoutData);
+ Text value = new Text(parent, SWT.BEGINNING | SWT.BORDER |SWT.READ_ONLY);
+ value.setText(""+obj.getSequenceNo());
+ value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false,3,1));
+
+ // Time row
+ key = new Label(parent, SWT.TRAIL);
+ key.setText(COLUMN_TIME);
+ key.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, true, false,1,1));
+ value = new Text(parent, SWT.BEGINNING | SWT.BORDER | SWT.READ_ONLY);
+ value.setText(""+obj.getTimeStamp());
+ value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false,3,1));
+
+ key = new Label(parent, SWT.TRAIL);
+ key.setText(COLUMN_TYPE);
+ key.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, true, false,1,1));
+ value = new Text(parent, SWT.BEGINNING | SWT.BORDER | SWT.READ_ONLY);
+ value.setText(""+obj.getType());
+ value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false,3,1));
+
+ key = new Label(parent, SWT.TRAIL);
+ key.setText(COLUMN_MSG);
+ key.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, true, false,1,1));
+ value = new Text(parent, SWT.MULTI | SWT.WRAP| SWT.BORDER | SWT.V_SCROLL | SWT.READ_ONLY);
+ value.setText(""+obj.getMessage());
+ GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1);
+ gridData.heightHint = 100;
+ value.setLayoutData(gridData);
+ }
+ });
+ }
+
+ @Override
+ public void refresh(ManagedBean mbean)
+ {
+ _mbean = mbean;
+ _notifications = null;
+ _tableViewer.getTable().clearAll();
+
+ if (_mbean == null)
+ {
+ _tableViewer.getTable().clearAll();
+ _subscribeButton.setEnabled(false);
+ _unsubscribeButton.setEnabled(false);
+ return;
+ }
+
+ if (!doesMBeanSendsNotification())
+ {
+ Control[] children = _form.getBody().getChildren();
+ for (int i = 0; i < children.length; i++)
+ {
+ children[i].setVisible(false);
+ }
+
+ String name = (_mbean.getName() != null) ? _mbean.getName() : _mbean.getType();
+ _form.setText(name + " does not send any notification");
+ return;
+ }
+
+ Control[] children = _form.getBody().getChildren();
+ for (int i = 0; i < children.length; i++)
+ {
+ children[i].setVisible(true);
+ }
+
+ populateNotificationInfo();
+ /*
+ ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(_mbean);
+ _notifications = serverRegistry.getNotifications(_mbean);
+ if (_notifications != null)
+ {
+ _tableViewer.setInput(_notifications);
+
+ }*/
+ //_tableViewer.setInput(null);
+ workerRunning = true;
+ _form.layout();
+ }
+
+ private void refresh()
+ {
+ _notifications = null;
+ _tableViewer.getTable().clearAll();
+ }
+
+ private void populateNotificationInfo()
+ {
+ notificationNameCombo.removeAll();
+ NotificationInfoModel[] items = MBeanUtility.getNotificationInfo(_mbean);
+ notificationNameCombo.add("Select Notification");
+ for (int i = 0; i < items.length; i++)
+ {
+ notificationNameCombo.add(items[i].getName());
+ notificationNameCombo.setData(items[i].getName(), items[i]);
+ }
+ notificationNameCombo.select(0);
+
+ typesCombo.removeAll();
+ typesCombo.add("Select Type", 0);
+ typesCombo.select(0);
+ typesCombo.setEnabled(false);
+
+ checkForEnablingButtons();
+ }
+
+ private void checkForEnablingButtons()
+ {
+ int nameIndex = notificationNameCombo.getSelectionIndex();
+ if (nameIndex == 0)
+ {
+ _subscribeButton.setEnabled(false);
+ _unsubscribeButton.setEnabled(false);
+ descriptionLabel.setText("");
+ return;
+ }
+
+ int typeIndex = typesCombo.getSelectionIndex();
+ if (typeIndex == 0)
+ {
+ _subscribeButton.setEnabled(false);
+ _unsubscribeButton.setEnabled(false);
+ return;
+ }
+
+ String type = typesCombo.getItem(typeIndex);
+ String name = notificationNameCombo.getItem(nameIndex);
+ ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(_mbean);
+
+ if (serverRegistry.hasSubscribedForNotifications(_mbean, name, type))
+ {
+ _subscribeButton.setEnabled(false);
+ _unsubscribeButton.setEnabled(true);
+ }
+ else
+ {
+ _subscribeButton.setEnabled(true);
+ _unsubscribeButton.setEnabled(false);
+ }
+ }
+
+ private boolean doesMBeanSendsNotification()
+ {
+ NotificationInfoModel[] items = MBeanUtility.getNotificationInfo(_mbean);
+ if (items == null || items.length == 0)
+ return false;
+ else
+ return true;
+ }
+
+ private class SelectionListenerImpl extends SelectionAdapter
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ if (_mbean == null)
+ return;
+
+ Button source = (Button)e.getSource();
+ String type = typesCombo.getItem(typesCombo.getSelectionIndex());
+ String name = notificationNameCombo.getItem(notificationNameCombo.getSelectionIndex());
+ if (source == _unsubscribeButton)
+ {
+ try
+ {
+ MBeanUtility.removeNotificationListener(_mbean, name, type);
+ }
+ catch(Exception ex)
+ {
+ MBeanUtility.handleException(ex);
+ }
+ }
+ else if (source == _subscribeButton)
+ {
+ try
+ {
+ MBeanUtility.createNotificationlistener(_mbean, name, type);
+ }
+ catch(Exception ex)
+ {
+ MBeanUtility.handleException(ex);
+ }
+ }
+ checkForEnablingButtons();
+ }
+ }
+
+
+ private class ComboSelectionListener extends SelectionAdapter
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ if (_mbean == null)
+ return;
+
+ Combo combo = (Combo)e.getSource();
+ if (combo == notificationNameCombo)
+ {
+ if (combo.getSelectionIndex() == 0)
+ {
+ descriptionLabel.setText("");
+ typesCombo.select(0);
+ typesCombo.setEnabled(false);
+ return;
+ }
+ String index = combo.getItem(combo.getSelectionIndex());
+ NotificationInfoModel data = (NotificationInfoModel)combo.getData(index);
+ descriptionLabel.setText(data.getDescription());
+ typesCombo.removeAll();
+ typesCombo.setItems(data.getTypes());
+ typesCombo.add("Select Type", 0);
+ typesCombo.select(0);
+ typesCombo.setEnabled(true);
+ }
+ checkForEnablingButtons();
+ }
+ }
+
+ private class ContentProviderImpl implements IStructuredContentProvider, INotificationViewer
+ {
+ public void inputChanged(Viewer v, Object oldInput, Object newInput)
+ {
+
+ }
+ public void dispose()
+ {
+
+ }
+ public Object[] getElements(Object parent)
+ {
+ return _notifications.toArray(new NotificationObject[0]);
+ }
+ public void addNotification(NotificationObject notification)
+ {
+ _tableViewer.add(notification);
+ }
+
+ public void addNotification(List<NotificationObject> notificationList)
+ {
+ _tableViewer.add(notificationList.toArray(new NotificationObject[0]));
+ }
+ }
+
+ private class LabelProviderImpl implements ITableLabelProvider
+ {
+ List<ILabelProviderListener> listeners = new ArrayList<ILabelProviderListener>();
+ public void addListener(ILabelProviderListener listener)
+ {
+ listeners.add(listener);
+ }
+
+ public void dispose(){
+
+ }
+
+ public Image getColumnImage(Object element, int columnIndex)
+ {
+ return null;
+ }
+
+ public String getColumnText(Object element, int columnIndex)
+ {
+ String result = null;
+ NotificationObject t = (NotificationObject)element;
+ switch(columnIndex)
+ {
+ case 0 :
+ result = String.valueOf(t.getSequenceNo());
+ break;
+ case 1 :
+ result = String.valueOf(t.getTimeStamp());
+ break;
+ case 2 :
+ result = t.getType();
+ break;
+ case 3 :
+ result = t.getMessage();
+ break;
+ default :
+ result = "";
+ }
+
+ return result;
+ }
+
+ public boolean isLabelProperty(Object element, String property)
+ {
+ return false;
+ }
+
+ public void removeListener(ILabelProviderListener listener)
+ {
+ listeners.remove(listener);
+ }
+ } // end of LabelProviderImpl
+
+ private boolean workerRunning = false;
+ private void setWorkerRunning(boolean running)
+ {
+ workerRunning = running;
+ }
+
+ private class Worker implements Runnable
+ {
+ public void run()
+ {
+ Display display = _tabFolder.getDisplay();
+ while(true)
+ {
+ if (!workerRunning || _mbean == null || display == null)
+ {
+ sleep();
+ continue;
+ }
+
+ display.syncExec(new Runnable()
+ {
+ public void run()
+ {
+ setWorkerRunning(_form.isVisible());
+ if (!workerRunning) return;
+
+ updateTableViewer();
+ }
+ });
+
+ sleep();
+ }
+ }
+
+ private void sleep()
+ {
+ try
+ {
+ Thread.sleep(2000);
+ }
+ catch(Exception ex)
+ {
+
+ }
+ }
+ }
+
+ private void updateTableViewer()
+ {
+ ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(_mbean);
+ List<NotificationObject> newList = serverRegistry.getNotifications(_mbean);
+ if (newList == null)
+ return;
+
+ /*
+ int notificationCount = 0;
+ if (_notifications != null)
+ notificationCount = _notifications.size();
+
+ for (int i = notificationCount; i < newList.size(); i++)
+ {
+ ((INotificationViewer)contentProvider).addNotification(newList.get(i));
+ }*/
+
+ _notifications = newList;
+ _tableViewer.setInput(_notifications);
+ _tableViewer.refresh();
+ }
+}
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
new file mode 100644
index 0000000000..8563bdb882
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/OperationTabControl.java
@@ -0,0 +1,718 @@
+/*
+ *
+ * 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.management.ui.views;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map.Entry;
+
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.TabularDataSupport;
+
+import org.apache.qpid.management.ui.ApplicationRegistry;
+import org.apache.qpid.management.ui.Constants;
+import org.apache.qpid.management.ui.ManagedBean;
+import org.apache.qpid.management.ui.ServerRegistry;
+import org.apache.qpid.management.ui.jmx.MBeanUtility;
+import org.apache.qpid.management.ui.model.OperationData;
+import org.apache.qpid.management.ui.model.ParameterData;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.ScrolledComposite;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.KeyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.events.VerifyListener;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.layout.FormLayout;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Combo;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.forms.widgets.Form;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+
+/**
+ * Control class for the MBean operations tab. It creates the required widgets
+ * for the selected MBean.
+ * @author Bhupendra Bhardwaj
+ *
+ */
+public class OperationTabControl extends TabControl
+{
+ private int heightForAParameter = 30;
+ private int labelNumerator = 30;
+ private int valueNumerator = labelNumerator + 20;
+
+ private FormToolkit _toolkit;
+ private Form _form;
+ private OperationData _opData;
+
+ private SelectionListener operationExecutionListener = new OperationExecutionListener();
+ private SelectionListener refreshListener = new RefreshListener();
+ private SelectionListener parameterSelectionListener = new ParameterSelectionListener();
+ private SelectionListener bolleanSelectionListener = new BooleanSelectionListener();
+ private VerifyListener verifyListener = new VerifyListenerImpl();
+ private KeyListener keyListener = new KeyListenerImpl();
+ private KeyListener headerBindingListener = new HeaderBindingKeyListener();
+
+ private Composite _headerComposite = null;
+ private Composite _paramsComposite = null;
+ private Composite _resultsComposite = null;
+ private Button _executionButton = null;
+
+ // for customized method in header exchange
+ private HashMap<Text, Text> headerBindingHashMap = null;
+
+ public OperationTabControl(TabFolder tabFolder)
+ {
+ super(tabFolder);
+ _toolkit = new FormToolkit(_tabFolder.getDisplay());
+ _form = _toolkit.createForm(_tabFolder);
+ _form.getBody().setLayout(new GridLayout());
+
+ // Form area is devided in four parts:
+ // Header composite - displays operaiton information
+ // Patameters composite - displays parameters if there
+ // Button - operation execution button
+ // Results composite - displays results for operations, which have
+ // no parameters but have some return value
+ _headerComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
+ _headerComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+
+ _paramsComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
+ _paramsComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+
+ _executionButton = _toolkit.createButton(_form.getBody(), Constants.BUTTON_EXECUTE, SWT.PUSH | SWT.CENTER);
+ _executionButton.setFont(ApplicationRegistry.getFont(Constants.FONT_BUTTON));
+ GridData layoutData = new GridData(SWT.CENTER, SWT.TOP, true, false);
+ layoutData.verticalIndent = 20;
+ _executionButton.setLayoutData(layoutData);
+
+ _resultsComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
+ layoutData = new GridData(SWT.FILL, SWT.FILL, true, true);
+ layoutData.verticalIndent = 20;
+ _resultsComposite.setLayoutData(layoutData);
+ _resultsComposite.setLayout(new GridLayout());
+ }
+
+ public Control getControl()
+ {
+ return _form;
+ }
+
+ public void refresh(ManagedBean mbean)
+ {
+ _mbean = mbean;
+ ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(mbean);
+ _opData = serverRegistry.getOperationModel(mbean).getOperations().get(0);
+ refresh(_mbean, _opData);
+ }
+ public void refresh(ManagedBean mbean, OperationData opData)
+ {
+ _mbean = mbean;
+ _opData = opData;
+
+ // Setting the form to be invisible. Just in case the mbean server connection
+ // is done and it takes time in getting the response, then the ui should be blank
+ // instead of having half the widgets displayed.
+ _form.setVisible(false);
+
+ ViewUtility.disposeChildren(_headerComposite);
+ ViewUtility.disposeChildren(_paramsComposite);
+ ViewUtility.disposeChildren(_resultsComposite);
+
+ setHeader();
+ createParameterWidgets();
+
+ List<ParameterData> params = opData.getParameters();
+ if (params != null && !params.isEmpty())
+ {
+ setButton(Constants.BUTTON_EXECUTE);
+ }
+ else if (opData.getImpact() == Constants.OPERATION_IMPACT_ACTION)
+ {
+ setButton(Constants.BUTTON_EXECUTE);
+ }
+ else if (opData.getImpact() == Constants.OPERATION_IMPACT_INFO)
+ {
+ setButton(Constants.BUTTON_REFRESH);
+ executeAndShowResults();
+ }
+
+ _form.setVisible(true);
+ _form.layout();
+ }
+
+ private void setHeader()
+ {
+ _form.setText(ViewUtility.getDisplayText(_opData.getName()));
+ _headerComposite.setLayout(new GridLayout(2, false));
+ //operation description
+ Label label = _toolkit.createLabel(_headerComposite, Constants.DESCRIPTION);
+ label.setFont(ApplicationRegistry.getFont(Constants.FONT_BOLD));
+ label.setLayoutData(new GridData(SWT.LEAD, SWT.TOP, false, false));
+
+ label = _toolkit.createLabel(_headerComposite, _opData.getDescription());
+ label.setFont(ApplicationRegistry.getFont(Constants.FONT_NORMAL));
+ label.setLayoutData(new GridData(SWT.LEAD, SWT.TOP, true, false));
+
+ _headerComposite.layout();
+ }
+
+ private void createParameterWidgets()
+ {
+ List<ParameterData> params = _opData.getParameters();
+ if (params == null || params.isEmpty())
+ {
+ return;
+ }
+
+ // Customised parameter widgets
+ if (_mbean.getType().equals(Constants.EXCHANGE) &&
+ "headers".equals(_mbean.getProperty(Constants.EXCHANGE_TYPE)) &&
+ _opData.getName().equalsIgnoreCase("createNewBinding"))
+ {
+ customCreateNewBinding();
+ return;
+ }
+ // end of Customised parameter widgets
+
+ _paramsComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ _paramsComposite.setLayout(new FormLayout());
+ for (ParameterData param : params)
+ {
+ boolean valueInCombo = false;
+ Label label = _toolkit.createLabel(_paramsComposite, ViewUtility.getDisplayText(param.getName()));
+ FormData formData = new FormData();
+ formData.top = new FormAttachment(0, params.indexOf(param) * heightForAParameter + 2);
+ formData.right = new FormAttachment(labelNumerator);
+ label.setLayoutData(formData);
+ label.setToolTipText(param.getDescription());
+
+ formData = new FormData();
+ formData.top = new FormAttachment(0, params.indexOf(param) * heightForAParameter);
+ formData.left = new FormAttachment(label, 5);
+ formData.right = new FormAttachment(valueNumerator);
+ if (param.getName().equals(Constants.QUEUE))
+ {
+ Combo combo = new Combo(_paramsComposite, SWT.READ_ONLY | SWT.DROP_DOWN);
+ String[] items = ApplicationRegistry.getServerRegistry(_mbean).getQueueNames();
+ combo.setItems(items);
+ combo.add("Select Queue", 0);
+ combo.select(0);
+ combo.setLayoutData(formData);
+ combo.setData(param);
+ combo.addSelectionListener(parameterSelectionListener);
+ valueInCombo = true;
+ }
+ else if (param.getName().equals(Constants.EXCHANGE))
+ {
+ Combo combo = new Combo(_paramsComposite, SWT.READ_ONLY | SWT.DROP_DOWN);
+ String[] items = ApplicationRegistry.getServerRegistry(_mbean).getExchangeNames();
+ combo.setItems(items);
+ combo.add("Select Exchange", 0);
+ combo.select(0);
+ combo.setLayoutData(formData);
+ combo.setData(param);
+ combo.addSelectionListener(parameterSelectionListener);
+ valueInCombo = true;
+ }
+ else if (param.getName().equals(Constants.EXCHANGE_TYPE))
+ {
+ Combo combo = new Combo(_paramsComposite, SWT.READ_ONLY | SWT.DROP_DOWN);
+ combo.setItems(Constants.EXCHANGE_TYPE_VALUES);
+ combo.add("Select Exchange Type", 0);
+ combo.select(0);
+ combo.setLayoutData(formData);
+ combo.setData(param);
+ combo.addSelectionListener(parameterSelectionListener);
+ valueInCombo = true;
+ }
+ else if (param.getType().equals("boolean") || param.getType().equals("java.lang.Boolean"))
+ {
+ Combo combo = new Combo(_paramsComposite, SWT.READ_ONLY | SWT.DROP_DOWN);
+ combo.setItems(new String[] {"false", "true"});
+ combo.select(0);
+ param.setValueFromString(combo.getItem(0));
+ combo.setLayoutData(formData);
+ combo.setData(param);
+ combo.addSelectionListener(bolleanSelectionListener);
+ valueInCombo = true;
+ }
+ else
+ {
+ Text text = _toolkit.createText(_paramsComposite, "", SWT.NONE);
+ formData = new FormData();
+ formData.top = new FormAttachment(0, params.indexOf(param) * heightForAParameter);
+ formData.left = new FormAttachment(label, 5);
+ formData.right = new FormAttachment(valueNumerator);
+ text.setLayoutData(formData);
+ text.addKeyListener(keyListener);
+ text.addVerifyListener(verifyListener);
+ text.setData(param);
+ }
+
+ // parameter type (int, String etc)
+ if (valueInCombo)
+ label = _toolkit.createLabel(_paramsComposite, "");
+ else
+ {
+ String str = param.getType() ;
+ if (param.getType().lastIndexOf(".") != -1)
+ str = param.getType().substring(1 + param.getType().lastIndexOf("."));
+
+ label = _toolkit.createLabel(_paramsComposite, "(" + str + ")");
+ }
+ formData = new FormData();
+ formData.top = new FormAttachment(0, params.indexOf(param) * heightForAParameter);
+ formData.left = new FormAttachment(valueNumerator, 5);
+ label.setLayoutData(formData);
+ }
+
+ //_parametersHolder.setMinSize(_parametersComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+ //_parametersComposite.layout();
+ }
+
+ private void customCreateNewBinding()
+ {
+ headerBindingHashMap = new HashMap<Text, Text>();
+
+ _paramsComposite.setLayout(new GridLayout());
+ _paramsComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, true));
+ final ScrolledComposite scrolledComposite = new ScrolledComposite(_paramsComposite, SWT.BORDER | SWT.V_SCROLL);
+ scrolledComposite.setExpandHorizontal(true);
+ scrolledComposite.setExpandVertical(true);
+ GridData layoutData = new GridData(SWT.FILL, SWT.TOP, true, true);
+ scrolledComposite.setLayoutData(layoutData);
+ scrolledComposite.setLayout(new GridLayout());
+
+ final Composite composite = _toolkit.createComposite(scrolledComposite, SWT.NONE);
+ scrolledComposite.setContent(composite);
+ layoutData = new GridData(SWT.FILL, SWT.FILL, true, true);
+ layoutData.verticalIndent = 20;
+ composite.setLayoutData(layoutData);
+ composite.setLayout(new FormLayout());
+
+ List<ParameterData> params = _opData.getParameters();
+ ParameterData param = params.get(0);
+ // Queue selection widget
+ Label label = _toolkit.createLabel(composite, ViewUtility.getDisplayText(param.getName()));
+ FormData formData = new FormData();
+ formData.top = new FormAttachment(0, 2);
+ formData.right = new FormAttachment(labelNumerator);
+ label.setLayoutData(formData);
+ label.setToolTipText(param.getDescription());
+
+ formData = new FormData();
+ formData.top = new FormAttachment(0);
+ formData.left = new FormAttachment(label, 5);
+ formData.right = new FormAttachment(valueNumerator);
+
+ Combo combo = new Combo(composite, SWT.READ_ONLY | SWT.DROP_DOWN);
+ String[] items = ApplicationRegistry.getServerRegistry(_mbean).getQueueNames();
+ combo.setItems(items);
+ combo.add("Select Queue", 0);
+ combo.select(0);
+ combo.setLayoutData(formData);
+ combo.setData(param);
+ combo.addSelectionListener(parameterSelectionListener);
+
+ // Binding creation widgets
+ createARowForCreatingHeadersBinding(composite, 1);
+ createARowForCreatingHeadersBinding(composite, 2);
+ createARowForCreatingHeadersBinding(composite, 3);
+ createARowForCreatingHeadersBinding(composite, 4);
+ createARowForCreatingHeadersBinding(composite, 5);
+ createARowForCreatingHeadersBinding(composite, 6);
+ createARowForCreatingHeadersBinding(composite, 7);
+ createARowForCreatingHeadersBinding(composite, 8);
+
+ final Button addMoreButton = _toolkit.createButton(composite, "Add More", SWT.PUSH);
+ formData = new FormData();
+ formData.top = new FormAttachment(0, heightForAParameter);
+ formData.left = new FormAttachment(70, 5);
+ addMoreButton.setLayoutData(formData);
+ addMoreButton.setData("rowCount", 8);
+ addMoreButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ int count = Integer.parseInt(addMoreButton.getData("rowCount").toString());
+ createARowForCreatingHeadersBinding(composite, ++count);
+ addMoreButton.setData("rowCount", count);
+ scrolledComposite.setMinSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+ composite.layout();
+ _form.layout();
+ }
+ });
+
+ scrolledComposite.setMinSize(composite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+ composite.layout();
+ }
+
+ private void createARowForCreatingHeadersBinding(Composite parent, int rowCount)
+ {
+ Label key = _toolkit.createLabel(parent, "Name");
+ FormData formData = new FormData();
+ formData.top = new FormAttachment(0, rowCount * heightForAParameter + 2);
+ formData.right = new FormAttachment(15);
+ key.setLayoutData(formData);
+
+ Text keyText = _toolkit.createText(parent, "", SWT.NONE);
+ formData = new FormData();
+ formData.top = new FormAttachment(0, rowCount * heightForAParameter);
+ formData.left = new FormAttachment(key, 5);
+ formData.right = new FormAttachment(40);
+ keyText.setLayoutData(formData);
+ keyText.addKeyListener(headerBindingListener);
+
+ Label value = _toolkit.createLabel(parent, "Value");
+ formData = new FormData();
+ formData.top = new FormAttachment(0, rowCount * heightForAParameter + 2);
+ formData.right = new FormAttachment(45);
+ value.setLayoutData(formData);
+
+ Text valueText = _toolkit.createText(parent, "", SWT.NONE);
+ formData = new FormData();
+ formData.top = new FormAttachment(0, rowCount * heightForAParameter);
+ formData.left = new FormAttachment(value, 5);
+ formData.right = new FormAttachment(70);
+ valueText.setLayoutData(formData);
+ valueText.addKeyListener(headerBindingListener);
+
+ // Add these to the map, to retrieve the values while setting the parameter value
+ headerBindingHashMap.put(keyText, valueText);
+ }
+
+ private void setButton(String text)
+ {
+ _executionButton.setText(text);
+ _executionButton.removeSelectionListener(refreshListener);
+ _executionButton.removeSelectionListener(operationExecutionListener);
+
+ if (Constants.BUTTON_EXECUTE.equals(text))
+ {
+ _executionButton.addSelectionListener(operationExecutionListener);
+ }
+ else
+ {
+ _executionButton.addSelectionListener(refreshListener);
+ }
+ }
+
+ private void populateResults(Object result)
+ {
+ Display display = Display.getCurrent();
+ int width = 600;
+ int height = 400;
+ Shell shell = ViewUtility.createPopupShell("Result", width, height);
+ populateResults(result, shell);
+
+ shell.open();
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch()) {
+ display.sleep();
+ }
+ }
+ shell.dispose();
+ }
+
+ private void populateResults(Object result, Composite parent)
+ {
+ if (result instanceof TabularDataSupport)
+ {
+ ViewUtility.createTabularDataHolder(parent, (TabularDataSupport)result);
+ }
+ else if (result instanceof CompositeDataSupport)
+ {
+ ViewUtility.populateCompositeDataHolder(parent, (CompositeDataSupport)result);
+ }
+ }
+
+ /**
+ * clears the parameter values entered.
+ * @param opName
+
+ private void clearParameterValues()
+ {
+ List<ParameterData> params = _opData.getParameters();
+ if (params != null && !params.isEmpty())
+ {
+ for (ParameterData param : params)
+ {
+ param.setValue(null);
+ }
+
+ Control[] controls = _paramsComposite.getChildren();
+
+ for (int i = 0; i < controls.length; i++)
+ {
+ if (controls[i] instanceof Combo)
+ ((Combo)controls[i]).select(0);
+ else if (controls[i] instanceof Text)
+ ((Text)controls[i]).setText("");
+ }
+ }
+ }*/
+
+ private void clearParameters()
+ {
+ List<ParameterData> params = _opData.getParameters();
+ if (params != null && !params.isEmpty())
+ {
+ for (ParameterData param : params)
+ {
+ param.setValue(null);
+ }
+ }
+ }
+
+ private void clearParameterValues(Composite control)
+ {
+ Control[] controls = control.getChildren();
+ if (controls == null || controls.length == 0)
+ return;
+
+ for (int i = 0; i < controls.length; i++)
+ {
+ if (controls[i] instanceof Combo)
+ ((Combo)controls[i]).select(0);
+ else if (controls[i] instanceof Text)
+ ((Text)controls[i]).setText("");
+ else if (controls[i] instanceof Composite)
+ clearParameterValues((Composite)controls[i]);
+ }
+ }
+
+ /**
+ * Listener class for operation execution events
+ */
+ private class OperationExecutionListener extends SelectionAdapter
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ List<ParameterData> params = _opData.getParameters();
+ if (params != null && !params.isEmpty())
+ {
+ for (ParameterData param : params)
+ {
+ if (param.getValue() == null || param.getValue().toString().length() == 0)
+ {
+ ViewUtility.popupInfoMessage(_form.getText(),
+ "Please select the " + ViewUtility.getDisplayText(param.getName()));
+
+ return;
+ }
+ }
+ }
+
+ if (_opData.getImpact() == Constants.OPERATION_IMPACT_ACTION)
+ {
+ String bean = _mbean.getName() == null ? _mbean.getType() : _mbean.getName();
+ int response = ViewUtility.popupConfirmationMessage(bean,
+ "Do you want to " + _form.getText()+ " ?");
+ if (response == SWT.YES)
+ {
+ executeAndShowResults();
+ }
+ }
+ else
+ {
+ executeAndShowResults();
+ }
+ clearParameters();
+ clearParameterValues(_paramsComposite);
+ }
+ }
+
+ private class RefreshListener extends SelectionAdapter
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ executeAndShowResults();
+ }
+ }
+
+
+ private void executeAndShowResults()
+ {
+ Object result = null;
+ try
+ {
+ result = MBeanUtility.execute(_mbean, _opData);
+ }
+ catch(Exception ex)
+ {
+ MBeanUtility.handleException(_mbean, ex);
+ return;
+ }
+
+ String title = _mbean.getType();
+ if (_mbean.getName() != null && _mbean.getName().length() != 0)
+ {
+ title = _mbean.getName();
+ }
+
+ if (_opData.getReturnType().equals("void") || _opData.getReturnType().equals("java.lang.Void"))
+ {
+ ViewUtility.popupInfoMessage(title, "Operation successful");
+ }
+ else if (_opData.getParameters() != null && !_opData.getParameters().isEmpty())
+ {
+ populateResults(result);
+ }
+ 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();
+ }
+
+ }
+
+ /**
+ * Listener class for the operation parameters widget
+ */
+ private class ParameterSelectionListener extends SelectionAdapter
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ Combo combo = (Combo)e.widget;
+ ParameterData parameter = (ParameterData)combo.getData();
+ if (combo.getSelectionIndex() > 0)
+ {
+ String item = combo.getItem(combo.getSelectionIndex());
+ parameter.setValueFromString(item);
+ }
+ else
+ {
+ parameter.setValue(null);
+ }
+ }
+ }
+
+ private class BooleanSelectionListener extends SelectionAdapter
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ Combo combo = (Combo)e.widget;
+ ParameterData parameter = (ParameterData)combo.getData();
+ String item = combo.getItem(combo.getSelectionIndex());
+ parameter.setValueFromString(item);
+ }
+ }
+
+ /**
+ * Listener class for the operation parameter value widget (Text field)
+ */
+ private class KeyListenerImpl extends KeyAdapter
+ {
+ public void keyReleased(KeyEvent e)
+ {
+ if (!(e.widget instanceof Text))
+ return;
+
+ Text text = (Text)e.widget;
+ // Get the parameters widget and assign the text to the parameter
+ String strValue = text.getText();
+ ParameterData parameter = (ParameterData)text.getData();
+ parameter.setValueFromString(strValue);
+ }
+ }
+
+ private class HeaderBindingKeyListener extends KeyAdapter
+ {
+ public void keyReleased(KeyEvent e)
+ {
+ ParameterData param = _opData.getParameters().get(1);
+ StringBuffer paramValue = new StringBuffer();
+ for (Entry<Text, Text> entry : headerBindingHashMap.entrySet())
+ {
+
+ Text nameText = entry.getKey();
+ String name = nameText.getText();
+ Text valueText = entry.getValue();
+ String value = valueText.getText();
+ if ((name != null) && (name.length() != 0) && (value != null) && (value.length() != 0))
+ {
+ if (paramValue.length() != 0)
+ {
+ paramValue.append(",");
+ }
+ paramValue.append(name + "=" + value);
+ }
+ }
+
+ param.setValue(paramValue.toString());
+ }
+ }
+
+ private class VerifyListenerImpl implements VerifyListener
+ {
+ public void verifyText(VerifyEvent event)
+ {
+ Text text = (Text)event.widget;
+ String string = event.text;
+ char [] chars = new char [string.length ()];
+ string.getChars (0, chars.length, chars, 0);
+
+ ParameterData parameter = (ParameterData)text.getData();
+ String type = parameter.getType();
+ if (type.equals("int") || type.equals("java.lang.Integer") ||
+ type.equals("long") || type.equals("java.lang.Long"))
+ {
+ for (int i=0; i<chars.length; i++)
+ {
+ if (!('0' <= chars [i] && chars [i] <= '9'))
+ {
+ event.doit = false;
+ return;
+ }
+ }
+
+ }
+ }
+ }
+
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TabControl.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TabControl.java
new file mode 100644
index 0000000000..4b89b7ca30
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TabControl.java
@@ -0,0 +1,57 @@
+/*
+ *
+ * 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.management.ui.views;
+
+import org.apache.qpid.management.ui.ManagedBean;
+import org.apache.qpid.management.ui.model.OperationData;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.TabFolder;
+
+public abstract class TabControl
+{
+ protected ManagedBean _mbean = null;
+ protected TabFolder _tabFolder = null;
+
+ public TabControl(TabFolder tabFolder)
+ {
+ _tabFolder = tabFolder;
+ }
+
+ public Control getControl()
+ {
+ return null;
+ }
+
+ public void refresh(ManagedBean mbean)
+ {
+
+ }
+
+ public void refresh(ManagedBean mbean, OperationData opData)
+ {
+
+ }
+
+ public void setFocus()
+ {
+
+ }
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TreeObject.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TreeObject.java
new file mode 100644
index 0000000000..36dc753a1e
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TreeObject.java
@@ -0,0 +1,125 @@
+/*
+ *
+ * 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.management.ui.views;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.qpid.management.ui.Constants;
+import org.apache.qpid.management.ui.ManagedBean;
+import org.apache.qpid.management.ui.ManagedObject;
+
+public class TreeObject
+{
+ private String _name;
+ private String _type;
+ private String _url;
+ private TreeObject _parent;
+ private List<TreeObject> _children = new ArrayList<TreeObject>();
+ private ManagedObject _object;
+
+ public TreeObject(String name, String type)
+ {
+ this._name = name;
+ this._type = type;
+ }
+
+ public TreeObject(ManagedObject obj)
+ {
+ _name = obj.getName();
+ if (_name == null && (obj instanceof ManagedBean))
+ {
+ _name = ((ManagedBean)obj).getType();
+ }
+ this._type = Constants.MBEAN;
+ this._object = obj;
+ }
+
+ public void addChild(TreeObject child)
+ {
+ _children.add(child);
+ }
+
+ public void addChildren(List<TreeObject> subList)
+ {
+ _children.addAll(subList);
+ }
+
+ public List<TreeObject> getChildren()
+ {
+ return _children;
+ }
+
+ public void setChildren(List<TreeObject> children)
+ {
+ this._children = children;
+ }
+
+ public void setName(String value)
+ {
+ _name = value;
+ }
+
+ public String getName()
+ {
+ return _name;
+ }
+ public String getType()
+ {
+ return _type;
+ }
+
+ public String getUrl()
+ {
+ return _url;
+ }
+
+ public void setUrl(String url)
+ {
+ this._url = url;
+ }
+
+ public ManagedObject getManagedObject()
+ {
+ return _object;
+ }
+
+ public void setManagedObject(ManagedObject obj)
+ {
+ this._object = obj;
+ }
+
+ public TreeObject getParent()
+ {
+ return _parent;
+ }
+
+ public void setParent(TreeObject parent)
+ {
+ this._parent = parent;
+
+ if (parent != null)
+ {
+ this._url = parent.getUrl();
+ parent.addChild(this);
+ }
+ }
+}
diff --git a/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/ViewUtility.java b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/ViewUtility.java
new file mode 100644
index 0000000000..995206f248
--- /dev/null
+++ b/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/ViewUtility.java
@@ -0,0 +1,512 @@
+/*
+ *
+ * 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.management.ui.views;
+
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import javax.management.openmbean.ArrayType;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.TabularType;
+
+import org.apache.qpid.management.ui.ApplicationWorkbenchAdvisor;
+import org.eclipse.core.runtime.IStatus;
+import org.eclipse.core.runtime.Status;
+import org.eclipse.jface.dialogs.ErrorDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Button;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.MessageBox;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Text;
+
+public class ViewUtility
+{
+ public static final String OP_NAME = "operation_name";
+ public static final String OP_PARAMS = "parameters";
+ public static final String PARAMS_TEXT = "text";
+
+ public static final String FIRST = "First";
+ public static final String LAST = "Last";
+ public static final String NEXT = "Next";
+ public static final String PREV = "Previous";
+ public static final String INDEX = "Index";
+
+ private static List<String> SUPPORTED_ARRAY_DATATYPES = new ArrayList<String>();
+ static
+ {
+ SUPPORTED_ARRAY_DATATYPES.add("java.lang.String");
+ SUPPORTED_ARRAY_DATATYPES.add("java.lang.Boolean");
+ SUPPORTED_ARRAY_DATATYPES.add("java.lang.Character");
+ SUPPORTED_ARRAY_DATATYPES.add("java.lang.Integer");
+ SUPPORTED_ARRAY_DATATYPES.add("java.lang.Long");
+ SUPPORTED_ARRAY_DATATYPES.add("java.lang.Double");
+ SUPPORTED_ARRAY_DATATYPES.add("java.util.Date");
+ }
+
+ @SuppressWarnings("unchecked")
+ public static void createTabularDataHolder(Composite parent, TabularDataSupport tabularData)
+ {
+ Composite composite = new Composite(parent, SWT.BORDER);
+ //composite.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_WHITE));
+ //composite.setBackground(parent.getBackground());
+ GridLayout layout = new GridLayout(4, true);
+ layout.horizontalSpacing = 0;
+ layout.marginWidth = 0;
+ layout.marginHeight = 10;
+ layout.verticalSpacing = 10;
+ composite.setLayout(layout);
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+ Set entrySet = tabularData.entrySet();
+ ArrayList<Map.Entry> list = new ArrayList<Map.Entry>(entrySet);
+ if (list.size() == 0)
+ {
+ Text text = new Text(composite, SWT.CENTER | SWT.SINGLE | SWT.READ_ONLY);
+ text.setText(" No records ");
+ //text.setBackground(parent.getBackground());
+ GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true, 4, 1);
+ text.setLayoutData(layoutData);
+ return;
+ }
+ // Attach the tabular record to be retrieve and shown
+ composite.setData(list);
+
+ // Create button and the composite for CompositeData
+ Composite compositeDataHolder = createCompositeDataHolder(composite,
+ tabularData.getTabularType().getRowType());
+
+ // display the first record
+ CompositeData data = (CompositeData)(list.get(0)).getValue();
+ composite.setData(INDEX, 0);
+ populateCompositeDataHolder(compositeDataHolder, data);
+ enableOrDisableTraversalButtons(composite);
+ }
+
+ public static void enableOrDisableTraversalButtons(Composite composite)
+ {
+ int index = (Integer)composite.getData(INDEX);
+ int size = ((List)composite.getData()).size();
+
+ ((Button)composite.getData(FIRST)).setEnabled(true);
+ ((Button)composite.getData(PREV)).setEnabled(true);
+ ((Button)composite.getData(NEXT)).setEnabled(true);
+ ((Button)composite.getData(LAST)).setEnabled(true);
+
+ if (index == 0)
+ {
+ ((Button)composite.getData(FIRST)).setEnabled(false);
+ ((Button)composite.getData(PREV)).setEnabled(false);
+ }
+ if (index == size -1)
+ {
+ ((Button)composite.getData(NEXT)).setEnabled(false);
+ ((Button)composite.getData(LAST)).setEnabled(false);
+ }
+ }
+
+ public static Composite createCompositeDataHolder(final Composite dataHolder, CompositeType compositeType)
+ {
+ Label description = new Label(dataHolder, SWT.CENTER);
+ description.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, true, false, 4, 1));
+ String desc = compositeType.getDescription();
+ // TODO nameLabel.setFont(font);
+ description.setText(desc);
+
+ // Add traversal buttons
+ final Button firstRecordButton = new Button(dataHolder, SWT.PUSH);
+ firstRecordButton.setText(FIRST);
+ GridData layoutData = new GridData (GridData.HORIZONTAL_ALIGN_END);
+ layoutData.widthHint = 80;
+ firstRecordButton.setLayoutData(layoutData);
+
+ final Button nextRecordButton = new Button(dataHolder, SWT.PUSH);
+ nextRecordButton.setText(NEXT);
+ layoutData = new GridData (GridData.HORIZONTAL_ALIGN_END);
+ layoutData.widthHint = 80;
+ nextRecordButton.setLayoutData(layoutData);
+
+ final Button previousRecordButton = new Button(dataHolder, SWT.PUSH);
+ previousRecordButton.setText(PREV);
+ layoutData = new GridData (GridData.HORIZONTAL_ALIGN_BEGINNING);
+ layoutData.widthHint = 80;
+ previousRecordButton.setLayoutData(layoutData);
+
+ final Button lastRecordButton = new Button(dataHolder, SWT.PUSH);
+ lastRecordButton.setText(LAST);
+ layoutData = new GridData (GridData.HORIZONTAL_ALIGN_BEGINNING);
+ layoutData.widthHint = 80;
+ lastRecordButton.setLayoutData(layoutData);
+
+ final Composite composite = new Composite(dataHolder, SWT.NONE);
+ GridLayout layout = new GridLayout();
+ layout.horizontalSpacing = layout.verticalSpacing = 0;
+ layout.marginHeight = layout.marginWidth = 0;
+ composite.setLayout(layout);
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 4, 1));
+
+ // Add button references. These references will be used when buttons
+ // are to enabled or disabled based of record index. e.g. for first record
+ // First and Previous buttons will be disabled.
+ dataHolder.setData(FIRST, firstRecordButton);
+ dataHolder.setData(NEXT, nextRecordButton);
+ dataHolder.setData(PREV, previousRecordButton);
+ dataHolder.setData(LAST, lastRecordButton);
+
+ // Listener for the traversal buttons
+ SelectionListener listener = new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ if (!(e.widget instanceof Button))
+ return;
+
+ Button traverseButton =(Button)e.widget;
+ CompositeData data = getCompositeData(dataHolder, traverseButton.getText());
+ populateCompositeDataHolder(composite, data);
+ enableOrDisableTraversalButtons(dataHolder);
+ }
+ };
+
+ firstRecordButton.addSelectionListener(listener);
+ nextRecordButton.addSelectionListener(listener);
+ previousRecordButton.addSelectionListener(listener);
+ lastRecordButton.addSelectionListener(listener);
+
+ return composite;
+ }
+
+ private static CompositeData getCompositeData(Composite compositeHolder, String dataIndex)
+ {
+ List objectData = (List)compositeHolder.getData();
+ if (objectData == null || objectData.isEmpty())
+ {
+ // TODO
+ }
+
+ // Get the index of record to be shown.
+ int index = 0;
+ if (compositeHolder.getData(INDEX) != null)
+ {
+ index = (Integer)compositeHolder.getData(INDEX);
+ }
+
+ if (FIRST.equals(dataIndex))
+ {
+ index = 0;
+ }
+ else if (NEXT.equals(dataIndex))
+ {
+ index = index + 1;
+ }
+ else if (PREV.equals(dataIndex))
+ {
+ index = (index != 0) ? (index = index - 1) : index;
+ }
+ else if (LAST.equals(dataIndex))
+ {
+ index = objectData.size() -1;
+ }
+
+ // Set the index being shown.
+ compositeHolder.setData(INDEX, index);
+ System.out.println("index :" + index);
+
+ return (CompositeData)((Map.Entry)objectData.get(index)).getValue();
+ }
+
+ @SuppressWarnings("unchecked")
+ public static void populateCompositeDataHolder(Composite parent, CompositeData data/*String dataIndex*/)
+ {
+ Control[] oldControls = parent.getChildren();
+ for (int i = 0; i < oldControls.length; i++)
+ {
+ oldControls[i].dispose();
+ }
+
+ Composite compositeHolder = new Composite(parent, SWT.NONE);
+ GridLayout layout = new GridLayout(4, false);
+ layout.horizontalSpacing = 10;
+ compositeHolder.setLayout(layout);
+ compositeHolder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+
+ // ItemNames in composite data
+ List<String> itemNames = new ArrayList<String>(data.getCompositeType().keySet());
+
+ for (String itemName : itemNames)
+ {
+ OpenType itemType = data.getCompositeType().getType(itemName);
+ if (compositeHolder.getData(itemName) == null)
+ {
+ Label keyLabel = new Label(compositeHolder, SWT.TRAIL);
+ keyLabel.setText(itemName);
+ GridData layoutData = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1);
+ layoutData.minimumWidth = 70;
+ keyLabel.setLayoutData(layoutData);
+ System.out.println(itemType);
+
+ if (itemType.isArray())
+ {
+ OpenType type = ((ArrayType)itemType).getElementOpenType();
+ System.out.println("Array Element type = " + type.getClassName());
+ // If Byte array and mimetype is text, convert to text string
+ if (type.getClassName().equals(Byte.class.getName()))
+ {
+ String mimeType = null;
+ String encoding = null;
+ if (data.containsKey("MimeType"))
+ {
+ mimeType = (String)data.get("MimeType");
+ encoding = (String)data.get("Encoding");
+ if (encoding == null || encoding.length() == 0)
+ {
+ encoding = Charset.defaultCharset().name();
+ }
+
+ if (mimeType.equals("text/plain"))
+ {
+ displayByteArray(compositeHolder, data, itemName, encoding);
+ }
+ }
+ else
+ {
+ displayNotSupportedDataType(compositeHolder);
+ }
+ }
+ // If array of any other supported type, show as a list of String array
+ else if (SUPPORTED_ARRAY_DATATYPES.contains(type.getClassName()))
+ {
+ displayArrayItem(compositeHolder, data, itemName);
+ }
+ else
+ {
+ displayNotSupportedDataType(compositeHolder);
+ }
+ }
+ else if (itemType instanceof TabularType)
+ {
+ Composite composite = new Composite(compositeHolder, SWT.NONE);
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 3, 1));
+ layout = new GridLayout();
+ layout.marginHeight = 0;
+ layout.marginWidth = 0;
+ composite.setLayout(layout);
+ createTabularDataHolder(composite, (TabularDataSupport)data.get(itemName));
+ }
+ else
+ {
+ Text valueText = new Text(compositeHolder, SWT.READ_ONLY | SWT.BORDER);
+ valueText.setText(String.valueOf(data.get(itemName)));
+ valueText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 3, 1));
+ }
+ }
+ }
+
+ // layout the composite after creating new widgets.
+ parent.layout();
+ } //end of method
+
+
+ private static void displayByteArray(Composite compositeHolder, CompositeData data, String itemName, String encoding)
+ {
+ Byte[] arrayItems = (Byte[])data.get(itemName);
+ byte[] byteArray = new byte[arrayItems.length];
+
+ for (int i = 0; i < arrayItems.length; i++)
+ {
+ byteArray[i] = arrayItems[i];
+ }
+ try
+ {
+ String textMessage = new String(byteArray, encoding);
+ System.out.println("\nMessage : \n" + textMessage + "\n");
+
+ Text valueText = new Text(compositeHolder, SWT.READ_ONLY | SWT.BORDER |
+ SWT.MULTI | SWT.WRAP | SWT.V_SCROLL);
+ valueText.setText(textMessage);
+ GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1);
+ gridData.heightHint = 300;
+ valueText.setLayoutData(gridData);
+ }
+ catch(Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+
+ public static int popupInfoMessage(String title, String message)
+ {
+ MessageBox messageBox = new MessageBox(Display.getCurrent().getActiveShell(),
+ SWT.ICON_INFORMATION | SWT.OK);
+ messageBox.setMessage(message);
+ messageBox.setText(title);
+ int response = messageBox.open();
+
+ return response;
+ }
+
+ public static int popupErrorMessage(String title, String message)
+ {
+ MessageBox messageBox = new MessageBox(Display.getCurrent().getActiveShell(),
+ SWT.ICON_ERROR | SWT.OK);
+ messageBox.setMessage(message);
+ messageBox.setText(title);
+ int response = messageBox.open();
+
+ return response;
+ }
+
+ public static int popupConfirmationMessage(String title, String message)
+ {
+ MessageBox messageBox = new MessageBox(Display.getCurrent().getActiveShell(),
+ SWT.ICON_QUESTION | SWT.YES | SWT.NO | SWT.CANCEL);
+ messageBox.setMessage(message);
+ messageBox.setText(title);
+ int response = messageBox.open();
+
+ return response;
+ }
+
+ public static void popupError(String title, String message, Exception ex)
+ {
+ IStatus status = new Status(IStatus.ERROR, ApplicationWorkbenchAdvisor.PERSPECTIVE_ID,
+ IStatus.ERROR, ex.getMessage(), ex);
+ ErrorDialog.openError(Display.getCurrent().getActiveShell(), title, message, status);
+
+ }
+
+ public static void popupError(String errorMsg)
+ {
+ Display display = Display.getCurrent();
+ Shell shell = new Shell(display, SWT.BORDER | SWT.CLOSE | SWT.MIN | SWT.MAX);
+ shell.setText("Attribute");
+ shell.setLayout(new GridLayout());
+ int x = display.getBounds().width;
+ int y = display.getBounds().height;
+ int width = 500;
+ int height = 250;
+ shell.setBounds(x/4, y/4, width, height);
+
+ Label label = new Label(shell, SWT.NONE);
+ label.setText(errorMsg);
+ label.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, false, false));
+
+ shell.open();
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch()) {
+ display.sleep();
+ }
+ }
+ shell.dispose();
+ }
+
+ public static Shell createPopupShell(String title, int width, int height)
+ {
+ Display display = Display.getCurrent();
+ Shell shell = new Shell(display, SWT.BORDER | SWT.CLOSE | SWT.MIN |SWT.MAX);
+ shell.setText(title);
+ shell.setLayout(new GridLayout());
+ int x = display.getBounds().width;
+ int y = display.getBounds().height;
+ shell.setBounds(x/4, y/4, width, height);
+
+ return shell;
+ }
+
+ private static void displayArrayItem(Composite compositeHolder, CompositeData data, String itemName)
+ {
+ Object[] arrayItems = (Object[])data.get(itemName);
+ String[] items = new String[arrayItems.length];
+ for (int i = 0; i < arrayItems.length; i++)
+ {
+ items[i] = String.valueOf(arrayItems[i]);
+ }
+ org.eclipse.swt.widgets.List list = new org.eclipse.swt.widgets.List(compositeHolder,
+ SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.READ_ONLY);
+ list.setItems(items);
+ list.setBackground(compositeHolder.getBackground());
+ list.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1));
+ }
+
+ private static void displayNotSupportedDataType(Composite compositeHolder)
+ {
+ Text valueText = new Text(compositeHolder, SWT.READ_ONLY);
+ valueText.setText("Format is not supported to be displayed");
+ valueText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 3, 1));
+ }
+
+ /**
+ * Converts the input string to displayable format by converting some character case or inserting space
+ * @param input
+ * @return
+ */
+ public static String getDisplayText(String input)
+ {
+ StringBuffer result = new StringBuffer(input);
+ if (Character.isLowerCase(result.charAt(0)))
+ {
+ result.setCharAt(0, Character.toUpperCase(result.charAt(0)));
+ }
+ for (int i = 1; i < input.length(); i++)
+ {
+ if (Character.isUpperCase(result.charAt(i)) && !Character.isWhitespace(result.charAt(i - 1))
+ && Character.isLowerCase(result.charAt(i - 1)))
+ {
+ result.insert(i, " ");
+ i++;
+ }
+ else if (Character.isLowerCase(result.charAt(i)) && Character.isWhitespace(result.charAt(i - 1)))
+ {
+ result.setCharAt(i, Character.toUpperCase(result.charAt(i)));
+ }
+
+ }
+
+ return result.toString();
+ }
+
+ public static void disposeChildren(Composite parent)
+ {
+ if (parent == null || parent.isDisposed())
+ return;
+
+ Control[] oldControls = parent.getChildren();
+ for (int i = 0; i < oldControls.length; i++)
+ {
+ oldControls[i].dispose();
+ }
+ }
+}
diff --git a/java/management/eclipse-plugin/startup.jar b/java/management/eclipse-plugin/startup.jar
new file mode 100644
index 0000000000..2f26eceece
--- /dev/null
+++ b/java/management/eclipse-plugin/startup.jar
Binary files differ
diff --git a/java/pom.xml b/java/pom.xml
index 5703ded592..e2158ef118 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -433,6 +433,8 @@
</snapshots>
</repository>
-->
+
+
</repositories>
<pluginRepositories>
diff --git a/java/systests/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTest.java b/java/systests/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTest.java
index 53ae097ea6..a7611df55d 100644
--- a/java/systests/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTest.java
+++ b/java/systests/src/test/java/org/apache/qpid/server/exchange/AbstractHeadersExchangeTest.java
@@ -20,26 +20,25 @@
*/
package org.apache.qpid.server.exchange;
-import org.apache.qpid.server.queue.AMQQueue;
-import org.apache.qpid.server.queue.NoConsumersException;
-import org.apache.qpid.server.queue.AMQMessage;
-import org.apache.qpid.server.store.MessageStore;
-import org.apache.qpid.server.store.SkeletonMessageStore;
-import org.apache.qpid.server.registry.ApplicationRegistry;
+import junit.framework.TestCase;
+import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.framing.BasicPublishBody;
-import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.ContentBody;
+import org.apache.qpid.framing.ContentHeaderBody;
import org.apache.qpid.framing.FieldTable;
-import org.apache.qpid.framing.BasicContentHeaderProperties;
-import org.apache.qpid.AMQException;
+import org.apache.qpid.framing.FieldTableFactory;
+import org.apache.qpid.server.queue.AMQMessage;
+import org.apache.qpid.server.queue.AMQQueue;
+import org.apache.qpid.server.registry.ApplicationRegistry;
+import org.apache.qpid.server.store.MessageStore;
+import org.apache.qpid.server.store.SkeletonMessageStore;
-import java.util.List;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Set;
import java.util.HashSet;
-
-import junit.framework.TestCase;
+import java.util.List;
+import java.util.Set;
public class AbstractHeadersExchangeTest extends TestCase
{
@@ -105,7 +104,7 @@ public class AbstractHeadersExchangeTest extends TestCase
static FieldTable getHeaders(String... entries)
{
- FieldTable headers = new FieldTable();
+ FieldTable headers = FieldTableFactory.newFieldTable();
for (String s : entries)
{
String[] parts = s.split("=", 2);
diff --git a/java/systests/src/test/java/org/apache/qpid/server/queue/SendPerfTest.java b/java/systests/src/test/java/org/apache/qpid/server/queue/SendPerfTest.java
index 6490b9f270..44cedf5d7d 100644
--- a/java/systests/src/test/java/org/apache/qpid/server/queue/SendPerfTest.java
+++ b/java/systests/src/test/java/org/apache/qpid/server/queue/SendPerfTest.java
@@ -90,7 +90,8 @@ public class SendPerfTest extends TimedRun
/**
* Delivers messages to a number of queues.
- * @param count the number of messages to deliver
+ *
+ * @param count the number of messages to deliver
* @param queues the list of queues
* @throws NoConsumersException
*/
@@ -121,7 +122,7 @@ public class SendPerfTest extends TimedRun
q.bind("routingKey", exchange);
try
{
- q.registerProtocolSession(createSession(), 1, "1", false);
+ q.registerProtocolSession(createSession(), 1, "1", false, null);
}
catch (Exception e)
{
@@ -135,7 +136,7 @@ public class SendPerfTest extends TimedRun
static AMQQueue createQueue(String name) throws AMQException
{
return new AMQQueue(name, false, null, false, ApplicationRegistry.getInstance().getQueueRegistry(),
- new OnCurrentThreadExecutor());
+ new OnCurrentThreadExecutor());
}
static AMQProtocolSession createSession() throws Exception
diff --git a/java/systests/src/test/java/org/apache/qpid/server/queue/TestSubscription.java b/java/systests/src/test/java/org/apache/qpid/server/queue/TestSubscription.java
index de6df4bc03..2de1a0fe69 100644
--- a/java/systests/src/test/java/org/apache/qpid/server/queue/TestSubscription.java
+++ b/java/systests/src/test/java/org/apache/qpid/server/queue/TestSubscription.java
@@ -70,6 +70,16 @@ public class TestSubscription implements Subscription
{
}
+ public boolean hasFilters()
+ {
+ return false;
+ }
+
+ public boolean hasInterest(AMQMessage msg)
+ {
+ return true;
+ }
+
public int hashCode()
{
return key.hashCode();
diff --git a/specs/amqp-8.0.xml b/specs/amqp-8.0.xml
index 6b3a438f08..6a91263a99 100644
--- a/specs/amqp-8.0.xml
+++ b/specs/amqp-8.0.xml
@@ -2085,6 +2085,13 @@ localised reply text
method it will raise a channel or connection exception.
</doc>
</field>
+
+ <field name="filter" type="table" label="arguments for consuming">
+ <doc>
+ A set of filters for the consume. The syntax and semantics
+ of these filters depends on the providers implementation.
+ </doc>
+ </field>
</method>
<method name = "consume-ok" synchronous = "1" index = "21">
@@ -2446,9 +2453,9 @@ localised reply text
A client MUST NOT use this method as a means of selecting messages
to process. A rejected message MAY be discarded or dead-lettered,
not necessarily passed to another client.
- </doc>
+ </doc>
<chassis name = "server" implement = "MUST" />
-
+
<field name = "delivery tag" domain = "delivery tag" />
<field name = "requeue" type = "bit">
@@ -2490,7 +2497,7 @@ localised reply text
The server MUST set the redelivered flag on all messages that are resent.
</doc>
<doc name="rule">
- The server MUST raise a channel exception if this is called on a
+ The server MUST raise a channel exception if this is called on a
transacted channel.
</doc>
</method>
@@ -2792,7 +2799,7 @@ localised reply text
<response name = "open-ok" />
<chassis name = "server" implement = "MUST" />
<chassis name = "client" implement = "MUST" />
-
+
<field name = "identifier" type = "shortstr">
staging identifier
<doc>
@@ -2829,7 +2836,7 @@ localised reply text
<response name = "stage" />
<chassis name = "server" implement = "MUST" />
<chassis name = "client" implement = "MUST" />
-
+
<field name = "staged size" type = "longlong">
already staged amount
<doc>
@@ -3045,7 +3052,7 @@ localised reply text
</doc>
<chassis name = "server" implement = "MUST" />
<field name = "delivery tag" domain = "delivery tag" />
-
+
<field name = "multiple" type = "bit">
acknowledge multiple messages
<doc>
@@ -3084,7 +3091,7 @@ localised reply text
not necessarily passed to another client.
</doc>
<chassis name = "server" implement = "MUST" />
-
+
<field name = "delivery tag" domain = "delivery tag" />
<field name = "requeue" type = "bit">
@@ -3483,7 +3490,7 @@ localised reply text
<doc>
Specifies the routing key name specified when the message was
published.
- </doc>
+ </doc>
</field>
</method>