summaryrefslogtreecommitdiff
path: root/qpid/java/management/eclipse-plugin/src/main
diff options
context:
space:
mode:
Diffstat (limited to 'qpid/java/management/eclipse-plugin/src/main')
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Activator.java83
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApiVersion.java110
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Application.java63
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationActionBarAdvisor.java96
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java189
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchAdvisor.java46
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchWindowAdvisor.java65
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Constants.java153
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedBean.java176
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedObject.java40
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedServer.java84
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Perspective.java46
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/RefreshIntervalComboPanel.java131
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ServerRegistry.java264
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AbstractAction.java220
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AddServer.java313
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/BackAction.java59
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/CloseConnection.java56
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/ReconnectServer.java264
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/Refresh.java53
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/RemoveServer.java50
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/VersionAction.java94
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/exceptions/InfoRequiredException.java36
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/exceptions/ManagementConsoleException.java31
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientListener.java84
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientNotificationListener.java40
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXManagedObject.java71
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXServerRegistry.java612
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/MBeanUtility.java619
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/AttributeData.java96
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/ManagedAttributeModel.java118
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationInfoModel.java51
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationObject.java132
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationData.java110
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationDataModel.java72
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/ParameterData.java95
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/AttributesTabControl.java922
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/INotificationViewer.java32
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanTabFolderFactory.java466
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanView.java605
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NavigationView.java1372
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NotificationsTabControl.java388
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NumberVerifyListener.java46
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/OperationTabControl.java920
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TabControl.java103
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TreeObject.java126
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/VHNotificationsTabControl.java484
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/ViewUtility.java1032
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/connection/ConnectionOperationsTabControl.java545
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/exchange/ExchangeOperationsTabControl.java722
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/exchange/HeadersExchangeOperationsTabControl.java711
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/ConfigurationFileTabControl.java591
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/LoggingTableContentProvider.java52
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/LoggingTableLabelProvider.java59
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/LoggingTableSorter.java90
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/RuntimeTabControl.java595
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/queue/QueueOperationsTabControl.java1111
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/ConnectionTypeTabControl.java50
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/ExchangeTypeTabControl.java45
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/MBeanTypeTabControl.java456
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/QueueTypeTabControl.java786
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/users/UserManagementTabControl.java925
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/vhost/VHostTabControl.java871
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/resources/.eclipseproduct23
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/resources/jmxremote.sasl-plugin/MANIFEST.MF20
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/Configuration/config.ini49
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/libcairo-swt.sobin0 -> 266168 bytes
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/qpidmcbin0 -> 52576 bytes
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/qpidmc.ini37
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/Configuration/config.ini49
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/libcairo-swt.sobin0 -> 335360 bytes
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/qpidmcbin0 -> 67927 bytes
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/qpidmc.ini37
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/resources/macosx/Configuration/config.ini49
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/resources/macosx/Contents/Info.plist55
-rwxr-xr-xqpid/java/management/eclipse-plugin/src/main/resources/macosx/Contents/MacOS/qpidmcbin0 -> 59200 bytes
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/resources/macosx/Contents/MacOS/qpidmc.ini42
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/resources/macosx/Contents/Resources/Console.icnsbin0 -> 51007 bytes
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Configuration/config.ini49
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.l.pm311
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.m.pm295
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.s.pm287
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.t.pm279
-rwxr-xr-xqpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/qpidmcbin0 -> 31668 bytes
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/qpidmc.ini40
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/Configuration/config.ini49
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.exebin0 -> 57344 bytes
-rw-r--r--qpid/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.ini36
88 files changed, 20634 insertions, 0 deletions
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Activator.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Activator.java
new file mode 100644
index 0000000000..d6a9c0b0c6
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Activator.java
@@ -0,0 +1,83 @@
+/*
+ *
+ * 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
+ * @author Bhupendra Bhardwaj
+ */
+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 final Activator PLUGIN = new Activator();
+
+ /**
+ * The constructor
+ */
+ public Activator()
+ {
+
+ }
+
+ /*
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+ */
+ public void start(BundleContext context) throws Exception
+ {
+ super.start(context);
+ }
+
+ /*
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ public void stop(BundleContext context) throws Exception
+ {
+ 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/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApiVersion.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApiVersion.java
new file mode 100644
index 0000000000..2bdcd77f08
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApiVersion.java
@@ -0,0 +1,110 @@
+/*
+ *
+ * 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 ApiVersion
+{
+ private int major;
+ private int minor;
+
+ public ApiVersion(int major, int minor)
+ {
+ this.major = major;
+ this.minor = minor;
+ }
+
+ public int getMajor()
+ {
+ return major;
+ }
+
+ public int getMinor()
+ {
+ return minor;
+ }
+
+ public boolean greaterThanOrEqualTo(int major, int minor)
+ {
+ if((this.major == major) && (this.minor >= minor))
+ {
+ return true;
+ }
+ else if (this.major > major)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ public boolean lessThanOrEqualTo(int major, int minor)
+ {
+ if((this.major == major) && (this.minor <= minor))
+ {
+ return true;
+ }
+ else if (this.major < major)
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ public boolean greaterThan(int major, int minor)
+ {
+ if(this.major > major)
+ {
+ return true;
+ }
+ else if ((this.major == major) && (this.minor > minor))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ public boolean lessThan(int major, int minor)
+ {
+ if(this.major < major)
+ {
+ return true;
+ }
+ else if ((this.major == major) && (this.minor < minor))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ public boolean equals(int major, int minor)
+ {
+ return (this.major == major) && (this.minor == minor);
+ }
+
+ public String toString()
+ {
+ return "major=" + major + ",minor=" + minor;
+ }
+
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Application.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Application.java
new file mode 100644
index 0000000000..a1c4b7ddb0
--- /dev/null
+++ b/qpid/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;
+
+ /*
+ * The call to createAndRunWorkbench will not return until the workbench is closed.
+ * The SWT event loop and other low-level logistics are handled inside this method.
+ * @see org.eclipse.core.runtime.IPlatformRunnable#run(java.lang.Object)
+ */
+ public Object run(Object args) throws Exception
+ {
+ 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/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationActionBarAdvisor.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationActionBarAdvisor.java
new file mode 100644
index 0000000000..b5c1b5074a
--- /dev/null
+++ b/qpid/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.apache.qpid.management.ui.actions.VersionAction;
+import org.eclipse.jface.action.Action;
+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 Action _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 = new VersionAction(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
+ helpMenu.add(_aboutAction);
+ }
+
+ protected void fillCoolBar(ICoolBarManager coolBar)
+ {
+
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java
new file mode 100644
index 0000000000..4a59176374
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationRegistry.java
@@ -0,0 +1,189 @@
+/*
+ *
+ * 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.io.File;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+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;
+
+/**
+ * Main Application Registry, which contains shared resources and map to all connected servers.
+ * @author Bhupendra Bhardwaj
+ */
+public abstract class ApplicationRegistry
+{
+ private static ImageRegistry imageRegistry = new ImageRegistry();
+ private static FontRegistry fontRegistry = new FontRegistry();
+ public static final boolean debug = Boolean.getBoolean("eclipse.consoleLog");
+ public static final long timeout = Long.parseLong(System.getProperty("timeout", "15000"));
+
+ //max supported broker management interface supported by this release of the management console
+ public static final int SUPPORTED_QPID_JMX_API_MAJOR_VERSION = 2;
+ public static final int SUPPORTED_QPID_JMX_API_MINOR_VERSION = 3;
+
+ public static final String DATA_DIR = System.getProperty("user.home") + File.separator + ".qpidmc";
+
+ static
+ {
+ imageRegistry.put(Constants.SUCCESS_IMAGE,
+ org.apache.qpid.management.ui.Activator.getImageDescriptor("/icons/success.gif"));
+ imageRegistry.put(Constants.FAILURE_IMAGE,
+ org.apache.qpid.management.ui.Activator.getImageDescriptor("/icons/failure.gif"));
+ 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"));
+ imageRegistry.put(Constants.LOGGING_MANAGEMENT_IMAGE,
+ org.apache.qpid.management.ui.Activator.getImageDescriptor("/icons/logging_management.gif"));
+ imageRegistry.put(Constants.USER_MANAGEMENT_IMAGE,
+ org.apache.qpid.management.ui.Activator.getImageDescriptor("/icons/user_management.gif"));
+ imageRegistry.put(Constants.CONFIGURATION_MANAGEMENT_IMAGE,
+ org.apache.qpid.management.ui.Activator.getImageDescriptor("/icons/configuration_management.gif"));
+ imageRegistry.put(Constants.SERVER_INFO_IMAGE,
+ org.apache.qpid.management.ui.Activator.getImageDescriptor("/icons/server_information.gif"));
+ imageRegistry.put(Constants.VHOST_MANAGER_IMAGE,
+ org.apache.qpid.management.ui.Activator.getImageDescriptor("/icons/virtualhost_manager.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.
+ */
+ private static ConcurrentHashMap<ManagedServer, ServerRegistry> _serverRegistryMap = new ConcurrentHashMap<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 getServerRegistry(server);
+ }
+
+ public static boolean isServerConnected(ManagedServer server)
+ {
+ if(server == null)
+ {
+ //checking for null is not permitted in a CHM
+ return false;
+ }
+
+ ServerRegistry reg = _serverRegistryMap.get(server);
+ if(reg !=null)
+ {
+ return !reg.isServerConnectionClosed();
+ }
+
+ return false;
+ }
+
+ // remove the server from the registry
+ public static void serverConnectionClosed(ManagedServer server)
+ {
+ _closedServerList.add(server);
+ removeServer(server);
+ }
+
+ // remove the server from the registry
+ public static void serverConnectionClosedRemotely(ManagedServer server)
+ {
+ ServerRegistry reg = _serverRegistryMap.get(server);
+ if(reg !=null)
+ {
+ synchronized(server)
+ {
+ if(reg.isServerConnectionClosed())
+ {
+ //the connection closure was already processed
+ return;
+ }
+
+ reg.serverConnectionClosed();
+ }
+ }
+
+ serverConnectionClosed(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/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchAdvisor.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchAdvisor.java
new file mode 100644
index 0000000000..a46fa870e4
--- /dev/null
+++ b/qpid/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/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchWindowAdvisor.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchWindowAdvisor.java
new file mode 100644
index 0000000000..00574440c5
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ApplicationWorkbenchWindowAdvisor.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.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;
+
+/**
+ *
+ * @author Bhupendra Bhardwaj
+ */
+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(9*x/10, 8*y/10));
+ configurer.setShowCoolBar(true);
+ configurer.setShowStatusLine(true);
+
+ configurer.setTitle(Constants.APPLICATION_NAME);
+ }
+
+ 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/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Constants.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Constants.java
new file mode 100644
index 0000000000..c8f95dd8cb
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Constants.java
@@ -0,0 +1,153 @@
+/*
+ *
+ * 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.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * Contains constants for the application
+ * @author Bhupendra Bhardwaj
+ *
+ */
+public class Constants
+{
+ public final static String APPLICATION_NAME = "Qpid JMX Management Console";
+ public static final String DEFAULT_DOMAIN = "org.apache.qpid";
+
+ public final static String ACTION_REMOVE_MBEANNODE = "Remove from list";
+ public final static String VALUE = "value";
+ public final static String TYPE = "type";
+ public final static String VERSION = "version";
+ public final static String NODE_TYPE_SERVER = "server";
+ public final static String NODE_TYPE_MBEANTYPE = "mbeantype";
+ // currently used only for virtual host instances, but will work as general also
+ public final static String NODE_TYPE_TYPEINSTANCE = "mbeantype_instance";
+ public final static String MBEAN = "mbean";
+ public final static String ATTRIBUTE = "Attribute";
+ public final static String ATTRIBUTES = "Attributes";
+ public final static String NOTIFICATIONS = "Notifications";
+ public final static String RESULT = "Result";
+ public final static String VIRTUAL_HOST = "VirtualHost";
+ public final static String DEFAULT_VH = "Default";
+ public final static String DEFAULT_USERNAME = "guest";
+ public final static String DEFAULT_PASSWORD = "guest";
+
+ public final static String USERNAME = "Username";
+ public final static String PASSWORD = "Password";
+
+ // Attributes and operations are used to customize the GUI for Qpid. If these are changes in the
+ // Qpid server, then these should be updated accordingly
+ public final static String ATTRIBUTE_QUEUE_OWNER = "owner";
+ public final static String ATTRIBUTE_QUEUE_DEPTH = "QueueDepth";
+ public final static String ATTRIBUTE_QUEUE_CONSUMERCOUNT = "ActiveConsumerCount";
+ public final static String OPERATION_CREATE_QUEUE = "createNewQueue";
+ public final static String OPERATION_CREATE_BINDING = "createNewBinding";
+ public final static String OPERATION_MOVE_MESSAGES = "moveMessages";
+
+ public final static String OPERATION_CREATEUSER = "createUser";
+ public final static String OPERATION_DELETEUSER = "deleteUser";
+ public final static String OPERATION_VIEWUSERS = "viewUsers";
+ public final static String OPERATION_PARAM_USERNAME = "username";
+
+ public final static String OPERATION_SUCCESSFUL = "Operation successful";
+ public final static String OPERATION_UNSUCCESSFUL = "Operation unsuccessful";
+
+ public final static String ALL = "All";
+
+ public final static String NAVIGATION_ROOT = "Qpid Connections";
+ public final static String DESCRIPTION = " Description";
+
+ public final static String ADMIN_MBEAN_TYPE = "UserManagement";
+ public final static String QUEUE = "Queue";
+ public final static String CONNECTION ="Connection";
+ public final static String EXCHANGE = "Exchange";
+ public final static String EXCHANGE_TYPE = "ExchangeType";
+
+ public final static String DIRECT_EXCHANGE = "direct";
+ public final static String FANOUT_EXCHANGE = "fanout";
+ public final static String HEADERS_EXCHANGE = "headers";
+ public final static String TOPIC_EXCHANGE = "topic";
+ public final static List<String> DEFAULT_EXCHANGE_TYPE_VALUES = Collections.unmodifiableList(
+ Arrays.asList(DIRECT_EXCHANGE, FANOUT_EXCHANGE, HEADERS_EXCHANGE, TOPIC_EXCHANGE));
+ public final static List<String> ATTRIBUTE_TABLE_TITLES = Collections.unmodifiableList(
+ Arrays.asList("Attribute Name", "Value"));
+
+ public final static String ACTION_ADDSERVER = "New Connection";
+ public final static String ACTION_RECONNECT = "Reconnect";
+ public final static String ACTION_CLOSE = "Close Connection";
+ public final static String ACTION_EDITATTRIBUTE = "Edit Attribute";
+ public final static String ACTION_LOGIN = "Login";
+
+ public final static String QUEUE_SORT_BY_NAME = "Queue Name";
+ public final static String QUEUE_SORT_BY_DEPTH = "Queue Depth";
+ public final static String QUEUE_SORT_BY_CONSUMERCOUNT = "Consumer Count";
+ public final static String QUEUE_SHOW_TEMP_QUEUES= "show temporary queues";
+
+ public final static String SUBSCRIBE_BUTTON = "Subscribe";
+ public final static String UNSUBSCRIBE_BUTTON = "Unsubscribe";
+
+
+ public final static String SUCCESS_IMAGE = "SuccessImage";
+ public final static String FAILURE_IMAGE = "FailureImage";
+ public final static String CONSOLE_IMAGE = "ConsoleImage";
+ 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 LOGGING_MANAGEMENT_IMAGE = "LoggingManagementImage";
+ public final static String USER_MANAGEMENT_IMAGE = "UserManagementImage";
+ public final static String CONFIGURATION_MANAGEMENT_IMAGE = "ConfigurationManagementImage";
+ public final static String SERVER_INFO_IMAGE = "ServerInfoImage";
+ public final static String VHOST_MANAGER_IMAGE = "VhostManagerImage";
+
+ 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";
+ 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 String BUTTON_UPDATE = "Update";
+
+
+ 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;
+
+ public final static String ERROR_SERVER_CONNECTION = "Server Connection Failed";
+ public final static String INFO_PROTOCOL = "Please select the protocol";
+ public final static String INFO_HOST_ADDRESS = "Please enter the host address";
+ public final static String INFO_HOST_PORT = "Please enter the port number";
+ public final static String INFO_USERNAME = "Please enter the " + USERNAME;
+ public final static String INFO_PASSWORD = "Please enter the " + PASSWORD;
+
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedBean.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedBean.java
new file mode 100644
index 0000000000..8ded3f35c6
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedBean.java
@@ -0,0 +1,176 @@
+/*
+ *
+ * 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 static org.apache.qpid.management.ui.Constants.ADMIN_MBEAN_TYPE;
+import static org.apache.qpid.management.ui.Constants.CONNECTION;
+import static org.apache.qpid.management.ui.Constants.DEFAULT_VH;
+import static org.apache.qpid.management.ui.Constants.EXCHANGE;
+import static org.apache.qpid.management.ui.Constants.QUEUE;
+import static org.apache.qpid.management.ui.Constants.VIRTUAL_HOST;
+
+import java.util.HashMap;
+
+import org.apache.qpid.management.common.mbeans.ManagedBroker;
+
+/**
+ * Class representing a managed bean on the managed server
+ */
+public abstract class ManagedBean extends ManagedObject
+{
+ private String _uniqueName = "";
+ private String _domain = "";
+ private String _type = "";
+ private String _virtualHostName = null;
+ private ManagedServer _server = null;
+ private HashMap _properties = null;
+ private int _version;
+
+ public String getProperty(String key)
+ {
+ return (String) _properties.get(key);
+ }
+
+ public HashMap getProperties()
+ {
+ return _properties;
+ }
+
+ public void setProperties(HashMap properties)
+ {
+ this._properties = properties;
+ setName(getProperty("name"));
+ setType(getProperty("type"));
+ setVersion(getProperty("version"));
+ _virtualHostName = getProperty(VIRTUAL_HOST);
+ }
+
+ public void setVersion(String version)
+ {
+ try
+ {
+ _version = Integer.parseInt(version);
+ }
+ catch (NumberFormatException nfe)
+ {
+ _version = 1;
+ }
+
+ }
+
+ public int getVersion()
+ {
+ return _version;
+ }
+
+ 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;
+ }
+
+ public String getVirtualHostName()
+ {
+ // To make it work with the broker with no virtual host implementation
+ return _virtualHostName == null ? DEFAULT_VH : _virtualHostName;
+ }
+
+ /**
+ * Returns mbean instance name. MBeans which have only one instance, the type attribute will be returned
+ *
+ * @return
+ */
+ public String getInstanceName()
+ {
+ if (getName() != null)
+ {
+ return getName();
+ }
+ else
+ {
+ return getType();
+ }
+ }
+
+ public boolean isQueue()
+ {
+ return _type.endsWith(QUEUE);
+ }
+
+ public boolean isConnection()
+ {
+ return _type.endsWith(CONNECTION);
+ }
+
+ public boolean isExchange()
+ {
+ return _type.endsWith(EXCHANGE);
+ }
+
+ public boolean isVirtualHostManager()
+ {
+ return _type.endsWith(ManagedBroker.TYPE);
+ }
+
+ public boolean isTempQueue()
+ {
+ return (isQueue() && getName().startsWith("tmp_"));
+ }
+
+ public boolean isAdmin()
+ {
+ return _type.endsWith(ADMIN_MBEAN_TYPE);
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedObject.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedObject.java
new file mode 100644
index 0000000000..96e0fa46c6
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedObject.java
@@ -0,0 +1,40 @@
+/*
+ *
+ * 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;
+
+/**
+ * Abstract class representing a managed object
+ * @author Bhupendra Bhardwaj
+ */
+public abstract class ManagedObject
+{
+ private String _name;
+
+ public String getName()
+ {
+ return _name;
+ }
+
+ public void setName(String name)
+ {
+ this._name = name;
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedServer.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedServer.java
new file mode 100644
index 0000000000..9ca8787bb5
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ManagedServer.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;
+
+/**
+ * Class representing a server being managed eg. MBeanServer
+ */
+public class ManagedServer extends ManagedObject
+{
+ private String _host;
+ private int _port;
+ private String _domain;
+ private String _user;
+ private String _password;
+
+ public ManagedServer(String host, int port, String domain)
+ {
+ this(host, port, domain, null, null);
+ }
+
+ public ManagedServer(String host, int port, String domain, String user, String password)
+ {
+ setName(host + ":" + port);
+ _host = host;
+ _port = port;
+ _domain = domain;
+ _user = user;
+ _password = password;
+ }
+
+ public String getDomain()
+ {
+ return _domain;
+ }
+
+ public String getHost()
+ {
+ return _host;
+ }
+
+ public int getPort()
+ {
+ return _port;
+ }
+
+ public String getPassword()
+ {
+ return _password;
+ }
+
+ public void setPassword(String password)
+ {
+ _password = password;
+ }
+
+ public String getUser()
+ {
+ return _user;
+ }
+
+ public void setUser(String user)
+ {
+ _user = user;
+ }
+
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Perspective.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Perspective.java
new file mode 100644
index 0000000000..f93200cadf
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/Perspective.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.apache.qpid.management.ui.views.MBeanView;
+import org.apache.qpid.management.ui.views.NavigationView;
+import org.eclipse.ui.IPageLayout;
+import org.eclipse.ui.IPerspectiveFactory;
+
+/**
+ *
+ * @author Bhupendra Bhardwaj
+ */
+public class Perspective implements IPerspectiveFactory
+{
+ public void createInitialLayout(IPageLayout layout)
+ {
+ 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.30f, editorArea);
+ layout.addStandaloneView(MBeanView.ID, true, IPageLayout.RIGHT, 0.70f, editorArea);
+
+ layout.getViewLayout(NavigationView.ID).setCloseable(false);
+ layout.getViewLayout(MBeanView.ID).setCloseable(false);
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/RefreshIntervalComboPanel.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/RefreshIntervalComboPanel.java
new file mode 100644
index 0000000000..ae60467bf5
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/RefreshIntervalComboPanel.java
@@ -0,0 +1,131 @@
+/*
+ *
+ * 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.jmx.MBeanUtility;
+import org.apache.qpid.management.ui.views.MBeanView;
+import org.apache.qpid.management.ui.views.NavigationView;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+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.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.menus.WorkbenchWindowControlContribution;
+
+public class RefreshIntervalComboPanel extends WorkbenchWindowControlContribution
+{
+ private Display _display = null;
+ private RefreshTask _refreshTask = null;
+
+ private static int DEFAULT_INDEX = 2; //15seconds
+ private static final int[] INTERVALS = new int[]{5,10,15,30,60,120,300,600};
+
+ public RefreshIntervalComboPanel()
+ {
+ super();
+ }
+
+ public RefreshIntervalComboPanel(String id)
+ {
+ super(id);
+ }
+
+ @Override
+ public Control createControl(Composite parent)
+ {
+ _display = parent.getDisplay();
+
+ Composite holder = new Composite(parent,SWT.NONE);
+ holder.setLayout(new GridLayout(2,false));
+ holder.setLayoutData(new GridData(SWT.LEFT,SWT.TOP,false,false));
+
+ Label refreshLabel = new Label(holder,SWT.NONE);
+ refreshLabel.setLayoutData(new GridData(SWT.LEFT,SWT.TOP,false,true));
+ refreshLabel.setText("Refresh Interval: ");
+
+ final Combo combo = new Combo(holder, SWT.NONE | SWT.DROP_DOWN | SWT.READ_ONLY);
+ combo.setLayoutData(new GridData(SWT.LEFT,SWT.TOP,false,false));
+ for(int i=0; i< INTERVALS.length ; i++)
+ {
+ combo.add(String.valueOf(INTERVALS[i]) + " seconds");
+ }
+ combo.select(DEFAULT_INDEX);
+
+ _refreshTask = new RefreshTask(INTERVALS[DEFAULT_INDEX]);
+ _display.timerExec(1000 * INTERVALS[DEFAULT_INDEX], _refreshTask);
+
+ combo.addModifyListener(
+ new ModifyListener()
+ {
+ public void modifyText(final ModifyEvent e)
+ {
+ _display.timerExec(-1, _refreshTask); //cancels existing refresh runnable
+ _refreshTask = new RefreshTask(INTERVALS[combo.getSelectionIndex()]);
+ _display.timerExec(0, _refreshTask); //immediately refresh and begin new schedule
+ }
+ });
+
+ return holder;
+ }
+
+
+ private class RefreshTask implements Runnable
+ {
+ private int seconds;
+
+ public RefreshTask(int secs)
+ {
+ this.seconds = secs;
+ }
+
+ @Override
+ public void run()
+ {
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ if(window != null)
+ {
+ final MBeanView mbView = (MBeanView)window.getActivePage().findView(MBeanView.ID);
+
+ final NavigationView navView = (NavigationView)window.getActivePage().findView(NavigationView.ID);
+ try
+ {
+ mbView.refresh();
+ navView.refresh();
+ }
+ catch (Exception ex)
+ {
+ MBeanUtility.handleException(ex);
+ }
+
+ _display.timerExec(1000 * seconds, this);
+ }
+ }
+
+ }
+
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ServerRegistry.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ServerRegistry.java
new file mode 100644
index 0000000000..c3c0277f7d
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/ServerRegistry.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.management.ui;
+
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.qpid.management.ui.jmx.ClientListener;
+import org.apache.qpid.management.ui.model.ManagedAttributeModel;
+import org.apache.qpid.management.ui.model.NotificationObject;
+import org.apache.qpid.management.ui.model.OperationDataModel;
+
+import java.util.Collections;
+
+public abstract class ServerRegistry
+{
+ private ManagedServer _managedServer = null;
+
+ // API version for the management interface on the broker
+ private ApiVersion _managementApiVersion = new ApiVersion(0,0);
+
+ // list of virtual hosts for this server
+ private List<String> _virtualHosts = new ArrayList<String>();
+ // map of all Connection mbeans
+ private ConcurrentMap<String,List<ManagedBean>> _connections = new ConcurrentHashMap<String,List<ManagedBean>>();
+ // map of all exchange mbeans
+ private ConcurrentMap<String,List<ManagedBean>> _exchanges = new ConcurrentHashMap<String,List<ManagedBean>>();
+ // map of all queue mbenas
+ private ConcurrentMap<String,List<ManagedBean>> _queues = new ConcurrentHashMap<String,List<ManagedBean>>();
+ // map of all virtual host manager mbeans
+ private ConcurrentMap<String,ManagedBean> _vhostManagers = new ConcurrentHashMap<String,ManagedBean>();
+
+ private AtomicBoolean _serverConnectionClosed = new AtomicBoolean(false);
+
+ public ServerRegistry()
+ {
+
+ }
+
+ public ServerRegistry(ManagedServer server)
+ {
+ _managedServer = server;
+ }
+
+ public void serverConnectionClosed()
+ {
+ _serverConnectionClosed.set(true);
+ }
+
+ public boolean isServerConnectionClosed()
+ {
+ return _serverConnectionClosed.get();
+ }
+
+ public void setManagementApiVersion(ApiVersion mgmtApiVersion)
+ {
+ _managementApiVersion = mgmtApiVersion;
+ }
+
+ public ApiVersion getManagementApiVersion()
+ {
+ return _managementApiVersion;
+ }
+
+ public ManagedServer getManagedServer()
+ {
+ return _managedServer;
+ }
+
+ public void setManagedServer(ManagedServer server)
+ {
+ _managedServer = server;
+ }
+
+ protected void addConnectionMBean(ManagedBean mbean)
+ {
+ String vHost = mbean.getVirtualHostName();
+ List<ManagedBean> vhostConnections = getVhostSubList(vHost, _connections);
+ vhostConnections.add(mbean);
+ }
+
+ protected void addExchangeMBean(ManagedBean mbean)
+ {
+ String vHost = mbean.getVirtualHostName();
+ List<ManagedBean> vhostExchanges = getVhostSubList(vHost, _exchanges);
+ vhostExchanges.add(mbean);
+ }
+
+ protected void addQueueMBean(ManagedBean mbean)
+ {
+ String vHost = mbean.getVirtualHostName();
+ List<ManagedBean> vhostQueues = getVhostSubList(vHost, _queues);
+ vhostQueues.add(mbean);
+ }
+
+ private List<ManagedBean> getVhostSubList(String vHost, ConcurrentMap<String,List<ManagedBean>> parentList)
+ {
+ //add an empty sublist for the vhost if required
+ if (!parentList.containsKey(vHost))
+ {
+ List<ManagedBean> subList = Collections.synchronizedList(new ArrayList<ManagedBean>());
+ parentList.putIfAbsent(vHost, subList);
+ }
+
+ return parentList.get(vHost);
+ }
+
+ protected void addVirtualHostManagerMBean(ManagedBean mbean)
+ {
+ String vHost = mbean.getVirtualHostName();
+ _vhostManagers.put(vHost, mbean);
+ }
+
+ protected void removeVirtualHostManagerMBean(ManagedBean mbean)
+ {
+ _vhostManagers.remove(mbean.getVirtualHostName());
+ }
+
+ public ManagedBean getVirtualHostManagerMBean(String virtualHost)
+ {
+ return _vhostManagers.get(virtualHost);
+ }
+
+ protected void removeConnectionMBean(ManagedBean mbean)
+ {
+ _connections.get(mbean.getVirtualHostName()).remove(mbean);
+ }
+
+ protected void removeExchangeMBean(ManagedBean mbean)
+ {
+ _exchanges.get(mbean.getVirtualHostName()).remove(mbean);
+ }
+
+ protected void removeQueueMBean(ManagedBean mbean)
+ {
+ _queues.get(mbean.getVirtualHostName()).remove(mbean);
+ }
+
+ public List<ManagedBean> getConnections(String virtualHost)
+ {
+ return getVhostObjects(virtualHost, _connections);
+ }
+
+ public List<ManagedBean> getExchanges(String virtualHost)
+ {
+ return getVhostObjects(virtualHost, _exchanges);
+ }
+
+ public List<ManagedBean> getQueues(String virtualHost)
+ {
+ return getVhostObjects(virtualHost, _queues);
+ }
+
+ public List<ManagedBean> getVhostObjects(String virtualHost, ConcurrentMap<String,List<ManagedBean>> parentList)
+ {
+ List<ManagedBean> objects = parentList.get(virtualHost);
+
+ if(objects == null)
+ {
+ return new ArrayList<ManagedBean>();
+ }
+
+ synchronized (objects)
+ {
+ return new ArrayList<ManagedBean>(objects);
+ }
+ }
+
+ //returns the requested ManagedBean, or null if it cant be found
+ public ManagedBean getQueue(String queueName, String virtualHost)
+ {
+ ManagedBean requestedQueue = null;
+
+ for(ManagedBean queue : _queues.get(virtualHost))
+ {
+ if(queueName.equals(queue.getName()))
+ {
+ requestedQueue = queue;
+ break;
+ }
+ }
+
+ return requestedQueue;
+ }
+
+ public void addVirtualHost(String name)
+ {
+ if (!_virtualHosts.contains(name))
+ {
+ _virtualHosts.add(name);
+ }
+ }
+
+ public List<String> getVirtualHosts()
+ {
+ return _virtualHosts;
+ }
+
+ public abstract void setUserList(List<String> list);
+
+ public abstract List<String> getUsernames();
+
+ public abstract void addManagedObject(ManagedBean key);
+
+ public abstract List<ManagedBean> getMBeans();
+
+ public abstract void removeManagedObject(ManagedBean mbean);
+
+ public abstract List<ManagedBean> getObjectsToBeRemoved();
+
+ public abstract ManagedAttributeModel getAttributeModel(ManagedBean mbean);
+
+ public abstract Object getServerConnection();
+
+ public abstract void closeServerConnection() throws Exception;
+
+ public abstract OperationDataModel getOperationModel(ManagedBean mbean);
+
+ public abstract List<String> getQueueNames(String vistualHostName);
+
+ public abstract String[] getExchangeNames(String vistualHostName);
+
+ public abstract String[] getConnectionNames(String vistualHostName);
+
+ public abstract List<NotificationObject> getNotifications(ManagedBean mbean);
+
+ public abstract List<NotificationObject> getNotifications(String virtualhost);
+
+ public abstract boolean hasSubscribedForNotifications(ManagedBean mbean, String name, String type);
+
+ public abstract void clearNotifications(ManagedBean mbean, List<NotificationObject> list);
+
+ public ClientListener getNotificationListener()
+ {
+ return null;
+ }
+
+ public ClientListener getClientListener()
+ {
+ return null;
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AbstractAction.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AbstractAction.java
new file mode 100644
index 0000000000..5d892f5503
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AbstractAction.java
@@ -0,0 +1,220 @@
+/*
+ *
+ * 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 static org.apache.qpid.management.ui.Constants.ERROR_SERVER_CONNECTION;
+
+import java.io.IOException;
+
+import javax.net.ssl.SSLException;
+import javax.net.ssl.SSLHandshakeException;
+import javax.net.ssl.SSLKeyException;
+import javax.net.ssl.SSLPeerUnverifiedException;
+
+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.ManagementConsoleException;
+import org.apache.qpid.management.ui.jmx.MBeanUtility;
+import org.apache.qpid.management.ui.views.NavigationView;
+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 AbstractAction
+{
+ private NavigationView _navigationView;
+
+ protected IWorkbenchWindow _window;
+
+ public static final String INVALID_PERSPECTIVE = "Invalid Perspective";
+ public static final String CHANGE_PERSPECTIVE = "Please use the Qpid Management Perspective";
+
+ private static final String SSL_EMPTY_TRUSTANCHORS = "the trustAnchors parameter must be non-empty";
+ private static final String SSL_UNABLE_TO_FIND_CERTPATH = "sun.security.provider.certpath.SunCertPathBuilderException: " +
+ "unable to find valid certification path to requested target";
+
+ /**
+ * 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;
+ if (_window.getShell() != null)
+ {
+ _window.getShell().setImage(ApplicationRegistry.getImage(Constants.CONSOLE_IMAGE));
+ }
+ }
+
+ protected NavigationView getNavigationView()
+ {
+ if (_navigationView == null)
+ {
+ _navigationView = (NavigationView)_window.getActivePage().findView(NavigationView.ID);
+ }
+
+ return _navigationView;
+ }
+
+ protected void handleException(Throwable ex, String title, String msg)
+ {
+ //ensure first that the exception is not due to running in the wrong eclipse perspective
+ NavigationView view = (NavigationView)_window.getActivePage().findView(NavigationView.ID);
+ if (view == null)
+ {
+ IStatus status = new Status(IStatus.WARNING, ApplicationWorkbenchAdvisor.PERSPECTIVE_ID,
+ IStatus.OK, CHANGE_PERSPECTIVE, null);
+ ErrorDialog.openError(_window.getShell(), "Warning", INVALID_PERSPECTIVE, status);
+ return;
+ }
+
+ //default title if none given
+ if (title == null)
+ {
+ title = ERROR_SERVER_CONNECTION;
+ }
+
+ //determine the error message to display
+ if (msg == null)
+ {
+ if (ex instanceof SSLException)
+ {
+ if (ex instanceof SSLKeyException)
+ {
+ msg = "SSL key was invalid, please check the certificate configuration.";
+ //Display error dialogue and return
+ displayErrorDialogue(msg, title);
+ return;
+ }
+ else if (ex instanceof SSLPeerUnverifiedException)
+ {
+ msg = "SSL peer identity could not be verified, please ensure valid certificate configuration.";
+ //Display error dialogue and return
+ displayErrorDialogue(msg, title);
+ return;
+ }
+ else if (ex instanceof SSLHandshakeException)
+ {
+ if (ex.getMessage().contains(SSL_UNABLE_TO_FIND_CERTPATH))
+ {
+ msg = "Unable to certify the provided SSL certificate using the current SSL trust store.";
+ }
+ else
+ {
+ //cause unknown, provide a trace too
+ MBeanUtility.printStackTrace(ex);
+ msg = "SSL handhshake error.";
+ }
+ //Display error dialogue and return
+ displayErrorDialogue(msg, title);
+ return;
+ }
+ else
+ {
+ //general SSL Exception.
+ if (ex.getMessage().contains(SSL_EMPTY_TRUSTANCHORS))
+ {
+ msg = "Unable to locate the specified SSL certificate trust store, please check the configuration.";
+ }
+ else
+ {
+ //cause unknown, print stack trace
+ MBeanUtility.printStackTrace(ex);
+ msg = "SSL connection error.";
+ }
+ //Display error dialogue and return
+ displayErrorDialogue(msg, title);
+ return;
+ }
+ }
+ else if (ex instanceof IOException || ex instanceof SecurityException )
+ {
+ msg = ex.getMessage();
+
+ //if msg is still null, try reporting the cause.
+ if ((msg == null) && (ex.getCause() != null))
+ {
+ msg = ex.getCause().getMessage();
+ }
+
+ //Display error dialogue and return
+ displayErrorDialogue(msg, title);
+ return;
+ }
+ else if (ex instanceof ManagementConsoleException)
+ {
+ msg = ex.getMessage();
+ displayErrorDialogue(msg, title);
+ return;
+ }
+ else
+ {
+ //Unknown exception type/reason.
+ msg = ex.getMessage();
+ }
+
+ //if msg is still null, try reporting the cause.
+ if ((msg == null) && (ex.getCause() != null))
+ {
+ msg = ex.getCause().getMessage();
+ }
+
+ //failing all else, default non-descript error message.
+ if (msg == null)
+ {
+ msg = "An unknown error has occured.";
+ }
+ }
+
+ //Display error dialogue and print the exception stack trace
+ MBeanUtility.printStackTrace(ex);
+ displayErrorDialogue(msg, title);
+ }
+
+ private void displayErrorDialogue(String msg, String title)
+ {
+ IStatus status = new Status(IStatus.ERROR, ApplicationWorkbenchAdvisor.PERSPECTIVE_ID,
+ IStatus.OK, msg, null);
+ ErrorDialog.openError(_window.getShell(), "Error", title, 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() {
+
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AddServer.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AddServer.java
new file mode 100644
index 0000000000..e487c02a67
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/AddServer.java
@@ -0,0 +1,313 @@
+/*
+ *
+ * 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 static org.apache.qpid.management.ui.Constants.*;
+
+import org.apache.qpid.management.ui.ApplicationRegistry;
+import org.apache.qpid.management.ui.exceptions.InfoRequiredException;
+import org.apache.qpid.management.ui.views.NumberVerifyListener;
+import org.apache.qpid.management.ui.views.ViewUtility;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+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.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+public class AddServer extends AbstractAction implements IWorkbenchWindowActionDelegate
+{
+ private String _host;
+ private String _port;
+ private String _domain = DEFAULT_DOMAIN;
+ private String _user;
+ private String _password;
+
+ private boolean _addServer;
+
+ public AddServer()
+ {
+
+ }
+
+ public void run(IAction action)
+ {
+ if(_window == null)
+ return;
+
+ reset();
+ createAddServerPopup();
+ try
+ {
+ if (_addServer)
+ {
+ getNavigationView().addNewServer(_host, Integer.parseInt(_port), _domain, _user, _password);
+ }
+ }
+ catch(InfoRequiredException ex)
+ {
+ ViewUtility.popupInfoMessage(ACTION_ADDSERVER, ex.getMessage());
+ }
+ catch (Exception ex)
+ {
+ handleException(ex, null, null);
+ }
+ }
+
+ private void reset()
+ {
+ _addServer = false;
+ _host = null;
+ _port = null;
+ _user = null;
+ _password = null;
+ }
+
+ /**
+ * Creates the shell and then opens the popup where user can enter new connection details.
+ * Connects to the new server and adds the server in the navigation page.
+ * Pops up any error occured in connecting to the new server
+ */
+ private void createAddServerPopup()
+ {
+ final Shell appShell = _window.getShell();
+
+ Display display = Display.getCurrent();
+ final Shell shell = new Shell(display, SWT.BORDER | SWT.CLOSE);
+ shell.setText(ACTION_ADDSERVER);
+ shell.setImage(ApplicationRegistry.getImage(CONSOLE_IMAGE));
+ shell.setLayout(new GridLayout());
+
+ createWidgets(shell);
+ shell.pack();
+
+ //get current size dialog, and application window size and location
+ int appWidth = appShell.getBounds().width;
+ int appHeight = appShell.getBounds().height;
+ int appLocX = appShell.getBounds().x;
+ int appLocY = appShell.getBounds().y;
+ int currentShellWidth = shell.getSize().x;
+ int currentShellHeight = shell.getSize().y;
+
+ //default sizes for the dialog
+ int minShellWidth = 425;
+ int minShellHeight= 265;
+ //ensure this is large enough, increase it if its not
+ int newShellWidth = currentShellWidth > minShellWidth ? currentShellWidth : minShellWidth;
+ int newShellHeight = currentShellHeight > minShellHeight ? currentShellHeight : minShellHeight;
+
+ //set the final size and centre the dialog within the app window
+ shell.setBounds((appWidth - newShellWidth)/2 + appLocX, (appHeight - newShellHeight)/2 + appLocY, newShellWidth, newShellHeight);
+
+ shell.open();
+ _window.getShell().setEnabled(false);
+
+ while (!shell.isDisposed())
+ {
+ if (!display.readAndDispatch())
+ {
+ display.sleep();
+ }
+ }
+
+ // enable the main shell
+ _window.getShell().setEnabled(true);
+ _window.getShell().open();
+ }
+
+ // Creates SWT widgets for the user to add server connection details.
+ // Adds listeners to the widgets to take appropriate action
+ private void createWidgets(final Shell shell)
+ {
+ 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);
+
+ /* Commenting this, as there is only one protocol at the moment.
+ * This can be uncommented and enhanced, if more protocols are added in future
+ 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(CONNECTION_PROTOCOLS);
+ 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();
+
+ 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));
+ // Verify if the value entered is numeric
+ textPort.addVerifyListener(new NumberVerifyListener());
+
+ Label user = new Label(composite, SWT.NONE);
+ user.setText(USERNAME);
+ user.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, false, false));
+
+ final Text textUser = new Text(composite, SWT.BORDER);
+ textUser.setText("");
+ textUser.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+
+ Label password = new Label(composite, SWT.NONE);
+ password.setText(PASSWORD);
+ password.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, false, false));
+
+ final Text textPwd = new Text(composite, SWT.BORDER | SWT.SINGLE | SWT.PASSWORD);
+ textPwd.setText("");
+ //textPwd.setEchoChar('*');
+ textPwd.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+
+ //Get the text widgets
+ Control[] widgets = composite.getChildren();
+ for (int i=0; i < widgets.length; i++)
+ {
+ widgets[i].addKeyListener(new KeyAdapter()
+ {
+ public void keyPressed(KeyEvent event)
+ {
+ if (event.character == SWT.ESC)
+ {
+ //Escape key acts as cancel on all widgets
+ shell.dispose();
+ }
+ }
+ });
+ }
+
+ 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(BUTTON_CONNECT);
+ GridData gridData = new GridData (SWT.TRAIL, SWT.BOTTOM, true, true);
+ gridData.widthHint = 100;
+ connectButton.setLayoutData(gridData);
+ connectButton.setFont(ApplicationRegistry.getFont(FONT_BUTTON));
+ connectButton.addSelectionListener(new SelectionAdapter(){
+ public void widgetSelected(SelectionEvent event)
+ {
+ _host = textHost.getText();
+ if ((_host == null) || (_host.trim().length() == 0))
+ {
+ ViewUtility.popupInfoMessage(ACTION_ADDSERVER, INFO_HOST_ADDRESS);
+ textHost.setText("");
+ textHost.setFocus();
+ return;
+ }
+
+ _port = textPort.getText();
+ if ((_port == null) || (_port.trim().length() == 0))
+ {
+ ViewUtility.popupInfoMessage(ACTION_ADDSERVER, INFO_HOST_PORT);
+ textPort.setText("");
+ textPort.setFocus();
+ return;
+ }
+
+ _user = textUser.getText();
+ if ((_user == null) || (_user.trim().length() == 0))
+ {
+ ViewUtility.popupInfoMessage(ACTION_ADDSERVER, INFO_USERNAME);
+ textUser.setText("");
+ textUser.setFocus();
+ return;
+ }
+
+ _password = textPwd.getText();
+ if (_password == null)
+ {
+ ViewUtility.popupInfoMessage(ACTION_ADDSERVER, INFO_PASSWORD);
+ textPwd.setText("");
+ textPwd.setFocus();
+ return;
+ }
+
+ _addServer = true;
+ shell.dispose();
+ }
+ });
+
+ final Button cancelButton = new Button(buttonsComposite, SWT.PUSH);
+ cancelButton.setText(BUTTON_CANCEL);
+ gridData = new GridData (SWT.LEAD, SWT.BOTTOM, true, true);
+ gridData.widthHint = 100;
+ cancelButton.setLayoutData(gridData);
+ cancelButton.setFont(ApplicationRegistry.getFont(FONT_BUTTON));
+ cancelButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent event)
+ {
+ shell.dispose();
+ }
+ });
+
+ //Get the ok/cancel button widgets and add a new key listener
+ widgets = buttonsComposite.getChildren();
+ for (int i=0; i < widgets.length; i++)
+ {
+ widgets[i].addKeyListener(new KeyAdapter()
+ {
+ public void keyPressed(KeyEvent event)
+ {
+ if (event.character == SWT.ESC)
+ {
+ //Escape key acts as cancel on all widgets
+ shell.dispose();
+ }
+ }
+ });
+ }
+
+ shell.setDefaultButton(connectButton);
+ }
+
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/BackAction.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/BackAction.java
new file mode 100644
index 0000000000..2998c5db53
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/BackAction.java
@@ -0,0 +1,59 @@
+/*
+ *
+ * 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.jmx.MBeanUtility;
+import org.apache.qpid.management.ui.views.MBeanView;
+import org.eclipse.jface.action.Action;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.actions.ActionFactory.IWorkbenchAction;
+
+
+public class BackAction extends Action implements IWorkbenchAction
+{
+ private static final String ID = "org.apache.qpid.management.ui.actions.back";
+
+ public BackAction()
+ {
+ setText("Back");
+ setImageDescriptor(org.apache.qpid.management.ui.Activator.getImageDescriptor("/icons/back.gif"));
+ setId(ID);
+ }
+
+ public void run()
+ {
+ MBeanView mbeanview = (MBeanView)PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().findView(MBeanView.ID);
+ try
+ {
+ mbeanview.back();
+ }
+ catch (Exception ex)
+ {
+ MBeanUtility.handleException(ex);
+ }
+
+ }
+
+ public void dispose()
+ {
+
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/CloseConnection.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/CloseConnection.java
new file mode 100644
index 0000000000..a3e52149df
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/CloseConnection.java
@@ -0,0 +1,56 @@
+/*
+ *
+ * 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 static org.apache.qpid.management.ui.Constants.ACTION_CLOSE;
+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.jface.action.IAction;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+public class CloseConnection extends AbstractAction implements IWorkbenchWindowActionDelegate
+{
+ 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(ACTION_CLOSE, ex.getMessage());
+ }
+ catch(Exception ex)
+ {
+ handleException(ex, null, null);
+ }
+ }
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/ReconnectServer.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/ReconnectServer.java
new file mode 100644
index 0000000000..5eb9d9a168
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/ReconnectServer.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.management.ui.actions;
+
+import static org.apache.qpid.management.ui.Constants.ACTION_LOGIN;
+import static org.apache.qpid.management.ui.Constants.CONSOLE_IMAGE;
+import static org.apache.qpid.management.ui.Constants.INFO_PASSWORD;
+import static org.apache.qpid.management.ui.Constants.INFO_USERNAME;
+import static org.apache.qpid.management.ui.Constants.PASSWORD;
+import static org.apache.qpid.management.ui.Constants.USERNAME;
+
+import org.apache.qpid.management.ui.ApplicationRegistry;
+import org.apache.qpid.management.ui.Constants;
+import org.apache.qpid.management.ui.exceptions.InfoRequiredException;
+import org.apache.qpid.management.ui.views.TreeObject;
+import org.apache.qpid.management.ui.views.ViewUtility;
+import org.eclipse.jface.action.IAction;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+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.Shell;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+public class ReconnectServer extends AbstractAction implements IWorkbenchWindowActionDelegate
+{
+ private String _title;
+ private String _serverName;
+ private String _user;
+ private String _password;
+ private boolean _connect;
+
+ public void run(IAction action)
+ {
+ if(_window == null)
+ return;
+
+ try
+ {
+ reset();
+ // Check if a server node is selected to be reconnected.
+ TreeObject serverNode = getNavigationView().getSelectedServerNode();
+ _serverName = serverNode.getName();
+ _title = ACTION_LOGIN + " (" + _serverName + ")";
+
+ // Get the login details(username/password)
+ createLoginPopup();
+
+ if (_connect)
+ {
+ // Connect the server
+ getNavigationView().reconnect(_user, _password);
+ }
+ }
+ catch(InfoRequiredException ex)
+ {
+ ViewUtility.popupInfoMessage("Reconnect Qpid server", ex.getMessage());
+ }
+ catch (Exception ex)
+ {
+ handleException(ex, null, null);
+ }
+ }
+
+ private void reset()
+ {
+ _connect = false;
+ _user = null;
+ _password = null;
+ }
+
+ // Create the login popup fot th user to enter usernaem and password
+ private void createLoginPopup()
+ {
+ final Shell appShell = _window.getShell();
+
+ Display display = Display.getCurrent();
+ final Shell shell = new Shell(display, SWT.BORDER | SWT.CLOSE);
+ shell.setText(_title);
+ shell.setImage(ApplicationRegistry.getImage(CONSOLE_IMAGE));
+ shell.setLayout(new GridLayout());
+
+ createWidgets(shell);
+ shell.pack();
+
+ //get current size dialog, and application window size and location
+ int appWidth = appShell.getBounds().width;
+ int appHeight = appShell.getBounds().height;
+ int appLocX = appShell.getBounds().x;
+ int appLocY = appShell.getBounds().y;
+ int currentShellWidth = shell.getSize().x;
+ int currentShellHeight = shell.getSize().y;
+
+ //default sizes for the dialog
+ int minShellWidth = 350;
+ int minShellHeight= 200;
+ //ensure this is large enough, increase it if its not
+ int newShellWidth = currentShellWidth > minShellWidth ? currentShellWidth : minShellWidth;
+ int newShellHeight = currentShellHeight > minShellHeight ? currentShellHeight : minShellHeight;
+
+ //set the final size and centre the dialog within the app window
+ shell.setBounds((appWidth - newShellWidth)/2 + appLocX, (appHeight - newShellHeight)/2 + appLocY, newShellWidth, newShellHeight);
+
+ shell.open();
+ _window.getShell().setEnabled(false);
+
+ while (!shell.isDisposed())
+ {
+ if (!display.readAndDispatch())
+ {
+ display.sleep();
+ }
+ }
+
+ // enable the main shell
+ _window.getShell().setEnabled(true);
+ _window.getShell().open();
+ }
+
+ // Creates the SWT widgets in the popup shell, to enter username and password.
+ // Adds listeners to the widgets to take appropriate action
+ private void createWidgets(final Shell shell)
+ {
+ 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 user = new Label(composite, SWT.NONE);
+ user.setText(USERNAME);
+ user.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, false, false));
+
+ final Text textUser = new Text(composite, SWT.BORDER);
+ textUser.setText("");
+ textUser.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ // Put cursor on this field
+ textUser.setFocus();
+
+ Label password = new Label(composite, SWT.NONE);
+ password.setText(PASSWORD);
+ password.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, false, false));
+
+ final Text textPwd = new Text(composite, SWT.BORDER | SWT.SINGLE | SWT.PASSWORD);
+ textPwd.setText("");
+ textPwd.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+
+ //Get the text widgets
+ Control[] widgets = composite.getChildren();
+ for (int i=0; i < widgets.length; i++)
+ {
+ widgets[i].addKeyListener(new KeyAdapter()
+ {
+ public void keyPressed(KeyEvent event)
+ {
+ if (event.character == SWT.ESC)
+ {
+ //Escape key acts as cancel on all widgets
+ shell.dispose();
+ }
+ }
+ });
+ }
+
+ 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)
+ {
+ _user = textUser.getText();
+ if ((_user == null) || (_user.trim().length() == 0))
+ {
+ ViewUtility.popupInfoMessage(_title, INFO_USERNAME);
+ textUser.setText("");
+ textUser.setFocus();
+ return;
+ }
+
+ _password = textPwd.getText();
+ if (_password == null)
+ {
+ ViewUtility.popupInfoMessage(_title, INFO_PASSWORD);
+ textPwd.setText("");
+ textPwd.setFocus();
+ return;
+ }
+
+ _connect = true;
+ shell.dispose();
+ }
+ });
+
+ 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();
+ }
+ });
+
+ //Get the ok/cancel button widgets and add a new key listener
+ widgets = buttonsComposite.getChildren();
+ for (int i=0; i < widgets.length; i++)
+ {
+ widgets[i].addKeyListener(new KeyAdapter()
+ {
+ public void keyPressed(KeyEvent event)
+ {
+ if (event.character == SWT.ESC)
+ {
+ //Escape key acts as cancel on all widgets
+ shell.dispose();
+ }
+ }
+ });
+ }
+
+ shell.setDefaultButton(connectButton);
+ }
+
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/Refresh.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/Refresh.java
new file mode 100644
index 0000000000..dd4cbffd84
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/Refresh.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.actions;
+
+import org.apache.qpid.management.ui.jmx.MBeanUtility;
+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.ui.IWorkbenchWindowActionDelegate;
+
+/**
+ * This action refreshes both the views -Navigation and MBeanView
+ * @author Bhupendra Bhardwaj
+ */
+public class Refresh extends AbstractAction implements IWorkbenchWindowActionDelegate
+{
+ 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);
+ try
+ {
+ mbeanview.refresh();
+ }
+ catch (Exception ex)
+ {
+ MBeanUtility.handleException(ex);
+ }
+ }
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/RemoveServer.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/RemoveServer.java
new file mode 100644
index 0000000000..e329255414
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/RemoveServer.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.actions;
+
+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.jface.action.IAction;
+import org.eclipse.ui.IWorkbenchWindowActionDelegate;
+
+public class RemoveServer extends AbstractAction implements IWorkbenchWindowActionDelegate
+{
+ 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)
+ {
+ handleException(ex, "Server could not be removed", null);
+ }
+ }
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/VersionAction.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/VersionAction.java
new file mode 100644
index 0000000000..be69fadbe8
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/actions/VersionAction.java
@@ -0,0 +1,94 @@
+/*
+ *
+ * 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 java.io.InputStream;
+import java.util.Properties;
+
+import org.apache.qpid.management.ui.Constants;
+import org.apache.qpid.management.ui.jmx.MBeanUtility;
+import org.eclipse.jface.action.Action;
+import org.eclipse.jface.dialogs.MessageDialog;
+import org.eclipse.ui.IWorkbenchWindow;
+
+public class VersionAction extends Action
+{
+ private IWorkbenchWindow _window;
+ public static final String VERSION_RESOURCE = "qpidversion.properties";
+
+ public static final String PRODUCT_NAME_PROPERTY = "qpid.name";
+ public static final String RELEASE_VERSION_PROPERTY = "qpid.version";
+ public static final String BUILD_VERSION_PROPERTY = "qpid.svnversion";
+
+ private static final String DEFAULT = "unknown";
+ private static String _releaseVersion;
+ private static String _buildVersion;
+ private static String _text;
+
+ static
+ {
+ Properties props = new Properties();
+ try
+ {
+ InputStream propertyStream = VersionAction.class.getClassLoader().getResourceAsStream(VERSION_RESOURCE);
+ if (propertyStream != null)
+ {
+ props.load(propertyStream);
+ _releaseVersion = readPropertyValue(props, RELEASE_VERSION_PROPERTY);
+ _buildVersion = readPropertyValue(props, BUILD_VERSION_PROPERTY);
+ _text = "Build Version : " + _buildVersion + "\n" +
+ "Release Version : " + _releaseVersion;
+ }
+ else
+ {
+ _text = "Build Version : \n" +
+ "Release Version : ";
+ }
+ }
+ catch (Exception ex)
+ {
+ MBeanUtility.printStackTrace(ex);
+ }
+ }
+
+ public VersionAction(IWorkbenchWindow window)
+ {
+ _window = window;
+ setText("About " + Constants.APPLICATION_NAME);
+ setId("qpidmc.about");
+ setActionDefinitionId("qpidmc.about");
+ }
+
+ private static String readPropertyValue(Properties props, String propertyName)
+ {
+ String retVal = (String) props.get(propertyName);
+ if (retVal == null)
+ {
+ retVal = DEFAULT;
+ }
+ return retVal;
+ }
+
+ public void run()
+ {
+ MessageDialog.openInformation(_window.getShell(), Constants.APPLICATION_NAME, _text);
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/exceptions/InfoRequiredException.java b/qpid/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/qpid/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/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/exceptions/ManagementConsoleException.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/exceptions/ManagementConsoleException.java
new file mode 100644
index 0000000000..17c127c01a
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/exceptions/ManagementConsoleException.java
@@ -0,0 +1,31 @@
+/*
+ *
+ * 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;
+
+@SuppressWarnings("serial")
+public class ManagementConsoleException extends Exception
+{
+ public ManagementConsoleException(String message)
+ {
+ super(message);
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientListener.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientListener.java
new file mode 100644
index 0000000000..6fa78b1d36
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientListener.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.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)
+ {
+ String type = notification.getType();
+
+ if(notification instanceof MBeanServerNotification)
+ {
+ ObjectName objName = ((MBeanServerNotification)notification).getMBeanName();
+
+ if (MBeanServerNotification.REGISTRATION_NOTIFICATION.equals(type))
+ {
+ getServerRegistry().registerManagedObject(objName);
+ }
+ else if (MBeanServerNotification.UNREGISTRATION_NOTIFICATION.equals(type))
+ {
+ getServerRegistry().unregisterManagedObject(objName);
+ }
+ }
+ else if (JMXConnectionNotification.FAILED.equals(type))
+ {
+ ApplicationRegistry.serverConnectionClosedRemotely(server);
+ MBeanUtility.printOutput("JMX Connection to " + server.getName() + " failed.");
+ }
+ else if (JMXConnectionNotification.CLOSED.equals(type))
+ {
+ ApplicationRegistry.serverConnectionClosedRemotely(server);
+ MBeanUtility.printOutput("JMX Connection to " + server.getName() + " was closed.");
+ }
+ }
+
+ protected JMXServerRegistry getServerRegistry()
+ {
+ if (serverRegistry == null)
+ serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(server);
+
+ return serverRegistry;
+ }
+ public ManagedServer getServer()
+ {
+ return server;
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientNotificationListener.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientNotificationListener.java
new file mode 100644
index 0000000000..2af8e681ae
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/ClientNotificationListener.java
@@ -0,0 +1,40 @@
+/*
+ *
+ * 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)
+ {
+ ObjectName objName = (ObjectName)notification.getSource();
+ getServerRegistry().addNotification(objName, notification);
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXManagedObject.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXManagedObject.java
new file mode 100644
index 0000000000..a8fb864cf6
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXManagedObject.java
@@ -0,0 +1,71 @@
+/*
+ *
+ * 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 java.util.Map;
+
+import javax.management.ObjectName;
+
+import org.apache.qpid.management.ui.ManagedBean;
+
+
+public class JMXManagedObject extends ManagedBean
+{
+ private ObjectName _objName;
+
+ public JMXManagedObject(ObjectName objName)
+ {
+ super();
+ this._objName = objName;
+ setUniqueName(_objName.toString());
+ setDomain(_objName.getDomain());
+
+ HashMap<String,String> props = new HashMap<String,String>(_objName.getKeyPropertyList());
+
+ for(Map.Entry<String,String> entry : props.entrySet())
+ {
+ String value = entry.getValue();
+
+ if(value != null)
+ {
+ try
+ {
+ //if the name is quoted in the ObjectName, unquote it
+ value = ObjectName.unquote(value);
+ entry.setValue(value);
+ }
+ catch(IllegalArgumentException e)
+ {
+ //ignore, this just means the name is not quoted
+ //and can be left unchanged
+ }
+ }
+ }
+
+ super.setProperties(props);
+ }
+
+ public ObjectName getObjectName()
+ {
+ return _objName;
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXServerRegistry.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXServerRegistry.java
new file mode 100644
index 0000000000..717f781334
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/JMXServerRegistry.java
@@ -0,0 +1,612 @@
+/*
+ *
+ * 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 static org.apache.qpid.management.ui.Constants.ALL;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+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 org.apache.qpid.management.common.JMXConnnectionFactory;
+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.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 String _securityMechanism = null;
+
+ private List<String> _usersList;
+ // When an mbean gets removed from mbean server, then the notification listener
+ // will add that mbean in this list.
+ private List<ManagedBean> _mbeansToBeRemoved = new ArrayList<ManagedBean>();
+
+ // Map containing all managed beans and mapped with unique mbean name
+ private HashMap<String, ManagedBean> _mbeansMap = new HashMap<String, ManagedBean>();
+ // Map containing MBeanInfo for all mbeans and mapped with unique mbean name
+ private HashMap<String, MBeanInfo> _mbeanInfoMap = new HashMap<String, MBeanInfo>();
+ // Map containing attribute model for all mbeans and mapped with unique mbean name
+ private HashMap<String, ManagedAttributeModel> _attributeModelMap = new HashMap<String, ManagedAttributeModel>();
+ // Map containing operation model for all mbeans and mapped with unique mbean name
+ private HashMap<String, OperationDataModel> _operationModelMap = new HashMap<String, OperationDataModel>();
+ // Map containing NotificationInfo for all mbeans and mapped with unique mbean name
+ private HashMap<String, List<NotificationInfoModel>> _notificationInfoMap = new HashMap<String, List<NotificationInfoModel>>();
+ // Map containing all notifications sent for all mbeans, which are registered for notification
+ private HashMap<String, List<NotificationObject>> _notificationsMap = new HashMap<String, List<NotificationObject>>();
+ // For mbeans which have subscribed for a notification type
+ // mbean unique name mapped with notification map. Notification map contains list of notification type
+ // mapped with notification name. Notification type list contains those notification types,
+ // which are subscribed for notification.
+ private HashMap<String, HashMap<String, List<String>>> _subscribedNotificationMap = new HashMap<String, HashMap<String, List<String>>>();
+
+ // listener for registration or unregistratioj of mbeans on mbean server
+ private ClientNotificationListener _notificationListener = null;
+ // listener for server connection. Receives notification if server connection goes down
+ private ClientListener _clientListener = null;
+
+ public JMXServerRegistry(ManagedServer server) throws Exception
+ {
+ super(server);
+
+ _jmxc = JMXConnnectionFactory.getJMXConnection(
+ ApplicationRegistry.timeout, server.getHost(),
+ server.getPort(), server.getUser(), server.getPassword());
+
+ _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;
+ }
+
+
+ public String getSecurityMechanism()
+ {
+ return _securityMechanism;
+ }
+
+ /**
+ * removes all listeners from the mbean server. This is required when user
+ * disconnects the Qpid server connection
+ */
+ public void closeServerConnection() throws IOException
+ {
+ if(isServerConnectionClosed())
+ {
+ //connection was already closed
+ return;
+ }
+
+ try
+ {
+ //remove the listener from the JMXConnector
+ if (_jmxc != null && _clientListener != null)
+ {
+ _jmxc.removeConnectionNotificationListener(_clientListener);
+ }
+ }
+ catch (Exception e)
+ {
+ //ignore
+ }
+
+ try
+ {
+ //remove the listener from the MBeanServerDelegate MBean
+ if (_mbsc != null && _clientListener != null)
+ {
+ _mbsc.removeNotificationListener(_serverObjectName, _clientListener);
+ }
+ }
+ catch (Exception e)
+ {
+ //ignore
+ }
+
+ if (_mbsc != null && _clientListener != null)
+ {
+ //remove any listeners from the Qpid MBeans
+ for (String mbeanName : _subscribedNotificationMap.keySet())
+ {
+ try
+ {
+ _mbsc.removeNotificationListener(new ObjectName(mbeanName), _notificationListener);
+ }
+ catch (Exception e)
+ {
+ //ignore
+ }
+ }
+ }
+
+ //close the JMXConnector
+ if (_jmxc != null)
+ {
+ _jmxc.close();
+ }
+
+ serverConnectionClosed();
+ }
+
+ public ManagedBean getManagedObject(String uniqueName)
+ {
+ return _mbeansMap.get(uniqueName);
+ }
+
+ public void addManagedObject(ManagedBean mbean)
+ {
+ if (mbean.isQueue())
+ {
+ addQueueMBean(mbean);
+ }
+ else if (mbean.isExchange())
+ {
+ addExchangeMBean(mbean);
+ }
+ else if (mbean.isConnection())
+ {
+ addConnectionMBean(mbean);
+ }
+ else if (mbean.isVirtualHostManager())
+ {
+ addVirtualHostManagerMBean(mbean);
+ }
+
+ addVirtualHost(mbean.getVirtualHostName());
+ _mbeansMap.put(mbean.getUniqueName(), mbean);
+ }
+
+ public void removeManagedObject(ManagedBean mbean)
+ {
+ if (mbean == null)
+ {
+ return;
+ }
+
+ _mbeansMap.remove(mbean.getUniqueName());
+
+ if (mbean.isQueue())
+ {
+ removeQueueMBean(mbean);
+ }
+ else if (mbean.isExchange())
+ {
+ removeExchangeMBean(mbean);
+ }
+ else if (mbean.isConnection())
+ {
+ removeConnectionMBean(mbean);
+ }
+ else if (mbean.isVirtualHostManager())
+ {
+ removeVirtualHostManagerMBean(mbean);
+ }
+ }
+
+ public void putMBeanInfo(ManagedBean mbean, MBeanInfo mbeanInfo)
+ {
+ _mbeanInfoMap.put(mbean.getUniqueName(), mbeanInfo);
+ }
+ public MBeanInfo getMBeanInfo(ManagedBean mbean)
+ {
+ return _mbeanInfoMap.get(mbean.getUniqueName());
+ }
+
+ public List<ManagedBean> getMBeans()
+ {
+ return new ArrayList<ManagedBean>(_mbeansMap.values());
+ }
+
+ 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);
+ }
+
+ /**
+ * Returns all the notification objects for a given mbean. If mbean is null, it returns
+ * notification objects for all the mbeans.
+ */
+ public List<NotificationObject> getNotifications(ManagedBean mbean)
+ {
+ if (mbean == null)
+ {
+ List<NotificationObject> totalList = new ArrayList<NotificationObject>();
+ for (List<NotificationObject> list : _notificationsMap.values())
+ {
+ totalList.addAll(list);
+ }
+ return totalList;
+ }
+ else
+ {
+ return _notificationsMap.get(mbean.getUniqueName());
+ }
+ }
+
+ public List<NotificationObject> getNotifications(String virtualhost)
+ {
+ List<NotificationObject> vhostNotificationsList = new ArrayList<NotificationObject>();
+
+ //iterate over all the notification lists for mbeans with subscribed notifications
+ for (List<NotificationObject> list : _notificationsMap.values())
+ {
+ if(list == null || list.isEmpty())
+ {
+ continue;
+ }
+
+ //Check the source vhost of the first notification
+ NotificationObject notification = list.get(0);
+
+ if (notification != null)
+ {
+ String sourceVhost = notification.getSourceVirtualHost();
+ if(sourceVhost != null)
+ {
+ if(sourceVhost.equalsIgnoreCase(virtualhost))
+ {
+ //If it matches, add the entire list as they are from the same vhost (same source mbean)
+ vhostNotificationsList.addAll(list);
+ }
+ }
+ }
+ }
+
+ return vhostNotificationsList;
+ }
+
+ public void clearNotifications(ManagedBean mbean, List<NotificationObject> list)
+ {
+ if (mbean == null)
+ {
+ if (list == null || list.isEmpty())
+ {
+ // All notifications of all mbeans to be cleared
+ _notificationsMap.clear();
+ }
+ else
+ {
+ // Clear the selected notifications
+ for (NotificationObject obj : list)
+ {
+ mbean = _mbeansMap.get(obj.getSource().toString());
+ List<NotificationObject> nList = _notificationsMap.get(mbean.getUniqueName());
+ if (nList != null && !nList.isEmpty())
+ {
+ nList.remove(obj);
+ }
+ }
+ }
+ }
+ else
+ {
+ if (list == null || list.isEmpty())
+ {
+ // All notifications of this mbean to be cleared
+ List<NotificationObject> nList = _notificationsMap.get(mbean.getUniqueName());
+ if (nList != null && !nList.isEmpty())
+ {
+ nList.clear();
+ }
+ }
+ else
+ {
+ // Clear the selected notifications
+ for (NotificationObject obj : list)
+ {
+ List<NotificationObject> nList = _notificationsMap.get(mbean.getUniqueName());
+ if (nList != null && !nList.isEmpty())
+ {
+ nList.remove(obj);
+ }
+ }
+ }
+ }
+ }
+
+
+
+ /**
+ * Adds notification name and type to the map. The map contains all the notification names,
+ * subscribed for an mbean.
+ * @param mbean
+ * @param name
+ * @param type
+ */
+ public void addNotificationListener(ManagedBean mbean, String name, String type)
+ {
+ // Get the subscribed notifications map for given mbean. If map is null then create a new one.
+ HashMap<String, List<String>> map = _subscribedNotificationMap.get(mbean.getUniqueName());
+ if (map == null)
+ {
+ map = new HashMap<String, List<String>>();
+ _subscribedNotificationMap.put(mbean.getUniqueName(),map);
+ }
+
+ // Get the list of notification types for given notification name. If null, then create a new list.
+ List<String> list = map.get(name);
+ if (list == null)
+ {
+ list = new ArrayList<String>();
+ map.put(name, list);
+ }
+ // Now add the notification type to the list
+ if (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());
+ }
+
+ /**
+ * Checks if the given notification name and type are subscribed for the mbean.
+ */
+ 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;
+ }
+
+ /**
+ * Clears the notification name and type information from the subscribed notifications map
+ * and removes the listener from mbeanserver connection
+ * @param mbean
+ * @param name
+ * @param type
+ * @throws Exception
+ */
+ 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()))
+ {
+ // get the notifications map. This map contains the notification name mapped with the notification types
+ HashMap<String, List<String>> map = _subscribedNotificationMap.get(mbean.getUniqueName());
+ if (map.containsKey(name))
+ {
+ if (ALL.equals(type))
+ {
+ map.remove(name);
+ }
+ else if (type != null)
+ {
+ map.get(name).remove(type);
+ if (map.get(name).isEmpty())
+ {
+ map.remove(name);
+ }
+ }
+ }
+ if (map.size() == 0)
+ {
+ _subscribedNotificationMap.remove(mbean.getUniqueName());
+ }
+
+ JMXManagedObject jmxbean = (JMXManagedObject)mbean;
+ _mbsc.removeNotificationListener(jmxbean.getObjectName(), _notificationListener);
+ }
+ }
+
+ /**
+ * When the mbean registration request is received from the mbean server, then the client listener
+ * can use this method. It will add the mbean to a list, which will be used to add the mbean to
+ * the registry and gui
+ * @param objName
+ */
+ public void registerManagedObject(ObjectName objName)
+ {
+ JMXManagedObject managedObject = new JMXManagedObject(objName);
+ managedObject.setServer(getManagedServer());
+ addManagedObject(managedObject);
+ }
+
+ /**
+ * When mbean unregistration notification is received from the mbean server, then client listener
+ * can invoke this method. It will add the mbean to the list of mbeans to be removed from registry
+ * @param objName
+ */
+ public void unregisterManagedObject(ObjectName objName)
+ {
+ ManagedBean mbean = _mbeansMap.get(objName.toString());
+ // Check if mbean was not available in the map. It can happen if mbean unregistration
+ // notification is received and the mbean is not added in the map.
+ if (mbean != null)
+ {
+ removeManagedObject(mbean);
+ _mbeansToBeRemoved.add(mbean);
+ }
+ }
+
+ 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 List<String> getQueueNames(String virtualHostName)
+ {
+ List<ManagedBean> list = getQueues(virtualHostName);
+ if (list == null)
+ return null;
+
+ List<String> queueNames = new ArrayList<String>();
+ for (ManagedBean mbean : list)
+ {
+ queueNames.add(mbean.getName());
+ }
+ return queueNames;
+ }
+
+ public String[] getExchangeNames(String virtualHostName)
+ {
+ List<ManagedBean> list = getExchanges(virtualHostName);
+ if (list == null)
+ return null;
+
+ String[] exchanges = new String[list.size()];
+ int i = 0;
+ for (ManagedBean mbean : list)
+ {
+ exchanges[i++] = mbean.getName();
+ }
+ return exchanges;
+ }
+
+ public String[] getConnectionNames(String virtualHostName)
+ {
+ List<ManagedBean> list = getExchanges(virtualHostName);
+ if (list == null)
+ return null;
+
+ String[] connections = new String[list.size()];
+ int i = 0;
+ for (ManagedBean mbean : list)
+ {
+ connections[i++] = mbean.getName();
+ }
+ return connections;
+ }
+
+ public void setUserList(List<String> list)
+ {
+ _usersList = list;
+ Collections.sort(_usersList);
+ }
+
+ public List<String> getUsernames()
+ {
+ return _usersList;
+ }
+
+ public ClientNotificationListener getNotificationListener()
+ {
+ return _notificationListener;
+ }
+
+ public ClientListener getClientListener()
+ {
+ return _clientListener;
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/MBeanUtility.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/MBeanUtility.java
new file mode 100644
index 0000000000..6d6aa80f4d
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/jmx/MBeanUtility.java
@@ -0,0 +1,619 @@
+/*
+ *
+ * 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.math.BigInteger;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+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.MBeanServerInvocationHandler;
+import javax.management.MalformedObjectNameException;
+import javax.management.ObjectInstance;
+import javax.management.ObjectName;
+import javax.management.ReflectionException;
+
+import org.apache.qpid.management.common.mbeans.ServerInformation;
+import org.apache.qpid.management.ui.ApiVersion;
+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.exceptions.ManagementConsoleException;
+import org.apache.qpid.management.ui.model.AttributeData;
+import org.apache.qpid.management.ui.model.ManagedAttributeModel;
+import org.apache.qpid.management.ui.model.NotificationInfoModel;
+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;
+
+/**
+ * Utility class for all mbeanserver related operations. Keeps all JMX code out from view and model classes
+ * @author Bhupendra Bhardwaj
+ */
+public class MBeanUtility
+{
+ public static final BigInteger MAX_LONG = BigInteger.valueOf(Long.MAX_VALUE);
+ public static final BigInteger MAX_INT = BigInteger.valueOf(Integer.MAX_VALUE);
+ /**
+ * Retrieves the MBeanInfo from MBeanServer and stores in the application registry
+ * @param mbean managed bean
+ * @return MBeanInfo
+ * @throws Exception, if server connection is null or if server throws Exception
+ */
+ public static MBeanInfo getMBeanInfo(ManagedBean mbean) throws Exception
+ {
+ ManagedServer server = mbean.getServer();
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(server);
+
+ MBeanServerConnection mbsc = serverRegistry.getServerConnection();
+ if (mbsc == null)
+ {
+ throw new ManagementConsoleException("Server connection is broken");
+ }
+
+ JMXManagedObject jmxbean = (JMXManagedObject)mbean;
+ MBeanInfo mbeanInfo = mbsc.getMBeanInfo(jmxbean.getObjectName());
+ serverRegistry.putMBeanInfo(mbean, mbeanInfo);
+
+ // populate the server registry with attribute and operation info
+ getAttributes(mbean);
+ getOperations(mbean);
+
+ return mbeanInfo;
+ }
+
+ /**
+ * executes the MBean operation
+ * @param mbean
+ * @param opData
+ * @return MBean operation return value
+ * @throws Exception if server connection is broken or if operation execution fails on the mbean server
+ */
+ public static Object execute(ManagedBean mbean, OperationData opData) throws Exception
+ {
+ String opName = opData.getName();
+ 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();
+ }
+ }
+
+ ManagedServer server = mbean.getServer();
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(server);
+
+ MBeanServerConnection mbsc = serverRegistry.getServerConnection();
+ if (mbsc == null)
+ {
+ throw new ManagementConsoleException("Server connection is broken");
+ // TODO
+ // try and get the connection again if it was disconnected
+ }
+ JMXManagedObject jmxbean = (JMXManagedObject)mbean;
+ return mbsc.invoke(jmxbean.getObjectName(), opName, values, signature);
+ }
+
+ /**
+ * @see MBeanUtility#handleException(ManagedBean, Exception)
+ */
+ public static void handleException(Exception ex)
+ {
+ handleException(null, ex);
+ }
+
+ /**
+ * handels the exception received. Shows the exception to the user in best suitable way
+ * @param mbean managed bean
+ * @param ex Exception
+ */
+ public static void handleException(ManagedBean mbean, Throwable ex)
+ {
+ if (mbean == null)
+ {
+ ViewUtility.popupErrorMessage("Error", "Managed Object is null \n" + ex.toString());
+ printStackTrace(ex);
+ }
+ else if (ex instanceof ReflectionException)
+ {
+ ViewUtility.popupErrorMessage(mbean.getInstanceName(), "Server has thrown error \n" + ex.toString());
+ printStackTrace(ex);
+ }
+ else if (ex instanceof InstanceNotFoundException)
+ {
+ ViewUtility.popupErrorMessage(mbean.getInstanceName(), "Managed Object Not Found \n" + ex.toString());
+ printStackTrace(ex);
+ }
+ else if (ex instanceof MBeanException)
+ {
+ String cause = ((MBeanException)ex).getTargetException().getMessage();
+ if (cause == null)
+ cause = ex.toString();
+ ViewUtility.popupInfoMessage(mbean.getInstanceName(), cause);
+ }
+ else if (ex instanceof JMException)
+ {
+ ViewUtility.popupErrorMessage(mbean.getInstanceName(), "Management Exception occured \n" + ex.toString());
+ }
+ else if (ex instanceof ManagementConsoleException)
+ {
+ ViewUtility.popupErrorMessage(mbean.getInstanceName(), ex.getMessage());
+ }
+ else if (ex instanceof SecurityException)
+ {
+ ViewUtility.popupErrorMessage(mbean.getInstanceName(), ex.getMessage());
+ }
+ else
+ {
+ if (ex.getCause() != null)
+ {
+ handleException(mbean, ex.getCause());
+ }
+ else
+ {
+ String msg = ex.getMessage();
+ if (msg == null)
+ {
+ msg = ex.toString();
+ }
+ ViewUtility.popupErrorMessage(mbean.getInstanceName(), msg);
+ printStackTrace(ex);
+ }
+ }
+
+ }
+
+ /**
+ * Registers the notification listener with the MBeanServer
+ * @param mbean managed bean
+ * @param name notification name
+ * @param type notification type
+ * @throws Exception if server connection is broken or if listener could not be created
+ */
+ public static void createNotificationlistener(ManagedBean mbean, String name, String type)
+ throws 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 ManagementConsoleException("Server connection is broken");
+ }
+ mbsc.addNotificationListener(jmxbean.getObjectName(), serverRegistry.getNotificationListener(), null, null);
+ }
+
+ public static void removeNotificationListener(ManagedBean mbean, String name, String type) throws Exception
+ {
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
+ serverRegistry.removeNotificationListener(mbean, name, type);
+ }
+
+ /**
+ * Checks if the server registry contains attribute information for this mbean. If not then it queries the
+ * mbean server for complete mbean information, else it gets the latest value of the given attribute
+ * from mbean server.
+ * @return attribute data for the given mbean attribute
+ */
+ public static AttributeData getAttributeData(ManagedBean mbean, String attribute) throws Exception
+ {
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
+ ManagedAttributeModel attributeModel = serverRegistry.getAttributeModel(mbean);
+ if (attributeModel == null)
+ {
+ // If process is here, it means the mbeanInfo is not retrieved from mbean server even once for this mbean
+ getMBeanInfo(mbean);
+ }
+ else
+ {
+ // refresh attribute value from mbean server
+ refreshAttribute(mbean, attribute);
+ }
+ attributeModel = serverRegistry.getAttributeModel(mbean);
+ return attributeModel.getAttribute(attribute);
+ }
+
+ /**
+ * Retrieves the latest attribute value from mbean server for the given mbean attribute
+ * and also sets that value in the attribute model in the server registry
+ * @return latest attribute value for the given mbean attribute
+ */
+ public static Object refreshAttribute(ManagedBean mbean, String attribute) throws Exception
+ {
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
+ MBeanServerConnection mbsc = serverRegistry.getServerConnection();
+
+ if (mbsc == null)
+ {
+ throw new ManagementConsoleException("Server connection is broken");
+ }
+
+ Object value = mbsc.getAttribute(((JMXManagedObject)mbean).getObjectName(), attribute);
+ // update the attribute data in server registry for this attribute
+ ManagedAttributeModel attributeModel = serverRegistry.getAttributeModel(mbean);
+ attributeModel.setAttributeValue(attribute, value);
+ return value;
+ }
+
+
+ /**
+ * Returns a List of Object arrays containing the requested attribute values (in the same sequence requested) for each queue in the virtualhost.
+ * If a particular attribute cant be found or raises an mbean/reflection exception whilst being gathered its value is substituted with the String "-".
+ */
+ public static List<List<Object>> getQueueAttributes(List<ManagedBean> mbeans, String[] attributes)
+ {
+ List<List<Object>> results = new ArrayList<List<Object>>();
+
+ MBeanServerConnection mbsc = null;
+ if(mbeans.isEmpty())
+ {
+ return results;
+ }
+ else
+ {
+ ManagedBean mbean = mbeans.get(0);
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
+ mbsc = serverRegistry.getServerConnection();
+ }
+
+ if(mbsc == null)
+ {
+ return results;
+ }
+
+ for(ManagedBean mbean : mbeans)
+ {
+ HashMap<String,Object> tempResults = new HashMap<String,Object>();
+
+ ObjectName objName = ((JMXManagedObject)mbean).getObjectName();
+ try
+ {
+ AttributeList list = mbsc.getAttributes(objName, attributes);
+
+ for (Attribute attr : list.toArray(new Attribute[0]))
+ {
+ tempResults.put(attr.getName(), attr.getValue());
+ }
+
+ List<Object> attributeValues = new ArrayList<Object>(attributes.length);
+
+ for(int i = 0; i <attributes.length; i++)
+ {
+ if(tempResults.containsKey(attributes[i]))
+ {
+ attributeValues.add(tempResults.get(attributes[i]));
+ }
+ else
+ {
+ attributeValues.add("-");
+ }
+ }
+
+ results.add(attributeValues);
+ }
+ catch (Exception ignore)
+ {
+ continue;
+ }
+ }
+
+ return results;
+ }
+
+
+ /**
+ * Retrieves the attribute values from MBeanSever and stores in the server registry.
+ * @param mbean
+ * @return the attribute model
+ * @throws Exception if attributes can not be retrieved from MBeanServer
+ */
+ public static ManagedAttributeModel getAttributes(ManagedBean mbean) throws Exception
+ {
+ ObjectName objName = ((JMXManagedObject)mbean).getObjectName();
+ String[] attributes = null;
+ AttributeList list = null;
+
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
+ MBeanServerConnection mbsc = serverRegistry.getServerConnection();
+ MBeanAttributeInfo[] attributesInfo = null;
+ ManagedAttributeModel attributeModel = serverRegistry.getAttributeModel(mbean);
+
+ if (attributeModel == null)
+ {
+ // If the process is here, then it means the attribute values are not retrieved from mbean server
+ // even once for this mbean. Create attribute model, retrieve values from mbean server and
+ // set the attribute model in server registry for this mbean
+ 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]);
+ }
+
+ 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());
+ }
+ }
+
+ serverRegistry.setAttributeModel(mbean, attributeModel);
+ return attributeModel;
+ }
+
+ /**
+ * Updates the attribute value of an MBean
+ * @param mbean
+ * @param attribute
+ * @param value
+ * @throws Exception if MBeanServer throws exception in updating the attribute value
+ */
+ public static void updateAttribute(ManagedBean mbean, AttributeData attribute, String value) throws Exception
+ {
+ JMXManagedObject jmxbean = (JMXManagedObject)mbean;
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
+
+ MBeanServerConnection mbsc = serverRegistry.getServerConnection();
+
+ Object newValue = value;
+ if (attribute.getDataType().equals(Long.class.getName()))
+ {
+ if (MAX_LONG.compareTo(new BigInteger(value)) == -1)
+ {
+ throw new ManagementConsoleException("Entered value is too big for \"" +
+ ViewUtility.getDisplayText(attribute.getName()) + "\"");
+ }
+ newValue = Long.parseLong(value);
+ }
+ else if (attribute.getDataType().equals(Integer.class.getName()))
+ {
+ if (MAX_INT.compareTo(new BigInteger(value)) == -1)
+ {
+ throw new ManagementConsoleException("Entered value is too big for " + attribute.getName());
+ }
+ newValue = Integer.parseInt(value);
+ }
+ else if (attribute.getDataType().equals(Boolean.class.getName()))
+ {
+ if (!value.equalsIgnoreCase("true") && !value.equalsIgnoreCase("false"))
+ {
+ throw new ManagementConsoleException("Entered value was not true or false");
+ }
+
+ newValue = Boolean.valueOf(value);
+ }
+
+ mbsc.setAttribute(jmxbean.getObjectName(), new Attribute(attribute.getName(), newValue));
+ // Update the value in the registry, to avoid refreshing from mbsc
+ ManagedAttributeModel attributeModel = serverRegistry.getAttributeModel(mbean);
+ attributeModel.setAttributeValue(attribute.getName(), newValue);
+ }
+
+ /**
+ * populates the operation data model in server registry for given mbean
+ * @param mbean
+ * @return operation data model
+ */
+ public static OperationDataModel getOperations(ManagedBean mbean)
+ {
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
+ OperationDataModel dataModel = serverRegistry.getOperationModel(mbean);
+ if (dataModel == null)
+ {
+ // Create operation model and set it in server registry for this mbean
+ MBeanOperationInfo[] operationsInfo = serverRegistry.getMBeanInfo(mbean).getOperations();
+ dataModel = new OperationDataModel();
+
+ for (int i = 0; i < operationsInfo.length; i++)
+ {
+ dataModel.addOperation(operationsInfo[i]);
+ }
+
+ serverRegistry.setOperationModel(mbean, dataModel);
+ }
+ return dataModel;
+ }
+
+ /**
+ * populates the notification in the server registry for given mbean
+ * @param mbean
+ * @return notification info model
+ */
+ public static NotificationInfoModel[] getNotificationInfo(ManagedBean mbean)
+ {
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(mbean);
+ MBeanNotificationInfo[] info = serverRegistry.getMBeanInfo(mbean).getNotifications();
+
+ // Check if this mbean sends any notification
+ if (info == null || info.length == 0)
+ return null;
+
+ // Create notification model if not already set in the server registry for this mbean
+ 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()));
+ }
+
+ // Set the notification model in the server registry for this mbean
+ serverRegistry.setNotificationInfo(mbean, list);
+ return list.toArray(new NotificationInfoModel[0]);
+ }
+
+ /**
+ * Retrieves all the MBeans from mbean server for a given domain
+ * @return list of ManagedBeans
+ */
+ public static List<ManagedBean> getManagedObjectsForDomain(ManagedServer server, String domain) throws MalformedObjectNameException, NullPointerException, IOException
+ {
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(server);
+ return getManagedObjectsForDomain(server,serverRegistry, domain);
+ }
+
+ /**
+ * Retrieves all the MBeans from mbean server for a given domain
+ * @return list of ManagedBeans
+ */
+ public static List<ManagedBean> getManagedObjectsForDomain(ManagedServer server, JMXServerRegistry serverRegistry, String domain) throws MalformedObjectNameException, NullPointerException, IOException
+ {
+ List<ManagedBean> mbeans = new ArrayList<ManagedBean>();
+
+ MBeanServerConnection mbsc = serverRegistry.getServerConnection();
+ ObjectName objName = new ObjectName(domain + ":*");
+ Set objectInstances = mbsc.queryMBeans(objName, null);
+
+ for (Iterator itr = objectInstances.iterator(); itr.hasNext();)
+ {
+ ObjectInstance instance = (ObjectInstance)itr.next();
+ ManagedBean obj = new JMXManagedObject(instance.getObjectName());
+ mbeans.add(obj);
+ }
+
+ return mbeans;
+ }
+
+ /**
+ * Classifies the management API version of the given server
+ * @return list of ManagedBeans
+ * @throws NullPointerException
+ * @throws ManagementConsoleException
+ * @throws MalformedObjectNameException
+ * @throws IOException
+ */
+ public static void classifyManagementApiVersion(ManagedServer server, JMXServerRegistry serverRegistry)
+ throws MalformedObjectNameException, NullPointerException, IOException
+ {
+ MBeanServerConnection mbsc = serverRegistry.getServerConnection();
+
+ //Detect if the ServerInformation MBean is present, and use it to retrieve the API version.
+ ObjectName objName = new ObjectName(server.getDomain() + ":type="+ ServerInformation.TYPE + ",*");
+ Set<ObjectName> objectInstances = mbsc.queryNames(objName, null);
+
+ if(objectInstances.size() != 0)
+ {
+ for (Iterator<ObjectName> itr = objectInstances.iterator(); itr.hasNext();)
+ {
+ ObjectName instance = (ObjectName)itr.next();
+ ServerInformation simb = (ServerInformation)
+ MBeanServerInvocationHandler.newProxyInstance(mbsc,
+ instance, ServerInformation.class, false);
+
+ int major = simb.getManagementApiMajorVersion();
+ int minor = simb.getManagementApiMinorVersion();
+
+ serverRegistry.setManagementApiVersion(new ApiVersion(major, minor));
+ }
+
+ return;
+ }
+
+ //ServerInformation mbean was not present, so this is a older pre-v1.3 API server.
+
+ //Detect the value of the 'version' key property on the UserManagement MBean ObjectName.
+ //If present, we have a v1.2 API server. If null, we have a v1.1 API server.
+ ObjectName umMBeanObjectName = null;
+ List<ManagedBean> mbeans = getManagedObjectsForDomain(server, serverRegistry, Constants.DEFAULT_DOMAIN);
+ for(ManagedBean mbean: mbeans)
+ {
+ if("UserManagement".equalsIgnoreCase(mbean.getType()))
+ {
+ umMBeanObjectName = ((JMXManagedObject) mbean).getObjectName();
+ break;
+ }
+ }
+
+ if(umMBeanObjectName != null)
+ {
+ //UserManagement MBean was present, determine if it has a version key
+ if(umMBeanObjectName.getKeyProperty("version") != null)
+ {
+ serverRegistry.setManagementApiVersion(new ApiVersion(1, 2));
+ }
+ else
+ {
+ //no version key,
+ serverRegistry.setManagementApiVersion(new ApiVersion(1, 1));
+ }
+
+ return;
+ }
+
+ //UserManagement MBean was not present, connected to an old server: classify as v1.0 API
+ serverRegistry.setManagementApiVersion(new ApiVersion(1, 0));
+ }
+
+ public static void printOutput(String statement)
+ {
+ if (ApplicationRegistry.debug)
+ {
+ System.out.println(statement);
+ }
+ }
+
+ public static void printStackTrace(Throwable ex)
+ {
+ if (ApplicationRegistry.debug)
+ {
+ ex.printStackTrace();
+ }
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/AttributeData.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/AttributeData.java
new file mode 100644
index 0000000000..ccd4cf8df8
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/AttributeData.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.model;
+
+public class AttributeData
+{
+ String name = "";
+ String description = "";
+ String dataType = "";
+ Object value = "";
+ 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)
+ {
+ if (value != null)
+ 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/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/ManagedAttributeModel.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/ManagedAttributeModel.java
new file mode 100644
index 0000000000..b3219f15ea
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/ManagedAttributeModel.java
@@ -0,0 +1,118 @@
+/*
+ *
+ * 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 AttributeData getAttribute(String name)
+ {
+ return _attributeMap.get(name);
+ }
+
+ public int getCount()
+ {
+ return _attributeMap.size();
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationInfoModel.java b/qpid/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/qpid/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/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationObject.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationObject.java
new file mode 100644
index 0000000000..35cc9f6e27
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/NotificationObject.java
@@ -0,0 +1,132 @@
+/*
+ *
+ * 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;
+
+import javax.management.ObjectName;
+
+import static org.apache.qpid.management.ui.Constants.VIRTUAL_HOST;
+
+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 getSourceName()
+ {
+ if (_source instanceof ObjectName)
+ {
+ return unquote(((ObjectName)_source).getKeyProperty("name"));
+ }
+
+ return null;
+ }
+
+ public String getSourceVirtualHost()
+ {
+ if (_source instanceof ObjectName)
+ {
+ return unquote(((ObjectName)_source).getKeyProperty(VIRTUAL_HOST));
+ }
+
+ return null;
+ }
+
+ private String unquote(String value)
+ {
+ if(value != null)
+ {
+ try
+ {
+ //if the value is quoted in the ObjectName, unquote it
+ value = ObjectName.unquote(value);
+ }
+ catch(IllegalArgumentException e)
+ {
+ //ignore, this just means the value is not quoted
+ //and can be left unchanged
+ }
+ }
+
+ return value;
+ }
+
+ 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/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationData.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationData.java
new file mode 100644
index 0000000000..bf3b730b3e
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationData.java
@@ -0,0 +1,110 @@
+/*
+ *
+ * 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;
+ }
+
+ public boolean isReturnTypeBoolean()
+ {
+ return (_returnType.equals("boolean") || _returnType.equals("java.lang.Boolean"));
+ }
+
+ public boolean isReturnTypeVoid()
+ {
+ return (_returnType.equals("void") || _returnType.equals("java.lang.Void"));
+ }
+
+ public Object getParameterValue(String paramName)
+ {
+ if (_parameters == null)
+ {
+ return null;
+ }
+
+ for (int i = 0; i < _parameters.size(); i++)
+ {
+ if (paramName.equalsIgnoreCase(_parameters.get(i).getName()))
+ {
+ return _parameters.get(i).getValue();
+ }
+ }
+
+ return null;
+ }
+} \ No newline at end of file
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationDataModel.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationDataModel.java
new file mode 100644
index 0000000000..96964a81ef
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/OperationDataModel.java
@@ -0,0 +1,72 @@
+/*
+ *
+ * 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(), paramInfo.getDescription(),
+ 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/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/ParameterData.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/ParameterData.java
new file mode 100644
index 0000000000..d12217c6eb
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/model/ParameterData.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;
+
+/**
+ * Class representing an mbean operation parameter
+ * @author Bhupendra Bhardwaj
+ */
+public class ParameterData
+{
+ private String _name;
+ private String _description;
+ private String _type;
+ private Object _value;
+
+ ParameterData(String name, String desc, String type)
+ {
+ this._name = name;
+ this._description = desc;
+ this._type = type;
+ setDefaultValue();
+ }
+
+ public String getDescription()
+ {
+ return _description;
+ }
+
+ public String getName()
+ {
+ return _name;
+ }
+
+ public String getType()
+ {
+ return _type;
+ }
+
+ public Object getValue()
+ {
+ return _value;
+ }
+
+ public void setValueFromString(String strValue)
+ {
+ if ("int".equals(_type))
+ _value = Integer.parseInt(strValue);
+ else if (isBoolean())
+ _value = Boolean.valueOf(strValue);
+ else if ("long".equals(_type))
+ _value = Long.parseLong(strValue);
+ else
+ _value = strValue;
+ }
+
+ public void setValue(Object value)
+ {
+ this._value = value;
+ }
+
+ public boolean isBoolean()
+ {
+ return (_type.equals("boolean") || _type.equals("java.lang.Boolean"));
+ }
+
+ public void setDefaultValue()
+ {
+ if (isBoolean())
+ {
+ _value = Boolean.valueOf("false");
+ }
+ else
+ {
+ _value = null;
+ }
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/AttributesTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/AttributesTabControl.java
new file mode 100644
index 0000000000..2b9f5042dc
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/AttributesTabControl.java
@@ -0,0 +1,922 @@
+/*
+ *
+ * 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 static org.apache.qpid.management.ui.Constants.*;
+
+import org.apache.qpid.management.ui.ApplicationRegistry;
+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.jface.viewers.ViewerSorter;
+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.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.FormToolkit;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+
+
+/**
+ * Creates controller composite for the attribute's tab.
+ * @author Bhupendra Bhardwaj
+ */
+public class AttributesTabControl extends TabControl
+{
+ private FormToolkit _toolkit;
+ private ScrolledForm _form;
+ private Table _table = null;
+ private TableViewer _tableViewer = null;
+ private int[] tableWidths = new int[] {275, 275};
+
+ private Composite _tableComposite = null;
+ private Composite _buttonsComposite = null;
+
+ private DisposeListener tableDisposeListener = new DisposeListenerImpl();
+ final Image image;
+ private Button _detailsButton = null;
+ private Button _editButton = null;
+ private Button _graphButton = 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;
+
+ public AttributesTabControl(TabFolder tabFolder)
+ {
+ super(tabFolder);
+ _toolkit = new FormToolkit(_tabFolder.getDisplay());
+ _form = _toolkit.createScrolledForm(_tabFolder);
+ GridLayout gridLayout = new GridLayout(2, false);
+ gridLayout.marginWidth = 0;
+ gridLayout.marginHeight = 0;
+ _form.getBody().setLayout(gridLayout);
+ _tableComposite = _toolkit.createComposite(_form.getBody());
+ _tableComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ _tableComposite.setLayout(new GridLayout());
+ _buttonsComposite = _toolkit.createComposite(_form.getBody());
+ _buttonsComposite.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, true));
+ _buttonsComposite.setLayout(new GridLayout());
+
+ image = Display.getCurrent().getSystemImage(SWT.ICON_INFORMATION);
+ createWidgets();
+ }
+
+ /**
+ * @see TabControl#getControl()
+ */
+ public Control getControl()
+ {
+ return _form;
+ }
+
+ /**
+ * Creates required widgets for Attribute's tab
+ */
+ protected void createWidgets()
+ {
+ createTable();
+ createTableViewer();
+ createButtons();
+ addTableListeners();
+ }
+
+ /**
+ * Creates table for listing the MBean attributes
+ */
+ private void createTable()
+ {
+ _table = _toolkit.createTable(_tableComposite, SWT.FULL_SELECTION);
+ GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+ _table.setLayoutData(gridData);
+
+ for (int i = 0; i < ATTRIBUTE_TABLE_TITLES.size(); ++i)
+ {
+ final TableColumn column = new TableColumn(_table, SWT.NONE);
+ column.setText(ATTRIBUTE_TABLE_TITLES.get(i));
+ column.setWidth(tableWidths[i]);
+ column.setResizable(true);
+ }
+
+ _table.setLinesVisible (true);
+ _table.setHeaderVisible (true);
+ }
+
+ /**
+ * Creates tableviewer for the attribute's table
+ */
+ private void createTableViewer()
+ {
+ _tableViewer = new TableViewer(_table);
+ _tableViewer.setUseHashlookup(true);
+ _tableViewer.setColumnProperties(
+ ATTRIBUTE_TABLE_TITLES.toArray(new String[ATTRIBUTE_TABLE_TITLES.size()]));
+ _tableViewer.setContentProvider(new ContentProviderImpl());
+ _tableViewer.setLabelProvider(new LabelProviderImpl());
+ _tableViewer.setSorter(new ViewerSorterImpl());
+ }
+
+ private void createButtons()
+ {
+ addDetailsButton();
+ addEditButton();
+ addGraphButton();
+ }
+
+ private void addDetailsButton()
+ {
+ // Create and configure the button for attribute details
+ _detailsButton = _toolkit.createButton(_buttonsComposite, BUTTON_DETAILS, SWT.PUSH | SWT.CENTER);
+ _detailsButton.setFont(ApplicationRegistry.getFont(FONT_BUTTON));
+ GridData gridData = new GridData(SWT.FILL, SWT.TOP, false, 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();
+ }
+ });
+ }
+
+ /**
+ * Creates the button for editing attributes.
+ */
+ private void addEditButton()
+ {
+ // Create and configure the button for editing attribute
+ _editButton = _toolkit.createButton(_buttonsComposite, BUTTON_EDIT_ATTRIBUTE, SWT.PUSH | SWT.CENTER);
+ _editButton.setFont(ApplicationRegistry.getFont(FONT_BUTTON));
+ GridData gridData = new GridData(SWT.FILL, SWT.TOP, false, 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();
+ }
+ });
+ }
+
+ /**
+ * Creates the button for viewing Graphs
+ */
+ private void addGraphButton()
+ {
+ _graphButton = _toolkit.createButton(_buttonsComposite, BUTTON_GRAPH, SWT.PUSH | SWT.CENTER);
+ _graphButton.setFont(ApplicationRegistry.getFont(FONT_BUTTON));
+ GridData gridData = new GridData(SWT.FILL, SWT.TOP, false, 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 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;
+ }
+ });
+ }
+
+ /**
+ * Listeners implementation class for showing table tooltip
+ * @author Bhupendra Bhardwaj
+ */
+ 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
+
+ /**
+ * Creates pop-up window for showing attribute details
+ * @param data - Selectes attribute
+ */
+ public void createDetailsPopup(AttributeData data)
+ {
+ int width = 500;
+ int height = 250;
+ if (!isSimpleType(data.getValue()))
+ {
+ 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();
+ }
+
+ /**
+ * Listener class for table tooltip label
+ */
+ 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;
+ }
+ }
+ };
+
+
+ /**
+ * Create the contents for the attribute details window pop-up
+ * @param shell - The shell that will be filled with details.
+ * @param attribute - Selected attribute
+ */
+ 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 = _toolkit.createComposite(shell, SWT.NONE);
+ parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ parent.setLayout(layout);
+
+ // Name
+ Label label = _toolkit.createLabel(parent, ATTRIBUTE_TABLE_TITLES.get(0), SWT.NONE);
+ GridData layoutData = new GridData(SWT.TRAIL, SWT.TOP, false, false);
+ label.setLayoutData(layoutData);
+ int textStyle = SWT.BEGINNING | SWT.BORDER |SWT.READ_ONLY;
+ Text value = _toolkit.createText(parent, ViewUtility.getDisplayText(attribute.getName()), textStyle);
+ value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+
+
+ // Description
+ label = _toolkit.createLabel(parent, DESCRIPTION, SWT.NONE);
+ label.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, false, false));
+ value = _toolkit.createText(parent, attribute.getDescription(), textStyle);
+ value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+
+ // value
+ label = _toolkit.createLabel(parent, ATTRIBUTE_TABLE_TITLES.get(1), SWT.NONE);
+ label.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, false, false));
+
+ if (!attribute.isReadable())
+ {
+ value = _toolkit.createText(parent, "", textStyle);
+ value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ }
+ else
+ {
+ if (!isSimpleType(attribute.getValue()))
+ {
+ if (attribute.getValue() instanceof String[])
+ {
+ String result = "";
+ for(String val : (String[]) attribute.getValue()){
+ result = result.concat(val+ "; ");
+ }
+ value = _toolkit.createText(parent, "", textStyle);
+
+ value.setText(result);
+ value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ }
+ else
+ {
+ Composite composite = new Composite(parent, SWT.BORDER);
+ composite.setLayout(new GridLayout());
+ composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+ ViewUtility.populateCompositeWithData(_toolkit, composite, attribute.getValue());
+ }
+ }
+ else
+ {
+ if (attribute.isWritable())
+ {
+ value = _toolkit.createText(parent, "", SWT.BEGINNING | SWT.BORDER);
+ if(attribute.isNumber())
+ {
+ value.addVerifyListener(new NumberVerifyListener());
+ }
+
+ // set data to access in the listener
+ parent.setData(attribute);
+ }
+ else
+ {
+ value = _toolkit.createText(parent, "", textStyle);
+ }
+
+ 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);
+ }
+ }
+
+ /**
+ * Create the button for updating attributes. This should be enabled for writable attribute
+ */
+ 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(BUTTON_UPDATE, updateButton);
+
+ updateButton.setText(BUTTON_UPDATE);
+ 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)
+ {
+ try
+ {
+ Button button = (Button)event.widget;
+ Text text = (Text)button.getData();
+ AttributeData data = (AttributeData)button.getParent().getData();
+ MBeanUtility.updateAttribute(_mbean, data, text.getText());
+ button.getShell().close();
+ refresh(_mbean);
+ }
+ catch (Exception ex)
+ {
+ MBeanUtility.handleException(_mbean, ex);
+ }
+ }
+ });
+
+ return updateButton;
+ }
+
+ /**
+ * 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 = null;
+ try
+ {
+ attributesList = MBeanUtility.getAttributes(mbean);
+ }
+ catch(Exception ex)
+ {
+ MBeanUtility.handleException(_mbean, ex);
+ }
+ _tableViewer.setInput(attributesList);
+ checkForEnablingButtons(getSelectionAttribute());
+
+ _form.layout(true);
+ _form.getBody().layout(true, true);
+ }
+
+ /**
+ * @see TabControl#setFocus()
+ */
+ public void setFocus()
+ {
+ _table.setFocus();
+ }
+
+ /**
+ * Checks which buttons are to be enabled or disabled. The graph button will be enabled only
+ * for readable number attributes. Editing is enabled for writeable attribtues.
+ * @param attribute
+ */
+ private void checkForEnablingButtons(AttributeData attribute)
+ {
+ if (attribute == null)
+ {
+ _detailsButton.setEnabled(false);
+ _editButton.setEnabled(false);
+ _graphButton.setEnabled(false);
+ return;
+ }
+
+ _detailsButton.setEnabled(true);
+ if (attribute.isWritable())
+ {
+ _editButton.setEnabled(true);
+ _graphButton.setEnabled(false);
+ }
+ else
+ {
+ _editButton.setEnabled(false);
+ // Currently only Queues are having attributes, which are suitable for a graph
+ if (attribute.isNumber() && _mbean.isQueue())
+ {
+ _graphButton.setEnabled(true);
+ }
+ else
+ {
+ _graphButton.setEnabled(false);
+ }
+ }
+ }
+
+ /**
+ * Creates graph in a pop-up window for given attribute.
+ * @param data
+ */
+ 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(TIMER_INTERVAL, this);
+ }
+ catch(Exception ex)
+ {
+ MBeanUtility.handleException(ex);
+ }
+ }
+ };
+
+ // Launch the timer
+ display.timerExec(TIMER_INTERVAL, runnable);
+
+ while (!shell.isDisposed())
+ {
+ if (!display.readAndDispatch())
+ {
+ display.sleep();
+ }
+ }
+
+ // Kill the timer
+ display.timerExec(-1, runnable);
+ shell.dispose();
+ }
+
+ /**
+ * @return selected attribute in the table
+ */
+ public AttributeData getSelectionAttribute()
+ {
+ int index = _table.getSelectionIndex();
+ if (index == -1)
+ return null;
+
+ return (AttributeData)_table.getItem(index).getData();
+ }
+
+ /**
+ * checks for newer values of selected attribute to update the graph
+ * @param canvas
+ * @param data
+ * @throws Exception
+ */
+ private void animate(Canvas canvas, AttributeData data) throws Exception
+ {
+ String attribute = data.getName();
+ Object valueObj = MBeanUtility.refreshAttribute(_mbean, attribute);
+ int value = Integer.parseInt(String.valueOf(valueObj));
+ 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();
+ }
+
+ /**
+ * @param maxAttributeValue
+ * @return dynamically calculated value for y-axis on the graph
+ */
+ 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;
+ }
+
+ /**
+ * Content Provider class for the table viewer
+ * @author Bhupendra Bhardwaj
+ */
+ private static 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();
+ }
+ }
+
+ /**
+ * Label Provider class for the table viewer
+ * @author Bhupendra Bhardwaj
+ */
+ 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)
+ if (attribute.getValue() instanceof String[])
+ {
+ for(String val : (String[]) attribute.getValue()){
+ result = result.concat(val+ "; ");
+ }
+ }
+ else
+ {
+ 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(FONT_TABLE_CELL);
+ }
+
+ public Color getForeground(Object element)
+ {
+ attribute = (AttributeData) element;
+ if (attribute.isWritable())
+ return Display.getCurrent().getSystemColor(SWT.COLOR_BLUE);
+ else
+ return Display.getCurrent().getSystemColor(SWT.COLOR_BLACK);
+ }
+ public Color getBackground(Object element)
+ {
+ return _form.getBackground();
+ }
+ }
+
+ private static class DisposeListenerImpl implements DisposeListener
+ {
+ public void widgetDisposed(DisposeEvent e)
+ {
+
+ }
+ }
+
+ /**
+ * Sorter class for the table viewer. It sorts the table for according to attribute name.
+ * @author Bhupendra Bhardwaj
+ *
+ */
+ private static class ViewerSorterImpl extends ViewerSorter
+ {
+ public int compare(Viewer viewer, Object o1, Object o2)
+ {
+ AttributeData attribtue1 = (AttributeData)o1;
+ AttributeData attribtue2 = (AttributeData)o2;
+
+ return collator.compare(attribtue1.getName(), attribtue2.getName());
+ }
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/INotificationViewer.java b/qpid/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/qpid/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/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanTabFolderFactory.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanTabFolderFactory.java
new file mode 100644
index 0000000000..527fc67be3
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanTabFolderFactory.java
@@ -0,0 +1,466 @@
+/*
+ *
+ * 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 static org.apache.qpid.management.ui.Constants.ATTRIBUTES;
+import static org.apache.qpid.management.ui.Constants.CONNECTION;
+import static org.apache.qpid.management.ui.Constants.EXCHANGE;
+import static org.apache.qpid.management.ui.Constants.EXCHANGE_TYPE;
+import static org.apache.qpid.management.ui.Constants.NOTIFICATIONS;
+import static org.apache.qpid.management.ui.Constants.QUEUE;
+
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.management.MBeanServerConnection;
+
+import org.apache.qpid.management.ui.ApplicationRegistry;
+import org.apache.qpid.management.ui.ManagedServer;
+import org.apache.qpid.management.ui.ServerRegistry;
+import org.apache.qpid.management.ui.jmx.JMXManagedObject;
+import org.apache.qpid.management.ui.jmx.MBeanUtility;
+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.views.queue.QueueOperationsTabControl;
+import org.apache.qpid.management.ui.views.type.ConnectionTypeTabControl;
+import org.apache.qpid.management.ui.views.type.ExchangeTypeTabControl;
+import org.apache.qpid.management.ui.views.type.QueueTypeTabControl;
+import org.apache.qpid.management.ui.views.users.UserManagementTabControl;
+import org.apache.qpid.management.ui.views.vhost.VHostTabControl;
+import org.apache.qpid.management.ui.views.connection.ConnectionOperationsTabControl;
+import org.apache.qpid.management.ui.views.exchange.ExchangeOperationsTabControl;
+import org.apache.qpid.management.ui.views.exchange.HeadersExchangeOperationsTabControl;
+import org.apache.qpid.management.ui.views.logging.ConfigurationFileTabControl;
+import org.apache.qpid.management.ui.views.logging.RuntimeTabControl;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FormAttachment;
+import org.eclipse.swt.layout.FormData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.TabItem;
+
+public class MBeanTabFolderFactory
+{
+ private static final String MBEANTYPE_QUEUE = "VirtualHost.Queue";
+ private static final String MBEANTYPE_CONNECTION = "VirtualHost.Connection";
+ private static final String MBEANTYPE_EXCHANGE = "VirtualHost.Exchange";
+ private static final String MBEANTYPE_VHOST_MANAGER = "VirtualHost.VirtualHostManager";
+ private static final String MBEANTYPE_LOGGING_MANAGEMENT = "LoggingManagement";
+ private static final String MBEANTYPE_USER_MANAGEMENT = "UserManagement";
+ private static final String MBEANTYPE_CONFIGURATION_MANAGEMENT = "ConfigurationManagement";
+
+ private MBeanTabFolderFactory()
+ {
+ //no instances
+ }
+
+ public static TabFolder generateMBeanTabFolder(final Composite parent, final JMXManagedObject mbean, final MBeanServerConnection mbsc)
+ {
+ TabFolder tabFolder = new TabFolder(parent, 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);
+
+ TabItem tab;
+ TabControl controller;
+ QpidMBeanType mbeanType = QpidMBeanType.get(mbean.getType());
+
+ switch(mbeanType)
+ {
+ case QUEUE:
+ createAttributesTab(tabFolder, mbean);
+
+ tab = new TabItem(tabFolder, SWT.NONE);
+ tab.setText("Operations");
+ controller = new QueueOperationsTabControl(tabFolder, mbean, mbsc);
+ tab.setControl(controller.getControl());
+ tab.setData(TabControl.CONTROLLER, controller);
+ break;
+ case CONNECTION:
+ createAttributesTab(tabFolder, mbean);
+
+ tab = new TabItem(tabFolder, SWT.NONE);
+ tab.setText("Operations");
+ controller = new ConnectionOperationsTabControl(tabFolder, mbean, mbsc);
+ tab.setControl(controller.getControl());
+ tab.setData(TabControl.CONTROLLER, controller);
+ break;
+ case EXCHANGE:
+ createAttributesTab(tabFolder, mbean);
+
+ if (mbean.getProperty(EXCHANGE_TYPE).equalsIgnoreCase("headers"))
+ {
+ tab = new TabItem(tabFolder, SWT.NONE);
+ tab.setText("Operations");
+ controller = new HeadersExchangeOperationsTabControl(tabFolder, mbean, mbsc);
+ tab.setControl(controller.getControl());
+ tab.setData(TabControl.CONTROLLER, controller);
+ }
+ else
+ {
+ tab = new TabItem(tabFolder, SWT.NONE);
+ tab.setText("Operations");
+ controller = new ExchangeOperationsTabControl(tabFolder, mbean, mbsc);
+ tab.setControl(controller.getControl());
+ tab.setData(TabControl.CONTROLLER, controller);
+ }
+ break;
+ case VHOST_MANAGER:
+ createAttributesTab(tabFolder, mbean);
+
+ tab = new TabItem(tabFolder, SWT.NONE);
+ tab.setText("Operations");
+ controller = new VHostTabControl(tabFolder, mbean, mbsc);
+ tab.setControl(controller.getControl());
+ tab.setData(TabControl.CONTROLLER, controller);
+ break;
+ case LOGGING_MANAGEMENT:
+ tab = new TabItem(tabFolder, SWT.NONE);
+ tab.setText("Runtime Options");
+ controller = new RuntimeTabControl(tabFolder, mbean, mbsc);
+ tab.setControl(controller.getControl());
+ tab.setData(TabControl.CONTROLLER, controller);
+
+ tab = new TabItem(tabFolder, SWT.NONE);
+ tab.setText("ConfigurationFile Options");
+ controller = new ConfigurationFileTabControl(tabFolder, mbean, mbsc);
+ tab.setControl(controller.getControl());
+ tab.setData(TabControl.CONTROLLER, controller);
+ break;
+ case USER_MANAGEMENT:
+ tab = new TabItem(tabFolder, SWT.NONE);
+ tab.setText("Operations");
+ controller = new UserManagementTabControl(tabFolder, mbean, mbsc);
+ tab.setControl(controller.getControl());
+ tab.setData(TabControl.CONTROLLER, controller);
+ break;
+ case CONFIGURATION_MANAGEMENT:
+ createGenericTabFolder(tabFolder, mbean);
+ break;
+ case UNKNOWN:
+ createGenericTabFolder(tabFolder, mbean);
+ break;
+ }
+
+ createNotificationsTabIfNecessary(tabFolder, mbean);
+
+ tabFolder.addListener(SWT.Selection, new Listener()
+ {
+ public void handleEvent(Event evt)
+ {
+ TabItem tab = (TabItem)evt.item;
+ TabControl controller = (TabControl)tab.getData(TabControl.CONTROLLER);
+ if(controller != null)
+ {
+ controller.refresh(mbean);
+ }
+ }
+ });
+
+ return tabFolder;
+ }
+
+ private static void createGenericTabFolder(TabFolder tabFolder, JMXManagedObject mbean)
+ {
+ createAttributesTab(tabFolder, mbean);
+ createOperationTabs(tabFolder, mbean);
+ }
+
+ private static void createAttributesTab(TabFolder tabFolder, JMXManagedObject mbean)
+ {
+ ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(mbean);
+ if(serverRegistry.getAttributeModel(mbean).getCount() == 0)
+ {
+ return;
+ }
+
+ TabItem tab = new TabItem(tabFolder, SWT.NONE);
+ tab.setText(ATTRIBUTES);
+ AttributesTabControl controller = new AttributesTabControl(tabFolder);
+ tab.setControl(controller.getControl());
+ tab.setData(TabControl.CONTROLLER, controller);
+ }
+
+ private static void createOperationTabs(TabFolder tabFolder, JMXManagedObject mbean)
+ {
+ ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(mbean);
+ int operationsCount = serverRegistry.getOperationModel(mbean).getCount();
+ if(operationsCount == 0)
+ {
+ return;
+ }
+
+ 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);
+ OperationTabControl control = new OperationTabControl(tabFolder, operationData);
+ operationTab.setData(TabControl.CONTROLLER, control);
+ operationTab.setControl(control.getControl());
+ }
+ }
+
+ private static void createNotificationsTabIfNecessary(TabFolder tabFolder, JMXManagedObject mbean)
+ {
+ NotificationInfoModel[] items = MBeanUtility.getNotificationInfo(mbean);
+ if(items == null || items.length == 0)
+ {
+ //the mbean has no notifications to subscribe for, do not create the tab.
+ return;
+ }
+
+ NotificationsTabControl controller = new NotificationsTabControl(tabFolder, mbean);
+
+ TabItem tab = new TabItem(tabFolder, SWT.NONE);
+ tab.setText(NOTIFICATIONS);
+ tab.setData(TabControl.CONTROLLER, controller);
+ tab.setControl(controller.getControl());
+ }
+
+ /**
+ * Creates TabFolder and tabs for all mbeantype (Connection, Queue, and Exchange)
+ */
+ public static TabFolder generateMBeanTypeTabFolder(final Composite parent, ManagedServer server, String virtualHost)
+ {
+ TabFolder tabFolder = new TabFolder(parent, 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);
+
+
+ TabItem tab;
+ TabControl controller;
+
+ tab = new TabItem(tabFolder, SWT.NONE);
+ tab.setText(CONNECTION);
+ controller = new ConnectionTypeTabControl(tabFolder,server,virtualHost);
+ tab.setData(TabControl.CONTROLLER, controller);
+ tab.setControl(controller.getControl());
+
+ tab = new TabItem(tabFolder, SWT.NONE);
+ tab.setText(EXCHANGE);
+ controller = new ExchangeTypeTabControl(tabFolder,server,virtualHost);
+ tab.setData(TabControl.CONTROLLER, controller);
+ tab.setControl(controller.getControl());
+
+ tab = new TabItem(tabFolder, SWT.NONE);
+ tab.setText(QUEUE);
+ controller = new QueueTypeTabControl(tabFolder,server,virtualHost);
+ tab.setData(TabControl.CONTROLLER, controller);
+ tab.setControl(controller.getControl());
+
+ tabFolder.addListener(SWT.Selection, new Listener()
+ {
+ public void handleEvent(Event evt)
+ {
+ TabItem tab = (TabItem)evt.item;
+ TabControl controller = (TabControl)tab.getData(TabControl.CONTROLLER);
+ if(controller != null)
+ {
+ controller.refresh(null);
+ }
+ }
+ });
+
+ return tabFolder;
+ }
+
+ /**
+ * Creates TabFolder and tab for the Connection selection view
+ */
+ public static TabFolder generateConnectionTypeTabFolder(final Composite parent, ManagedServer server, String virtualHost)
+ {
+ TabFolder tabFolder = new TabFolder(parent, 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);
+
+ TabItem tab;
+ TabControl controller;
+
+ tab = new TabItem(tabFolder, SWT.NONE);
+ tab.setText(CONNECTION);
+ controller = new ConnectionTypeTabControl(tabFolder,server,virtualHost);
+ tab.setData(TabControl.CONTROLLER, controller);
+ tab.setControl(controller.getControl());
+
+ tabFolder.addListener(SWT.Selection, new Listener()
+ {
+ public void handleEvent(Event evt)
+ {
+ TabItem tab = (TabItem)evt.item;
+ TabControl controller = (TabControl)tab.getData(TabControl.CONTROLLER);
+ if(controller != null)
+ {
+ controller.refresh(null);
+ }
+ }
+ });
+
+ return tabFolder;
+ }
+
+ /**
+ * Creates TabFolder and tab for the Exchange selection view
+ */
+ public static TabFolder generateExchangeTypeTabFolder(final Composite parent, ManagedServer server, String virtualHost)
+ {
+ TabFolder tabFolder = new TabFolder(parent, 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);
+
+ TabItem tab;
+ TabControl controller;
+
+ tab = new TabItem(tabFolder, SWT.NONE);
+ tab.setText(EXCHANGE);
+ controller = new ExchangeTypeTabControl(tabFolder,server,virtualHost);
+ tab.setData(TabControl.CONTROLLER, controller);
+ tab.setControl(controller.getControl());
+
+ tabFolder.addListener(SWT.Selection, new Listener()
+ {
+ public void handleEvent(Event evt)
+ {
+ TabItem tab = (TabItem)evt.item;
+ TabControl controller = (TabControl)tab.getData(TabControl.CONTROLLER);
+ if(controller != null)
+ {
+ controller.refresh(null);
+ }
+ }
+ });
+
+ return tabFolder;
+ }
+
+ /**
+ * Creates TabFolder and tab for the Queue selection view
+ */
+ public static TabFolder generateQueueTypeTabFolder(final Composite parent, ManagedServer server, String virtualHost)
+ {
+ TabFolder tabFolder = new TabFolder(parent, 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);
+
+ TabItem tab;
+ TabControl controller;
+
+ tab = new TabItem(tabFolder, SWT.NONE);
+ tab.setText(QUEUE);
+ controller = new QueueTypeTabControl(tabFolder,server,virtualHost);
+ tab.setData(TabControl.CONTROLLER, controller);
+ tab.setControl(controller.getControl());
+
+ tabFolder.addListener(SWT.Selection, new Listener()
+ {
+ public void handleEvent(Event evt)
+ {
+ TabItem tab = (TabItem)evt.item;
+ TabControl controller = (TabControl)tab.getData(TabControl.CONTROLLER);
+ if(controller != null)
+ {
+ controller.refresh(null);
+ }
+ }
+ });
+
+ return tabFolder;
+ }
+
+ private enum QpidMBeanType
+ {
+ QUEUE (MBEANTYPE_QUEUE),
+ CONNECTION (MBEANTYPE_CONNECTION),
+ EXCHANGE (MBEANTYPE_EXCHANGE),
+ VHOST_MANAGER (MBEANTYPE_VHOST_MANAGER),
+ LOGGING_MANAGEMENT (MBEANTYPE_LOGGING_MANAGEMENT),
+ USER_MANAGEMENT (MBEANTYPE_USER_MANAGEMENT),
+ CONFIGURATION_MANAGEMENT (MBEANTYPE_CONFIGURATION_MANAGEMENT),
+ UNKNOWN (null);
+
+ private static final Map<String,QpidMBeanType> lookup = new HashMap<String,QpidMBeanType>();
+
+ static
+ {
+ for(QpidMBeanType m : EnumSet.allOf(QpidMBeanType.class))
+ {
+ lookup.put(m.getType(), m);
+ }
+ }
+
+ private String type;
+
+ private QpidMBeanType()
+ {
+
+ }
+
+ private QpidMBeanType(String type)
+ {
+ this.type = type;
+ }
+
+ public String getType()
+ {
+ return type;
+ }
+
+ public static QpidMBeanType get(String type)
+ {
+ QpidMBeanType t= lookup.get(type);
+ if (t != null)
+ {
+ return t;
+ }
+ else
+ {
+ return UNKNOWN;
+ }
+
+ }
+ }
+
+
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanView.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanView.java
new file mode 100644
index 0000000000..65615a6d18
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/MBeanView.java
@@ -0,0 +1,605 @@
+/*
+ *
+ * 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.LinkedList;
+
+import javax.management.MBeanServerConnection;
+
+import static org.apache.qpid.management.ui.Constants.*;
+
+import org.apache.qpid.management.ui.ApiVersion;
+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.ServerRegistry;
+import org.apache.qpid.management.ui.actions.BackAction;
+import org.apache.qpid.management.ui.jmx.JMXManagedObject;
+import org.apache.qpid.management.ui.jmx.JMXServerRegistry;
+import org.apache.qpid.management.ui.jmx.MBeanUtility;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.swt.SWT;
+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.widgets.Composite;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.TabItem;
+import org.eclipse.ui.IActionBars;
+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;
+
+/**
+ * MBean View create appropriate view based on the user selection on the Navigation View.
+ */
+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 String _formText = APPLICATION_NAME;
+ private static ManagedServer _server = null;
+ private TreeObject _selectedNode = null;
+ private ManagedBean _mbean = null;
+ private static String _virtualHostName = null;
+ private static MBeanServerConnection _mbsc = null;
+ private TabFolder _tabFolder = null;
+ private ISelectionListener _selectionListener = new SelectionListenerImpl();
+
+ // TabFolder to list all the mbeans for a given mbeantype(eg Connection, Queue, Exchange)
+ private TabFolder _typeTabFolder = null;
+
+ private TabFolder _notificationTabFolder = null;
+
+ private LinkedList<Object> _backHistory;
+ private BackAction _backAction;
+
+ /*
+ * 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;
+ _selectedNode = (TreeObject)ss.getFirstElement();
+
+
+ // mbean should be set to null. A selection done on the navigation view can be either an mbean or
+ // an mbeantype. For mbeantype selection(eg Connection, Queue, Exchange) _mbean will remain null.
+ _mbean = null;
+ clearView();
+
+ //clear the back history, it is only for use when opening subsequent mbeans not in the nav tree
+ _backHistory.clear();
+ _backAction.setEnabled(false);
+
+ // If a selected node(mbean) gets unregistered from mbean server, mbeanview should
+ // make the tabfolber for that mbean invisible
+ if (_selectedNode == null)
+ {
+ return;
+ }
+
+ setServer();
+
+ if(!ApplicationRegistry.isServerConnected(_server))
+ {
+ return;
+ }
+
+ if (MBEAN.equals(_selectedNode.getType()))
+ {
+ _mbean = (ManagedBean)_selectedNode.getManagedObject();
+ }
+
+ setFormTitle();
+ showRelevantTabView();
+ }
+ }
+
+ public void openMBean(ManagedBean mbean)
+ {
+ openMBean(mbean, false);
+ }
+
+ private void openMBean(ManagedBean mbean, boolean undoing)
+ {
+ if(mbean == null)
+ {
+ return;
+ }
+
+ //if an mbean is about to be opened (but not returning to using back) from the mbean view,
+ //then record the current viewed area/object as a means of back history
+ if(!undoing)
+ {
+ if(_backHistory.isEmpty())
+ {
+ //ensure the button is enabled if this is to be the first history item
+ _backAction.setEnabled(true);
+ }
+
+ if(_mbean == null)
+ {
+ //queue etc selection area is open, record the tree object
+ _backHistory.addLast(_selectedNode);
+ }
+ else
+ {
+ _backHistory.addLast(_mbean);
+ }
+ }
+
+ _mbean = mbean;
+
+ try
+ {
+ clearView();
+
+ setFormTitle();
+ showMBean(mbean);
+
+ _form.layout(true);
+ _form.getBody().layout(true, true);
+ }
+ catch(Exception ex)
+ {
+ MBeanUtility.handleException(mbean, ex);
+ }
+ }
+
+ private void setFormTitle()
+ {
+ if (_mbean != null)
+ {
+ _formText = _mbean.getType();
+ if ((_mbean.getVirtualHostName() != null) && (!DEFAULT_VH.equals(_mbean.getVirtualHostName())) )
+ {
+ _formText = _formText.replaceFirst(VIRTUAL_HOST, _mbean.getVirtualHostName());
+ if (_mbean.getName() != null && _mbean.getName().length() != 0)
+ {
+ _formText = _formText + ": " + _mbean.getName();
+ }
+ }
+ }
+ else if ((_selectedNode.getVirtualHost() != null) && (!DEFAULT_VH.equals(_selectedNode.getVirtualHost())))
+ {
+ _formText = _selectedNode.getVirtualHost();
+ }
+ else
+ {
+ _formText = APPLICATION_NAME;
+ }
+ _form.setText(_formText);
+ }
+
+ public void showRelevantTabView()
+ {
+ try
+ {
+ if (_selectedNode == null)
+ {
+ return;
+ }
+
+ String mbeanType = _selectedNode.getType();
+
+ if (NODE_TYPE_TYPEINSTANCE.equals(mbeanType))
+ {
+ // An virtual host instance is selected
+ generateTypeTabFolder();
+ }
+ else if (NODE_TYPE_MBEANTYPE.equals(mbeanType))
+ {
+ showTypeTabFolder(_selectedNode.getName());
+ }
+ else if (NOTIFICATIONS.equals(mbeanType))
+ {
+ refreshNotificationPage();
+ }
+ else if (MBEAN.equals(mbeanType))
+ {
+ showMBean(_mbean);
+ }
+ else if(NODE_TYPE_SERVER.equals(mbeanType))
+ {
+ ServerRegistry serverReg = ApplicationRegistry.getServerRegistry(_server);
+
+ //check the server is connected
+ if(serverReg != null)
+ {
+ //post a message if the server supports a newer API version.
+ ApiVersion serverAPI = serverReg.getManagementApiVersion();
+ int supportedMajor = ApplicationRegistry.SUPPORTED_QPID_JMX_API_MAJOR_VERSION;
+ int supportedMinor = ApplicationRegistry.SUPPORTED_QPID_JMX_API_MINOR_VERSION;
+
+ if(serverAPI.greaterThan(supportedMajor, supportedMinor))
+ {
+ _form.setText("The server supports an updated management API and may offer " +
+ "functionality not available with this console. " +
+ "Please check for an updated console release.");
+ }
+
+ }
+ }
+ else
+ {
+ return;
+ }
+
+ _form.layout(true);
+ _form.getBody().layout(true, true);
+ }
+ catch(Exception ex)
+ {
+ MBeanUtility.handleException(_mbean, ex);
+ }
+ }
+
+ /**
+ * Sets the managedServer based on the selection in the navigation view
+ * At any given time MBeanView will be displaying information for an mbean of mbeantype
+ * for a specifiv managed server. This server information will be used by the tab controllers
+ * to get server registry.
+ */
+ private void setServer()
+ {
+ if (NODE_TYPE_SERVER.equals(_selectedNode.getType()))
+ {
+ _server = (ManagedServer)_selectedNode.getManagedObject();
+ _virtualHostName = null;
+ }
+ else
+ {
+ TreeObject parent = _selectedNode.getParent();
+ while (parent != null && !parent.getType().equals(NODE_TYPE_SERVER))
+ {
+ parent = parent.getParent();
+ }
+
+ if (parent != null && parent.getType().equals(NODE_TYPE_SERVER))
+ _server = (ManagedServer)parent.getManagedObject();
+
+ _virtualHostName = _selectedNode.getVirtualHost();
+ }
+
+ JMXServerRegistry serverRegistry = (JMXServerRegistry)ApplicationRegistry.getServerRegistry(_server);
+ if(serverRegistry != null){
+ _mbsc = serverRegistry.getServerConnection();
+ }
+ }
+
+ public static ManagedServer getServer()
+ {
+ return _server;
+ }
+
+ public static String getVirtualHost()
+ {
+ return _virtualHostName;
+ }
+
+ private void showMBean(ManagedBean mbean) throws Exception
+ {
+ try
+ {
+ MBeanUtility.getMBeanInfo(mbean);
+ }
+ catch(Exception ex)
+ {
+ MBeanUtility.handleException(mbean, ex);
+ return;
+ }
+
+ if (_tabFolder != null && !_tabFolder.isDisposed())
+ {
+ _tabFolder.dispose();
+ }
+
+ _tabFolder = MBeanTabFolderFactory.generateMBeanTabFolder(_form.getBody(),(JMXManagedObject)mbean,_mbsc);
+
+ int tabIndex = 0;
+ if (NOTIFICATIONS.equals(_selectedNode.getType()))
+ {
+ tabIndex = _tabFolder.getItemCount() -1;
+ }
+
+ TabItem tab = _tabFolder.getItem(tabIndex);
+ // If folder is being set as visible after tab refresh, then the tab
+ // doesn't have the focus.
+ _tabFolder.setSelection(tabIndex);
+ refreshTab(tab);
+ }
+
+ public void createPartControl(Composite parent)
+ {
+ // Create the Form
+ _toolkit = new FormToolkit(parent.getDisplay());
+ _form = _toolkit.createForm(parent);
+ _form.getBody().setLayout(new FormLayout());
+ _form.setText(APPLICATION_NAME);
+
+ // Add selection listener for selection events in the Navigation view
+ getSite().getPage().addSelectionListener(NavigationView.ID, _selectionListener);
+
+ createNotificationsTabFolder();
+
+ ViewUtility.setMBeanView(this);
+
+ _backAction = new BackAction();
+ getViewSite().getActionBars().getToolBarManager().add(_backAction);
+ _backAction.setEnabled(false);
+ _backHistory = new LinkedList<Object>();
+ }
+
+ private void refreshTab(TabItem tab)
+ {
+ if (tab == null)
+ {
+ return;
+ }
+
+ TabControl controller = (TabControl)tab.getData(TabControl.CONTROLLER);
+ if(controller != null)
+ {
+ controller.refresh(_mbean);
+ }
+ }
+
+ public void setFocus()
+ {
+ //_form.setFocus();
+ }
+
+ public void dispose()
+ {
+ _toolkit.dispose();
+ super.dispose();
+ }
+
+
+ private void createNotificationsTabFolder()
+ {
+ _notificationTabFolder = 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);
+ _notificationTabFolder.setLayoutData(layoutData);
+ _notificationTabFolder.setVisible(false);
+
+ VHNotificationsTabControl controller = new VHNotificationsTabControl(_notificationTabFolder);
+ TabItem tab = new TabItem(_notificationTabFolder, SWT.NONE);
+ tab.setText(NOTIFICATIONS);
+ tab.setData(TabControl.CONTROLLER, controller);
+ tab.setControl(controller.getControl());
+ }
+
+ private void refreshNotificationPage()
+ {
+ TabItem tab = _notificationTabFolder.getItem(0);
+ VHNotificationsTabControl controller = (VHNotificationsTabControl)tab.getData(TabControl.CONTROLLER);
+ controller.refresh();
+ _notificationTabFolder.setVisible(true);
+ }
+
+
+
+ private void generateTypeTabFolder() throws Exception
+ {
+ if (_typeTabFolder != null && !_typeTabFolder.isDisposed())
+ {
+ _typeTabFolder.dispose();
+ }
+
+ //Generates the full Queue/Connection/Exchange selection tab set
+ _typeTabFolder = MBeanTabFolderFactory.generateMBeanTypeTabFolder(
+ _form.getBody(), getServer(), getVirtualHost());
+ refreshTab(_typeTabFolder.getItem(0));
+ }
+
+ private void showTypeTabFolder(String type) throws Exception
+ {
+ if (_typeTabFolder != null && !_typeTabFolder.isDisposed())
+ {
+ _typeTabFolder.dispose();
+ }
+
+ if (CONNECTION.equals(type))
+ {
+ //Generates the Connection selection tab
+ _typeTabFolder = MBeanTabFolderFactory.generateConnectionTypeTabFolder(
+ _form.getBody(), getServer(), getVirtualHost());
+ refreshTab(_typeTabFolder.getItem(0));
+ }
+ else if (EXCHANGE.equals(type))
+ {
+ //Generates the Exchange selection tab
+ _typeTabFolder = MBeanTabFolderFactory.generateExchangeTypeTabFolder(
+ _form.getBody(), getServer(), getVirtualHost());
+ refreshTab(_typeTabFolder.getItem(0));
+ }
+ else if (QUEUE.equals(type))
+ {
+ //Generates the Queue selection tab
+ _typeTabFolder = MBeanTabFolderFactory.generateQueueTypeTabFolder(
+ _form.getBody(), getServer(), getVirtualHost());
+ refreshTab(_typeTabFolder.getItem(0));
+ }
+ }
+
+ private void clearView()
+ {
+ if (_tabFolder != null && !_tabFolder.isDisposed())
+ {
+ _tabFolder.setVisible(false);
+ }
+
+ if (_typeTabFolder != null && !_typeTabFolder.isDisposed())
+ {
+ _typeTabFolder.setVisible(false);
+ }
+
+ if (_notificationTabFolder != null && !_notificationTabFolder.isDisposed())
+ {
+ _notificationTabFolder.setVisible(false);
+ }
+
+ _form.setText(APPLICATION_NAME);
+ clearStatusBar();
+ }
+
+ public void mbeanUnregistered(ManagedBean mbean)
+ {
+ //if the mbean is actually open, clear the view and empty the Back history
+ if(mbean == _mbean)
+ {
+ clearView();
+ _backHistory.clear();
+ _backAction.setEnabled(false);
+ ViewUtility.popupInfoMessage("MBean Unregistered",
+ "The open MBean was unregistered from the server.");
+ }
+ }
+
+ public void refresh()
+ {
+ if(!ApplicationRegistry.isServerConnected(_server))
+ {
+ return;
+ }
+
+ if (_tabFolder != null && !_tabFolder.isDisposed())
+ {
+ if(_tabFolder.getVisible())
+ {
+ int selectedTab = _tabFolder.getSelectionIndex();
+ TabItem tab = _tabFolder.getItem(selectedTab);
+ TabControl controller = (TabControl) tab.getData(TabControl.CONTROLLER);
+ if(controller != null)
+ {
+ controller.refresh(_mbean);
+ }
+ return;
+ }
+ }
+
+ if (_typeTabFolder != null && !_typeTabFolder.isDisposed())
+ {
+
+ if(_typeTabFolder.getVisible())
+ {
+ int selectedTab = _typeTabFolder.getSelectionIndex();
+ TabItem tab = _typeTabFolder.getItem(selectedTab);
+ TabControl controller = (TabControl) tab.getData(TabControl.CONTROLLER);
+ if(controller != null)
+ {
+ controller.refresh(_mbean);
+ }
+ return;
+ }
+ }
+
+ if (_notificationTabFolder != null && !_notificationTabFolder.isDisposed())
+ {
+ if(_notificationTabFolder.getVisible())
+ {
+ int selectedTab = _notificationTabFolder.getSelectionIndex();
+ TabItem tab = _notificationTabFolder.getItem(selectedTab);
+ TabControl controller = (TabControl) tab.getData(TabControl.CONTROLLER);
+ if(controller != null)
+ {
+ controller.refresh(_mbean);
+ }
+ return;
+ }
+ }
+ }
+
+ public void populateStatusBar(Image icon, String message)
+ {
+ IActionBars bars = getViewSite().getActionBars();
+ bars.getStatusLineManager().setMessage(icon, message);
+ }
+
+ public void populateStatusBar(String message)
+ {
+ IActionBars bars = getViewSite().getActionBars();
+ bars.getStatusLineManager().setMessage(message);
+ }
+
+ public void clearStatusBar()
+ {
+ populateStatusBar("");
+ }
+
+ public void back() throws Exception
+ {
+ if(_backHistory.isEmpty())
+ {
+ return;
+ }
+
+ Object previous = _backHistory.removeLast();
+ if(_backHistory.isEmpty())
+ {
+ //if this is the last history item, disable the action button
+ _backAction.setEnabled(false);
+ }
+
+ if(previous instanceof ManagedBean)
+ {
+ openMBean((ManagedBean)previous, true);
+ }
+ else if (previous instanceof TreeObject)
+ {
+ _mbean = null;
+ clearView();
+ setFormTitle();
+
+ TreeObject node = (TreeObject) previous;
+ String mbeanType = node.getType();
+
+ if (NODE_TYPE_TYPEINSTANCE.equals(mbeanType))
+ {
+ generateTypeTabFolder();
+ }
+ else if (NODE_TYPE_MBEANTYPE.equals(mbeanType))
+ {
+ showTypeTabFolder(node.getName());
+ }
+ }
+
+ _form.layout(true);
+ _form.getBody().layout(true, true);
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NavigationView.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NavigationView.java
new file mode 100644
index 0000000000..417734e5fb
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NavigationView.java
@@ -0,0 +1,1372 @@
+/*
+ *
+ * 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 static org.apache.qpid.management.ui.Constants.*;
+import static org.apache.qpid.management.ui.ApplicationRegistry.DATA_DIR;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.qpid.management.common.mbeans.ConfigurationManagement;
+import org.apache.qpid.management.common.mbeans.LoggingManagement;
+import org.apache.qpid.management.common.mbeans.ServerInformation;
+import org.apache.qpid.management.common.mbeans.UserManagement;
+import org.apache.qpid.management.ui.ApiVersion;
+import org.apache.qpid.management.ui.ApplicationRegistry;
+import org.apache.qpid.management.ui.ManagedBean;
+import org.apache.qpid.management.ui.ManagedObject;
+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.exceptions.ManagementConsoleException;
+import org.apache.qpid.management.ui.jmx.JMXServerRegistry;
+import org.apache.qpid.management.ui.jmx.MBeanUtility;
+import org.eclipse.jface.preference.PreferenceStore;
+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.StructuredSelection;
+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.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.Tree;
+import org.eclipse.swt.widgets.TreeItem;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.part.ViewPart;
+
+/**
+ * Navigation View for navigating the managed servers and managed beans on
+ * those servers
+ * @author Bhupendra Bhardwaj
+ */
+public class NavigationView extends ViewPart
+{
+ public static final String ID = "org.apache.qpid.management.ui.navigationView";
+ public static final String INI_FILENAME = DATA_DIR + File.separator + "qpidmc_navigation.ini";
+
+ private static final String INI_SERVERS = "Servers";
+ private static final String INI_QUEUES = QUEUE + "s";
+ private static final String INI_CONNECTIONS = CONNECTION + "s";
+ private static final String INI_EXCHANGES = EXCHANGE + "s";
+
+ private TreeViewer _treeViewer = null;
+ private TreeObject _serversRootNode = null;
+
+ private PreferenceStore _preferences;
+ // Map of connected servers
+ private ConcurrentHashMap<ManagedServer, TreeObject> _managedServerMap = new ConcurrentHashMap<ManagedServer, TreeObject>();
+
+ private static HashSet<String> _serverTopLevelMBeans = new HashSet<String>();
+ {
+ _serverTopLevelMBeans.add(UserManagement.TYPE);
+ _serverTopLevelMBeans.add(LoggingManagement.TYPE);
+ _serverTopLevelMBeans.add(ConfigurationManagement.TYPE);
+ _serverTopLevelMBeans.add(ServerInformation.TYPE);
+ }
+
+ 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.grabExcessHorizontalSpace = true;
+ layoutData.grabExcessVerticalSpace = true;
+ layoutData.horizontalAlignment = GridData.FILL;
+ layoutData.verticalAlignment = GridData.FILL;
+ _treeViewer.getControl().setLayoutData(layoutData);
+ _treeViewer.setUseHashlookup(true);
+
+ createListeners();
+ }
+
+ /**
+ * Creates listeners for the JFace treeviewer
+ */
+ 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)
+ {
+ getSite().getShell().getDisplay().asyncExec(
+ new Runnable()
+ {
+ public void run()
+ {
+ _treeViewer.refresh();
+ }
+ });
+ }
+
+ public void treeCollapsed(TreeExpansionEvent event)
+ {
+ getSite().getShell().getDisplay().asyncExec(
+ new Runnable()
+ {
+ public void run()
+ {
+ _treeViewer.refresh();
+ }
+ });
+ }
+ });
+
+ // This listener is for popup menu, which pops up if a queue,exchange or connection is selected
+ // with right click.
+ _treeViewer.getTree().addListener(SWT.MenuDetect, new Listener()
+ {
+ Display display = getSite().getShell().getDisplay();
+ final Shell shell = new Shell(display);
+
+ public void handleEvent(Event event)
+ {
+ Tree widget = (Tree) event.widget;
+ TreeItem[] items = widget.getSelection();
+ if (items == null)
+ {
+ return;
+ }
+
+ // Get the selected node
+ final TreeObject selectedNode = (TreeObject) items[0].getData();
+ final TreeObject parentNode = selectedNode.getParent();
+
+ // This popup is only for mbeans and only connection,exchange and queue types
+ if ((parentNode == null) || !MBEAN.equals(selectedNode.getType())
+ || !(CONNECTION.equals(parentNode.getName()) || QUEUE.equals(parentNode.getName())
+ || EXCHANGE.equals(parentNode.getName())))
+ {
+ return;
+ }
+
+ Menu menu = new Menu(shell, SWT.POP_UP);
+ MenuItem item = new MenuItem(menu, SWT.PUSH);
+ // Add the action item, which will remove the node from the tree if selected
+ item.setText(ACTION_REMOVE_MBEANNODE);
+ item.addListener(SWT.Selection, new Listener()
+ {
+ public void handleEvent(Event e)
+ {
+ removeManagedObject(parentNode, (ManagedBean) selectedNode.getManagedObject(), true);
+ _treeViewer.refresh();
+ // set the selection to the parent node
+ _treeViewer.setSelection(new StructuredSelection(parentNode));
+ }
+ });
+ menu.setLocation(event.x, event.y);
+ menu.setVisible(true);
+ while (!menu.isDisposed() && menu.isVisible())
+ {
+ if (!display.readAndDispatch())
+ {
+ display.sleep();
+ }
+ }
+
+ menu.dispose();
+ }
+ });
+ }
+
+ /**
+ * Creates Qpid Server connection
+ * @param server
+ * @throws Exception
+ */
+ private void createJMXServerConnection(ManagedServer server) throws Exception
+ {
+ // Currently Qpid Management Console only supports JMX MBeanServer
+ JMXServerRegistry serverRegistry = new JMXServerRegistry(server);
+
+ try
+ {
+ //determine the management API version of the server just connected to
+ MBeanUtility.classifyManagementApiVersion(server, serverRegistry);
+ }
+ catch (Exception e)
+ {
+ //Exception classifying the server API, clean up the connection and rethrow
+ serverRegistry.closeServerConnection();
+ throw e;
+ }
+
+ //check that the console supports the API major version encountered, otherwise abort.
+ ApiVersion serverAPI = serverRegistry.getManagementApiVersion();
+
+ int serverMajor = serverAPI.getMajor();
+ int supportedMajor = ApplicationRegistry.SUPPORTED_QPID_JMX_API_MAJOR_VERSION;
+
+ if(serverMajor > supportedMajor)
+ {
+ serverRegistry.closeServerConnection();
+ throw new ManagementConsoleException("The server management API version encountered is not supported"
+ + " by this console release. Please check for an updated console release.");
+ }
+
+ //connection succeeded, add the ServerRegistry to the ApplicationRegistry
+ ApplicationRegistry.addServer(server, serverRegistry);
+ }
+
+ /**
+ * Adds a new server node in the navigation view if server connection is successful.
+ * @param transportProtocol
+ * @param host
+ * @param port
+ * @param domain
+ * @throws Exception
+ */
+ public void addNewServer(String host, int port, String domain, String user, String pwd)
+ throws Exception
+ {
+ ManagedServer managedServer = new ManagedServer(host, port, domain, user, pwd);
+
+ String server = managedServer.getName();
+ List<TreeObject> list = _serversRootNode.getChildren();
+ for (TreeObject node : list)
+ {
+ ManagedServer nodeServer = (ManagedServer)node.getManagedObject();
+ if (server.equals(nodeServer.getName()))
+ {
+ // Server is already in the list of added servers, so now connect it.
+ // Set the server node as selected and then connect it.
+ _treeViewer.setSelection(new StructuredSelection(node));
+ reconnect(user, pwd);
+
+ return;
+ }
+ }
+
+ // The server is not in the list of already added servers, so now connect and add it.
+ createJMXServerConnection(managedServer);
+
+ // Server connection is successful. Now add the server in the tree
+ TreeObject serverNode = new TreeObject(server, NODE_TYPE_SERVER);
+ serverNode.setManagedObject(managedServer);
+ _serversRootNode.addChild(serverNode);
+
+ // Add server in the connected server map
+ _managedServerMap.put(managedServer, serverNode);
+
+ // populate the server tree
+ try
+ {
+ populateServer(serverNode);
+ }
+ catch (SecurityException ex)
+ {
+ disconnect(managedServer);
+ throw ex;
+ }
+
+ // Add the Queue/Exchanges/Connections from config file into the navigation tree
+ addConfiguredItems(managedServer);
+
+ _treeViewer.refresh();
+
+ expandInitialMBeanView(serverNode);
+
+ //(re)select the server node now that it is connected to force a selectionEvent
+ _treeViewer.setSelection(new StructuredSelection(serverNode));
+ _treeViewer.refresh();
+
+ // save server address in file
+ addServerInConfigFile(server);
+ }
+
+ /**
+ * Create the config file, if it doesn't already exist.
+ * Exits the application if the file could not be created.
+ */
+ private void createConfigFile()
+ {
+ File dir = new File(DATA_DIR);
+ if (!dir.exists())
+ {
+ if(!dir.mkdir())
+ {
+ System.out.println("Could not create application data directory " + DATA_DIR);
+ System.exit(1);
+ }
+ }
+
+ File file = new File(INI_FILENAME);
+ try
+ {
+ if (!file.exists())
+ {
+ file.createNewFile();
+ }
+ }
+ catch (IOException ex)
+ {
+ System.out.println("Could not write to the file " + INI_FILENAME);
+ System.out.println(ex);
+ System.exit(1);
+ }
+ }
+
+ /**
+ * Server addresses are stored in a file. When user launches the application again, the
+ * server addresses are picked up from the file and shown in the navigfation view. This method
+ * adds the server address in a file, when a new server is added in the navigation view.
+ * @param serverAddress
+ */
+ private void addServerInConfigFile(String serverAddress)
+ {
+ // Check if the address already exists
+ List<String> list = getServerListFromFile();
+ if ((list != null) && list.contains(serverAddress))
+ {
+ return;
+ }
+
+ // Get the existing server list and add to that
+ String servers = _preferences.getString(INI_SERVERS);
+ String value = (servers.length() != 0) ? (servers + "," + serverAddress) : serverAddress;
+ _preferences.putValue(INI_SERVERS, value);
+ try
+ {
+ _preferences.save();
+ }
+ catch (IOException ex)
+ {
+ System.err.println("Could not add " + serverAddress + " in " + INI_SERVERS + " (" + INI_FILENAME + ")");
+ System.out.println(ex);
+ }
+ }
+
+ /**
+ * Adds the item (Queue/Exchange/Connection) to the config file
+ * @param server
+ * @param virtualhost
+ * @param type - (Queue or Exchange or Connection)
+ * @param name - item name
+ */
+ private void addItemInConfigFile(TreeObject node)
+ {
+ ManagedBean mbean = (ManagedBean) node.getManagedObject();
+ String server = mbean.getServer().getName();
+ String virtualhost = mbean.getVirtualHostName();
+ String type = node.getParent().getName() + "s";
+ String name = node.getName();
+ String itemKey = server + "." + virtualhost + "." + type;
+
+ // Check if the item already exists in the config file
+ List<String> list = getConfiguredItemsFromFile(itemKey);
+ if ((list != null) && list.contains(name))
+ {
+ return;
+ }
+
+ // Add this item to the existing list of items
+ String items = _preferences.getString(itemKey);
+ String value = (items.length() != 0) ? (items + "," + name) : name;
+ _preferences.putValue(itemKey, value);
+ try
+ {
+ _preferences.save();
+ }
+ catch (IOException ex)
+ {
+ System.err.println("Could not add " + name + " in " + itemKey + " (" + INI_FILENAME + ")");
+ System.out.println(ex);
+ }
+ }
+
+ private void removeItemFromConfigFile(TreeObject node)
+ {
+ ManagedBean mbean = (ManagedBean) node.getManagedObject();
+ String server = mbean.getServer().getName();
+ String vHost = mbean.getVirtualHostName();
+ String type = node.getParent().getName() + "s";
+ String itemKey = server + "." + vHost + "." + type;
+
+ List<String> list = getConfiguredItemsFromFile(itemKey);
+ if (list.contains(node.getName()))
+ {
+ list.remove(node.getName());
+ String value = "";
+ for (String item : list)
+ {
+ value += item + ",";
+ }
+
+ value = (value.lastIndexOf(",") != -1) ? value.substring(0, value.lastIndexOf(",")) : value;
+
+ _preferences.putValue(itemKey, value);
+ try
+ {
+ _preferences.save();
+ }
+ catch (IOException ex)
+ {
+ System.err.println("Error in updating the config file " + INI_FILENAME);
+ System.out.println(ex);
+ }
+ }
+ }
+
+ //check if the MBeanInfo can be retrieved.
+ private boolean haveAccessPermission(ManagedBean mbean)
+ {
+ try
+ {
+ MBeanUtility.getMBeanInfo(mbean);
+ }
+ catch(Exception ex)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Queries the qpid server for MBeans and populates the navigation view with all MBeans for
+ * the given server node.
+ * @param serverNode
+ * @throws Exception
+ */
+ private void populateServer(TreeObject serverNode) throws Exception
+ {
+ ManagedServer server = (ManagedServer) serverNode.getManagedObject();
+ String domain = server.getDomain();
+
+ List<ManagedBean> mbeans = MBeanUtility.getManagedObjectsForDomain(server, domain);
+ for (ManagedBean mbean : mbeans)
+ {
+ mbean.setServer(server);
+ ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(server);
+ serverRegistry.addManagedObject(mbean);
+
+ // Add all mbeans other than Connections, Exchanges and Queues. Because these will be added
+ // manually by selecting from MBeanView
+ if (!(mbean.isConnection() || mbean.isExchange() || mbean.isQueue()))
+ {
+ //if we cant get the MBeanInfo then we cant display the mbean, so dont add it to the tree
+ if (haveAccessPermission(mbean))
+ {
+ addManagedBean(serverNode, mbean);
+ }
+ }
+ }
+ // To make it work with the broker without virtual host implementation.
+ // This will add the default nodes to the domain node
+ boolean hasVirtualHost = false;
+ for (TreeObject child : serverNode.getChildren())
+ {
+ if (child.getName().startsWith(VIRTUAL_HOST))
+ {
+ hasVirtualHost = true;
+ break;
+ }
+ }
+
+ if (!hasVirtualHost){
+ addDefaultNodes(serverNode);
+ }
+ }
+
+ /**
+ * Add these three types - Connection, Exchange, Queue
+ * By adding these, these will always be available, even if there are no mbeans under thse types
+ * This is required because, the mbeans will be added from mbeanview, by selecting from the list
+ * @param parent Node
+ */
+ private void addDefaultNodes(TreeObject parent)
+ {
+ TreeObject typeChild = new TreeObject(CONNECTION, NODE_TYPE_MBEANTYPE);
+ typeChild.setParent(parent);
+ typeChild.setVirtualHost(parent.getVirtualHost());
+ typeChild = new TreeObject(EXCHANGE, NODE_TYPE_MBEANTYPE);
+ typeChild.setParent(parent);
+ typeChild.setVirtualHost(parent.getVirtualHost());
+ typeChild = new TreeObject(QUEUE, NODE_TYPE_MBEANTYPE);
+ typeChild.setParent(parent);
+ typeChild.setVirtualHost(parent.getVirtualHost());
+
+ // Add common notification node for virtual host
+ TreeObject notificationNode = new TreeObject(NOTIFICATIONS, NOTIFICATIONS);
+ notificationNode.setParent(parent);
+ notificationNode.setVirtualHost(parent.getVirtualHost());
+ }
+
+ /**
+ * Checks if a particular mbeantype is already there in the navigation view for a domain.
+ * This is used while populating domain with mbeans.
+ * @param parent
+ * @param typeName
+ * @return Node if given mbeantype already exists, otherwise null
+ */
+ private TreeObject getMBeanTypeNode(TreeObject parent, String typeName)
+ {
+ List<TreeObject> childNodes = parent.getChildren();
+ for (TreeObject child : childNodes)
+ {
+ if ((NODE_TYPE_MBEANTYPE.equals(child.getType()) || NODE_TYPE_TYPEINSTANCE.equals(child.getType()))
+ && typeName.equals(child.getName()))
+ {
+ return child;
+ }
+ }
+
+ return null;
+ }
+
+ private boolean doesMBeanNodeAlreadyExist(TreeObject typeNode, String mbeanName)
+ {
+ List<TreeObject> childNodes = typeNode.getChildren();
+ for (TreeObject child : childNodes)
+ {
+ if (MBEAN.equals(child.getType()) && mbeanName.equals(child.getName()))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Adds the given MBean to the given domain node.
+ * sample ObjectNames -
+ * org.apache.qpid:type=VirtualHost.VirtualHostManager,VirtualHost=localhost
+ * org.apache.qpid:type=VirtualHost.Queue,VirtualHost=test,name=ping_1
+ * @param parent parent tree node to add the mbean to
+ * @param mbean mbean to add
+ */
+ private void addManagedBean(TreeObject parent, ManagedBean mbean)
+ {
+ String name = mbean.getName();
+ // Split the mbean type into array of Strings, to create hierarchy
+ // eg. type=VirtualHost.VirtualHostManager,VirtualHost=localhost will be:
+ // localhost->VirtualHostManager
+ // eg. type=org.apache.qpid:type=VirtualHost.Queue,VirtualHost=test,name=ping will be:
+ // test->Queue->ping
+ String[] types = mbean.getType().split("\\.");
+ TreeObject typeNode = null;
+ TreeObject parentNode = parent;
+
+ // Run this loop till all nodes(hierarchy) for this mbean are created. This loop only creates
+ // all the required parent nodes for the mbean
+ for (int i = 0; i < types.length; i++)
+ {
+ String type = types[i];
+
+ if(types.length == 1 && _serverTopLevelMBeans.contains(type))
+ {
+ //This mbean is not to be contained in a type hierarchy
+ //Just add it as a child of the server node.
+ break;
+ }
+
+ String valueOftype = mbean.getProperty(type);
+ // If value is not null, then there will be a parent node for this mbean
+ // eg. for type=VirtualHost the value is "test"
+ typeNode = getMBeanTypeNode(parentNode, type);
+
+ // create the type node if not already created
+ if (typeNode == null)
+ {
+ // If the ObjectName doesn't have name property, that means there will be only one instance
+ // of this mbean for given "type". So there will be no type node created for this mbean.
+ if ((name == null) && (i == (types.length - 1)))
+ {
+ break;
+ }
+
+ // create a node for "type"
+ typeNode = createTypeNode(parentNode, type);
+ if (!type.equals(VIRTUAL_HOST))
+ {
+ typeNode.setVirtualHost(mbean.getVirtualHostName());
+ }
+ }
+
+ // now type node create becomes the parent node for next node in hierarchy
+ parentNode = typeNode;
+
+ /*
+ * Now create instances node for this type if value exists.
+ */
+ if (valueOftype == null)
+ {
+ // No instance node will be created when value is null (eg type=Queue)
+ break;
+ }
+
+ // For different virtual hosts, the nodes with given value will be created.
+ // eg type=VirtualHost, value=test
+ typeNode = getMBeanTypeNode(parentNode, valueOftype);
+ if (typeNode == null)
+ {
+ typeNode = createTypeInstanceNode(parentNode, valueOftype);
+ typeNode.setVirtualHost(mbean.getVirtualHostName());
+
+ // Create default nodes for VHost instances
+ if (type.equals(VIRTUAL_HOST))
+ {
+ addDefaultNodes(typeNode);
+ }
+ }
+
+ parentNode = typeNode;
+ }
+
+ if (typeNode == null)
+ {
+ typeNode = parentNode;
+ }
+
+ // Check if an MBean is already added
+ if (doesMBeanNodeAlreadyExist(typeNode, name))
+ {
+ return;
+ }
+
+ // Add the mbean node now
+ TreeObject mbeanNode = new TreeObject(mbean);
+ mbeanNode.setVirtualHost(mbean.getVirtualHostName());
+ mbeanNode.setParent(typeNode);
+
+ // Add the mbean to the config file
+ if (mbean.isQueue() || mbean.isExchange() || mbean.isConnection())
+ {
+ addItemInConfigFile(mbeanNode);
+ }
+ }
+
+ private TreeObject createTypeNode(TreeObject parent, String name)
+ {
+ TreeObject typeNode = new TreeObject(name, NODE_TYPE_MBEANTYPE);
+ typeNode.setParent(parent);
+
+ return typeNode;
+ }
+
+ private TreeObject createTypeInstanceNode(TreeObject parent, String name)
+ {
+ TreeObject typeNode = new TreeObject(name, NODE_TYPE_TYPEINSTANCE);
+ typeNode.setParent(parent);
+
+ return typeNode;
+ }
+
+ /**
+ * Removes all the child nodes of the given parent node. Used when closing a server.
+ * @param parent
+ */
+ private void removeManagedObject(TreeObject parent)
+ {
+ if(parent == null)
+ {
+ return;
+ }
+
+ 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, boolean removeFromConfigFile)
+ {
+ List<TreeObject> list = parent.getChildren();
+ TreeObject objectToRemove = null;
+ for (TreeObject child : list)
+ {
+ if (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, removeFromConfigFile);
+ }
+ }
+
+ if (objectToRemove != null)
+ {
+ list.remove(objectToRemove);
+ if(removeFromConfigFile)
+ {
+ removeItemFromConfigFile(objectToRemove);
+ }
+ }
+
+ }
+
+ /**
+ * Closes the Qpid server connection
+ */
+ public void disconnect() throws Exception
+ {
+ TreeObject selectedNode = getSelectedServerNode();
+ ManagedServer managedServer = (ManagedServer) selectedNode.getManagedObject();
+ disconnect(managedServer);
+ }
+
+ private void disconnect(ManagedServer managedServer) throws Exception
+ {
+ if (!_managedServerMap.containsKey(managedServer))
+ {
+ return;
+ }
+
+ // Close server connection
+ ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(managedServer);
+ if (serverRegistry == null) // server connection is already closed
+ {
+ return;
+ }
+
+ // Add server to the closed server list and the worker thread will remove the server from required places.
+ ApplicationRegistry.serverConnectionClosed(managedServer);
+
+ //close the connection
+ serverRegistry.closeServerConnection();
+ }
+
+ /**
+ * Connects the selected server node
+ * @throws Exception
+ */
+ public void reconnect(String user, String password) throws Exception
+ {
+ TreeObject selectedNode = getSelectedServerNode();
+ ManagedServer managedServer = (ManagedServer) selectedNode.getManagedObject();
+ if (_managedServerMap.containsKey(managedServer))
+ {
+ throw new InfoRequiredException("Server " + managedServer.getName() + " is already connected");
+ }
+
+ managedServer.setUser(user);
+ managedServer.setPassword(password);
+ createJMXServerConnection(managedServer);
+
+ // put the server in the managed server map
+ _managedServerMap.put(managedServer, selectedNode);
+
+ try
+ {
+ // populate the server tree now
+ populateServer(selectedNode);
+ }
+ catch (SecurityException ex)
+ {
+ disconnect(managedServer);
+ throw ex;
+ }
+
+
+ // Add the Queue/Exchanges/Connections from config file into the navigation tree
+ addConfiguredItems(managedServer);
+
+ expandInitialMBeanView(selectedNode);
+
+ //(re)select the server node now that it is connected to force a selectionEvent
+ _treeViewer.setSelection(new StructuredSelection(selectedNode));
+ _treeViewer.refresh();
+ }
+
+ private void expandInitialMBeanView(TreeObject serverNode)
+ {
+ if (serverNode.getChildren().size() == 0 )
+ {
+ return;
+ }
+ else
+ {
+ _treeViewer.setExpandedState(serverNode , true);
+ }
+
+ List<TreeObject> children = serverNode.getChildren();
+ for (TreeObject child : children)
+ {
+ if (child.getChildren().size() > 0)
+ {
+ _treeViewer.setExpandedState(child, true);
+ }
+ }
+ }
+
+ /**
+ * Adds the items(queues/exchanges/connectins) from config file to the server tree
+ * @param server
+ */
+ private void addConfiguredItems(ManagedServer server)
+ {
+ ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(server);
+ List<String> list = serverRegistry.getVirtualHosts();
+ for (String virtualHost : list)
+ {
+ // Add Queues
+ String itemKey = server.getName() + "." + virtualHost + "." + INI_QUEUES;
+ List<String> items = getConfiguredItemsFromFile(itemKey);
+ List<ManagedBean> mbeans = serverRegistry.getQueues(virtualHost);
+ addConfiguredItems(items, mbeans);
+
+ // Add Exchanges
+ itemKey = server.getName() + "." + virtualHost + "." + INI_EXCHANGES;
+ items = getConfiguredItemsFromFile(itemKey);
+ mbeans = serverRegistry.getExchanges(virtualHost);
+ addConfiguredItems(items, mbeans);
+
+ // Add Connections
+ itemKey = server.getName() + "." + virtualHost + "." + INI_CONNECTIONS;
+ items = getConfiguredItemsFromFile(itemKey);
+ mbeans = serverRegistry.getConnections(virtualHost);
+ addConfiguredItems(items, mbeans);
+ }
+ }
+
+ /**
+ * Gets the mbeans corresponding to the items and adds those to the navigation tree
+ * @param items
+ * @param mbeans
+ */
+ private void addConfiguredItems(List<String> items, List<ManagedBean> mbeans)
+ {
+ if ((items == null) || (items.isEmpty() || (mbeans == null)) || mbeans.isEmpty())
+ {
+ return;
+ }
+
+ for (String item : items)
+ {
+ for (ManagedBean mbean : mbeans)
+ {
+ if (item.equals(mbean.getName()))
+ {
+ addManagedBean(mbean);
+
+ break;
+ }
+ }
+ }
+ }
+
+ /**
+ * Closes the Qpid server connection if not already closed and removes the server node from the navigation view and
+ * also from the ini file stored in the system.
+ * @throws Exception
+ */
+ 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);
+ }
+
+ _treeViewer.refresh();
+
+ // Remove from the ini file
+ removeServerFromConfigFile(serverNodeName);
+ }
+
+ private void removeServerFromConfigFile(String serverNodeName)
+ {
+ List<String> serversList = getServerListFromFile();
+ serversList.remove(serverNodeName);
+
+ String value = "";
+ for (String item : serversList)
+ {
+ value += item + ",";
+ }
+
+ value = (value.lastIndexOf(",") != -1) ? value.substring(0, value.lastIndexOf(",")) : value;
+
+ _preferences.putValue(INI_SERVERS, value);
+
+ try
+ {
+ _preferences.save();
+ }
+ catch (IOException ex)
+ {
+ System.err.println("Error in updating the config file " + INI_FILENAME);
+ System.out.println(ex);
+ }
+ }
+
+ /**
+ * @return the server addresses from the ini file
+ * @throws Exception
+ */
+ private List<String> getServerListFromFile()
+ {
+ return getConfiguredItemsFromFile(INI_SERVERS);
+ }
+
+ /**
+ * Returns the list of items from the config file.
+ * sample ini file:
+ * Servers=localhost:8999,127.0.0.1:8999
+ * localhost.virtualhost1.Queues=queue1,queue2
+ * localhost.virtualhost1.Exchanges=exchange1,exchange2
+ * localhost.virtualhost2.Connections=conn1
+ * @param key
+ * @return
+ */
+ private List<String> getConfiguredItemsFromFile(String key)
+ {
+ List<String> list = new ArrayList<String>();
+ String items = _preferences.getString(key);
+ if (items.length() != 0)
+ {
+ String[] array = items.split(",");
+ for (String item : array)
+ {
+ list.add(item);
+ }
+ }
+
+ return list;
+ }
+
+ public TreeObject getSelectedServerNode() throws Exception
+ {
+ IStructuredSelection ss = (IStructuredSelection) _treeViewer.getSelection();
+ TreeObject selectedNode = (TreeObject) ss.getFirstElement();
+ if (ss.isEmpty() || (selectedNode == null) || (!selectedNode.getType().equals(NODE_TYPE_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);
+ _serversRootNode = new TreeObject(NAVIGATION_ROOT, "ROOT");
+
+ _treeViewer.setInput(_serversRootNode);
+ // 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();
+
+ createConfigFile();
+ _preferences = new PreferenceStore(INI_FILENAME);
+
+ try
+ {
+ _preferences.load();
+ }
+ catch (IOException ex)
+ {
+ System.out.println(ex);
+ }
+
+ // load the list of servers already added from file
+ List<String> serversList = getServerListFromFile();
+ if (serversList != null)
+ {
+ for (String serverAddress : serversList)
+ {
+ String[] server = serverAddress.split(":");
+ ManagedServer managedServer = new ManagedServer(server[0], Integer.parseInt(server[1]), "org.apache.qpid");
+ TreeObject serverNode = new TreeObject(serverAddress, NODE_TYPE_SERVER);
+ serverNode.setManagedObject(managedServer);
+ _serversRootNode.addChild(serverNode);
+ }
+ }
+
+ _treeViewer.refresh();
+
+ }
+
+ /**
+ * Passing the focus request to the viewer's control.
+ */
+ public void setFocus()
+ { }
+
+ public void refresh()
+ {
+ _treeViewer.refresh();
+ }
+
+ /**
+ * Content provider class for the tree viewer
+ */
+ private static 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
+ }
+ }
+
+ /**
+ * Label provider class for the tree viewer
+ */
+ private class LabelProviderImpl extends LabelProvider implements IFontProvider
+ {
+ public Image getImage(Object element)
+ {
+ TreeObject node = (TreeObject) element;
+ if (node.getType().equals(NOTIFICATIONS))
+ {
+ return ApplicationRegistry.getImage(NOTIFICATION_IMAGE);
+ }
+ else if (!node.getType().equals(MBEAN))
+ {
+ if (_treeViewer.getExpandedState(node))
+ {
+ return ApplicationRegistry.getImage(OPEN_FOLDER_IMAGE);
+ }
+ else
+ {
+ return ApplicationRegistry.getImage(CLOSED_FOLDER_IMAGE);
+ }
+
+ }
+ else
+ {
+ ManagedObject obj = node.getManagedObject();
+ if(obj instanceof ManagedBean)
+ {
+ ManagedBean mbean = (ManagedBean) obj;
+ String mbeanType = mbean.getType();
+
+ if(mbeanType.equals(LoggingManagement.TYPE))
+ {
+ return ApplicationRegistry.getImage(LOGGING_MANAGEMENT_IMAGE);
+ }
+ else if(mbeanType.equals(UserManagement.TYPE))
+ {
+ return ApplicationRegistry.getImage(USER_MANAGEMENT_IMAGE);
+ }
+ else if(mbeanType.equals(ConfigurationManagement.TYPE))
+ {
+ return ApplicationRegistry.getImage(CONFIGURATION_MANAGEMENT_IMAGE);
+ }
+ else if(mbeanType.equals(ServerInformation.TYPE))
+ {
+ return ApplicationRegistry.getImage(SERVER_INFO_IMAGE);
+ }
+ else if(mbeanType.equals("VirtualHost.VirtualHostManager"))
+ {
+ return ApplicationRegistry.getImage(VHOST_MANAGER_IMAGE);
+ }
+ else
+ {
+ return ApplicationRegistry.getImage(MBEAN_IMAGE);
+ }
+
+ }
+ else
+ {
+ return ApplicationRegistry.getImage(MBEAN_IMAGE);
+ }
+ }
+ }
+
+ public String getText(Object element)
+ {
+ TreeObject node = (TreeObject) element;
+ if (node.getType().equals(NODE_TYPE_MBEANTYPE))
+ {
+ return node.getName() + "s";
+ }
+ else
+ {
+ return node.getName();
+ }
+ }
+
+ public Font getFont(Object element)
+ {
+ TreeObject node = (TreeObject) element;
+ if (node.getType().equals(NODE_TYPE_SERVER))
+ {
+ if (node.getChildren().isEmpty())
+ {
+ return ApplicationRegistry.getFont(FONT_NORMAL);
+ }
+ else
+ {
+ return ApplicationRegistry.getFont(FONT_BOLD);
+ }
+ }
+
+ return ApplicationRegistry.getFont(FONT_NORMAL);
+ }
+ } // End of LabelProviderImpl
+
+ private static class ViewerSorterImpl extends ViewerSorter
+ {
+ public int category(Object element)
+ {
+ TreeObject node = (TreeObject) element;
+ if (node.getType().equals(MBEAN))
+ {
+ return 1;
+ }
+ if (node.getType().equals(NOTIFICATIONS))
+ {
+ return 2;
+ }
+ return 3;
+ }
+ }
+
+ /**
+ * 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())
+ {
+ refreshRemovedObjects();
+ refreshClosedServerConnections();
+ }
+
+ try
+ {
+ Thread.sleep(2000);
+ }
+ catch (InterruptedException ex)
+ {
+ //ignore
+ }
+
+ } // end of while loop
+ } // end of run method.
+ } // end of Worker class
+
+ /**
+ * Adds the mbean to the navigation tree
+ * @param mbean mbean to add to the tree
+ */
+ public void addManagedBean(ManagedBean mbean)
+ {
+ TreeObject treeServerObject = _managedServerMap.get(mbean.getServer());
+ addManagedBean(treeServerObject, mbean);
+ _treeViewer.refresh();
+ }
+
+ private void refreshRemovedObjects()
+ {
+ for (ManagedServer server : _managedServerMap.keySet())
+ {
+ final ServerRegistry serverRegistry = 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()
+ {
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ final MBeanView view = (MBeanView)window.getActivePage().findView(MBeanView.ID);
+
+ for (ManagedBean mbean : removalList)
+ {
+ TreeObject treeServerObject = _managedServerMap.get(mbean.getServer());
+
+ if(view != null)
+ {
+ //notify the MBeanView in case the unregistered mbean is being viewed
+ view.mbeanUnregistered(mbean);
+ }
+
+ removeManagedObject(treeServerObject, mbean, false);
+ }
+
+ _treeViewer.refresh();
+ }
+ });
+ }
+ }
+ }
+
+ /**
+ * Gets the list of closed server connection from the ApplicationRegistry and then removes
+ * the closed server nodes from the navigation view
+ */
+ 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)
+ {
+ if(server == null)
+ {
+ continue;
+ }
+
+ TreeObject node = _managedServerMap.get(server);
+ if(node ==null)
+ {
+ continue;
+ }
+
+ removeManagedObject(node);
+ _managedServerMap.remove(server);
+ ApplicationRegistry.removeServer(server);
+ }
+
+ _treeViewer.refresh();
+ }
+ });
+ }
+ }
+
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NotificationsTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NotificationsTabControl.java
new file mode 100644
index 0000000000..ea49a5c006
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NotificationsTabControl.java
@@ -0,0 +1,388 @@
+/*
+ *
+ * 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 static org.apache.qpid.management.ui.Constants.BUTTON_CLEAR;
+import static org.apache.qpid.management.ui.Constants.DESCRIPTION;
+import static org.apache.qpid.management.ui.Constants.FONT_BOLD;
+import static org.apache.qpid.management.ui.Constants.FONT_BUTTON;
+import static org.apache.qpid.management.ui.Constants.FONT_ITALIC;
+import static org.apache.qpid.management.ui.Constants.SUBSCRIBE_BUTTON;
+import static org.apache.qpid.management.ui.Constants.UNSUBSCRIBE_BUTTON;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.qpid.management.ui.ApplicationRegistry;
+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.IStructuredSelection;
+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.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.Label;
+import org.eclipse.swt.widgets.TabFolder;
+
+/**
+ * Creates control composite for Notifications tab
+ * @author Bhupendra Bhardwaj
+ */
+public class NotificationsTabControl extends VHNotificationsTabControl
+{
+ private static final String SELECT_NOTIFICATIONNAME = "Select Notification";
+ private static final String SELECT_NOTIFICATIONTYPE = "Select Type";
+ private SelectionListener selectionListener;
+ private SelectionListener comboListener;
+
+ private Combo _notificationNameCombo;
+ private Combo _typesCombo;
+ private Label _descriptionLabel;
+ private Button _subscribeButton;
+ private Button _unsubscribeButton;
+
+ public NotificationsTabControl(TabFolder tabFolder, ManagedBean mbean)
+ {
+ super(tabFolder);
+ _mbean = mbean;
+
+ populateNotificationInfo();
+ }
+
+ protected void createWidgets()
+ {
+ selectionListener = new SelectionListenerImpl();
+ comboListener = new ComboSelectionListener();
+ createNotificationInfoComposite();
+ addButtons();
+ createTableViewer();
+ }
+
+ /**
+ * Creates composite and populates for displaying Notification Information (name, type, description)
+ * and creates buttons for subscribing or unsubscribing for notifications
+ */
+ 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(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(FONT_BUTTON));
+ _subscribeButton.setText(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(FONT_BUTTON));
+ _unsubscribeButton.setText(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(DESCRIPTION + " : ");
+ fixedLabel.setFont(ApplicationRegistry.getFont(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(100);
+ _descriptionLabel.setLayoutData(formData);
+ _descriptionLabel.setText(" ");
+ _descriptionLabel.setFont(ApplicationRegistry.getFont(FONT_ITALIC));
+ }
+
+ /**
+ * Creates clear button
+ */
+ protected void addButtons()
+ {
+ Composite composite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
+ composite.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false));
+ composite.setLayout(new GridLayout(2,false));
+
+ // Add Clear Button
+ _clearButton = _toolkit.createButton(composite, BUTTON_CLEAR, SWT.PUSH | SWT.CENTER);
+ _clearButton.setFont(ApplicationRegistry.getFont(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(MBeanView.getServer());
+ IStructuredSelection ss = (IStructuredSelection)_tableViewer.getSelection();
+ if(!ss.isEmpty())
+ {
+ //clear selected Notifications
+ serverRegistry.clearNotifications(_mbean, ss.toList());
+ }
+ else if(_notifications != null)
+ {
+ //clear all the notifications, if there are any
+
+ //check the user is certain of this clear-all operation
+ int response = ViewUtility.popupOkCancelConfirmationMessage(
+ "Clear Notifications", "Clear all Notifications for this MBean?");
+ if(response != SWT.OK)
+ {
+ return;
+ }
+
+ synchronized(this)
+ {
+ List<NotificationObject> newList = new ArrayList<NotificationObject>();
+ newList.addAll(_notifications);
+ serverRegistry.clearNotifications(_mbean, newList);
+ }
+ }
+
+ refresh();
+ }
+ });
+ //add description
+ Label desc = _toolkit.createLabel(composite,"Clears the selected Notifications, or all if none are selected");
+ desc.setLayoutData(new GridData(SWT.LEFT,SWT.CENTER, false, false));
+ }
+
+ @Override
+ public void refresh(ManagedBean mbean)
+ {
+ refresh();
+ }
+
+ /**
+ * Fills the notification information widgets for selected mbean
+ */
+ private void populateNotificationInfo()
+ {
+ _notificationNameCombo.removeAll();
+ NotificationInfoModel[] items = MBeanUtility.getNotificationInfo(_mbean);
+ if (items.length > 1)
+ {
+ _notificationNameCombo.add(SELECT_NOTIFICATIONNAME);
+ }
+
+ 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);
+
+ populateNotificationType(_notificationNameCombo.getItem(0));
+ checkForEnablingButtons();
+ }
+
+ /**
+ * Checks and the enabing/disabling of buttons
+ */
+ private void checkForEnablingButtons()
+ {
+ int nameIndex = _notificationNameCombo.getSelectionIndex();
+ int itemCount = _notificationNameCombo.getItems().length;
+ if ((itemCount > 1) && (nameIndex == 0))
+ {
+ _subscribeButton.setEnabled(false);
+ _unsubscribeButton.setEnabled(false);
+ _descriptionLabel.setText("");
+ return;
+ }
+
+ int typeIndex = _typesCombo.getSelectionIndex();
+ itemCount = _typesCombo.getItems().length;
+ if ((itemCount > 1) && (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);
+ }
+ }
+
+ /**
+ * Selection listener for subscribing or unsubscribing the notifications
+ */
+ 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();
+ }
+ }
+
+ /**
+ * Selection listener class for the Notification Name. The notification type and description will be
+ * displayed accordingly
+ */
+ private class ComboSelectionListener extends SelectionAdapter
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ if (_mbean == null)
+ return;
+
+ Combo combo = (Combo)e.getSource();
+ if (combo == _notificationNameCombo)
+ {
+ String selectedItem = combo.getItem(combo.getSelectionIndex());
+ populateNotificationType(selectedItem);
+ }
+ checkForEnablingButtons();
+ }
+ }
+
+ private void populateNotificationType(String notificationName)
+ {
+ NotificationInfoModel data = (NotificationInfoModel)_notificationNameCombo.getData(notificationName);
+ if (data == null)
+ {
+ _descriptionLabel.setText("");
+ _typesCombo.select(0);
+ _typesCombo.setEnabled(false);
+ return;
+ }
+ _descriptionLabel.setText(data.getDescription());
+ _typesCombo.removeAll();
+ _typesCombo.setItems(data.getTypes());
+ if (_typesCombo.getItemCount() > 1)
+ {
+ _typesCombo.add(SELECT_NOTIFICATIONTYPE, 0);
+ }
+ _typesCombo.select(0);
+ _typesCombo.setEnabled(true);
+ }
+
+ /**
+ * Updates the table with new notifications received from mbean server for the selected mbean
+ */
+ protected void updateTableViewer()
+ {
+ ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(_mbean);
+ List<NotificationObject> newList = serverRegistry.getNotifications(_mbean);
+ synchronized(this)
+ {
+ _notifications = newList;
+ _tableViewer.setInput(_notifications);
+ }
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NumberVerifyListener.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NumberVerifyListener.java
new file mode 100644
index 0000000000..1774209dae
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/NumberVerifyListener.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.views;
+
+import org.eclipse.swt.events.VerifyEvent;
+import org.eclipse.swt.events.VerifyListener;
+
+/**
+ * Implementation of VeryfyListener for numeric values
+ * @author Bhupendra Bhardwaj
+ */
+public class NumberVerifyListener implements 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;
+ }
+ }
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/OperationTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/OperationTabControl.java
new file mode 100644
index 0000000000..d0b70f4340
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/OperationTabControl.java
@@ -0,0 +1,920 @@
+/*
+ *
+ * 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.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map.Entry;
+
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularDataSupport;
+
+import static org.apache.qpid.management.ui.Constants.*;
+
+import org.apache.qpid.management.ui.ApplicationRegistry;
+import org.apache.qpid.management.ui.ManagedBean;
+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.
+ */
+public class OperationTabControl extends TabControl
+{
+ private static final int heightForAParameter = 30;
+ private static final int labelWidth = 30;
+ private static final int valueWidth = labelWidth + 25;
+
+ 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 booleanSelectionListener = 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;
+ private String _virtualHostName = null;
+
+ public OperationTabControl(TabFolder tabFolder, OperationData opData)
+ {
+ super(tabFolder);
+ _toolkit = new FormToolkit(_tabFolder.getDisplay());
+ _form = _toolkit.createForm(_tabFolder);
+ _form.getBody().setLayout(new GridLayout());
+ _opData = opData;
+ createComposites();
+ setHeader();
+ }
+
+ /**
+ * 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
+ */
+ private void createComposites()
+ {
+ //
+ _headerComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
+ _headerComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+
+ List<ParameterData> params = _opData.getParameters();
+ if (params != null && !params.isEmpty())
+ {
+ _paramsComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
+ _paramsComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ }
+ _executionButton = _toolkit.createButton(_form.getBody(), BUTTON_EXECUTE, SWT.PUSH | SWT.CENTER);
+ _executionButton.setFont(ApplicationRegistry.getFont(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());
+ }
+
+ /**
+ * @see TabControl#getControl()
+ */
+ public Control getControl()
+ {
+ return _form;
+ }
+
+ @Override
+ public void refresh(ManagedBean mbean)
+ {
+ _mbean = mbean;
+ _virtualHostName = _mbean.getVirtualHostName();
+
+ // 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(_paramsComposite);
+ createParameterWidgets();
+
+ // Set button text and add appropriate listener to button.
+ // If there are no parameters and it is info operation, then operation gets executed
+ // and result is displayed
+ List<ParameterData> params = _opData.getParameters();
+ if (params != null && !params.isEmpty())
+ {
+ setButton(BUTTON_EXECUTE);
+ }
+ else if (_opData.getImpact() == OPERATION_IMPACT_ACTION)
+ {
+ setButton(BUTTON_EXECUTE);
+ }
+ else if (_opData.getImpact() == OPERATION_IMPACT_INFO)
+ {
+ setButton(BUTTON_REFRESH);
+ executeAndShowResults();
+ }
+
+ _form.setVisible(true);
+ layout();
+ }
+
+ public void layout()
+ {
+ _form.layout(true);
+ _form.getBody().layout(true, true);
+ }
+
+ /**
+ * populates the header composite, containing the operation name and description.
+ */
+ private void setHeader()
+ {
+ _form.setText(ViewUtility.getDisplayText(_opData.getName()));
+ _headerComposite.setLayout(new GridLayout(2, false));
+ //operation description
+ Label label = _toolkit.createLabel(_headerComposite, DESCRIPTION + " : ");
+ label.setFont(ApplicationRegistry.getFont(FONT_BOLD));
+ label.setLayoutData(new GridData(SWT.LEAD, SWT.TOP, false, false));
+
+ label = _toolkit.createLabel(_headerComposite, _opData.getDescription());
+ label.setFont(ApplicationRegistry.getFont(FONT_NORMAL));
+ label.setLayoutData(new GridData(SWT.LEAD, SWT.TOP, true, false));
+
+ _headerComposite.layout();
+ }
+
+ /**
+ * Creates the widgets for operation parameters if there are any
+ */
+ private void createParameterWidgets()
+ {
+ List<ParameterData> params = _opData.getParameters();
+ if (params == null || params.isEmpty())
+ {
+ return;
+ }
+
+ // Customised parameter widgets
+ if (_mbean.isExchange() &&
+ HEADERS_EXCHANGE.equals(_mbean.getProperty(EXCHANGE_TYPE)) &&
+ _opData.getName().equalsIgnoreCase(OPERATION_CREATE_BINDING))
+ {
+ customCreateNewBinding();
+ return;
+ }
+ // end of Customised parameter widgets
+
+ _paramsComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ _paramsComposite.setLayout(new FormLayout());
+ int parameterPositionOffset = 0;
+ for (ParameterData param : params)
+ {
+ boolean valueInCombo = false;
+ Label label = _toolkit.createLabel(_paramsComposite, ViewUtility.getDisplayText(param.getName()));
+ FormData formData = new FormData();
+ if (params.indexOf(param) == 0)
+ {
+ parameterPositionOffset = 0;
+ }
+ else
+ {
+ parameterPositionOffset += heightForAParameter;
+ }
+ formData.top = new FormAttachment(0, parameterPositionOffset + 2);
+ formData.right = new FormAttachment(labelWidth);
+ label.setLayoutData(formData);
+ label.setToolTipText(param.getDescription());
+
+ formData = new FormData();
+ formData.top = new FormAttachment(0, parameterPositionOffset);
+ formData.left = new FormAttachment(label, 5);
+ formData.right = new FormAttachment(valueWidth);
+ // this will contain the list of items, if the list is to be made available to choose from
+ // e.g. the list of exchanges
+ String[] items = null;
+ if (param.getName().equals(QUEUE))
+ {
+ List<String> qList = ApplicationRegistry.getServerRegistry(_mbean).getQueueNames(_virtualHostName);
+ // Customization for AMQQueueMBean method OPERATION_MOVE_MESSAGES
+ if (_opData.getName().equals(OPERATION_MOVE_MESSAGES))
+ {
+ qList.remove(_mbean.getName());
+ }
+ // End of Customization
+ items = qList.toArray(new String[0]);
+ }
+ else if (param.getName().equals(EXCHANGE))
+ {
+ items = ApplicationRegistry.getServerRegistry(_mbean).getExchangeNames(_virtualHostName);
+ }
+ else if (param.getName().equals(EXCHANGE_TYPE))
+ {
+ items = DEFAULT_EXCHANGE_TYPE_VALUES.toArray(new String[DEFAULT_EXCHANGE_TYPE_VALUES.size()]);
+ }
+ else if (isUserListParameter(param))
+ {
+ List<String> list = ApplicationRegistry.getServerRegistry(_mbean).getUsernames();
+ if (list != null && !list.isEmpty())
+ {
+ items = list.toArray(new String[0]);
+ }
+ }
+
+ if (items != null)
+ {
+ org.eclipse.swt.widgets.List _list = new org.eclipse.swt.widgets.List(_paramsComposite, SWT.BORDER | SWT.V_SCROLL);
+ int listSize = _form.getClientArea().height * 2 / 3;
+ int itemsHeight = items.length * (_list.getItemHeight() + 2);
+ // Set a min height for the list widget (set it to min 4 items)
+ if (items.length < 4)
+ {
+ itemsHeight = 4 * (_list.getItemHeight() + 2);
+ }
+
+ listSize = (listSize > itemsHeight) ? itemsHeight : listSize;
+ parameterPositionOffset = parameterPositionOffset + listSize;
+ formData.bottom = new FormAttachment(0, parameterPositionOffset);
+ _list.setLayoutData(formData);
+ _list.setData(param);
+ _list.setItems(items);
+ _list.addSelectionListener(parameterSelectionListener);
+ valueInCombo = true;
+ }
+ else if (param.isBoolean())
+ {
+ Button booleanButton = _toolkit.createButton(_paramsComposite, "", SWT.CHECK);
+ booleanButton.setLayoutData(formData);
+ booleanButton.setData(param);
+ booleanButton.addSelectionListener(booleanSelectionListener);
+ valueInCombo = true;
+ }
+ else
+ {
+ int style = SWT.NONE;
+ if (PASSWORD.equalsIgnoreCase(param.getName()))
+ {
+ style = SWT.PASSWORD;
+ }
+ Text text = _toolkit.createText(_paramsComposite, "", style);
+ formData = new FormData();
+ formData.top = new FormAttachment(0, parameterPositionOffset);
+ formData.left = new FormAttachment(label, 5);
+ formData.right = new FormAttachment(valueWidth);
+ text.setLayoutData(formData);
+ // Listener to assign value to the parameter
+ text.addKeyListener(keyListener);
+ // Listener to verify if the entered key is valid
+ text.addVerifyListener(verifyListener);
+ text.setData(param);
+ }
+
+ // display the parameter data type next to the text field
+ if (valueInCombo)
+ {
+ label = _toolkit.createLabel(_paramsComposite, "");
+ }
+ else if (PASSWORD.equalsIgnoreCase(param.getName()))
+ {
+ label = _toolkit.createLabel(_paramsComposite, "(String)");
+ }
+ 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, parameterPositionOffset);
+ formData.left = new FormAttachment(valueWidth, 5);
+ label.setLayoutData(formData);
+ }
+ }
+
+ private boolean isUserListParameter(ParameterData param)
+ {
+ if (_mbean.isAdmin() && param.getName().equals(OPERATION_PARAM_USERNAME)
+ && !_opData.getName().equals(OPERATION_CREATEUSER))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Creates customized dispaly for a method "CreateNewBinding" for Headers exchange
+ *
+ */
+ 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(labelWidth);
+ 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(valueWidth);
+
+ Combo combo = new Combo(composite, SWT.READ_ONLY | SWT.DROP_DOWN);
+ List<String> qList = ApplicationRegistry.getServerRegistry(_mbean).getQueueNames(_virtualHostName);
+ combo.setItems(qList.toArray(new String[0]));
+ 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();
+ }
+
+ /**
+ * Adds a row for adding a binding for Headers Exchange. Used by the method, which creates the customized
+ * layout and widgest for Header's exchange method createNewBinding.
+ * @param parent composite
+ * @param rowCount - row number
+ */
+ 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);
+ }
+
+ /**
+ * Sets text and listener for the operation execution button
+ * @param text
+ */
+ private void setButton(String text)
+ {
+ _executionButton.setText(text);
+ _executionButton.removeSelectionListener(refreshListener);
+ _executionButton.removeSelectionListener(operationExecutionListener);
+
+ if (BUTTON_EXECUTE.equals(text))
+ {
+ _executionButton.addSelectionListener(operationExecutionListener);
+ }
+ else
+ {
+ _executionButton.addSelectionListener(refreshListener);
+ }
+ }
+
+ /**
+ * displays the operation result in a pop-up window
+ * @param result
+ */
+ private void populateResults(Object result)
+ {
+ Display display = Display.getCurrent();
+ int width = 610;
+ int height = 400;
+ Shell shell = ViewUtility.createPopupShell(RESULT, width, height);
+ shell.setImage(ApplicationRegistry.getImage(CONSOLE_IMAGE));
+ ViewUtility.populateCompositeWithData(_toolkit, shell, result);
+
+ shell.open();
+ while (!shell.isDisposed()) {
+ if (!display.readAndDispatch()) {
+ display.sleep();
+ }
+ }
+ shell.dispose();
+ }
+
+ /**
+ * Clears the parameter values of the operation
+ */
+ private void clearParameters()
+ {
+ List<ParameterData> params = _opData.getParameters();
+ if (params != null && !params.isEmpty())
+ {
+ for (ParameterData param : params)
+ {
+ param.setDefaultValue();
+ }
+ }
+ }
+
+ /**
+ * Clears the values entered by the user from parameter value widgets
+ * @param control
+ */
+ private void clearParameterValues(Composite control)
+ {
+ if (control == null || (control.isDisposed()))
+ return;
+
+ 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);
+ if (controls[i] instanceof org.eclipse.swt.widgets.List)
+ ((org.eclipse.swt.widgets.List)controls[i]).deselectAll();
+ else if (controls[i] instanceof Text)
+ ((Text)controls[i]).setText("");
+ else if (controls[i] instanceof Button)
+ ((Button)controls[i]).setSelection(false);
+ 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)
+ {
+ // Customized check, because for this parameter null is allowed
+ if (param.getName().equals(ATTRIBUTE_QUEUE_OWNER) &&
+ _opData.getName().equals(OPERATION_CREATE_QUEUE))
+ {
+ continue;
+ }
+ // End of custom code
+
+ ViewUtility.popupInfoMessage(_form.getText(), "Please select the " + ViewUtility.getDisplayText(param.getName()));
+ return;
+ }
+
+ //Custom handling for the PASSWORD field
+ if (param.getName().equalsIgnoreCase(PASSWORD))
+ {
+ //Convert the String value to a character array if that is what is required.
+ if (param.getType().equals("[C"))
+ {
+ // Retreive the mBean type and version.
+ // If we have a version 1 UserManagement class mbean then it expects the password
+ // to be sent as the hashed version.
+ if (_mbean.getType().equals("UserManagement") && _mbean.getVersion() == 1)
+ {
+ try
+ {
+ param.setValue(ViewUtility.getHash((String) param.getValue()));
+ }
+ catch (Exception hashException)
+ {
+ ViewUtility.popupErrorMessage(_form.getText(),
+ "Unable to calculate hash for Password:"
+ + hashException.getMessage());
+ return;
+ }
+ }
+ else
+ {
+ param.setValue(((String) param.getValue()).toCharArray());
+ }
+ }
+ }
+ // end of customization
+
+ }
+ }
+
+ if (_opData.getImpact() == 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();
+ }
+
+ if (_mbean.isAdmin() && _opData.getName().equals(OPERATION_DELETEUSER))
+ {
+ refresh(_mbean);
+ }
+ else
+ {
+ clearParameters();
+ clearParameterValues(_paramsComposite);
+ }
+ }
+ }
+
+ // Listener for the "Refresh" execution button
+ private class RefreshListener extends SelectionAdapter
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ executeAndShowResults();
+ }
+ }
+
+ /**
+ * Executres the operation, gets the result from server and displays to the user
+ */
+ private void executeAndShowResults()
+ {
+ Object result = null;
+ try
+ {
+ result = MBeanUtility.execute(_mbean, _opData);
+ }
+ catch(Exception ex)
+ {
+ MBeanUtility.handleException(_mbean, ex);
+ return;
+ }
+
+ // Custom code for Admin mbean operation
+ /* These custome codes here are to make the GUI look more user friendly.
+ * Here we are adding the users to a list, which will be used to list username to be selected on
+ * pages like "delete user", "set password" instead of typing the username
+ */
+ if (_mbean.isAdmin())
+ {
+ if (_opData.getName().equals(OPERATION_VIEWUSERS))
+ {
+ ApplicationRegistry.getServerRegistry(_mbean).setUserList(extractUserList(result));
+ }
+ else if (_opData.getName().equals(OPERATION_DELETEUSER))
+ {
+ List<String> list = ApplicationRegistry.getServerRegistry(_mbean).getUsernames();
+ Object userName = _opData.getParameterValue(OPERATION_PARAM_USERNAME);
+ if ((list != null) && !list.isEmpty() && (userName != null))
+ {
+ list.remove(userName);
+ ApplicationRegistry.getServerRegistry(_mbean).setUserList(list);
+ }
+ }
+ else if (_opData.getName().equals(OPERATION_CREATEUSER))
+ {
+ List<String> list = ApplicationRegistry.getServerRegistry(_mbean).getUsernames();
+ Object userName = _opData.getParameterValue(OPERATION_PARAM_USERNAME);
+ if ((list != null) && !list.isEmpty() && (userName != null))
+ {
+ list.add(userName.toString());
+ ApplicationRegistry.getServerRegistry(_mbean).setUserList(list);
+ }
+ }
+ }
+ // end of custom code
+
+ // Some mbeans have only "type" and no "name".
+ String title = _mbean.getType();
+ if (_mbean.getName() != null && _mbean.getName().length() != 0)
+ {
+ title = _mbean.getName();
+ }
+
+ if (_opData.isReturnTypeVoid())
+ {
+ ViewUtility.popupInfoMessage(title, OPERATION_SUCCESSFUL);
+ }
+ else if (_opData.isReturnTypeBoolean())
+ {
+ boolean success = Boolean.parseBoolean(result.toString());
+ String message = success ? OPERATION_SUCCESSFUL : OPERATION_UNSUCCESSFUL;
+ if(success)
+ {
+ ViewUtility.popupInfoMessage(title, message);
+ }
+ else
+ {
+ ViewUtility.popupErrorMessage(title, message);
+ }
+ }
+ else if (_opData.getParameters() != null && !_opData.getParameters().isEmpty())
+ {
+ populateResults(result);
+ }
+ else
+ {
+ ViewUtility.disposeChildren(_resultsComposite);
+ ViewUtility.populateCompositeWithData(_toolkit, _resultsComposite, result);
+ _resultsComposite.layout();
+ _form.layout();
+ }
+
+ }
+
+ private List<String> extractUserList(Object result)
+ {
+ if (!(result instanceof TabularDataSupport))
+ {
+ return null;
+ }
+
+ TabularDataSupport tabularData = (TabularDataSupport)result;
+ Collection<Object> records = tabularData.values();
+ List<String> list = new ArrayList<String>();
+ for (Object o : records)
+ {
+ CompositeData data = (CompositeData) o;
+ if (data.containsKey(USERNAME))
+ {
+ list.add(data.get(USERNAME).toString());
+ }
+ }
+
+ return list;
+ }
+
+ /**
+ * Listener class for the operation parameters widget
+ */
+ private static class ParameterSelectionListener extends SelectionAdapter
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ ParameterData parameter = (ParameterData)e.widget.getData();
+ parameter.setValue(null);
+ if (e.widget instanceof Combo)
+ {
+ Combo combo = (Combo)e.widget;
+ if (combo.getSelectionIndex() > 0)
+ {
+ String item = combo.getItem(combo.getSelectionIndex());
+ parameter.setValueFromString(item);
+ }
+ }
+ else if (e.widget instanceof org.eclipse.swt.widgets.List)
+ {
+ org.eclipse.swt.widgets.List list = (org.eclipse.swt.widgets.List)e.widget;
+ String[] selectedItems = list.getSelection();
+ if (selectedItems.length > 0)
+ {
+ parameter.setValueFromString(selectedItems[0]);
+ }
+ }
+ }
+ }
+
+ /**
+ * Listener class for boolean parameter widgets
+ */
+ private static class BooleanSelectionListener extends SelectionAdapter
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ ParameterData parameter = (ParameterData)(e.widget.getData());
+ if (e.widget instanceof Button)
+ {
+ Button button = (Button)e.widget;
+ parameter.setValue(button.getSelection());
+ }
+ else if (e.widget instanceof Combo)
+ {
+ Combo combo = (Combo)e.widget;
+ String item = combo.getItem(combo.getSelectionIndex());
+ parameter.setValueFromString(item);
+ }
+ }
+ }
+
+ /**
+ * Listener class for the operation parameter value widget (Text field)
+ */
+ private static 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();
+ try
+ {
+ parameter.setValueFromString(strValue);
+ }
+ catch(Exception ex)
+ {
+ // Exception occured in setting parameter value.
+ // ignore it. The value will not be assigned to the parameter
+ }
+ }
+ }
+
+ /**
+ * Listener class for HeaderExchange's new binding widgets. Used when the new bindings are
+ * being created for Header's Exchange
+ */
+ 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());
+ }
+ }
+
+ /**
+ * Listener class for verifying the user input with parameter type
+ */
+ private static class VerifyListenerImpl implements VerifyListener
+ {
+ public void verifyText(VerifyEvent event)
+ {
+ ParameterData parameter = (ParameterData)event.widget.getData();
+ String text = event.text;
+ char [] chars = new char [text.length ()];
+ text.getChars(0, chars.length, chars, 0);
+ 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/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TabControl.java
new file mode 100644
index 0000000000..156543d603
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TabControl.java
@@ -0,0 +1,103 @@
+/*
+ *
+ * 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 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;
+
+/**
+ * Abstract class for all the control classes of tabs.
+ * @author Bhupendra Bhardwaj
+ */
+public abstract class TabControl
+{
+ public static final String CONTROLLER = "controller";
+ protected ManagedBean _mbean = null;
+ protected TabFolder _tabFolder = null;
+
+ private static java.util.List<String> simpleTypes = new ArrayList<String>();
+
+ static
+ {
+ simpleTypes.add("java.math.BigDecimal");
+ simpleTypes.add("java.math.BigInteger");
+ simpleTypes.add("java.lang.Boolean");
+ simpleTypes.add("java.lang.Byte");
+ simpleTypes.add("java.lang.Character");
+ simpleTypes.add("java.util.Date");
+ simpleTypes.add("java.lang.Double");
+ simpleTypes.add("java.lang.Float");
+ simpleTypes.add("java.lang.Integer");
+ simpleTypes.add("java.lang.Long");
+ simpleTypes.add("javax.management.ObjectName");
+ simpleTypes.add("java.lang.Short");
+ simpleTypes.add("java.lang.String");
+ simpleTypes.add("boolean");
+ }
+
+ public TabControl(TabFolder tabFolder)
+ {
+ _tabFolder = tabFolder;
+ }
+
+ /**
+ * @return controller composite for the tab
+ */
+ public Control getControl()
+ {
+ return null;
+ }
+
+ public void refresh(ManagedBean mbean)
+ {
+ if (mbean == null)
+ {
+ refresh();
+ }
+ }
+
+ public void refresh()
+ {
+
+ }
+
+ public void refresh(ManagedBean mbean, OperationData opData)
+ {
+
+ }
+
+ /**
+ * Sets focus on a widget
+ */
+ public void setFocus()
+ {
+
+ }
+
+ public boolean isSimpleType(Object data)
+ {
+ return simpleTypes.contains(data.getClass().getName());
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TreeObject.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TreeObject.java
new file mode 100644
index 0000000000..9545ed9876
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/TreeObject.java
@@ -0,0 +1,126 @@
+/*
+ *
+ * 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 _virtualHost;
+ 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))
+ {
+ String[] types = ((ManagedBean)obj).getType().split("\\.");
+ _name = types[types.length - 1];
+ }
+ 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 getVirtualHost()
+ {
+ // To make it work with the broker with no virtual host implementation
+ return _virtualHost == null ? Constants.DEFAULT_VH : _virtualHost;
+ }
+
+ public void setVirtualHost(String vHost)
+ {
+ _virtualHost = vHost;
+ }
+
+ 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)
+ {
+ parent.addChild(this);
+ }
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/VHNotificationsTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/VHNotificationsTabControl.java
new file mode 100644
index 0000000000..d23355501f
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/VHNotificationsTabControl.java
@@ -0,0 +1,484 @@
+/*
+ *
+ * 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 static org.apache.qpid.management.ui.Constants.BUTTON_CLEAR;
+import static org.apache.qpid.management.ui.Constants.CONSOLE_IMAGE;
+import static org.apache.qpid.management.ui.Constants.FONT_BUTTON;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.qpid.management.ui.ApplicationRegistry;
+import org.apache.qpid.management.ui.ServerRegistry;
+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.IStructuredSelection;
+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.graphics.Image;
+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.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;
+
+public class VHNotificationsTabControl extends TabControl
+{
+ protected FormToolkit _toolkit;
+ protected Form _form;
+ protected Table _table = null;
+ protected TableViewer _tableViewer = null;
+
+ protected Thread _worker = null;
+ protected boolean _workerRunning = false;
+
+ protected List<NotificationObject> _notifications = null;
+
+ private static final String COLUMN_OBJ = "Object Name";
+ 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[] TABLE_TITLES = new String [] {
+ COLUMN_OBJ,
+ COLUMN_SEQ,
+ COLUMN_TIME,
+ COLUMN_TYPE,
+ COLUMN_MSG
+ };
+
+ protected Button _clearButton = null;
+
+ public VHNotificationsTabControl(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();
+ }
+
+ protected void createWidgets()
+ {
+ addButtons();
+ createTableViewer();
+ }
+
+ /**
+ * @see TabControl#getControl()
+ */
+ public Control getControl()
+ {
+ return _form;
+ }
+
+ /**
+ * Creates clear buttin and refresh button
+ */
+ protected void addButtons()
+ {
+ Composite composite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
+ composite.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false));
+ composite.setLayout(new GridLayout(2,false));
+
+ // Add Clear Button
+ _clearButton = _toolkit.createButton(composite, BUTTON_CLEAR, SWT.PUSH | SWT.CENTER);
+ _clearButton.setFont(ApplicationRegistry.getFont(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)
+ {
+ ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(MBeanView.getServer());
+ IStructuredSelection ss = (IStructuredSelection)_tableViewer.getSelection();
+ if(!ss.isEmpty())
+ {
+ //clear selected Notifications
+ serverRegistry.clearNotifications(null, ss.toList());
+ }
+ else if(_notifications != null)
+ {
+ //clear all the notifications, if there are any
+
+ //check the user is certain of this clear-all operation
+ int response = ViewUtility.popupOkCancelConfirmationMessage(
+ "Clear Notifications", "Clear all Notifications for this VirtualHost?");
+ if(response != SWT.OK)
+ {
+ return;
+ }
+
+ synchronized(this)
+ {
+ serverRegistry.clearNotifications(null, _notifications);
+ }
+ }
+
+ refresh();
+ }
+ });
+ //add description
+ Label desc = _toolkit.createLabel(composite,"Clears the selected Notifications, or all if none are selected");
+ desc.setLayoutData(new GridData(SWT.LEFT,SWT.CENTER, false, false));
+ }
+
+ /**
+ * Creates table to display notifications
+ */
+ private void createTable()
+ {
+ _table = _toolkit.createTable(_form.getBody(), SWT.MULTI | SWT.FULL_SELECTION);
+ _table.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+ TableColumn column = new TableColumn(_table, SWT.NONE);
+ column.setText(TABLE_TITLES[0]);
+ column.setWidth(100);
+
+ column = new TableColumn(_table, SWT.NONE);
+ column.setText(TABLE_TITLES[1]);
+ column.setWidth(100);
+
+ column = new TableColumn(_table, SWT.NONE);
+ column.setText(TABLE_TITLES[2]);
+ column.setWidth(130);
+
+ column = new TableColumn(_table, SWT.NONE);
+ column.setText(TABLE_TITLES[3]);
+ column.setWidth(100);
+
+ column = new TableColumn(_table, SWT.NONE);
+ column.setText(TABLE_TITLES[4]);
+ column.setWidth(500);
+
+ _table.setHeaderVisible(true);
+ _table.setLinesVisible(true);
+ }
+
+ /**
+ * Creates JFace viewer for the notifications table
+ */
+ protected void createTableViewer()
+ {
+ createTable();
+ _tableViewer = new TableViewer(_table);
+ _tableViewer.setUseHashlookup(true);
+ _tableViewer.setContentProvider(new ContentProviderImpl());
+ _tableViewer.setLabelProvider(new LabelProviderImpl());
+ _tableViewer.setColumnProperties(TABLE_TITLES);
+
+ addTableListeners();
+ }
+
+ /**
+ * Adds listeners to the viewer for displaying notification details
+ */
+ protected void addTableListeners()
+ {
+ _tableViewer.addDoubleClickListener(new IDoubleClickListener()
+ {
+ Display display = null;
+ Shell shell = null;
+ public void doubleClick(DoubleClickEvent event)
+ {
+ display = Display.getCurrent();
+ shell = new Shell(display, SWT.BORDER | SWT.CLOSE | SWT.MIN | SWT.MAX | SWT.RESIZE);
+ shell.setText("Notification");
+ shell.setImage(ApplicationRegistry.getImage(CONSOLE_IMAGE));
+
+ 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 = _toolkit.createComposite(shell, SWT.NONE);
+ parent.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ GridLayout layout = new GridLayout(4, true);
+ parent.setLayout(layout);
+
+ // Object name record
+ Label key = _toolkit.createLabel(parent, COLUMN_OBJ, SWT.TRAIL);
+ GridData layoutData = new GridData(SWT.TRAIL, SWT.TOP, false, false,1,1);
+ key.setLayoutData(layoutData);
+ Text value = _toolkit.createText(parent, obj.getSourceName(), SWT.BEGINNING | SWT.BORDER |SWT.READ_ONLY);
+ value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false,3,1));
+
+ // Sequence no record
+ key = _toolkit.createLabel(parent, COLUMN_SEQ, SWT.TRAIL);
+ layoutData = new GridData(SWT.TRAIL, SWT.TOP, false, false,1,1);
+ key.setLayoutData(layoutData);
+ value = _toolkit.createText(parent, ""+obj.getSequenceNo(), SWT.BEGINNING | SWT.BORDER |SWT.READ_ONLY);
+ value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false,3,1));
+
+ // Time row
+ key = _toolkit.createLabel(parent, COLUMN_TIME, SWT.TRAIL);
+ key.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, true, false,1,1));
+ value = _toolkit.createText(parent, obj.getTimeStamp(), SWT.BEGINNING | SWT.BORDER | SWT.READ_ONLY);
+ value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false,3,1));
+
+ key = _toolkit.createLabel(parent, COLUMN_TYPE, SWT.TRAIL);
+ key.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, true, false,1,1));
+ value = _toolkit.createText(parent, obj.getType(), SWT.BEGINNING | SWT.BORDER | SWT.READ_ONLY);
+ value.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false,3,1));
+
+ key = _toolkit.createLabel(parent, COLUMN_MSG, SWT.TRAIL);
+ key.setLayoutData(new GridData(SWT.TRAIL, SWT.TOP, true, false,1,1));
+ value = _toolkit.createText(parent, obj.getMessage(), SWT.MULTI | SWT.WRAP| SWT.BORDER | SWT.V_SCROLL | SWT.READ_ONLY);
+ GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1);
+ gridData.heightHint = 100;
+ value.setLayoutData(gridData);
+ }
+ });
+ }
+
+ public void refresh()
+ {
+ if(_workerRunning)
+ {
+ //perform an single immediate-update
+ updateTableViewer();
+ }
+ else
+ {
+ //start a worker to do the update and keep going as required
+ _workerRunning = true;
+ _worker = new Thread(new Worker());
+ _worker.start();
+ }
+
+ _form.layout(true);
+ _form.getBody().layout(true, true);
+ }
+
+ /**
+ * Content provider class for the table viewer
+ */
+ protected class ContentProviderImpl implements IStructuredContentProvider, INotificationViewer
+ {
+ public void inputChanged(Viewer v, Object oldInput, Object newInput)
+ {
+
+ }
+ public void dispose()
+ {
+
+ }
+ public Object[] getElements(Object parent)
+ {
+ synchronized(VHNotificationsTabControl.this)
+ {
+ 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]));
+ }
+ }
+
+ /**
+ * Label provider for the table viewer
+ */
+ protected static 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 = t.getSourceName();
+ break;
+ case 1 :
+ result = String.valueOf(t.getSequenceNo());
+ break;
+ case 2 :
+ result = String.valueOf(t.getTimeStamp());
+ break;
+ case 3 :
+ result = t.getType();
+ break;
+ case 4 :
+ 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
+
+
+ protected void setWorkerRunning(boolean running)
+ {
+ _workerRunning = running;
+ }
+
+ /**
+ * Worker class which keeps looking if there are new notifications coming from server for the selected mbean
+ */
+ private class Worker implements Runnable
+ {
+ private boolean keepGoing = true;
+
+ public void run()
+ {
+ final Display display = _tabFolder.getDisplay();
+
+ while(keepGoing)
+ {
+ if (display == null || display.isDisposed())
+ {
+ setWorkerRunning(false);
+ break; //stop the thread
+ }
+
+ display.syncExec(new Runnable()
+ {
+ public void run()
+ {
+ if (_form == null || _form.isDisposed())
+ {
+ setWorkerRunning(false);
+ keepGoing = false; //exit the loop and stop the thread
+ }
+ else
+ {
+ keepGoing = _form.isVisible();
+ setWorkerRunning(keepGoing);
+ }
+
+ if (keepGoing)
+ {
+ updateTableViewer();
+ }
+ }
+ });
+
+ if (keepGoing)
+ {
+ sleep();
+ }
+ }
+ }
+
+ private void sleep()
+ {
+ try
+ {
+ Thread.sleep(2000);
+ }
+ catch(Exception ex)
+ {
+
+ }
+ }
+ }
+
+ /**
+ * Updates the table with new notifications received from mbean server for all mbeans in this virtual host
+ */
+ protected void updateTableViewer()
+ {
+ String virtualhost = MBeanView.getVirtualHost();
+
+ ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(MBeanView.getServer());
+ List<NotificationObject> newList = serverRegistry.getNotifications(virtualhost);
+
+ synchronized(this)
+ {
+ _notifications = newList;
+ _tableViewer.setInput(_notifications);
+ }
+ }
+
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/ViewUtility.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/ViewUtility.java
new file mode 100644
index 0000000000..8e4bea39e9
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/ViewUtility.java
@@ -0,0 +1,1032 @@
+/*
+ *
+ * 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.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+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.CompositeDataSupport;
+import javax.management.openmbean.CompositeType;
+import javax.management.openmbean.OpenType;
+import javax.management.openmbean.TabularDataSupport;
+import javax.management.openmbean.TabularType;
+
+import org.apache.commons.codec.binary.Hex;
+import org.apache.qpid.management.ui.ApplicationRegistry;
+import static org.apache.qpid.management.ui.Constants.FAILURE_IMAGE;
+import static org.apache.qpid.management.ui.Constants.SUCCESS_IMAGE;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.events.SelectionListener;
+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.Button;
+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.MessageBox;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.swt.widgets.ScrollBar;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+/**
+ * Utility Class for displaying OpenMbean data types by creating required SWT widgets
+ */
+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 final Comparator tabularDataComparator = new TabularDataComparator();
+
+ private static MBeanView _mbeanView = null;
+
+ 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");
+ }
+
+ private static final int DEFAULT_CONTENT_SIZE = 198;
+ static Button _firstButton, _nextButton, _previousButton, _lastButton;
+ static Text _hexNumTextToEnd, _hexNumTextToStart;
+
+ /**
+ * Populates the composite with given openmbean data type (TabularType or CompositeType)
+ * @param toolkit
+ * @param parent composite
+ * @param data open mbean data type(either composite type or tabular data type)
+ */
+ public static void populateCompositeWithData(FormToolkit toolkit, Composite parent, Object data)
+ {
+ if (data instanceof TabularDataSupport)
+ {
+ ViewUtility.createTabularDataHolder(toolkit, parent, (TabularDataSupport)data);
+ }
+ else if (data instanceof CompositeDataSupport)
+ {
+ ViewUtility.populateCompositeWithCompositeData(toolkit, parent, (CompositeDataSupport)data);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private static void createTabularDataHolder(FormToolkit toolkit, Composite parent, TabularDataSupport tabularData)
+ {
+ Composite composite = toolkit.createComposite(parent, SWT.BORDER);
+ 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 = toolkit.createText(composite, " No records ", SWT.CENTER | SWT.SINGLE | SWT.READ_ONLY);
+ GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true, 4, 1);
+ text.setLayoutData(layoutData);
+ return;
+ }
+
+ Collections.sort(list, tabularDataComparator);
+
+ // Attach the tabular record to be retrieved and shown later when record is traversed
+ // using first/next/previous/last buttons
+ composite.setData(list);
+
+ // Create button and the composite for CompositeData
+ Composite compositeDataHolder = createCompositeDataHolder(toolkit, composite,
+ tabularData.getTabularType().getRowType());
+
+ // display the first record
+ CompositeData data = (CompositeData)(list.get(0)).getValue();
+ composite.setData(INDEX, 0);
+ populateCompositeWithCompositeData(toolkit, compositeDataHolder, data);
+ enableOrDisableTraversalButtons(composite);
+ }
+
+ private 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);
+ }
+ }
+
+ /**
+ * Sets up the given composite for holding a CompositeData. Create traversal buttons, label etc and
+ * creates a child Composite, which should be populated with the CompositeData
+ * @param toolkit
+ * @param dataHolder
+ * @param compositeType
+ * @return
+ */
+ private static Composite createCompositeDataHolder(final FormToolkit toolkit, final Composite dataHolder, CompositeType compositeType)
+ {
+ String desc = compositeType.getDescription();
+ Label description = toolkit.createLabel(dataHolder, desc, SWT.CENTER);
+ description.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, true, false, 4, 1));
+ // TODO nameLabel.setFont(font);
+ description.setText(desc);
+
+ // Add traversal buttons
+ final Button firstRecordButton = toolkit.createButton(dataHolder, FIRST, SWT.PUSH);
+ GridData layoutData = new GridData (GridData.HORIZONTAL_ALIGN_END);
+ layoutData.widthHint = 80;
+ firstRecordButton.setLayoutData(layoutData);
+
+ final Button previousRecordButton = toolkit.createButton(dataHolder, PREV, SWT.PUSH);
+ layoutData = new GridData (GridData.HORIZONTAL_ALIGN_END);
+ layoutData.widthHint = 80;
+ previousRecordButton.setLayoutData(layoutData);
+
+ final Button nextRecordButton = toolkit.createButton(dataHolder, NEXT, SWT.PUSH);
+ layoutData = new GridData (GridData.HORIZONTAL_ALIGN_BEGINNING);
+ layoutData.widthHint = 80;
+ nextRecordButton.setLayoutData(layoutData);
+
+ final Button lastRecordButton = toolkit.createButton(dataHolder, LAST, SWT.PUSH);
+ layoutData = new GridData (GridData.HORIZONTAL_ALIGN_BEGINNING);
+ layoutData.widthHint = 80;
+ lastRecordButton.setLayoutData(layoutData);
+
+ // Now create the composite, which will hold the CompositeData
+ final Composite composite = toolkit.createComposite(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. When a button is clicked the respective
+ // CompositeData will be populated in the composite
+ SelectionListener listener = new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ if (!(e.widget instanceof Button))
+ return;
+
+ Button traverseButton =(Button)e.widget;
+ // Get the CompositeData respective to the button selected
+ CompositeData data = getCompositeData(dataHolder, traverseButton.getText());
+ populateCompositeWithCompositeData(toolkit, composite, data);
+ enableOrDisableTraversalButtons(dataHolder);
+ }
+ };
+
+ firstRecordButton.addSelectionListener(listener);
+ nextRecordButton.addSelectionListener(listener);
+ previousRecordButton.addSelectionListener(listener);
+ lastRecordButton.addSelectionListener(listener);
+
+ return composite;
+ }
+
+ /**
+ * The CompositeData is set as data with the Composite and using the index, this method will
+ * return the corresponding CompositeData
+ * @param compositeHolder
+ * @param dataIndex
+ * @return the CompositeData respective to the index
+ */
+ 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);
+
+ return (CompositeData)((Map.Entry)objectData.get(index)).getValue();
+ }
+
+ /**
+ * Populates the given composite with the CompositeData. Creates required widgets to hold the data types
+ * @param toolkit
+ * @param parent
+ * @param data CompositeData
+ */
+ @SuppressWarnings("unchecked")
+ private static void populateCompositeWithCompositeData(FormToolkit toolkit, Composite parent, CompositeData data)
+ {
+ Control[] oldControls = parent.getChildren();
+ for (int i = 0; i < oldControls.length; i++)
+ {
+ oldControls[i].dispose();
+ }
+
+ Composite compositeHolder = toolkit.createComposite(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);
+ Label keyLabel = toolkit.createLabel(compositeHolder, itemName, SWT.TRAIL);
+ GridData layoutData = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1);
+ layoutData.minimumWidth = 70;
+ keyLabel.setLayoutData(layoutData);
+
+ if (itemType.isArray())
+ {
+ OpenType type = ((ArrayType)itemType).getElementOpenType();
+ // 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");
+ }
+ if (data.containsKey("Encoding"))
+ {
+ encoding = (String)data.get("Encoding");
+ }
+
+ if (encoding == null || encoding.length() == 0)
+ {
+ encoding = Charset.defaultCharset().name();
+ }
+
+ if ("text/plain".equals(mimeType))
+ {
+ convertByteArray(toolkit, compositeHolder, data, itemName, encoding);
+ }
+ else
+ {
+ handleBinaryMessageContent(toolkit, compositeHolder, data, itemName, encoding);
+ }
+ }
+ // If array of any other supported type, show as a list of String array
+ else if (SUPPORTED_ARRAY_DATATYPES.contains(type.getClassName()))
+ {
+ convertArrayItemForDisplay(compositeHolder, data, itemName);
+ }
+ else
+ {
+ setNotSupportedDataType(toolkit, compositeHolder);
+ }
+ }
+ else if (itemType instanceof TabularType)
+ {
+ Composite composite = toolkit.createComposite(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(toolkit, composite, (TabularDataSupport)data.get(itemName));
+ }
+ else
+ {
+ Text valueText = toolkit.createText(compositeHolder, String.valueOf(data.get(itemName)), SWT.READ_ONLY | SWT.BORDER);
+ 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 convertByteArray(FormToolkit toolkit, 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);
+
+ Text valueText = toolkit.createText(compositeHolder, textMessage, SWT.READ_ONLY | SWT.BORDER |
+ SWT.MULTI | SWT.WRAP | SWT.V_SCROLL);
+ GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1);
+ gridData.heightHint = 300;
+ valueText.setLayoutData(gridData);
+ }
+ catch(Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+
+ private static Shell getShell()
+ {
+ Shell shell = Display.getCurrent().getActiveShell();
+
+ // Under linux GTK getActiveShell returns null so we need to make a new shell for display.
+ // Under windows this is fine.
+ if (shell == null)
+ {
+ // This occurs under linux gtk
+ shell = new Shell(Display.getCurrent(), SWT.BORDER | SWT.CLOSE | SWT.MIN | SWT.MAX);
+ }
+
+ return shell;
+ }
+
+ private static int showBox(String title, String message, int icon)
+ {
+ MessageBox messageBox = new MessageBox(getShell(), icon);
+ messageBox.setMessage(message);
+ messageBox.setText(title);
+
+ return messageBox.open();
+ }
+
+ /**
+ * Creates widgets for object messages and populates the content in hexadecimal format.
+ * @param toolkit
+ * @param compositeHolder
+ * @param data
+ * @param itemName
+ * @param encoding
+ */
+ private static void handleBinaryMessageContent(FormToolkit toolkit, Composite compositeHolder, CompositeData data, String itemName, String encoding)
+ {
+ final String thisEncoding = encoding;
+ final Byte[] arrayItems = (Byte[]) data.get(itemName);
+ final byte[] byteArray = new byte[arrayItems.length];
+
+ for (int i = 0; i < arrayItems.length; i++)
+ {
+ byteArray[i] = arrayItems[i];
+ }
+
+ try
+ {
+ //create a new composite to contain the widgets required to display object messages.
+ final Composite localComposite = toolkit.createComposite(compositeHolder, SWT.NONE);
+ localComposite.setData("currentBytePos", 0);
+ localComposite.setData("startingBytePos", 0);
+ GridLayout layout = new GridLayout(2, true);
+ layout.marginWidth = 0;
+ layout.marginHeight = 0;
+ localComposite.setLayout(layout);
+ localComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1));
+
+ int startContentSize = DEFAULT_CONTENT_SIZE;
+
+ if (byteArray.length < DEFAULT_CONTENT_SIZE)
+ {
+ startContentSize = byteArray.length;
+ }
+
+ //create a text to display the hexadecimal views of object messages, it takes more space than ascii view as
+ //a hex uses 2 chars and 1 space, while ascii only uses 1 char and 1 space.
+ final Text hexText = toolkit.createText(localComposite,
+ displayByteFormat(localComposite, byteArray, startContentSize * 2, thisEncoding, "<<", true),
+ SWT.READ_ONLY | SWT.MULTI | SWT.WRAP | SWT.V_SCROLL | SWT.BORDER);
+ GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1);
+ gridData.widthHint = 144; //set to 222 if not using any fonts
+ gridData.heightHint = 200;
+ hexText.setLayoutData(gridData);
+
+ final Text asciiText = toolkit.createText(localComposite,
+ displayByteFormat(localComposite, byteArray, startContentSize * 2, thisEncoding, "<<", false),
+ SWT.READ_ONLY | SWT.MULTI | SWT.WRAP | SWT.V_SCROLL | SWT.BORDER);
+
+
+ gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 1, 1);
+ gridData.widthHint = 52;//set to 98 if not using any fonts
+ gridData.heightHint = 200;
+ asciiText.setLayoutData(gridData);
+
+ //use a monospaced font for a better layout
+ Font font = new Font(compositeHolder.getDisplay(), "Courier", 10, SWT.NORMAL);
+ hexText.setFont(font);
+ asciiText.setFont(font);
+
+ final ScrollBar hexScrollBar = hexText.getVerticalBar();
+ final ScrollBar asciiScrollBar = asciiText.getVerticalBar();
+
+ //create a sub composite to contain all the buttons
+ final Composite buttonComposite = toolkit.createComposite(localComposite, SWT.NONE);
+ layout = new GridLayout(7, false);
+ layout.marginWidth = 0;
+ buttonComposite.setLayout(layout);
+ buttonComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 2, 1));
+
+ _firstButton = toolkit.createButton(buttonComposite, "<<", SWT.PUSH);
+ GridData layoutData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ layoutData.widthHint = 40;
+ _firstButton.setLayoutData(layoutData);
+ _firstButton.setToolTipText("See the first n bytes");
+
+ _previousButton = toolkit.createButton(buttonComposite, "<", SWT.PUSH);
+ layoutData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ layoutData.widthHint = 40;
+ _previousButton.setLayoutData(layoutData);
+ _previousButton.setToolTipText("See the previous n bytes");
+ _previousButton.setEnabled(false);
+
+ _hexNumTextToStart = toolkit.createText(buttonComposite, "0");
+ layoutData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ layoutData.widthHint = 40;
+ _hexNumTextToStart.setLayoutData(layoutData);
+ _hexNumTextToStart.setEditable(false);
+
+ final Text hexNumText = toolkit.createText(buttonComposite, "" + startContentSize);
+ layoutData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ layoutData.widthHint = 40;
+ hexNumText.setLayoutData(layoutData);
+
+ _hexNumTextToEnd = toolkit.createText(buttonComposite, "" + (byteArray.length - startContentSize));
+ layoutData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ layoutData.widthHint = 40;
+ _hexNumTextToEnd.setLayoutData(layoutData);
+ _hexNumTextToEnd.setEditable(false);
+
+ _nextButton = toolkit.createButton(buttonComposite, ">", SWT.PUSH);
+ layoutData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ layoutData.widthHint = 40;
+ _nextButton.setLayoutData(layoutData);
+ _nextButton.setToolTipText("See the next n bytes");
+ _nextButton.setEnabled(true);
+
+ _lastButton = toolkit.createButton(buttonComposite, ">>", SWT.PUSH);
+ layoutData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
+ layoutData.widthHint = 40;
+ _lastButton.setToolTipText("See the last n bytes");
+ _lastButton.setLayoutData(layoutData);
+
+ SelectionListener listener = new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ if (e.widget instanceof Button)
+ {
+ String numOfBytes = hexNumText.getText();
+ try
+ {
+ int n = Integer.parseInt(numOfBytes);
+
+ //Reset range display if user requests a large value
+ if (n > byteArray.length)
+ {
+ n = (byteArray.length > DEFAULT_CONTENT_SIZE) ? DEFAULT_CONTENT_SIZE : byteArray.length;
+ hexNumText.setText("" + n);
+ }
+
+ //rest if the user requests 0
+ if (n < 1)
+ {
+ n = DEFAULT_CONTENT_SIZE;
+ hexNumText.setText("" + n);
+ }
+
+ Button button = (Button) e.widget;
+ hexText.setText(displayByteFormat(localComposite, byteArray, n * 2, thisEncoding,
+ button.getText(), true));
+ asciiText.setText(displayByteFormat(localComposite, byteArray, n * 2, thisEncoding,
+ button.getText(), false));
+ }
+ catch (NumberFormatException exp)
+ {
+ popupErrorMessage("Error", "Please input the number of bytes you wish to look at");
+ }
+ }
+ if (e.widget instanceof ScrollBar)
+ {
+ //synchronize the movements of the two scrollbars
+ ScrollBar sb = (ScrollBar) e.widget;
+ if (sb.getParent().equals(hexText))
+ {
+ asciiScrollBar.setIncrement(sb.getIncrement());
+ asciiScrollBar.setSelection(sb.getSelection());
+ }
+ else if (sb.getParent().equals(asciiText))
+ {
+ hexScrollBar.setSelection(sb.getSelection());
+ hexScrollBar.setIncrement(sb.getIncrement());
+ }
+ }
+ }
+ };
+ localComposite.addControlListener(new ControlAdapter()
+ {
+ public void controlResized(ControlEvent e)
+ {
+ //if the control is resized, set different parameters to make a single line displays the same contents.
+ if (((GridLayout) localComposite.getLayout()).makeColumnsEqualWidth)
+ {
+ ((GridLayout) localComposite.getLayout()).makeColumnsEqualWidth = false;
+ ((GridLayout) localComposite.getLayout()).numColumns = 2;
+ ((GridData) hexText.getLayoutData()).horizontalSpan = 1;
+ ((GridData) hexText.getLayoutData()).widthHint = 144;
+ ((GridData) asciiText.getLayoutData()).horizontalSpan = 1;
+ ((GridData) asciiText.getLayoutData()).widthHint = 52;
+ ((GridData) buttonComposite.getLayoutData()).horizontalSpan = 2;
+ }
+ else
+ {
+ ((GridLayout) localComposite.getLayout()).makeColumnsEqualWidth = true;
+ ((GridLayout) localComposite.getLayout()).numColumns = 42; //set to 47 if not using any fonts
+ ((GridData) hexText.getLayoutData()).horizontalSpan = 25; // set to 30 if not using any fonts
+ ((GridData) asciiText.getLayoutData()).horizontalSpan = 17; // set to 17 if not using any fonts
+ ((GridData) buttonComposite.getLayoutData()).horizontalSpan = 42;
+ }
+ }
+ });
+
+ _firstButton.addSelectionListener(listener);
+ _previousButton.addSelectionListener(listener);
+ _nextButton.addSelectionListener(listener);
+ _lastButton.addSelectionListener(listener);
+ hexScrollBar.addSelectionListener(listener);
+ asciiScrollBar.addSelectionListener(listener);
+ //f.dispose();
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+
+ /**
+ * Format object messages to have a hexadecimal view and a ascii view.
+ * @param numOfBytes
+ * @param encoding
+ * @return
+ */
+ private static String displayByteFormat(Composite localComposite, byte[] byteArray, int numOfBytes,
+ String encoding, String direction, boolean isHex)
+ {
+ final Hex hexeconder = new Hex();
+ final byte[] encoded = hexeconder.encode(byteArray);
+
+ int hexLength = byteArray.length * 2;
+ StringBuilder sb = new StringBuilder();
+ int currentBytePos = (Integer) localComposite.getData("currentBytePos");
+ int startingBytePos = (Integer) localComposite.getData("startingBytePos");
+
+ int strLength = 0;
+ int offset = 0;
+ String encStr;
+ if (isHex)
+ {
+ if (direction.equals("<<"))
+ {
+ strLength = (numOfBytes > hexLength) ? hexLength : numOfBytes;
+ offset = 0;
+ }
+ else if (direction.equals("<"))
+ {
+ strLength = (startingBytePos - numOfBytes < 0) ? startingBytePos : numOfBytes;
+ offset = (startingBytePos - numOfBytes < 0) ? 0 : startingBytePos - numOfBytes;
+ }
+ else if (direction.equals(">"))
+ {
+ strLength = (numOfBytes > (hexLength - currentBytePos)) ? hexLength - currentBytePos : numOfBytes;
+ offset = currentBytePos;
+ }
+ else if (direction.equals(">>"))
+ {
+ strLength = (numOfBytes > hexLength) ? hexLength : numOfBytes;
+ offset = (hexLength - numOfBytes > 0) ? hexLength - numOfBytes : 0;
+ }
+ else
+ {
+ strLength = hexLength;
+ offset = 0;
+ }
+ localComposite.setData("strLength", strLength);
+ localComposite.setData("currentBytePos", offset + strLength);
+ localComposite.setData("startingBytePos", offset);
+
+ if (_lastButton != null && !_lastButton.isDisposed())
+ {
+ //Set button state
+ _previousButton.setEnabled(offset != 0);
+ _nextButton.setEnabled(offset + strLength != hexLength);
+
+ //set the text fields
+ _hexNumTextToStart.setText("" + offset / 2);
+ _hexNumTextToEnd.setText("" + (hexLength - (offset + strLength)) / 2);
+ }
+ }
+
+ try
+ {
+ if (isHex)
+ {
+ encStr = new String(encoded, offset, strLength, encoding);
+ for (int c = 0; c < strLength; c++)
+ {
+ sb.append(encStr.charAt(c));
+ if (c % 2 == 1)
+ {
+ sb.append(" ");
+ }
+ }
+ return sb.toString().toUpperCase();
+ }
+ else
+ {
+ strLength = (Integer) localComposite.getData("strLength");
+ sb = new StringBuilder();
+ encStr = new String(byteArray, startingBytePos / 2, strLength / 2, encoding);
+ for (int c = 0; c < encStr.length(); c++)
+ {
+ char ch = encStr.charAt(c);
+ if (ch > 31 && ch < 127)
+ {
+ sb.append(ch);
+ }
+ else
+ {
+ sb.append("?");
+ }
+
+ sb.append(" ");
+ }
+ }
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ e.printStackTrace();
+ }
+ return sb.toString();
+ }
+
+ public static int popupInfoMessage(String title, String message)
+ {
+ return showBox(title, message, SWT.ICON_INFORMATION | SWT.OK);
+ }
+
+ public static int popupErrorMessage(String title, String message)
+ {
+ return showBox(title, message, SWT.ICON_ERROR | SWT.OK);
+ }
+
+ public static int popupConfirmationMessage(String title, String message)
+ {
+ return showBox(title, message,SWT.ICON_QUESTION | SWT.YES | SWT.NO);
+ }
+
+ public static int popupOkCancelConfirmationMessage(String title, String message)
+ {
+ return showBox(title, message,SWT.ICON_QUESTION | SWT.OK | SWT.CANCEL);
+ }
+
+
+ public static Shell createPopupShell(String title, int width, int height)
+ {
+ Display display = Display.getCurrent();
+ final 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);
+
+ shell.addListener(SWT.Traverse, new Listener () {
+ public void handleEvent (Event event) {
+ switch (event.detail) {
+ case SWT.TRAVERSE_ESCAPE:
+ shell.close ();
+ event.detail = SWT.TRAVERSE_NONE;
+ event.doit = false;
+ break;
+ }
+ }
+ });
+
+ return shell;
+ }
+
+ public static Shell createModalDialogShell(Shell parent, String title)
+ {
+ final Shell shell = new Shell(parent, SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL);
+ shell.setText(title);
+ shell.setLayout(new GridLayout());
+
+ shell.addListener(SWT.Traverse, new Listener () {
+ public void handleEvent (Event event) {
+ switch (event.detail) {
+ case SWT.TRAVERSE_ESCAPE:
+ shell.close ();
+ event.detail = SWT.TRAVERSE_NONE;
+ event.doit = false;
+ break;
+ }
+ }
+ });
+
+ return shell;
+ }
+
+ /**
+ * Creates a List widget for displaying array of strings
+ * @param compositeHolder
+ * @param data - containing the array item value
+ * @param itemName - item name
+ */
+ private static void convertArrayItemForDisplay(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 setNotSupportedDataType(FormToolkit toolkit, Composite compositeHolder)
+ {
+ Text valueText = toolkit.createText(compositeHolder, "--- Content can not be displayed ---", SWT.READ_ONLY);
+ 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 formatted string
+ */
+ 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();
+ }
+
+ /**
+ * Disposes the children of given Composite if not null and not already disposed
+ * @param parent composite
+ */
+ 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();
+ }
+ }
+
+ public static char[] getHash(String text) throws NoSuchAlgorithmException, UnsupportedEncodingException
+ {
+ byte[] data = text.getBytes("utf-8");
+
+ MessageDigest md = MessageDigest.getInstance("MD5");
+
+ for (byte b : data)
+ {
+ md.update(b);
+ }
+
+ byte[] digest = md.digest();
+
+ char[] hash = new char[digest.length ];
+
+ int index = 0;
+ for (byte b : digest)
+ {
+ hash[index++] = (char) b;
+ }
+
+ return hash;
+ }
+
+ private static class TabularDataComparator implements java.util.Comparator<Map.Entry>
+ {
+ public int compare(Map.Entry data1, Map.Entry data2)
+ {
+ if (data1.getKey() instanceof List)
+ {
+ Object obj1 = ((List)data1.getKey()).get(0);
+ Object obj2 = ((List)data2.getKey()).get(0);
+ String str1 = obj1.toString();
+ String str2 = obj2.toString();
+ if (obj1 instanceof String)
+ {
+ return str1.compareTo(str2);
+ }
+
+ try
+ {
+ return Long.valueOf(str1).compareTo(Long.valueOf(str2));
+ }
+ catch (Exception ex)
+ {
+ return -1;
+ }
+ }
+
+ return -1;
+ }
+ }
+
+ public static void setMBeanView(MBeanView mbeanView)
+ {
+ _mbeanView = mbeanView;
+ }
+
+ /**
+ * Report feedback for the operation
+ * @param result true if success, false if unsuccessful, null if invoked but void result type.
+ * @param successMessage
+ * @param failureMessage
+ */
+ public static void operationResultFeedback(Boolean result, String successMessage, String failureMessage)
+ {
+ Image icon;
+
+ if(_mbeanView != null)
+ {
+ if(result == null)
+ {
+ icon = ApplicationRegistry.getImage(SUCCESS_IMAGE);
+ _mbeanView.populateStatusBar(icon, successMessage);
+ }
+ else if(result)
+ {
+ icon = ApplicationRegistry.getImage(SUCCESS_IMAGE);
+ _mbeanView.populateStatusBar(icon, successMessage);
+ }
+ else
+ {
+ icon = ApplicationRegistry.getImage(FAILURE_IMAGE);
+ _mbeanView.populateStatusBar(icon, failureMessage);
+ popupErrorMessage("Operation Failed", failureMessage);
+ }
+ }
+ }
+
+ public static void operationFailedStatusBarMessage(String failureMessage)
+ {
+ Image icon = ApplicationRegistry.getImage(FAILURE_IMAGE);
+
+ if(_mbeanView != null)
+ {
+ _mbeanView.populateStatusBar(icon, failureMessage);
+ }
+ }
+
+ public static void clearStatusBar()
+ {
+ if(_mbeanView != null)
+ {
+ _mbeanView.clearStatusBar();
+ }
+ }
+
+ public static void centerChildInParentShell(Shell parent, Shell child)
+ {
+ //get current parent shell size and location
+ int parentLocX = parent.getBounds().x;
+ int parentLocY = parent.getBounds().y;
+ int parentWidth = parent.getBounds().width;
+ int parentHeight = parent.getBounds().height;
+
+ //get current child size
+ int childWidth = child.getSize().x;
+ int childHeight = child.getSize().y;
+
+ //centre the child within/over the parent
+ child.setBounds((parentWidth - childWidth)/2 + parentLocX,
+ (parentHeight - childHeight)/2 + parentLocY,
+ childWidth, childHeight);
+ }
+
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/connection/ConnectionOperationsTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/connection/ConnectionOperationsTabControl.java
new file mode 100644
index 0000000000..35171773ad
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/connection/ConnectionOperationsTabControl.java
@@ -0,0 +1,545 @@
+/*
+ *
+ * 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.connection;
+
+import static org.apache.qpid.management.common.mbeans.ManagedConnection.CHAN_ID;
+import static org.apache.qpid.management.common.mbeans.ManagedConnection.DEFAULT_QUEUE;
+import static org.apache.qpid.management.common.mbeans.ManagedConnection.FLOW_BLOCKED;
+import static org.apache.qpid.management.common.mbeans.ManagedConnection.TRANSACTIONAL;
+import static org.apache.qpid.management.common.mbeans.ManagedConnection.UNACKED_COUNT;
+
+import java.util.Collection;
+
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.TabularDataSupport;
+
+import org.apache.qpid.management.ui.ApiVersion;
+import org.apache.qpid.management.ui.ApplicationRegistry;
+import org.apache.qpid.management.ui.ManagedBean;
+import org.apache.qpid.management.ui.ServerRegistry;
+import org.apache.qpid.management.common.mbeans.ManagedConnection;
+import org.apache.qpid.management.ui.jmx.JMXManagedObject;
+import org.apache.qpid.management.ui.jmx.MBeanUtility;
+import org.apache.qpid.management.ui.views.MBeanView;
+import org.apache.qpid.management.ui.views.TabControl;
+import org.apache.qpid.management.ui.views.ViewUtility;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+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.jface.viewers.ViewerSorter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+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.Group;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.forms.widgets.Form;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+
+/**
+ * Control class for the Connection mbean Operations tab.
+ */
+public class ConnectionOperationsTabControl extends TabControl
+{
+ private FormToolkit _toolkit;
+ private Form _form;
+ private Table _table = null;
+ private TableViewer _tableViewer = null;
+ private Composite _paramsComposite = null;
+
+ private TabularDataSupport _channels = null;
+ private ManagedConnection _cmb;
+ private ApiVersion _ApiVersion;
+
+ public ConnectionOperationsTabControl(TabFolder tabFolder, JMXManagedObject mbean, MBeanServerConnection mbsc)
+ {
+ super(tabFolder);
+ _mbean = mbean;
+ _ApiVersion = ApplicationRegistry.getServerRegistry(mbean).getManagementApiVersion();
+ _cmb = (ManagedConnection) MBeanServerInvocationHandler.newProxyInstance(mbsc,
+ mbean.getObjectName(), ManagedConnection.class, false);
+ _toolkit = new FormToolkit(_tabFolder.getDisplay());
+ _form = _toolkit.createForm(_tabFolder);
+ _form.getBody().setLayout(new GridLayout());
+ createComposites();
+ createWidgets();
+ }
+
+ private void createComposites()
+ {
+ _paramsComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
+ _paramsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ _paramsComposite.setLayout(new GridLayout());
+ }
+
+ /**
+ * @see TabControl#getControl()
+ */
+ public Control getControl()
+ {
+ return _form;
+ }
+
+ /**
+ * @see TabControl#setFocus()
+ */
+ public void setFocus()
+ {
+ _table.setFocus();
+ }
+
+ @Override
+ public void refresh(ManagedBean mbean)
+ {
+ _channels = null;
+ try
+ {
+ //gather a list of all channels on the connection for display and selection
+ _channels = (TabularDataSupport) _cmb.channels();
+ }
+ catch (Exception e)
+ {
+ MBeanUtility.handleException(mbean,e);
+ }
+
+ _tableViewer.setInput(_channels);
+
+ layout();
+ }
+
+ public void layout()
+ {
+ _form.layout(true);
+ _form.getBody().layout(true, true);
+ }
+
+ private void createWidgets()
+ {
+ Group viewChannelsGroup = new Group(_paramsComposite, SWT.SHADOW_NONE);
+ viewChannelsGroup.setBackground(_paramsComposite.getBackground());
+ viewChannelsGroup.setText("Channels");
+ viewChannelsGroup.setLayout(new GridLayout());
+ GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+ gridData.heightHint = 250;
+ gridData.minimumHeight = 250;
+
+ viewChannelsGroup.setLayoutData(gridData);
+
+ _table = new Table (viewChannelsGroup, SWT.SINGLE | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION);
+ _table.setLinesVisible (true);
+ _table.setHeaderVisible (true);
+ GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
+ _table.setLayoutData(data);
+
+ _tableViewer = new TableViewer(_table);
+ final TableSorter tableSorter = new TableSorter();
+
+ String[] titles;
+ if(_ApiVersion.greaterThanOrEqualTo(1, 5))
+ {
+ titles = new String[]{"Id", "Transactional", "Num Unacked Msg", "Default Queue", "Flow Blocked"};
+ }
+ else
+ {
+ titles = new String[]{"Id", "Transactional", "Num Unacked Msg", "Default Queue"};
+ }
+ int[] bounds = { 50, 110, 145, 200, 110 };
+ for (int i = 0; i < titles.length; i++)
+ {
+ final int index = i;
+ final TableColumn column = new TableColumn (_table, SWT.NONE);
+
+ column.setText(titles[i]);
+ column.setWidth(bounds[i]);
+ column.setResizable(true);
+
+ //Setting the right sorter
+ column.addSelectionListener(new SelectionAdapter()
+ {
+ @Override
+ public void widgetSelected(SelectionEvent e)
+ {
+ tableSorter.setColumn(index);
+ final TableViewer viewer = _tableViewer;
+ int dir = viewer .getTable().getSortDirection();
+ if (viewer.getTable().getSortColumn() == column)
+ {
+ dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
+ }
+ else
+ {
+ dir = SWT.UP;
+ }
+ viewer.getTable().setSortDirection(dir);
+ viewer.getTable().setSortColumn(column);
+ viewer.refresh();
+ }
+ });
+
+ }
+
+ _tableViewer.setContentProvider(new ContentProviderImpl());
+ _tableViewer.setLabelProvider(new LabelProviderImpl());
+ _tableViewer.setSorter(tableSorter);
+ _table.setSortColumn(_table.getColumn(0));
+ _table.setSortDirection(SWT.UP);
+
+ Composite buttonsComposite = _toolkit.createComposite(viewChannelsGroup);
+ gridData = new GridData(SWT.RIGHT, SWT.BOTTOM, false, false);
+ buttonsComposite.setLayoutData(gridData);
+ buttonsComposite.setLayout(new GridLayout(2,false));
+
+ final Button commitButton = _toolkit.createButton(buttonsComposite, "Commit Transactions", SWT.PUSH);
+ commitButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
+ commitButton.setEnabled(false);
+ commitButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ int selectionIndex = _table.getSelectionIndex();
+
+ if (selectionIndex != -1)
+ {
+ final CompositeData selectedChannel = (CompositeData)_table.getItem(selectionIndex).getData();
+ Integer id = (Integer) selectedChannel.get(CHAN_ID);
+
+ int response = ViewUtility.popupOkCancelConfirmationMessage("Commit Transactions",
+ "Commit transactions for channel:" + id + " ?");
+
+ if (response == SWT.OK)
+ {
+ try
+ {
+ _cmb.commitTransactions(id);
+ ViewUtility.operationResultFeedback(null, "Commited transactions", null);
+ }
+ catch (Exception e1)
+ {
+ ViewUtility.operationFailedStatusBarMessage("Error commiting transactions");
+ MBeanUtility.handleException(_mbean, e1);
+ }
+
+ refresh(_mbean);;
+ }
+ }
+ }
+ });
+
+ final Button rollbackButton = _toolkit.createButton(buttonsComposite, "Rollback Transactions", SWT.PUSH);
+ rollbackButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
+ rollbackButton.setEnabled(false);
+ rollbackButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ int selectionIndex = _table.getSelectionIndex();
+
+ if (selectionIndex != -1)
+ {
+ final CompositeData selectedChannel = (CompositeData)_table.getItem(selectionIndex).getData();
+ Integer id = (Integer) selectedChannel.get(CHAN_ID);
+
+ int response = ViewUtility.popupOkCancelConfirmationMessage("Rollback Transactions",
+ "Rollback transactions for channel:" + id + " ?");
+
+ if (response == SWT.OK)
+ {
+ try
+ {
+ _cmb.rollbackTransactions(id);
+ ViewUtility.operationResultFeedback(null, "Rolled back transactions", null);
+ }
+ catch (Exception e1)
+ {
+ ViewUtility.operationFailedStatusBarMessage("Error rolling back transactions");
+ MBeanUtility.handleException(_mbean, e1);
+ }
+
+ refresh(_mbean);;
+ }
+ }
+
+ }
+ });
+
+ //listener for double clicking to open the selection mbean
+ _table.addMouseListener(new MouseListener()
+ {
+ // MouseListener implementation
+ public void mouseDoubleClick(MouseEvent event)
+ {
+ openMBean(_table);
+ }
+
+ public void mouseDown(MouseEvent e){}
+ public void mouseUp(MouseEvent e){}
+ });
+
+ _tableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
+ public void selectionChanged(SelectionChangedEvent evt)
+ {
+ int selectionIndex = _table.getSelectionIndex();
+
+ if (selectionIndex != -1)
+ {
+ final CompositeData selectedChannel = (CompositeData)_table.getItem(selectionIndex).getData();
+ Boolean transactional = (Boolean) selectedChannel.get(TRANSACTIONAL);
+
+ if(transactional)
+ {
+ rollbackButton.setEnabled(true);
+ commitButton.setEnabled(true);
+ }
+ else
+ {
+ rollbackButton.setEnabled(false);
+ commitButton.setEnabled(false);
+ }
+ }
+ else
+ {
+ rollbackButton.setEnabled(false);
+ commitButton.setEnabled(true);
+ }
+ }
+ });
+
+ Composite opsComposite = _toolkit.createComposite(_paramsComposite);
+ gridData = new GridData(SWT.LEFT, SWT.FILL, false, true);
+ opsComposite.setLayoutData(gridData);
+ opsComposite.setLayout(new GridLayout(3,false));
+
+ Group closeConnectionGroup = new Group(opsComposite, SWT.SHADOW_NONE);
+ closeConnectionGroup.setBackground(opsComposite.getBackground());
+ closeConnectionGroup.setText("Close Connection");
+ gridData = new GridData(SWT.LEFT, SWT.TOP, true, false);
+ closeConnectionGroup.setLayoutData(gridData);
+ closeConnectionGroup.setLayout(new GridLayout());
+
+ final Button closeConnectionButton = _toolkit.createButton(closeConnectionGroup, "Close Connection", SWT.PUSH);
+ closeConnectionButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ int response = ViewUtility.popupOkCancelConfirmationMessage("Close Connection",
+ "Are you sure you wish to close the Connection?");
+
+ if (response == SWT.OK)
+ {
+ try
+ {
+ _cmb.closeConnection();
+ }
+ catch (Exception e1)
+ {
+ MBeanUtility.handleException(_mbean, e1);
+ }
+ }
+ }
+ });
+ }
+
+
+ /**
+ * Content Provider class for the table viewer
+ */
+ private static class ContentProviderImpl implements IStructuredContentProvider
+ {
+
+ public void inputChanged(Viewer v, Object oldInput, Object newInput)
+ {
+
+ }
+
+ public void dispose()
+ {
+
+ }
+
+ public Object[] getElements(Object parent)
+ {
+ Collection<Object> rowCollection = ((TabularDataSupport) parent).values();
+
+ return rowCollection.toArray();
+ }
+ }
+
+ /**
+ * Label Provider class for the table viewer
+ */
+ private static class LabelProviderImpl extends LabelProvider implements ITableLabelProvider
+ {
+ public String getColumnText(Object element, int columnIndex)
+ {
+ switch (columnIndex)
+ {
+ case 0 : // id column
+ return String.valueOf(((CompositeDataSupport) element).get(CHAN_ID));
+ case 1 : // transactional column
+ return String.valueOf(((CompositeDataSupport) element).get(TRANSACTIONAL));
+ case 2 : // num unacked msgs column
+ return String.valueOf(((CompositeDataSupport) element).get(UNACKED_COUNT));
+ case 3 : // default queue column
+ return String.valueOf(((CompositeDataSupport) element).get(DEFAULT_QUEUE));
+ case 4 : // flow blocked column
+ return String.valueOf(((CompositeDataSupport) element).get(FLOW_BLOCKED));
+ default :
+ return "-";
+ }
+ }
+
+ public Image getColumnImage(Object element, int columnIndex)
+ {
+ return null;
+ }
+
+ }
+
+ /**
+ * Sorter class for the table viewer.
+ *
+ */
+ public static class TableSorter extends ViewerSorter
+ {
+ private int column;
+ private static final int ASCENDING = 0;
+ private static final int DESCENDING = 1;
+
+ private int direction = DESCENDING;
+
+ public TableSorter()
+ {
+ this.column = 0;
+ direction = ASCENDING;
+ }
+
+ public void setColumn(int column)
+ {
+ if (column == this.column)
+ {
+ // Same column as last sort; toggle the direction
+ direction = 1 - direction;
+ }
+ else
+ {
+ // New column; do an ascending sort
+ this.column = column;
+ direction = ASCENDING;
+ }
+ }
+
+ @Override
+ public int compare(Viewer viewer, Object e1, Object e2)
+ {
+ CompositeData chan1 = (CompositeData) e1;
+ CompositeData chan2 = (CompositeData) e2;
+
+ int comparison = 0;
+ switch(column)
+ {
+ case 0:
+ comparison = ((Integer) chan1.get(CHAN_ID)).compareTo((Integer)chan2.get(CHAN_ID));
+ break;
+ case 1:
+ comparison = String.valueOf(chan1.get(TRANSACTIONAL)).compareTo(
+ String.valueOf(chan2.get(TRANSACTIONAL)));
+ break;
+ case 2:
+ comparison = ((Long) chan1.get(UNACKED_COUNT)).compareTo((Long)chan2.get(UNACKED_COUNT));
+ break;
+ case 3:
+ comparison = String.valueOf(chan1.get(DEFAULT_QUEUE)).compareTo(
+ String.valueOf(chan2.get(DEFAULT_QUEUE)));
+ break;
+ case 4:
+ comparison = String.valueOf(chan1.get(FLOW_BLOCKED)).compareTo(
+ String.valueOf(chan2.get(FLOW_BLOCKED)));
+ break;
+ default:
+ comparison = 0;
+ }
+ // If descending order, flip the direction
+ if(direction == DESCENDING)
+ {
+ comparison = -comparison;
+ }
+ return comparison;
+ }
+ }
+
+ private void openMBean(Table table)
+ {
+ int selectionIndex = table.getSelectionIndex();
+
+ if (selectionIndex == -1)
+ {
+ return;
+ }
+
+ CompositeData channelResult = (CompositeData) table.getItem(selectionIndex).getData();
+ String queueName = (String) channelResult.get(DEFAULT_QUEUE);
+
+ if(queueName == null)
+ {
+ return;
+ }
+
+ ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(_mbean);
+ ManagedBean selectedMBean = serverRegistry.getQueue(queueName, _mbean.getVirtualHostName());
+
+ if(selectedMBean == null)
+ {
+ ViewUtility.popupErrorMessage("Error", "Unable to retrieve the selected MBean to open it");
+ return;
+ }
+
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ MBeanView view = (MBeanView) window.getActivePage().findView(MBeanView.ID);
+ try
+ {
+ view.openMBean(selectedMBean);
+ }
+ catch (Exception ex)
+ {
+ MBeanUtility.handleException(selectedMBean, ex);
+ }
+ }
+
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/exchange/ExchangeOperationsTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/exchange/ExchangeOperationsTabControl.java
new file mode 100644
index 0000000000..b51cb85427
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/exchange/ExchangeOperationsTabControl.java
@@ -0,0 +1,722 @@
+/*
+ *
+ * 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.exchange;
+
+import static org.apache.qpid.management.common.mbeans.ManagedExchange.BINDING_KEY;
+import static org.apache.qpid.management.common.mbeans.ManagedExchange.QUEUE_NAMES;
+import static org.apache.qpid.management.ui.Constants.EXCHANGE_TYPE;
+import static org.apache.qpid.management.ui.Constants.DIRECT_EXCHANGE;
+import static org.apache.qpid.management.ui.Constants.FANOUT_EXCHANGE;
+import static org.apache.qpid.management.ui.Constants.TOPIC_EXCHANGE;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.TabularDataSupport;
+
+import org.apache.qpid.management.ui.ApiVersion;
+import org.apache.qpid.management.ui.ApplicationRegistry;
+import org.apache.qpid.management.ui.ManagedBean;
+import org.apache.qpid.management.ui.ServerRegistry;
+import org.apache.qpid.management.common.mbeans.ManagedExchange;
+import org.apache.qpid.management.ui.jmx.JMXManagedObject;
+import org.apache.qpid.management.ui.jmx.MBeanUtility;
+import org.apache.qpid.management.ui.views.MBeanView;
+import org.apache.qpid.management.ui.views.TabControl;
+import org.apache.qpid.management.ui.views.ViewUtility;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+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.jface.viewers.ViewerSorter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+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.Group;
+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.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+
+
+/**
+ * Control class for the Exchange mbean Operations tab.
+ */
+public class ExchangeOperationsTabControl extends TabControl
+{
+ private FormToolkit _toolkit;
+ private ScrolledForm _form;
+ private Table _keysTable = null;
+ private TableViewer _keysTableViewer = null;
+ private Table _queuesTable = null;
+ private TableViewer _queuesTableViewer = null;
+ private Composite _paramsComposite = null;
+
+ private TabularDataSupport _bindings = null;
+ private ManagedExchange _emb;
+ private ApiVersion _ApiVersion;
+
+ public ExchangeOperationsTabControl(TabFolder tabFolder, JMXManagedObject mbean, MBeanServerConnection mbsc)
+ {
+ super(tabFolder);
+ _mbean = mbean;
+ _ApiVersion = ApplicationRegistry.getServerRegistry(mbean).getManagementApiVersion();
+ _emb = (ManagedExchange) MBeanServerInvocationHandler.newProxyInstance(mbsc,
+ mbean.getObjectName(), ManagedExchange.class, false);
+ _toolkit = new FormToolkit(_tabFolder.getDisplay());
+ _form = _toolkit.createScrolledForm(_tabFolder);
+ _form.getBody().setLayout(new GridLayout());
+ createComposites();
+ createWidgets();
+ }
+
+ private void createComposites()
+ {
+ _paramsComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
+ _paramsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ _paramsComposite.setLayout(new GridLayout());
+ }
+
+ /**
+ * @see TabControl#getControl()
+ */
+ public Control getControl()
+ {
+ return _form;
+ }
+
+ /**
+ * @see TabControl#setFocus()
+ */
+ public void setFocus()
+ {
+ _keysTable.setFocus();
+ }
+
+ @Override
+ public void refresh(ManagedBean mbean)
+ {
+ _bindings = null;
+ try
+ {
+ //gather a list of all keys and queues for display and selection
+ _bindings = (TabularDataSupport) _emb.bindings();
+ }
+ catch (Exception e)
+ {
+ MBeanUtility.handleException(_mbean,e);
+ }
+
+ _keysTableViewer.setInput(_bindings);
+
+ //if we have a Qpid JMX API 1.3+ server
+ if(_ApiVersion.greaterThanOrEqualTo(1, 3))
+ {
+ //if it is a fanout exchange
+ if(isFanoutExchange())
+ {
+ //if there are any queue bindings, there is a single wildcard binding key
+ //auto-select it to show all the queues bound to the exchange
+ if (_keysTable.getItemCount() == 1)
+ {
+ _keysTable.setSelection(0);
+ updateQueuesTable();
+ }
+ }
+ }
+
+ layout();
+ }
+
+ public void layout()
+ {
+ _form.layout(true);
+ _form.getBody().layout(true, true);
+ }
+
+ private void createWidgets()
+ {
+ Group bindingsGroup = new Group(_paramsComposite, SWT.SHADOW_NONE);
+ bindingsGroup.setBackground(_paramsComposite.getBackground());
+ bindingsGroup.setText("Bindings");
+ bindingsGroup.setLayout(new GridLayout(2,false));
+ GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+ bindingsGroup.setLayoutData(gridData);
+
+ Composite tablesComposite = _toolkit.createComposite(bindingsGroup);
+ gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+ gridData.minimumHeight = 250;
+ gridData.heightHint = 250;
+ tablesComposite.setLayoutData(gridData);
+ tablesComposite.setLayout(new GridLayout(2,false));
+
+ _keysTable = new Table (tablesComposite, SWT.SINGLE | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION);
+ _keysTable.setLinesVisible(true);
+ _keysTable.setHeaderVisible(true);
+ GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
+ _keysTable.setLayoutData(data);
+
+ _keysTableViewer = new TableViewer(_keysTable);
+ final TableSorter tableSorter = new TableSorter(BINDING_KEY);
+
+ String[] titles = {"Binding Key"};
+ int[] bounds = {200};
+ for (int i = 0; i < titles.length; i++)
+ {
+ final int index = i;
+ final TableColumn column = new TableColumn (_keysTable, SWT.NONE);
+
+ column.setText(titles[i]);
+ column.setWidth(bounds[i]);
+ column.setResizable(true);
+
+ //Setting the right sorter
+ column.addSelectionListener(new SelectionAdapter()
+ {
+ @Override
+ public void widgetSelected(SelectionEvent e)
+ {
+ tableSorter.setColumn(index);
+ final TableViewer viewer = _keysTableViewer;
+ int dir = viewer .getTable().getSortDirection();
+ if (viewer.getTable().getSortColumn() == column)
+ {
+ dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
+ }
+ else
+ {
+ dir = SWT.UP;
+ }
+ viewer.getTable().setSortDirection(dir);
+ viewer.getTable().setSortColumn(column);
+ viewer.refresh();
+ }
+ });
+
+ }
+
+ _keysTableViewer.setContentProvider(new ContentProviderImpl(BINDING_KEY));
+ _keysTableViewer.setLabelProvider(new LabelProviderImpl(BINDING_KEY));
+ _keysTableViewer.setSorter(tableSorter);
+ _keysTable.setSortColumn(_keysTable.getColumn(0));
+ _keysTable.setSortDirection(SWT.UP);
+
+
+ _queuesTable = new Table (tablesComposite, SWT.SINGLE | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION);
+ _queuesTable.setLinesVisible (true);
+ _queuesTable.setHeaderVisible (true);
+ data = new GridData(SWT.FILL, SWT.FILL, true, true);
+ _queuesTable.setLayoutData(data);
+
+ _queuesTableViewer = new TableViewer(_queuesTable);
+ final TableSorter queuesTableSorter = new TableSorter(QUEUE_NAMES);
+
+ titles = new String[]{"Queue Names"};
+ bounds = new int[]{225};
+ for (int i = 0; i < titles.length; i++)
+ {
+ final int index = i;
+ final TableColumn column = new TableColumn (_queuesTable, SWT.NONE);
+
+ column.setText(titles[i]);
+ column.setWidth(bounds[i]);
+ column.setResizable(true);
+
+ //Setting the right sorter
+ column.addSelectionListener(new SelectionAdapter()
+ {
+ @Override
+ public void widgetSelected(SelectionEvent e)
+ {
+ queuesTableSorter.setColumn(index);
+ final TableViewer viewer = _queuesTableViewer;
+ int dir = viewer .getTable().getSortDirection();
+ if (viewer.getTable().getSortColumn() == column)
+ {
+ dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
+ }
+ else
+ {
+ dir = SWT.UP;
+ }
+ viewer.getTable().setSortDirection(dir);
+ viewer.getTable().setSortColumn(column);
+ viewer.refresh();
+ }
+ });
+
+ }
+
+ _queuesTableViewer.setContentProvider(new ContentProviderImpl(QUEUE_NAMES));
+ _queuesTableViewer.setLabelProvider(new LabelProviderImpl(QUEUE_NAMES));
+ _queuesTableViewer.setSorter(queuesTableSorter);
+ _queuesTable.setSortColumn(_queuesTable.getColumn(0));
+ _queuesTable.setSortDirection(SWT.UP);
+ _queuesTableViewer.setInput(new String[]{"Select a binding key to view queues"});
+
+ //listener for double clicking to open the selection mbean
+ _queuesTable.addMouseListener(new MouseListener()
+ {
+ // MouseListener implementation
+ public void mouseDoubleClick(MouseEvent event)
+ {
+ openMBean(_queuesTable);
+ }
+
+ public void mouseDown(MouseEvent e){}
+ public void mouseUp(MouseEvent e){}
+ });
+
+ _keysTableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
+ public void selectionChanged(SelectionChangedEvent evt)
+ {
+ updateQueuesTable();
+ }
+ });
+
+ //Side Buttons
+ Composite buttonsComposite = _toolkit.createComposite(bindingsGroup);
+ gridData = new GridData(SWT.FILL, SWT.FILL, false, true);
+ buttonsComposite.setLayoutData(gridData);
+ buttonsComposite.setLayout(new GridLayout());
+
+ final Button createBindingButton = _toolkit.createButton(buttonsComposite, "Create ...", SWT.PUSH);
+ createBindingButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ createNewBinding(createBindingButton.getShell());
+ }
+ });
+
+ if(_ApiVersion.greaterThanOrEqualTo(1, 9)
+ && (isDirectExchange() ||isTopicExchange()))
+ {
+ final Button removeBindingButton = _toolkit.createButton(buttonsComposite, "Delete ...", SWT.PUSH);
+ removeBindingButton.setEnabled(false);
+ removeBindingButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ removeBinding(removeBindingButton.getShell());
+ }
+ });
+
+ _queuesTableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
+ public void selectionChanged(SelectionChangedEvent evt)
+ {
+ int selectionIndex = _queuesTable.getSelectionIndex();
+
+ if (selectionIndex != -1)
+ {
+ removeBindingButton.setEnabled(true);
+ }
+ else
+ {
+ removeBindingButton.setEnabled(false);
+ }
+ }
+ });
+ }
+ }
+
+ private void updateQueuesTable()
+ {
+ int selectionIndex = _keysTable.getSelectionIndex();
+
+ if (selectionIndex != -1)
+ {
+ final CompositeData selectedMsg = (CompositeData)_keysTable.getItem(selectionIndex).getData();
+
+ String[] queues = (String[]) selectedMsg.get(QUEUE_NAMES);
+ _queuesTableViewer.setInput(queues);
+ }
+ else
+ {
+ _queuesTableViewer.setInput(new String[]{"Select a binding key to view queues"});
+ }
+ }
+
+ private boolean isFanoutExchange()
+ {
+ return _mbean.getProperty(EXCHANGE_TYPE).equalsIgnoreCase(FANOUT_EXCHANGE);
+ }
+
+ private boolean isDirectExchange()
+ {
+ return _mbean.getProperty(EXCHANGE_TYPE).equalsIgnoreCase(DIRECT_EXCHANGE);
+ }
+
+ private boolean isTopicExchange()
+ {
+ return _mbean.getProperty(EXCHANGE_TYPE).equalsIgnoreCase(TOPIC_EXCHANGE);
+ }
+
+ /**
+ * Content Provider class for the table viewer
+ */
+ private static class ContentProviderImpl implements IStructuredContentProvider
+ {
+ String type;
+
+ public ContentProviderImpl(String type)
+ {
+ this.type = type;
+ }
+
+ public void inputChanged(Viewer v, Object oldInput, Object newInput)
+ {
+
+ }
+
+ public void dispose()
+ {
+
+ }
+
+ public Object[] getElements(Object parent)
+ {
+ if(type.equals(BINDING_KEY))
+ {
+ Collection<Object> rowCollection = ((TabularDataSupport) parent).values();
+
+ return rowCollection.toArray();
+ }
+ else
+ {
+ //we have the list of queues, return directly
+ return (String[]) parent;
+ }
+ }
+ }
+
+ /**
+ * Label Provider class for the routing key table viewer
+ */
+ private static class LabelProviderImpl extends LabelProvider implements ITableLabelProvider
+ {
+ String type;
+
+ public LabelProviderImpl(String type)
+ {
+ this.type = type;
+ }
+
+ public String getColumnText(Object element, int columnIndex)
+ {
+ if(type.equals(BINDING_KEY)) //binding num and queue name table
+ {
+ switch (columnIndex)
+ {
+ case 0 : // key column
+ return String.valueOf(((CompositeDataSupport) element).get(BINDING_KEY));
+ default :
+ return "";
+ }
+ }
+ else //binding key-value pair table
+ {
+ switch (columnIndex)
+ {
+ case 0 : //queue name column
+ return String.valueOf(element);
+ default :
+ return "";
+ }
+ }
+ }
+
+ public Image getColumnImage(Object element, int columnIndex)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Sorter class for the table viewer.
+ *
+ */
+ public static class TableSorter extends ViewerSorter
+ {
+ private int column;
+ private static final int ASCENDING = 0;
+ private static final int DESCENDING = 1;
+
+ private int direction = DESCENDING;
+
+ private String type;
+
+ public TableSorter(String type)
+ {
+ this.type = type;
+ this.column = 0;
+ direction = ASCENDING;
+ }
+
+ public void setColumn(int column)
+ {
+ if (column == this.column)
+ {
+ // Same column as last sort; toggle the direction
+ direction = 1 - direction;
+ }
+ else
+ {
+ // New column; do an ascending sort
+ this.column = column;
+ direction = ASCENDING;
+ }
+ }
+
+ @Override
+ public int compare(Viewer viewer, Object e1, Object e2)
+ {
+ int comparison = 0;
+
+ if(type.equals(BINDING_KEY))//binding num and queue name table
+ {
+ CompositeData binding1 = (CompositeData) e1;
+ CompositeData binding2 = (CompositeData) e2;
+
+ switch(column)
+ {
+ case 0:
+ comparison = ((String) binding1.get(BINDING_KEY)).compareTo((String) binding2.get(BINDING_KEY));
+ break;
+ default:
+ comparison = 0;
+ }
+ }
+ else //binding key-value pair table
+ {
+ switch(column)
+ {
+ case 0:
+ comparison = ((String)e1).compareTo((String) e2);
+ break;
+ default:
+ comparison = 0;
+ }
+ }
+
+
+ // If descending order, flip the direction
+ if(direction == DESCENDING)
+ {
+ comparison = -comparison;
+ }
+ return comparison;
+ }
+ }
+
+ private void createNewBinding(Shell parent)
+ {
+ final Shell shell = ViewUtility.createModalDialogShell(parent, "Create New Binding");
+
+ Composite destinationComposite = _toolkit.createComposite(shell, SWT.NONE);
+ destinationComposite.setBackground(shell.getBackground());
+ destinationComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ destinationComposite.setLayout(new GridLayout(2,false));
+
+ _toolkit.createLabel(destinationComposite,"Queue:").setBackground(shell.getBackground());
+ final Combo destinationCombo = new Combo(destinationComposite,SWT.NONE | SWT.READ_ONLY);
+ destinationCombo.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+
+ Composite bindingComposite = _toolkit.createComposite(shell, SWT.NONE);
+ bindingComposite.setBackground(shell.getBackground());
+ bindingComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ bindingComposite.setLayout(new GridLayout(2,false));
+
+ _toolkit.createLabel(bindingComposite,"Binding:").setBackground(shell.getBackground());
+ final Text bindingText = new Text(bindingComposite, SWT.BORDER);
+ bindingText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ if(isFanoutExchange())
+ {
+ bindingText.setText("*");
+ }
+
+ Composite okCancelButtonsComp = _toolkit.createComposite(shell);
+ okCancelButtonsComp.setBackground(shell.getBackground());
+ okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
+ okCancelButtonsComp.setLayout(new GridLayout(2,false));
+
+ Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
+ okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+ Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
+ cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+
+ List<String> queueList = ApplicationRegistry.getServerRegistry(_mbean).getQueueNames(_mbean.getVirtualHostName());
+
+ if(queueList.size() == 0)
+ {
+ destinationCombo.setItems(new String[]{"No queues available"});
+ okButton.setEnabled(false);
+ }
+ else
+ {
+ Collections.sort(queueList);
+ destinationCombo.setItems(queueList.toArray(new String[0]));
+ }
+ destinationCombo.select(0);
+
+ okButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ String binding = bindingText.getText();
+
+ if (!isFanoutExchange() && (binding == null || binding.length() == 0))
+ {
+ ViewUtility.popupErrorMessage("Create New Binding", "Please enter a valid binding");
+ return;
+ }
+
+ String destQueue = destinationCombo.getItem(destinationCombo.getSelectionIndex()).toString();
+
+ shell.dispose();
+
+ try
+ {
+ _emb.createNewBinding(destQueue, binding);
+ ViewUtility.operationResultFeedback(null, "Created new Binding", null);
+ }
+ catch (Exception e4)
+ {
+ ViewUtility.operationFailedStatusBarMessage("Error creating new Binding");
+ MBeanUtility.handleException(_mbean, e4);
+ }
+
+ refresh(_mbean);
+ }
+ });
+
+ cancelButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ shell.dispose();
+ }
+ });
+
+ shell.setDefaultButton(okButton);
+ shell.pack();
+ ViewUtility.centerChildInParentShell(parent, shell);
+
+ shell.open();
+ }
+
+ private void removeBinding(Shell parent)
+ {
+ int selectionIndex = _keysTable.getSelectionIndex();
+ if (selectionIndex == -1)
+ {
+ return;
+ }
+
+ final CompositeData selectedBindingRecord = (CompositeData)_keysTable.getItem(selectionIndex).getData();
+
+ final String bindingKey = (String) selectedBindingRecord.get(BINDING_KEY);
+
+ selectionIndex = _queuesTable.getSelectionIndex();
+ if (selectionIndex == -1)
+ {
+ return;
+ }
+
+ final String queueName = (String)_queuesTable.getItem(selectionIndex).getData();
+
+
+ int response = ViewUtility.popupOkCancelConfirmationMessage("Delete Binding",
+ "Delete the following binding?\n\n" +
+ "Binding Key: " + bindingKey + "\n" +
+ "Queue: " + queueName + "\n" +
+ "Exchange: " + _mbean.getName());
+
+ if (response == SWT.OK)
+ {
+ try
+ {
+ _emb.removeBinding(queueName, bindingKey);
+ ViewUtility.operationResultFeedback(null, "Removed Binding", null);
+ }
+ catch (Exception e)
+ {
+ ViewUtility.operationFailedStatusBarMessage("Error removing Binding");
+ MBeanUtility.handleException(_mbean, e);
+ }
+
+ refresh(_mbean);
+ }
+ }
+
+ private void openMBean(Table table)
+ {
+ int selectionIndex = table.getSelectionIndex();
+
+ if (selectionIndex == -1)
+ {
+ return;
+ }
+
+ String queueName = (String) table.getItem(selectionIndex).getData();
+ ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(_mbean);
+ ManagedBean selectedMBean = serverRegistry.getQueue(queueName, _mbean.getVirtualHostName());
+
+ if(selectedMBean == null)
+ {
+ ViewUtility.popupErrorMessage("Error", "Unable to retrieve the selected MBean to open it");
+ return;
+ }
+
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ MBeanView view = (MBeanView) window.getActivePage().findView(MBeanView.ID);
+ try
+ {
+ view.openMBean(selectedMBean);
+ }
+ catch (Exception ex)
+ {
+ MBeanUtility.handleException(selectedMBean, ex);
+ }
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/exchange/HeadersExchangeOperationsTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/exchange/HeadersExchangeOperationsTabControl.java
new file mode 100644
index 0000000000..e22898fb93
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/exchange/HeadersExchangeOperationsTabControl.java
@@ -0,0 +1,711 @@
+/*
+ *
+ * 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.exchange;
+
+import static org.apache.qpid.management.common.mbeans.ManagedExchange.HDR_BINDING_NUMBER;
+import static org.apache.qpid.management.common.mbeans.ManagedExchange.HDR_QUEUE_BINDINGS;
+import static org.apache.qpid.management.common.mbeans.ManagedExchange.HDR_QUEUE_NAME;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.TabularDataSupport;
+
+import org.apache.qpid.management.ui.ApplicationRegistry;
+import org.apache.qpid.management.ui.ManagedBean;
+import org.apache.qpid.management.ui.ServerRegistry;
+import org.apache.qpid.management.common.mbeans.ManagedExchange;
+import org.apache.qpid.management.ui.jmx.JMXManagedObject;
+import org.apache.qpid.management.ui.jmx.MBeanUtility;
+import org.apache.qpid.management.ui.views.MBeanView;
+import org.apache.qpid.management.ui.views.TabControl;
+import org.apache.qpid.management.ui.views.ViewUtility;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+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.jface.viewers.ViewerSorter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.ScrolledComposite;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+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.Group;
+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.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+
+
+/**
+ * Control class for the Headers Exchange mbean Operations tab.
+ */
+public class HeadersExchangeOperationsTabControl extends TabControl
+{
+ private FormToolkit _toolkit;
+ private ScrolledForm _form;
+ private Table _bindingNumberTable = null;
+ private TableViewer _bindingNumberTableViewer = null;
+ private Table _headersTable = null;
+ private TableViewer _headersTableViewer = null;
+ private Composite _paramsComposite = null;
+
+ private TabularDataSupport _bindings = null;
+ private ManagedExchange _emb;
+
+ public HeadersExchangeOperationsTabControl(TabFolder tabFolder, JMXManagedObject mbean, MBeanServerConnection mbsc)
+ {
+ super(tabFolder);
+ _mbean = mbean;
+ _emb = (ManagedExchange) MBeanServerInvocationHandler.newProxyInstance(mbsc,
+ mbean.getObjectName(), ManagedExchange.class, false);
+ _toolkit = new FormToolkit(_tabFolder.getDisplay());
+ _form = _toolkit.createScrolledForm(_tabFolder);
+ _form.getBody().setLayout(new GridLayout());
+ createComposites();
+ createWidgets();
+ }
+
+ private void createComposites()
+ {
+ _paramsComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
+ _paramsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ _paramsComposite.setLayout(new GridLayout());
+ }
+
+ /**
+ * @see TabControl#getControl()
+ */
+ public Control getControl()
+ {
+ return _form;
+ }
+
+ /**
+ * @see TabControl#setFocus()
+ */
+ public void setFocus()
+ {
+ _bindingNumberTable.setFocus();
+ }
+
+ @Override
+ public void refresh(ManagedBean mbean)
+ {
+
+ _bindings = null;
+ try
+ {
+ //gather a list of all keys and queues for display and selection
+ _bindings = (TabularDataSupport) _emb.bindings();
+ }
+ catch (Exception e)
+ {
+ MBeanUtility.handleException(_mbean,e);
+ }
+
+ _bindingNumberTableViewer.setInput(_bindings);
+
+ layout();
+ }
+
+ public void layout()
+ {
+ _form.layout(true);
+ _form.getBody().layout(true, true);
+ }
+
+ private void createWidgets()
+ {
+ Group bindingsGroup = new Group(_paramsComposite, SWT.SHADOW_NONE);
+ bindingsGroup.setBackground(_paramsComposite.getBackground());
+ bindingsGroup.setText("Bindings");
+ bindingsGroup.setLayout(new GridLayout(2,false));
+ GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+ bindingsGroup.setLayoutData(gridData);
+
+ Composite tablesComposite = _toolkit.createComposite(bindingsGroup);
+ gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+ gridData.minimumHeight = 250;
+ gridData.heightHint = 250;
+ tablesComposite.setLayoutData(gridData);
+ tablesComposite.setLayout(new GridLayout(2,false));
+
+ //table of bindings for the exchange
+ _bindingNumberTable = new Table (tablesComposite, SWT.SINGLE | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION);
+ _bindingNumberTable.setLinesVisible(true);
+ _bindingNumberTable.setHeaderVisible(true);
+ GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
+ data.minimumHeight = 300;
+ data.heightHint = 300;
+ _bindingNumberTable.setLayoutData(data);
+
+ _bindingNumberTableViewer = new TableViewer(_bindingNumberTable);
+ final TableSorter tableSorter = new TableSorter(HDR_BINDING_NUMBER);
+
+ String[] titles = {"Binding Number", "Queue Name"};
+ int[] bounds = {135, 175};
+ for (int i = 0; i < titles.length; i++)
+ {
+ final int index = i;
+ final TableColumn column = new TableColumn (_bindingNumberTable, SWT.NONE);
+
+ column.setText(titles[i]);
+ column.setWidth(bounds[i]);
+ column.setResizable(true);
+
+ //Setting the right sorter
+ column.addSelectionListener(new SelectionAdapter()
+ {
+ @Override
+ public void widgetSelected(SelectionEvent e)
+ {
+ tableSorter.setColumn(index);
+ final TableViewer viewer = _bindingNumberTableViewer;
+ int dir = viewer .getTable().getSortDirection();
+ if (viewer.getTable().getSortColumn() == column)
+ {
+ dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
+ }
+ else
+ {
+ dir = SWT.UP;
+ }
+ viewer.getTable().setSortDirection(dir);
+ viewer.getTable().setSortColumn(column);
+ viewer.refresh();
+ }
+ });
+
+ }
+
+ _bindingNumberTableViewer.setContentProvider(new ContentProviderImpl(HDR_BINDING_NUMBER));
+ _bindingNumberTableViewer.setLabelProvider(new LabelProviderImpl(HDR_BINDING_NUMBER));
+ _bindingNumberTableViewer.setSorter(tableSorter);
+ _bindingNumberTable.setSortColumn(_bindingNumberTable.getColumn(0));
+ _bindingNumberTable.setSortDirection(SWT.UP);
+
+ //table of header bindings
+ _headersTable = new Table (tablesComposite, SWT.SINGLE | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION);
+ _headersTable.setLinesVisible (true);
+ _headersTable.setHeaderVisible (true);
+ data = new GridData(SWT.FILL, SWT.FILL, true, true);
+ data.minimumHeight = 300;
+ data.heightHint = 300;
+ _headersTable.setLayoutData(data);
+
+ _headersTableViewer = new TableViewer(_headersTable);
+ final TableSorter queuesTableSorter = new TableSorter(HDR_QUEUE_BINDINGS);
+
+ titles = new String[]{"Header Bindings"};
+ bounds = new int[]{225};
+ for (int i = 0; i < titles.length; i++)
+ {
+ final int index = i;
+ final TableColumn column = new TableColumn (_headersTable, SWT.NONE);
+
+ column.setText(titles[i]);
+ column.setWidth(bounds[i]);
+ column.setResizable(true);
+
+ //Setting the right sorter
+ column.addSelectionListener(new SelectionAdapter()
+ {
+ @Override
+ public void widgetSelected(SelectionEvent e)
+ {
+ queuesTableSorter.setColumn(index);
+ final TableViewer viewer = _headersTableViewer;
+ int dir = viewer .getTable().getSortDirection();
+ if (viewer.getTable().getSortColumn() == column)
+ {
+ dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
+ }
+ else
+ {
+ dir = SWT.UP;
+ }
+ viewer.getTable().setSortDirection(dir);
+ viewer.getTable().setSortColumn(column);
+ viewer.refresh();
+ }
+ });
+
+ }
+
+ _headersTableViewer.setContentProvider(new ContentProviderImpl(HDR_QUEUE_BINDINGS));
+ _headersTableViewer.setLabelProvider(new LabelProviderImpl(HDR_QUEUE_BINDINGS));
+ _headersTableViewer.setSorter(queuesTableSorter);
+ _headersTable.setSortColumn(_headersTable.getColumn(0));
+ _headersTable.setSortDirection(SWT.UP);
+ _headersTableViewer.setInput(new String[]{"Select a binding to view key-value pairs"});
+
+ _bindingNumberTableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
+ public void selectionChanged(SelectionChangedEvent evt)
+ {
+ int selectionIndex = _bindingNumberTable.getSelectionIndex();
+
+ if (selectionIndex != -1)
+ {
+ final CompositeData selectedMsg = (CompositeData)_bindingNumberTable.getItem(selectionIndex).getData();
+
+ String[] bindings = (String[]) selectedMsg.get(HDR_QUEUE_BINDINGS);
+ _headersTableViewer.setInput(bindings);
+ }
+ else
+ {
+ _headersTableViewer.setInput(new String[]{"Select a binding to view key-value pairs"});
+ }
+ }
+ });
+
+ //listener for double clicking to open the selection mbean
+ _bindingNumberTable.addMouseListener(new MouseListener()
+ {
+ // MouseListener implementation
+ public void mouseDoubleClick(MouseEvent event)
+ {
+ openMBean(_bindingNumberTable);
+ }
+
+ public void mouseDown(MouseEvent e){}
+ public void mouseUp(MouseEvent e){}
+ });
+
+ //Side Buttons
+ Composite buttonsComposite = _toolkit.createComposite(bindingsGroup);
+ gridData = new GridData(SWT.FILL, SWT.FILL, false, true);
+ buttonsComposite.setLayoutData(gridData);
+ buttonsComposite.setLayout(new GridLayout());
+
+ final Button createBindingButton = _toolkit.createButton(buttonsComposite, "Create ...", SWT.PUSH);
+ createBindingButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ createNewBinding(createBindingButton.getShell());
+ }
+ });
+
+ }
+
+
+ /**
+ * Content Provider class for the table viewer
+ */
+ private static class ContentProviderImpl implements IStructuredContentProvider
+ {
+ String type;
+
+ public ContentProviderImpl(String type)
+ {
+ this.type = type;
+ }
+
+ public void inputChanged(Viewer v, Object oldInput, Object newInput)
+ {
+
+ }
+
+ public void dispose()
+ {
+
+ }
+
+ public Object[] getElements(Object parent)
+ {
+ if(type.equals(HDR_BINDING_NUMBER))
+ {
+ Collection<Object> rowCollection = ((TabularDataSupport) parent).values();
+
+ return rowCollection.toArray();
+ }
+ else
+ {
+ //we have the list of bindings, return directly
+ return (String[]) parent;
+ }
+ }
+ }
+
+ /**
+ * Label Provider class for the routing key table viewer
+ */
+ private static class LabelProviderImpl extends LabelProvider implements ITableLabelProvider
+ {
+ String type;
+
+ public LabelProviderImpl(String type)
+ {
+ this.type = type;
+ }
+
+ public String getColumnText(Object element, int columnIndex)
+ {
+ if(type.equals(HDR_BINDING_NUMBER)) //binding num and queue name table
+ {
+ switch (columnIndex)
+ {
+ case 0 : // binding number column
+ return String.valueOf(((CompositeDataSupport) element).get(HDR_BINDING_NUMBER));
+ case 1 : // queue name column
+ return (String) ((CompositeDataSupport) element).get(HDR_QUEUE_NAME);
+ default :
+ return "";
+ }
+ }
+ else //binding key-value pair table
+ {
+ switch (columnIndex)
+ {
+ case 0 : //header binding column
+ return String.valueOf(element);
+ default :
+ return "";
+ }
+ }
+ }
+
+ public Image getColumnImage(Object element, int columnIndex)
+ {
+ return null;
+ }
+ }
+
+ /**
+ * Sorter class for the table viewer.
+ *
+ */
+ public static class TableSorter extends ViewerSorter
+ {
+ private int column;
+ private static final int ASCENDING = 0;
+ private static final int DESCENDING = 1;
+
+ private int direction = DESCENDING;
+
+ private String type;
+
+ public TableSorter(String type)
+ {
+ this.type = type;
+ this.column = 0;
+ direction = ASCENDING;
+ }
+
+ public void setColumn(int column)
+ {
+ if (column == this.column)
+ {
+ // Same column as last sort; toggle the direction
+ direction = 1 - direction;
+ }
+ else
+ {
+ // New column; do an ascending sort
+ this.column = column;
+ direction = ASCENDING;
+ }
+ }
+
+ @Override
+ public int compare(Viewer viewer, Object e1, Object e2)
+ {
+ int comparison = 0;
+
+ if(type.equals(HDR_BINDING_NUMBER)) //binding num and queue name table
+ {
+ CompositeData binding1 = (CompositeData) e1;
+ CompositeData binding2 = (CompositeData) e2;
+
+ switch(column)
+ {
+ case 0: // binding number column
+ comparison = ((Integer) binding1.get(HDR_BINDING_NUMBER)).compareTo((Integer) binding2.get(HDR_BINDING_NUMBER));
+ break;
+ case 1: // queue name column
+ comparison = ((String) binding1.get(HDR_QUEUE_NAME)).compareTo((String) binding2.get(HDR_QUEUE_NAME));
+ break;
+ default:
+ comparison = 0;
+ }
+ }
+ else //binding key-value pair table
+ {
+ switch(column)
+ {
+ case 0: //header binding column
+ comparison = ((String)e1).compareTo((String) e2);
+ break;
+ default:
+ comparison = 0;
+ }
+ }
+
+ // If descending order, flip the direction
+ if(direction == DESCENDING)
+ {
+ comparison = -comparison;
+ }
+ return comparison;
+ }
+ }
+
+ private void createNewBinding(Shell parent)
+ {
+ final Shell shell = ViewUtility.createModalDialogShell(parent, "Create New Binding");
+
+ Composite queueNameComposite = _toolkit.createComposite(shell, SWT.NONE);
+ queueNameComposite.setBackground(shell.getBackground());
+ GridData layoutData = new GridData(SWT.CENTER, SWT.TOP, true, false);
+ layoutData.minimumWidth = 300;
+ queueNameComposite.setLayoutData(layoutData);
+ queueNameComposite.setLayout(new GridLayout(2,false));
+
+ _toolkit.createLabel(queueNameComposite,"Queue:").setBackground(shell.getBackground());
+ final Combo destinationCombo = new Combo(queueNameComposite,SWT.NONE | SWT.READ_ONLY);
+ destinationCombo.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+
+ final ScrolledComposite scrolledComposite = new ScrolledComposite(shell, SWT.V_SCROLL);
+ scrolledComposite.setExpandHorizontal(true);
+ scrolledComposite.setLayout(new GridLayout());
+ scrolledComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ scrolledComposite.setBackground(shell.getBackground());
+
+ final Composite bindingComposite = _toolkit.createComposite(scrolledComposite, SWT.NONE);
+ bindingComposite.setBackground(scrolledComposite.getBackground());
+ bindingComposite.setLayout(new GridLayout(2,true));
+ layoutData = new GridData(SWT.FILL, SWT.TOP, true, false);
+ bindingComposite.setLayoutData(layoutData);
+ scrolledComposite.setContent(bindingComposite);
+
+ Composite addMoreButtonComp = _toolkit.createComposite(shell);
+ addMoreButtonComp.setBackground(shell.getBackground());
+ addMoreButtonComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
+ addMoreButtonComp.setLayout(new GridLayout());
+
+ final Button addMoreButton = _toolkit.createButton(addMoreButtonComp, "Add additional field", SWT.PUSH);
+
+ Composite okCancelButtonsComp = _toolkit.createComposite(shell);
+ okCancelButtonsComp.setBackground(shell.getBackground());
+ okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
+ okCancelButtonsComp.setLayout(new GridLayout(2,false));
+
+ Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
+ okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+ Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
+ cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+
+ List<String> queueList = ApplicationRegistry.getServerRegistry(_mbean).getQueueNames(_mbean.getVirtualHostName());
+
+ if(queueList.size() == 0)
+ {
+ destinationCombo.setItems(new String[]{"No queues available"});
+ okButton.setEnabled(false);
+ }
+ else
+ {
+ Collections.sort(queueList);
+ destinationCombo.setItems(queueList.toArray(new String[0]));
+ }
+ destinationCombo.select(0);
+
+ final HashMap<Text, Text> headerBindingHashMap = new HashMap<Text, Text>();
+
+ //add headings
+ Label keyLabel = _toolkit.createLabel(bindingComposite,"Key:");
+ keyLabel.setBackground(bindingComposite.getBackground());
+ keyLabel.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, true, false));
+
+ Label valueLabel = _toolkit.createLabel(bindingComposite,"Value:");
+ valueLabel.setBackground(bindingComposite.getBackground());
+ valueLabel.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, true, false));
+
+ //add the x-match key by default and offer a comobo to select its value
+ final Text xmatchKeyText = new Text(bindingComposite, SWT.BORDER);
+ xmatchKeyText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ xmatchKeyText.setText("x-match");
+ xmatchKeyText.setEditable(false);
+
+ final Combo xmatchValueCombo = new Combo(bindingComposite,SWT.NONE | SWT.READ_ONLY);
+ xmatchValueCombo.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ xmatchValueCombo.setItems(new String[]{"any", "all"});
+ xmatchValueCombo.select(0);
+
+ //make some empty key-value fields
+ for(int i=0; i < 4; i++)
+ {
+ Text keyText = new Text(bindingComposite, SWT.BORDER);
+ Text valueText = new Text(bindingComposite, SWT.BORDER);
+ keyText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ valueText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+
+ headerBindingHashMap.put(keyText, valueText);
+ }
+ bindingComposite.setSize(bindingComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+
+ //allow adding more fields for additional key-value pairs
+ addMoreButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ Text keyText = new Text(bindingComposite, SWT.BORDER);
+ Text valueText = new Text(bindingComposite, SWT.BORDER);
+ keyText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ valueText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+
+ headerBindingHashMap.put(keyText, valueText);
+
+ bindingComposite.setSize(bindingComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT));
+ bindingComposite.layout(true);
+ scrolledComposite.layout(true);
+ }
+ });
+
+ okButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ String xMatchString = xmatchValueCombo.getText();
+
+ String destQueue = destinationCombo.getItem(destinationCombo.getSelectionIndex()).toString();
+
+ StringBuffer bindingValue = new StringBuffer();
+
+ //insert the x-match key-value pair
+ if (xMatchString.equalsIgnoreCase("any"))
+ {
+ bindingValue.append("x-match=any");
+ }
+ else
+ {
+ bindingValue.append("x-match=all");
+ }
+
+ //insert the other key-value pairs
+ for (Text keyText : headerBindingHashMap.keySet())
+ {
+
+ String key = keyText.getText();
+ if(key == null || key.length() == 0)
+ {
+ continue;
+ }
+
+ Text valueText = headerBindingHashMap.get(keyText);
+ String value = valueText.getText();
+
+ bindingValue.append(",");
+ bindingValue.append(key + "=");
+ //empty values are permitted, signalling only key-presence is required
+ if(value != null && value.length() > 0)
+ {
+ bindingValue.append(value);
+ }
+ }
+
+ shell.dispose();
+
+ try
+ {
+ _emb.createNewBinding(destQueue, bindingValue.toString());
+ ViewUtility.operationResultFeedback(null, "Created new Binding", null);
+ }
+ catch (Exception e4)
+ {
+ ViewUtility.operationFailedStatusBarMessage("Error creating new Binding");
+ MBeanUtility.handleException(_mbean, e4);
+ }
+
+ refresh(_mbean);
+ }
+ });
+
+ cancelButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ shell.dispose();
+ }
+ });
+
+ shell.setDefaultButton(okButton);
+ shell.pack();
+ ViewUtility.centerChildInParentShell(parent, shell);
+
+ shell.open();
+ }
+
+ private void openMBean(Table table)
+ {
+ int selectionIndex = table.getSelectionIndex();
+
+ if (selectionIndex == -1)
+ {
+ return;
+ }
+
+ CompositeData bindingResult = (CompositeData) table.getItem(selectionIndex).getData();
+ String queueName = (String) bindingResult.get(HDR_QUEUE_NAME);
+ ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(_mbean);
+ ManagedBean selectedMBean = serverRegistry.getQueue(queueName, _mbean.getVirtualHostName());
+
+ if(selectedMBean == null)
+ {
+ ViewUtility.popupErrorMessage("Error", "Unable to retrieve the selected MBean to open it");
+ return;
+ }
+
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ MBeanView view = (MBeanView) window.getActivePage().findView(MBeanView.ID);
+ try
+ {
+ view.openMBean(selectedMBean);
+ }
+ catch (Exception ex)
+ {
+ MBeanUtility.handleException(selectedMBean, ex);
+ }
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/ConfigurationFileTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/ConfigurationFileTabControl.java
new file mode 100644
index 0000000000..1ae48f5c6c
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/ConfigurationFileTabControl.java
@@ -0,0 +1,591 @@
+/*
+ *
+ * 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.logging;
+
+import static org.apache.qpid.management.common.mbeans.LoggingManagement.LOGGER_LEVEL;
+import static org.apache.qpid.management.common.mbeans.LoggingManagement.LOGGER_NAME;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularDataSupport;
+
+import static org.apache.qpid.management.ui.Constants.FONT_BOLD;
+
+import org.apache.qpid.management.ui.ApiVersion;
+import org.apache.qpid.management.ui.ApplicationRegistry;
+import org.apache.qpid.management.ui.ManagedBean;
+import org.apache.qpid.management.common.mbeans.LoggingManagement;
+import org.apache.qpid.management.ui.jmx.JMXManagedObject;
+import org.apache.qpid.management.ui.jmx.MBeanUtility;
+import org.apache.qpid.management.ui.views.TabControl;
+import org.apache.qpid.management.ui.views.ViewUtility;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.SelectionChangedEvent;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+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.Group;
+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.FormToolkit;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+
+
+/**
+ * Control class for the LoggingManagement mbean ConfigFile Options tab.
+ */
+public class ConfigurationFileTabControl extends TabControl
+{
+ private FormToolkit _toolkit;
+ private ScrolledForm _form;
+ private Table _table = null;
+ private TableViewer _tableViewer = null;
+ private Composite _headerComposite = null;
+ private Composite _paramsComposite = null;
+
+ private Label _configFileRootLoggerLevelLabel = null;
+ private Label _logWatchIntervalLabel = null;
+ private String[] _availableLoggerLevels;
+ private TabularDataSupport _configFileLoggerLevels = null;
+ private LoggingManagement _lmmb;
+ private ApiVersion _ApiVersion;
+
+ public ConfigurationFileTabControl(TabFolder tabFolder, JMXManagedObject mbean, MBeanServerConnection mbsc)
+ {
+ super(tabFolder);
+ _mbean = mbean;
+ _lmmb = (LoggingManagement)
+ MBeanServerInvocationHandler.newProxyInstance(mbsc, mbean.getObjectName(),
+ LoggingManagement.class, false);
+ _ApiVersion = ApplicationRegistry.getServerRegistry(mbean).getManagementApiVersion();
+ _toolkit = new FormToolkit(_tabFolder.getDisplay());
+ _form = _toolkit.createScrolledForm(_tabFolder);
+ _form.getBody().setLayout(new GridLayout());
+ createComposites();
+ createWidgets();
+ }
+
+ private void createComposites()
+ {
+
+ _headerComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
+ _headerComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ _headerComposite.setLayout(new GridLayout());
+
+ _paramsComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
+ _paramsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ _paramsComposite.setLayout(new GridLayout());
+ }
+
+ /**
+ * @see TabControl#getControl()
+ */
+ public Control getControl()
+ {
+ return _form;
+ }
+
+ /**
+ * @see TabControl#setFocus()
+ */
+ public void setFocus()
+ {
+ _table.setFocus();
+ }
+
+ @Override
+ public void refresh(ManagedBean mbean)
+ {
+ String configFileRootLoggerLevel = "-";
+ try
+ {
+ configFileRootLoggerLevel = _lmmb.getConfigFileRootLoggerLevel();
+ }
+ catch (Exception e1)
+ {
+ MBeanUtility.handleException(_mbean, e1);
+ }
+
+ int log4jLogWatchInterval = -1;
+ try
+ {
+ log4jLogWatchInterval = _lmmb.getLog4jLogWatchInterval();
+ }
+ catch (Exception e2)
+ {
+ MBeanUtility.handleException(_mbean, e2);
+ }
+
+ _configFileLoggerLevels = null;
+ try
+ {
+ _configFileLoggerLevels = (TabularDataSupport) _lmmb.viewConfigFileLoggerLevels();
+ }
+ catch (Exception e3)
+ {
+ MBeanUtility.handleException(_mbean, e3);
+ }
+
+ _configFileRootLoggerLevelLabel.setText(String.valueOf(configFileRootLoggerLevel));
+ if (log4jLogWatchInterval == 0)
+ {
+ _logWatchIntervalLabel.setText("Disabled (0 sec)");
+ }
+ else
+ {
+ _logWatchIntervalLabel.setText(String.valueOf(log4jLogWatchInterval) + " seconds");
+ }
+ _tableViewer.setInput(_configFileLoggerLevels);
+
+ layout();
+ }
+
+ public void layout()
+ {
+ _form.layout(true);
+ _form.getBody().layout(true, true);
+ }
+
+ private void createWidgets()
+ {
+ try
+ {
+ _availableLoggerLevels = _lmmb.getAvailableLoggerLevels();
+ }
+ catch(Exception e)
+ {
+ _availableLoggerLevels = new String[]{"ALL","TRACE","DEBUG","INFO","WARN","ERROR","FATAL","OFF"};
+ }
+
+ Label noteLabel = _toolkit.createLabel(_headerComposite,
+ "NOTE: These options modify the configuration file. " +
+ "Changes only take effect automatically if LogWatch is enabled.");
+ Label noteLabel2 = _toolkit.createLabel(_headerComposite,
+ "A child Logger set to a non-inherited Level in the Runtime tab " +
+ "will retain that value after the file is reloaded.");
+ GridData gridData = new GridData(SWT.FILL, SWT.FILL, false, true);
+ noteLabel.setLayoutData(gridData);
+ gridData = new GridData(SWT.FILL, SWT.FILL, false, true);
+ noteLabel2.setLayoutData(gridData);
+
+ Group configFileLoggerLevelsGroup = new Group(_paramsComposite, SWT.SHADOW_NONE);
+ configFileLoggerLevelsGroup.setBackground(_paramsComposite.getBackground());
+ configFileLoggerLevelsGroup.setText("Configuration File Logger Levels");
+ configFileLoggerLevelsGroup.setLayout(new GridLayout());
+ gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+ configFileLoggerLevelsGroup.setLayoutData(gridData);
+
+ Composite tableComposite = _toolkit.createComposite(configFileLoggerLevelsGroup);
+ gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+ gridData.heightHint = 250;
+ gridData.minimumHeight = 250;
+ tableComposite.setLayoutData(gridData);
+ GridLayout gridLayout = new GridLayout();
+
+ tableComposite.setLayout(gridLayout);
+
+ _table = new Table (tableComposite, SWT.MULTI | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION);
+ _table.setLinesVisible (true);
+ _table.setHeaderVisible (true);
+ GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
+ _table.setLayoutData(data);
+
+ _tableViewer = new TableViewer(_table);
+ final LoggingTableSorter tableSorter = new LoggingTableSorter();
+
+ String[] titles = { LOGGER_NAME, LOGGER_LEVEL };
+ int[] bounds = { 600, 75 };
+ for (int i = 0; i < titles.length; i++)
+ {
+ final int index = i;
+ final TableViewerColumn viewerColumn = new TableViewerColumn(_tableViewer, SWT.NONE);
+ final TableColumn column = viewerColumn.getColumn();
+
+ column.setText(titles[i]);
+ column.setWidth(bounds[i]);
+ column.setResizable(true);
+
+ //Setting the right sorter
+ column.addSelectionListener(new SelectionAdapter()
+ {
+ @Override
+ public void widgetSelected(SelectionEvent e)
+ {
+ tableSorter.setColumn(index);
+ final TableViewer viewer = _tableViewer;
+ int dir = viewer .getTable().getSortDirection();
+ if (viewer.getTable().getSortColumn() == column)
+ {
+ dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
+ }
+ else
+ {
+ dir = SWT.UP;
+ }
+ viewer.getTable().setSortDirection(dir);
+ viewer.getTable().setSortColumn(column);
+ viewer.refresh();
+ }
+ });
+
+ }
+
+ _tableViewer.setContentProvider(new LoggingTableContentProvider());
+ _tableViewer.setLabelProvider(new LoggingTableLabelProvider());
+ _tableViewer.setSorter(tableSorter);
+ _table.setSortColumn(_table.getColumn(0));
+ _table.setSortDirection(SWT.UP);
+ _table.addMouseListener(new MouseListener()
+ {
+ public void mouseDoubleClick(MouseEvent event)
+ {
+ editLoggerLevel(_table.getShell());
+ }
+
+ public void mouseDown(MouseEvent e){}
+ public void mouseUp(MouseEvent e){}
+ });
+
+ final Button logLevelEditButton = _toolkit.createButton(configFileLoggerLevelsGroup, "Edit Selected Logger(s)...", SWT.PUSH);
+ logLevelEditButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
+ logLevelEditButton.setEnabled(false);
+ logLevelEditButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ editLoggerLevel(logLevelEditButton.getShell());
+ }
+ });
+
+ _tableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
+ public void selectionChanged(SelectionChangedEvent evt)
+ {
+ int selectionIndex = _table.getSelectionIndex();
+
+ if(selectionIndex != -1)
+ {
+ logLevelEditButton.setEnabled(true);
+ }
+ else
+ {
+ logLevelEditButton.setEnabled(false);
+ }
+ }
+ });
+
+
+ Composite attributesComposite = _toolkit.createComposite(_paramsComposite);
+ gridData = new GridData(SWT.LEFT, SWT.FILL, false, true);
+ attributesComposite.setLayoutData(gridData);
+ gridLayout = new GridLayout(3,false);
+ attributesComposite.setLayout(gridLayout);
+
+ Group configFileRootLoggerLevelGroup = new Group(attributesComposite, SWT.SHADOW_NONE);
+ configFileRootLoggerLevelGroup.setBackground(attributesComposite.getBackground());
+ configFileRootLoggerLevelGroup.setText("Config File RootLogger Level");
+ gridData = new GridData(SWT.LEFT, SWT.TOP, true, false);
+ configFileRootLoggerLevelGroup.setLayoutData(gridData);
+ configFileRootLoggerLevelGroup.setLayout(new GridLayout(2,false));
+
+ _configFileRootLoggerLevelLabel = _toolkit.createLabel(configFileRootLoggerLevelGroup, "-");
+ _configFileRootLoggerLevelLabel.setFont(ApplicationRegistry.getFont(FONT_BOLD));
+ _configFileRootLoggerLevelLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));
+
+ final Button configFileRootLoggerLevelButton = _toolkit.createButton(configFileRootLoggerLevelGroup, "Edit ...", SWT.PUSH);
+ configFileRootLoggerLevelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false));
+ configFileRootLoggerLevelButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ editRootLoggerLevel(configFileRootLoggerLevelButton.getShell());
+ }
+ });
+
+
+ Group logWatchIntervalGroup = new Group(attributesComposite, SWT.SHADOW_NONE);
+ logWatchIntervalGroup.setBackground(attributesComposite.getBackground());
+ logWatchIntervalGroup.setText("LogWatch Interval");
+ gridData = new GridData(SWT.LEFT, SWT.FILL, true, false);
+ logWatchIntervalGroup.setLayoutData(gridData);
+ logWatchIntervalGroup.setLayout(new GridLayout());
+
+ _logWatchIntervalLabel = _toolkit.createLabel(logWatchIntervalGroup, "-");
+ _logWatchIntervalLabel.setFont(ApplicationRegistry.getFont(FONT_BOLD));
+ _logWatchIntervalLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, true));
+
+ if(_ApiVersion.greaterThanOrEqualTo(1, 4))
+ {
+ Group reloadConfigFileGroup = new Group(attributesComposite, SWT.SHADOW_NONE);
+ reloadConfigFileGroup.setBackground(attributesComposite.getBackground());
+ reloadConfigFileGroup.setText("Reload Configuration File");
+ gridData = new GridData(SWT.LEFT, SWT.TOP, true, false);
+ reloadConfigFileGroup.setLayoutData(gridData);
+ reloadConfigFileGroup.setLayout(new GridLayout());
+
+ final Button reloadConfigFileButton = _toolkit.createButton(reloadConfigFileGroup, "Reload Config File", SWT.PUSH);
+ reloadConfigFileButton.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, true, false));
+ reloadConfigFileButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ int response = ViewUtility.popupOkCancelConfirmationMessage("Reload",
+ "Reload Logging Configuration File?");
+ if (response == SWT.OK)
+ {
+ try
+ {
+ _lmmb.reloadConfigFile();
+ ViewUtility.operationResultFeedback(null, "Reloaded Logging Configuration File", null);
+
+ }
+ catch (Exception ex)
+ {
+ ViewUtility.operationFailedStatusBarMessage("Error Reloading Logging Configuration File");
+ MBeanUtility.handleException(_mbean, ex);
+ }
+
+ refresh(_mbean);;
+ }
+ }
+ });
+ }
+ }
+
+
+
+ private void editLoggerLevel(Shell parent)
+ {
+ int selectionIndex = _table.getSelectionIndex();
+
+ if (selectionIndex != -1)
+ {
+ int[] selectedIndices = _table.getSelectionIndices();
+
+ final ArrayList<String> selectedLoggers = new ArrayList<String>();
+
+ for(int index = 0; index < selectedIndices.length ; index++)
+ {
+ CompositeData selectedLogger = (CompositeData)_table.getItem(selectedIndices[index]).getData();
+ String user = (String) selectedLogger.get(LOGGER_NAME);
+ selectedLoggers.add(user);
+ }
+
+ final Shell shell = ViewUtility.createModalDialogShell(parent, "Set Config File Logger Level(s)");
+
+ _toolkit.createLabel(shell, "Logger(s): ").setBackground(shell.getBackground());
+
+ final Text headerText = new Text(shell, SWT.WRAP | SWT.V_SCROLL | SWT.BORDER );
+ headerText.setEditable(false);
+ GridData data = new GridData(SWT.FILL, SWT.FILL, false, false);
+ data.minimumHeight = 125;
+ data.heightHint = 125;
+ data.minimumWidth = 575;
+ data.widthHint = 575;
+ headerText.setLayoutData(data);
+
+ String lineSeperator = System.getProperty("line.separator");
+ for(String loggerName : selectedLoggers)
+ {
+ headerText.append(loggerName + lineSeperator);
+ }
+ headerText.setSelection(0);
+
+ Composite levelComp = _toolkit.createComposite(shell);
+ levelComp.setBackground(shell.getBackground());
+ levelComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ levelComp.setLayout(new GridLayout(2,false));
+
+ _toolkit.createLabel(levelComp,"Level: ").setBackground(levelComp.getBackground());
+ final Combo levelCombo = new Combo (levelComp, SWT.READ_ONLY );
+ levelCombo.setItems(_availableLoggerLevels);
+ levelCombo.select(0);
+
+ Composite okCancelButtonsComp = _toolkit.createComposite(shell);
+ okCancelButtonsComp.setBackground(shell.getBackground());
+ okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
+ okCancelButtonsComp.setLayout(new GridLayout(2,false));
+
+ Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
+ okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+ Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
+ cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+
+ okButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ String level = levelCombo.getItem(levelCombo.getSelectionIndex()).toString();
+
+ shell.close();
+
+ try
+ {
+ HashMap<String,Boolean> results = new HashMap<String,Boolean>();
+
+ //perform the updates, save the results.
+ for(String logger : selectedLoggers)
+ {
+ boolean result = _lmmb.setConfigFileLoggerLevel(logger, level);
+ results.put(logger, result);
+ }
+
+ //categorise the overall result
+ boolean overallResult = true;
+ for(boolean result : results.values())
+ {
+ if (!result)
+ {
+ overallResult = false;
+ }
+ }
+
+ //output the result to status bar if all succeed, and dialogue if not
+ if(overallResult)
+ {
+ ViewUtility.operationResultFeedback(overallResult, "Updated ConfigFile Logger Level(s)", null);
+ }
+ else
+ {
+ String failedToSetLevelOfLoggers = "";
+ for(String logger : results.keySet())
+ {
+ if(!results.get(logger))
+ {
+ failedToSetLevelOfLoggers = failedToSetLevelOfLoggers.concat(logger + ", ");
+ }
+ }
+
+ //cut off last ", "
+ int lastIndex = failedToSetLevelOfLoggers.lastIndexOf(',');
+ if (lastIndex != -1)
+ {
+ failedToSetLevelOfLoggers = failedToSetLevelOfLoggers.substring(0, lastIndex);
+ }
+
+ ViewUtility.operationResultFeedback(overallResult, null,
+ "Failed to update ConfigFile Logger Level(s): "
+ + failedToSetLevelOfLoggers);
+ }
+ }
+ catch(Exception e4)
+ {
+ ViewUtility.operationFailedStatusBarMessage("Error updating Config File Logger Level(s)");
+ MBeanUtility.handleException(_mbean, e4);
+ }
+
+ refresh(_mbean);
+ }
+ });
+
+ cancelButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ shell.dispose();
+ }
+ });
+
+ shell.setDefaultButton(okButton);
+ shell.pack();
+ ViewUtility.centerChildInParentShell(parent, shell);
+
+ shell.open();
+ }
+ }
+
+ private void editRootLoggerLevel(Shell parent)
+ {
+ final Shell shell = ViewUtility.createModalDialogShell(parent, "ConfigFile RootLogger Level");
+
+ Composite levelComp = _toolkit.createComposite(shell);
+ levelComp.setBackground(shell.getBackground());
+ levelComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ levelComp.setLayout(new GridLayout(2,false));
+
+ _toolkit.createLabel(levelComp,"RootLogger level: ").setBackground(levelComp.getBackground());
+ final Combo levelCombo = new Combo (levelComp, SWT.READ_ONLY );
+ levelCombo.setItems(_availableLoggerLevels);
+ levelCombo.select(0);
+
+ Composite okCancelButtonsComp = _toolkit.createComposite(shell);
+ okCancelButtonsComp.setBackground(shell.getBackground());
+ okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
+ okCancelButtonsComp.setLayout(new GridLayout(2,false));
+
+ Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
+ okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+ Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
+ cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+
+ okButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ String selection = levelCombo.getItem(levelCombo.getSelectionIndex()).toString();
+ shell.dispose();
+ try
+ {
+ boolean result = _lmmb.setConfigFileRootLoggerLevel(selection);
+ ViewUtility.operationResultFeedback(result,
+ "Updated ConfigFile RootLogger Level", "Failed to update ConfigFile RootLogger Level");
+ }
+ catch (Exception e5)
+ {
+ ViewUtility.operationFailedStatusBarMessage("Error updating ConfigFile RootLogger Level");
+ MBeanUtility.handleException(_mbean, e5);
+ }
+ refresh(_mbean);
+ }
+ });
+
+ cancelButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ shell.dispose();
+ }
+ });
+
+ shell.setDefaultButton(okButton);
+ shell.pack();
+ ViewUtility.centerChildInParentShell(parent, shell);
+
+ shell.open();
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/LoggingTableContentProvider.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/LoggingTableContentProvider.java
new file mode 100644
index 0000000000..6ef3ab70a7
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/LoggingTableContentProvider.java
@@ -0,0 +1,52 @@
+/*
+ *
+ * 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.logging;
+
+import java.util.Collection;
+
+import javax.management.openmbean.TabularDataSupport;
+
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.Viewer;
+
+/**
+ * Content Provider class for theLogging Management table viewers
+ */
+public class LoggingTableContentProvider implements IStructuredContentProvider
+{
+
+ public void inputChanged(Viewer v, Object oldInput, Object newInput)
+ {
+
+ }
+
+ public void dispose()
+ {
+
+ }
+
+ public Object[] getElements(Object parent)
+ {
+ Collection<Object> rowCollection = ((TabularDataSupport) parent).values();
+
+ return rowCollection.toArray();
+ }
+} \ No newline at end of file
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/LoggingTableLabelProvider.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/LoggingTableLabelProvider.java
new file mode 100644
index 0000000000..3156e3f1c4
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/LoggingTableLabelProvider.java
@@ -0,0 +1,59 @@
+/*
+ *
+ * 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.logging;
+
+import static org.apache.qpid.management.common.mbeans.LoggingManagement.LOGGER_LEVEL;
+import static org.apache.qpid.management.common.mbeans.LoggingManagement.LOGGER_NAME;
+
+
+import javax.management.openmbean.CompositeDataSupport;
+
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.graphics.Image;
+
+/**
+ * Label Provider class for the LoggingManagement table viewers
+ */
+public class LoggingTableLabelProvider extends LabelProvider implements ITableLabelProvider
+{
+ @Override
+ public String getColumnText(Object element, int columnIndex)
+ {
+ switch (columnIndex)
+ {
+ case 0 : // logger name column
+ return (String) ((CompositeDataSupport) element).get(LOGGER_NAME);
+ case 1 : // logger level column
+ return (String) ((CompositeDataSupport) element).get(LOGGER_LEVEL);
+ default :
+ return "-";
+ }
+ }
+
+ @Override
+ public Image getColumnImage(Object element, int columnIndex)
+ {
+ return null;
+ }
+
+
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/LoggingTableSorter.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/LoggingTableSorter.java
new file mode 100644
index 0000000000..99d22f2cb8
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/LoggingTableSorter.java
@@ -0,0 +1,90 @@
+/*
+ *
+ * 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.logging;
+
+import static org.apache.qpid.management.common.mbeans.LoggingManagement.LOGGER_LEVEL;
+import static org.apache.qpid.management.common.mbeans.LoggingManagement.LOGGER_NAME;
+
+import javax.management.openmbean.CompositeData;
+
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+
+/**
+ * Sorter class for the Logging Management table viewers.
+ */
+public class LoggingTableSorter extends ViewerSorter
+{
+ private static final int ASCENDING = 0;
+ private static final int DESCENDING = 1;
+
+ private int column;
+ private int direction;
+
+ public LoggingTableSorter()
+ {
+ this.column = 0;
+ direction = ASCENDING;
+ }
+
+ public void setColumn(int column)
+ {
+ if (column == this.column)
+ {
+ // Same column as last sort; toggle the direction
+ direction = 1 - direction;
+ }
+ else
+ {
+ // New column; do an ascending sort
+ this.column = column;
+ direction = ASCENDING;
+ }
+ }
+
+ @Override
+ public int compare(Viewer viewer, Object e1, Object e2)
+ {
+ CompositeData logger1 = (CompositeData) e1;
+ CompositeData logger2 = (CompositeData) e2;
+
+ int comparison = 0;
+ switch(column)
+ {
+ case 0:
+ comparison = String.valueOf(logger1.get(LOGGER_NAME)).compareTo(
+ String.valueOf(logger2.get(LOGGER_NAME)));
+ break;
+ case 1:
+ comparison = String.valueOf(logger1.get(LOGGER_LEVEL)).compareTo(
+ String.valueOf(logger2.get(LOGGER_LEVEL)));
+ break;
+ default:
+ comparison = 0;
+ }
+ // If descending order, flip the direction
+ if (direction == DESCENDING)
+ {
+ comparison = -comparison;
+ }
+ return comparison;
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/RuntimeTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/RuntimeTabControl.java
new file mode 100644
index 0000000000..1ae97cfcb6
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/logging/RuntimeTabControl.java
@@ -0,0 +1,595 @@
+/*
+ *
+ * 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.logging;
+
+import static org.apache.qpid.management.common.mbeans.LoggingManagement.LOGGER_LEVEL;
+import static org.apache.qpid.management.common.mbeans.LoggingManagement.LOGGER_NAME;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.TabularDataSupport;
+
+import static org.apache.qpid.management.ui.Constants.FONT_BOLD;
+
+import org.apache.qpid.management.common.mbeans.LoggingManagement;
+import org.apache.qpid.management.ui.ApplicationRegistry;
+import org.apache.qpid.management.ui.ManagedBean;
+import org.apache.qpid.management.ui.jmx.JMXManagedObject;
+import org.apache.qpid.management.ui.jmx.MBeanUtility;
+import org.apache.qpid.management.ui.views.TabControl;
+import org.apache.qpid.management.ui.views.ViewUtility;
+import org.eclipse.jface.viewers.IColorProvider;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+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.TableViewerColumn;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Image;
+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.Group;
+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.FormToolkit;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+
+
+/**
+ * Control class for the LoggingManagement mbean Runtime Options tab.
+ */
+public class RuntimeTabControl extends TabControl
+{
+ private FormToolkit _toolkit;
+ private ScrolledForm _form;
+ private Table _table = null;
+ private TableViewer _tableViewer = null;
+ private Composite _headerComposite = null;
+ private Composite _paramsComposite = null;
+
+ private Label _runtimeRootLoggerLevelLabel = null;
+ private String[] _availableLoggerLevels;
+ private TabularDataSupport _runtimeLoggerLevels = null;
+ private ArrayList<String> _configFileLoggerNames = new ArrayList<String>();
+ private LoggingManagement _lmmb;
+
+ public RuntimeTabControl(TabFolder tabFolder, JMXManagedObject mbean, MBeanServerConnection mbsc)
+ {
+ super(tabFolder);
+ _mbean = mbean;
+ _lmmb = (LoggingManagement)
+ MBeanServerInvocationHandler.newProxyInstance(mbsc, mbean.getObjectName(),
+ LoggingManagement.class, false);
+ _toolkit = new FormToolkit(_tabFolder.getDisplay());
+ _form = _toolkit.createScrolledForm(_tabFolder);
+ _form.getBody().setLayout(new GridLayout());
+ createComposites();
+ createWidgets();
+ }
+
+ private void createComposites()
+ {
+
+ _headerComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
+ _headerComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ _headerComposite.setLayout(new GridLayout());
+
+ _paramsComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
+ _paramsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ _paramsComposite.setLayout(new GridLayout());
+ }
+
+ /**
+ * @see TabControl#getControl()
+ */
+ public Control getControl()
+ {
+ return _form;
+ }
+
+ /**
+ * @see TabControl#setFocus()
+ */
+ public void setFocus()
+ {
+ _table.setFocus();
+ }
+
+ @Override
+ public void refresh(ManagedBean mbean)
+ {
+ String runtimeRootLoggerLevel = "-";
+ try
+ {
+ runtimeRootLoggerLevel = _lmmb.getRuntimeRootLoggerLevel();
+ }
+ catch(Exception e1)
+ {
+ MBeanUtility.handleException(_mbean, e1);
+ }
+
+ _runtimeLoggerLevels = null;
+ try
+ {
+ _runtimeLoggerLevels = (TabularDataSupport) _lmmb.viewEffectiveRuntimeLoggerLevels();
+ }
+ catch(Exception e2)
+ {
+ MBeanUtility.handleException(_mbean, e2);
+ }
+
+
+ try
+ {
+ TabularDataSupport confLoggers = (TabularDataSupport) _lmmb.viewConfigFileLoggerLevels();
+ ArrayList<String> confLoggerNames = new ArrayList<String>();
+
+ for(Object obj : confLoggers.values())
+ {
+ CompositeData comp = (CompositeData) obj;
+ confLoggerNames.add((String) comp.get(LOGGER_NAME));
+ }
+
+ _configFileLoggerNames = confLoggerNames;
+ }
+ catch(Exception e2)
+ {
+ //dont signal the failure, just dont highlight the config file loggers, empty the existing list.
+ _configFileLoggerNames.clear();
+ }
+
+ _runtimeRootLoggerLevelLabel.setText(String.valueOf(runtimeRootLoggerLevel));
+ _tableViewer.setInput(_runtimeLoggerLevels);
+
+ layout();
+ }
+
+ public void layout()
+ {
+ _form.layout(true);
+ _form.getBody().layout(true, true);
+ }
+
+ private void createWidgets()
+ {
+ try
+ {
+ _availableLoggerLevels = _lmmb.getAvailableLoggerLevels();
+ }
+ catch(Exception e)
+ {
+ _availableLoggerLevels = new String[]{"ALL","TRACE","DEBUG","INFO","WARN","ERROR","FATAL","OFF"};
+ }
+
+ Label noteLabel = _toolkit.createLabel(_headerComposite,
+ "NOTE: These options modify only the live runtime settings. " +
+ "Non-default values will be lost following broker restart.");
+ Label noteLabel2 = _toolkit.createLabel(_headerComposite,
+ "Loggers currently defined in the configuration file are " +
+ "highlighted. The other Loggers inherit a Level by default.");
+ GridData gridData = new GridData(SWT.FILL, SWT.FILL, false, true);
+ noteLabel.setLayoutData(gridData);
+ gridData = new GridData(SWT.FILL, SWT.FILL, false, true);
+ noteLabel2.setLayoutData(gridData);
+
+ Group effectiveRuntimeLoggerLevelsGroup = new Group(_paramsComposite, SWT.SHADOW_NONE);
+ effectiveRuntimeLoggerLevelsGroup.setBackground(_paramsComposite.getBackground());
+ effectiveRuntimeLoggerLevelsGroup.setText("Effective Runtime Logger Levels");
+ effectiveRuntimeLoggerLevelsGroup.setLayout(new GridLayout());
+ gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+ effectiveRuntimeLoggerLevelsGroup.setLayoutData(gridData);
+
+ Composite tableComposite = _toolkit.createComposite(effectiveRuntimeLoggerLevelsGroup);
+ gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+ gridData.heightHint = 250;
+ gridData.minimumHeight = 250;
+ tableComposite.setLayoutData(gridData);
+ GridLayout gridLayout = new GridLayout();
+ tableComposite.setLayout(gridLayout);
+
+ _table = new Table (tableComposite, SWT.MULTI | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION);
+ _table.setLinesVisible (true);
+ _table.setHeaderVisible (true);
+ GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
+ _table.setLayoutData(data);
+
+ _tableViewer = new TableViewer(_table);
+ final LoggingTableSorter tableSorter = new LoggingTableSorter();
+
+ String[] titles = { LOGGER_NAME, LOGGER_LEVEL };
+ int[] bounds = { 600, 75 };
+ for (int i = 0; i < titles.length; i++)
+ {
+ final int index = i;
+ final TableViewerColumn viewerColumn = new TableViewerColumn(_tableViewer, SWT.NONE);
+ final TableColumn column = viewerColumn.getColumn();
+
+ column.setText(titles[i]);
+ column.setWidth(bounds[i]);
+ column.setResizable(true);
+
+ //Setting the right sorter
+ column.addSelectionListener(new SelectionAdapter()
+ {
+ @Override
+ public void widgetSelected(SelectionEvent e)
+ {
+ tableSorter.setColumn(index);
+ final TableViewer viewer = _tableViewer;
+ int dir = viewer.getTable().getSortDirection();
+ if (viewer.getTable().getSortColumn() == column)
+ {
+ dir = (dir == SWT.UP ? SWT.DOWN : SWT.UP);
+ }
+ else
+ {
+ dir = SWT.UP;
+ }
+ viewer.getTable().setSortDirection(dir);
+ viewer.getTable().setSortColumn(column);
+ viewer.refresh();
+ }
+ });
+
+ }
+
+ _tableViewer.setContentProvider(new LoggingTableContentProvider());
+ _tableViewer.setLabelProvider(new RuntimeLoggingTableLabelProvider());
+ _tableViewer.setSorter(tableSorter);
+ _table.setSortColumn(_table.getColumn(0));
+ _table.setSortDirection(SWT.UP);
+ _table.addMouseListener(new MouseListener()
+ {
+ public void mouseDoubleClick(MouseEvent event)
+ {
+ editLoggerLevel(_table.getShell());
+ }
+
+ public void mouseDown(MouseEvent e){}
+ public void mouseUp(MouseEvent e){}
+ });
+
+ final Button logLevelEditButton = _toolkit.createButton(effectiveRuntimeLoggerLevelsGroup, "Edit Selected Logger(s)...", SWT.PUSH);
+ logLevelEditButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false));
+ logLevelEditButton.setEnabled(false);
+ logLevelEditButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ editLoggerLevel(logLevelEditButton.getShell());
+ }
+ });
+
+ _tableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
+ public void selectionChanged(SelectionChangedEvent evt)
+ {
+ int selectionIndex = _table.getSelectionIndex();
+
+ if (selectionIndex != -1)
+ {
+ logLevelEditButton.setEnabled(true);
+ }
+ else
+ {
+ logLevelEditButton.setEnabled(false);
+ }
+ }
+ });
+
+ Composite attributesComposite = _toolkit.createComposite(_paramsComposite);
+ gridData = new GridData(SWT.FILL, SWT.FILL, false, true);
+ attributesComposite.setLayoutData(gridData);
+ gridLayout = new GridLayout(3,false);
+ attributesComposite.setLayout(gridLayout);
+
+ Group runtimeRootLoggerGroup = new Group(attributesComposite, SWT.SHADOW_NONE);
+ runtimeRootLoggerGroup.setBackground(attributesComposite.getBackground());
+ runtimeRootLoggerGroup.setText("Runtime RootLogger Level");
+ gridData = new GridData(SWT.LEFT, SWT.TOP, true, false);
+ runtimeRootLoggerGroup.setLayoutData(gridData);
+ runtimeRootLoggerGroup.setLayout(new GridLayout(2,false));
+
+ _runtimeRootLoggerLevelLabel = _toolkit.createLabel(runtimeRootLoggerGroup, "-");
+ _runtimeRootLoggerLevelLabel.setFont(ApplicationRegistry.getFont(FONT_BOLD));
+ _runtimeRootLoggerLevelLabel.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, false));
+
+ final Button runtimeRootLoggerLevelButton = _toolkit.createButton(runtimeRootLoggerGroup, "Edit ...", SWT.PUSH);
+ runtimeRootLoggerLevelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, false));
+ runtimeRootLoggerLevelButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ editRootLoggerLevel(runtimeRootLoggerLevelButton.getShell());
+ }
+ });
+ }
+
+ private void editLoggerLevel(Shell parent)
+ {
+ int selectionIndex = _table.getSelectionIndex();
+
+ if (selectionIndex != -1)
+ {
+ int[] selectedIndices = _table.getSelectionIndices();
+
+ final ArrayList<String> selectedLoggers = new ArrayList<String>();
+
+ for(int index = 0; index < selectedIndices.length ; index++)
+ {
+ CompositeData selectedLogger = (CompositeData)_table.getItem(selectedIndices[index]).getData();
+ String user = (String) selectedLogger.get(LOGGER_NAME);
+ selectedLoggers.add(user);
+ }
+
+ final Shell shell = ViewUtility.createModalDialogShell(parent, "Set Runtime Logger Level(s)");
+
+ _toolkit.createLabel(shell, "Logger(s): ").setBackground(shell.getBackground());
+
+ final Text headerText = new Text(shell, SWT.WRAP | SWT.V_SCROLL | SWT.BORDER );
+ headerText.setEditable(false);
+ GridData data = new GridData(SWT.FILL, SWT.FILL, false, false);
+ data.minimumHeight = 125;
+ data.heightHint = 125;
+ data.minimumWidth = 575;
+ data.widthHint = 575;
+ headerText.setLayoutData(data);
+
+ String lineSeperator = System.getProperty("line.separator");
+ for(String loggerName : selectedLoggers)
+ {
+ headerText.append(loggerName + lineSeperator);
+ }
+ headerText.setSelection(0);
+
+ Composite levelComp = _toolkit.createComposite(shell);
+ levelComp.setBackground(shell.getBackground());
+ levelComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ levelComp.setLayout(new GridLayout(2,false));
+
+ _toolkit.createLabel(levelComp,"Level: ").setBackground(levelComp.getBackground());
+ final Combo levelCombo = new Combo (levelComp, SWT.READ_ONLY );
+ levelCombo.setItems(_availableLoggerLevels);
+ levelCombo.select(0);
+
+ Composite okCancelButtonsComp = _toolkit.createComposite(shell);
+ okCancelButtonsComp.setBackground(shell.getBackground());
+ okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
+ okCancelButtonsComp.setLayout(new GridLayout(2,false));
+
+ Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
+ okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+ Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
+ cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+
+ okButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ String level = levelCombo.getItem(levelCombo.getSelectionIndex()).toString();
+
+ shell.close();
+
+ try
+ {
+ HashMap<String,Boolean> results = new HashMap<String,Boolean>();
+
+ //perform the updates, save the results.
+ for(String logger : selectedLoggers)
+ {
+ boolean result = _lmmb.setRuntimeLoggerLevel(logger, level);
+ results.put(logger, result);
+ }
+
+ //categorise the overall result
+ boolean overallResult = true;
+ for(boolean result : results.values())
+ {
+ if (!result)
+ {
+ overallResult = false;
+ }
+ }
+
+ //output the result to status bar if all succeed, and dialogue if not
+ if(overallResult)
+ {
+ ViewUtility.operationResultFeedback(overallResult, "Updated Runtime Logger Level(s)", null);
+ }
+ else
+ {
+ String failedToSetLevelOfLoggers = "";
+ for(String logger : results.keySet())
+ {
+ if(!results.get(logger))
+ {
+ failedToSetLevelOfLoggers = failedToSetLevelOfLoggers.concat(logger + ", ");
+ }
+ }
+
+ //cut off last ", "
+ int lastIndex = failedToSetLevelOfLoggers.lastIndexOf(',');
+ if (lastIndex != -1)
+ {
+ failedToSetLevelOfLoggers = failedToSetLevelOfLoggers.substring(0, lastIndex);
+ }
+
+ ViewUtility.operationResultFeedback(overallResult, null,
+ "Failed to update Runtime Logger Level(s): "
+ + failedToSetLevelOfLoggers);
+ }
+ }
+ catch(Exception e3)
+ {
+ ViewUtility.operationFailedStatusBarMessage("Error updating Runtime Logger Level(s)");
+ MBeanUtility.handleException(_mbean, e3);
+ }
+
+ refresh(_mbean);
+ }
+ });
+
+ cancelButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ shell.dispose();
+ }
+ });
+
+ shell.setDefaultButton(okButton);
+ shell.pack();
+ ViewUtility.centerChildInParentShell(parent, shell);
+
+ shell.open();
+ }
+ }
+
+ private void editRootLoggerLevel(Shell parent)
+ {
+ final Shell shell = ViewUtility.createModalDialogShell(parent, "Runtime RootLogger Level");
+
+ Composite levelComp = _toolkit.createComposite(shell);
+ levelComp.setBackground(shell.getBackground());
+ levelComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ levelComp.setLayout(new GridLayout(2,false));
+
+ _toolkit.createLabel(levelComp,"RootLogger level: ").setBackground(levelComp.getBackground());
+ final Combo levelCombo = new Combo (levelComp, SWT.READ_ONLY );
+ levelCombo.setItems(_availableLoggerLevels);
+ levelCombo.select(0);
+
+ Composite okCancelButtonsComp = _toolkit.createComposite(shell);
+ okCancelButtonsComp.setBackground(shell.getBackground());
+ okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
+ okCancelButtonsComp.setLayout(new GridLayout(2,false));
+
+ Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
+ okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+ Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
+ cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+
+ okButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ String selection = levelCombo.getItem(levelCombo.getSelectionIndex()).toString();
+ shell.dispose();
+
+ try
+ {
+ boolean result = _lmmb.setRuntimeRootLoggerLevel(selection);
+ ViewUtility.operationResultFeedback(result,
+ "Updated Runtime RootLogger Level", "Failed to update Runtime Logger Level");
+ }
+ catch(Exception e4)
+ {
+ ViewUtility.operationFailedStatusBarMessage("Error updating Runtime Logger Level");
+ MBeanUtility.handleException(_mbean, e4);
+ }
+
+ refresh(_mbean);
+ }
+ });
+
+ cancelButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ shell.dispose();
+ }
+ });
+
+ shell.setDefaultButton(okButton);
+ shell.pack();
+ ViewUtility.centerChildInParentShell(parent, shell);
+
+ shell.open();
+ }
+
+ /**
+ * Label Provider class for the RuntimeLoggers table viewer
+ */
+ public class RuntimeLoggingTableLabelProvider extends LabelProvider implements ITableLabelProvider, IColorProvider
+ {
+
+ @Override
+ public String getColumnText(Object element, int columnIndex)
+ {
+ switch (columnIndex)
+ {
+ case 0 : // logger name column
+ return (String) ((CompositeDataSupport) element).get(LOGGER_NAME);
+ case 1 : // logger level column
+ return (String) ((CompositeDataSupport) element).get(LOGGER_LEVEL);
+ default :
+ return "-";
+ }
+ }
+
+ @Override
+ public Image getColumnImage(Object element, int columnIndex)
+ {
+ return null;
+ }
+
+ @Override
+ public Color getBackground(Object element)
+ {
+ return null;
+ }
+
+ @Override
+ public Color getForeground(Object element)
+ {
+ String loggerName = (String) ((CompositeData) element).get(LOGGER_NAME);
+ if(_configFileLoggerNames.contains(loggerName))
+ {
+ return Display.getCurrent().getSystemColor(SWT.COLOR_BLUE);
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/queue/QueueOperationsTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/queue/QueueOperationsTabControl.java
new file mode 100644
index 0000000000..ee6bd3522b
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/queue/QueueOperationsTabControl.java
@@ -0,0 +1,1111 @@
+/*
+ *
+ * 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.queue;
+
+import static org.apache.qpid.management.common.mbeans.ManagedQueue.MSG_AMQ_ID;
+import static org.apache.qpid.management.common.mbeans.ManagedQueue.MSG_HEADER;
+import static org.apache.qpid.management.common.mbeans.ManagedQueue.MSG_QUEUE_POS;
+import static org.apache.qpid.management.common.mbeans.ManagedQueue.MSG_REDELIVERED;
+import static org.apache.qpid.management.common.mbeans.ManagedQueue.MSG_SIZE;
+import static org.apache.qpid.management.ui.Constants.CONSOLE_IMAGE;
+import static org.apache.qpid.management.ui.Constants.RESULT;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.SortedSet;
+import java.util.TreeSet;
+
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.CompositeDataSupport;
+import javax.management.openmbean.TabularDataSupport;
+
+import org.apache.qpid.management.ui.ApiVersion;
+import org.apache.qpid.management.ui.ApplicationRegistry;
+import org.apache.qpid.management.ui.ManagedBean;
+import org.apache.qpid.management.common.mbeans.ManagedQueue;
+import org.apache.qpid.management.ui.jmx.JMXManagedObject;
+import org.apache.qpid.management.ui.jmx.MBeanUtility;
+import org.apache.qpid.management.ui.views.NumberVerifyListener;
+import org.apache.qpid.management.ui.views.TabControl;
+import org.apache.qpid.management.ui.views.ViewUtility;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+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.jface.viewers.ViewerSorter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.KeyAdapter;
+import org.eclipse.swt.events.KeyEvent;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+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.Group;
+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.FormToolkit;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+
+
+/**
+ * Control class for the Queue mbean Operations tab.
+ */
+public class QueueOperationsTabControl extends TabControl
+{
+ private FormToolkit _toolkit;
+ private ScrolledForm _form;
+ private Table _table = null;
+ private TableViewer _tableViewer = null;
+ private Composite _paramsComposite = null;
+
+ private ApiVersion _ApiVersion;
+
+ private Text _fromMsgText;
+ private Text _toMsgText;
+ private static final String FROM_DEFAULT = "1";
+ private static final String TO_DEFAULT = "50";
+ private long _interval = 50; //(to-from)+1
+ private Long _fromMsg = new Long(FROM_DEFAULT);
+ private Long _toMsg = new Long(TO_DEFAULT);
+
+ private TabularDataSupport _messages = null;
+ private ManagedQueue _qmb;
+
+ private Button _previousButton;
+ private Button _nextButton;
+
+ public QueueOperationsTabControl(TabFolder tabFolder, JMXManagedObject mbean, MBeanServerConnection mbsc)
+ {
+ super(tabFolder);
+ _mbean = mbean;
+ _ApiVersion = ApplicationRegistry.getServerRegistry(mbean).getManagementApiVersion();
+ _qmb = (ManagedQueue) MBeanServerInvocationHandler.newProxyInstance(mbsc,
+ mbean.getObjectName(), ManagedQueue.class, false);
+ _toolkit = new FormToolkit(_tabFolder.getDisplay());
+ _form = _toolkit.createScrolledForm(_tabFolder);
+ _form.getBody().setLayout(new GridLayout());
+ createComposites();
+ createWidgets();
+ }
+
+ private void createComposites()
+ {
+ _paramsComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
+ _paramsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ _paramsComposite.setLayout(new GridLayout());
+ }
+
+ /**
+ * @see TabControl#getControl()
+ */
+ public Control getControl()
+ {
+ return _form;
+ }
+
+ /**
+ * @see TabControl#setFocus()
+ */
+ public void setFocus()
+ {
+ _table.setFocus();
+ }
+
+ @Override
+ public void refresh(ManagedBean mbean)
+ {
+ _messages = null;
+ try
+ {
+ if(_ApiVersion.greaterThanOrEqualTo(1, 3))
+ { //broker supports Qpid JMX API 1.3 and takes Long values
+
+ //gather a list of all messages on the queue for display and selection
+ _messages = (TabularDataSupport) _qmb.viewMessages(_fromMsg,_toMsg);
+ }
+ else
+ { //broker supports Qpid JMX API 1.2 or below and takes int values
+
+ if(_toMsg > Integer.MAX_VALUE || _toMsg > Integer.MAX_VALUE)
+ {
+ ViewUtility.popupErrorMessage("Error", "This broker only supports viewing up to message " + Integer.MAX_VALUE);
+ _tableViewer.setInput(null);
+ return;
+ }
+
+ //gather a list of all messages on the queue for display and selection
+ _messages = (TabularDataSupport) _qmb.viewMessages(_fromMsg.intValue(), _toMsg.intValue());
+ }
+ }
+ catch (Exception e)
+ {
+ MBeanUtility.handleException(mbean,e);
+ }
+
+ _tableViewer.setInput(_messages);
+
+ layout();
+ }
+
+ public void layout()
+ {
+ _form.layout(true);
+ _form.getBody().layout(true, true);
+ }
+
+ private void createWidgets()
+ {
+ Group messagesGroup = new Group(_paramsComposite, SWT.SHADOW_NONE | SWT.SCROLL_LINE);
+ messagesGroup.setBackground(_paramsComposite.getBackground());
+ messagesGroup.setText("Messages");
+ messagesGroup.setLayout(new GridLayout());
+ GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+ messagesGroup.setLayoutData(gridData);
+
+ //from and to fields for selecting the viewing range
+ Composite viewMessageRangeComposite = _toolkit.createComposite(messagesGroup);
+ gridData = new GridData(SWT.LEFT, SWT.FILL, false, false);
+ viewMessageRangeComposite.setLayoutData(gridData);
+ viewMessageRangeComposite.setLayout(new GridLayout(8,false));
+
+ _toolkit.createLabel(viewMessageRangeComposite, "Queue pos: ");
+ _fromMsgText = new Text(viewMessageRangeComposite, SWT.BORDER);
+ _fromMsgText.setText(FROM_DEFAULT);
+ gridData = new GridData(SWT.LEFT, SWT.FILL, false, false);
+ gridData.widthHint = 75;
+ _fromMsgText.setLayoutData(gridData);
+ _fromMsgText.addVerifyListener(new NumberVerifyListener());
+ _fromMsgText.addKeyListener(new KeyAdapter()
+ {
+ public void keyPressed(KeyEvent event)
+ {
+ if (event.character == SWT.CR)
+ {
+ updateMessageInterval();
+ }
+ }
+ });
+
+ _toolkit.createLabel(viewMessageRangeComposite, "to");
+
+ _toMsgText = new Text(viewMessageRangeComposite, SWT.BORDER);
+ _toMsgText.setText(TO_DEFAULT);
+ gridData = new GridData(SWT.LEFT, SWT.FILL, false, false);
+ gridData.widthHint = 75;
+ _toMsgText.setLayoutData(gridData);
+ _toMsgText.addVerifyListener(new NumberVerifyListener());
+ _toMsgText.addKeyListener(new KeyAdapter()
+ {
+ public void keyPressed(KeyEvent event)
+ {
+ if (event.character == SWT.CR)
+ {
+ updateMessageInterval();
+ }
+ }
+ });
+
+ final Button setButton = _toolkit.createButton(viewMessageRangeComposite, "Set", SWT.PUSH);
+ setButton.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, false, false));
+ setButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ updateMessageInterval();
+ }
+ });
+
+ _toolkit.createLabel(viewMessageRangeComposite, " "); //spacer
+
+ _previousButton = _toolkit.createButton(viewMessageRangeComposite, "< Prev " + _interval, SWT.PUSH);
+ _previousButton.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, false, false));
+ _previousButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ //make 'to' be 'from - 1' unless from is 1 (ie there are no previous messages)
+ if(_fromMsg > 1)
+ {
+ _toMsg = _fromMsg - 1;
+ _toMsgText.setText(_toMsg.toString());
+ }
+
+ //make 'from' be 'from - INTERVAL', or make it 1 if that would make it 0 or less
+ _fromMsg = (_fromMsg - _interval < 1) ? 1 : _fromMsg - _interval;
+ _fromMsgText.setText(_fromMsg.toString());
+
+ refresh(_mbean);
+ }
+ });
+
+ _nextButton = _toolkit.createButton(viewMessageRangeComposite, "Next " + _interval + " >", SWT.PUSH);
+ _nextButton.setLayoutData(new GridData(SWT.LEFT, SWT.FILL, false, false));
+ _nextButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ //make 'from' be 'to + 1' unless 'to' is already Long.MAX_VALUE
+ if(_toMsg != Long.MAX_VALUE)
+ {
+ _fromMsg = _toMsg + 1;
+ _fromMsgText.setText(_fromMsg.toString());
+ }
+
+ //make 'to' be 'to + INTERVAL', or make it Long.MAX_VALUE if that would too large
+ _toMsg = (Long.MAX_VALUE - _toMsg > _interval) ? _toMsg + _interval : Long.MAX_VALUE;
+ _toMsgText.setText(_toMsg.toString());
+
+ refresh(_mbean);
+ }
+ });
+
+ //message table
+ Composite tableAndButtonsComposite = _toolkit.createComposite(messagesGroup);
+ gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+ gridData.minimumHeight = 180;
+ gridData.heightHint = 180;
+ tableAndButtonsComposite.setLayoutData(gridData);
+ tableAndButtonsComposite.setLayout(new GridLayout(2,false));
+
+ _table = new Table (tableAndButtonsComposite, SWT.MULTI | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION);
+ _table.setLinesVisible (true);
+ _table.setHeaderVisible (true);
+ GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
+ _table.setLayoutData(data);
+
+ _tableViewer = new TableViewer(_table);
+ final TableSorter tableSorter = new TableSorter();
+
+ String[] titles = {"AMQ ID", "Size(bytes)"};
+ if(_ApiVersion.greaterThanOrEqualTo(1, 3))
+ {
+ //if server management API is >= 1.3, show message's queue position
+ titles = new String[]{"AMQ ID", "Size(bytes)", "Queue Position"};
+ }
+
+ int[] bounds = { 175, 175, 140 };
+ for (int i = 0; i < titles.length; i++)
+ {
+ final int index = i;
+ final TableColumn column = new TableColumn (_table, SWT.NONE);
+
+ column.setText(titles[i]);
+ column.setWidth(bounds[i]);
+ column.setResizable(true);
+
+ //Setting the right sorter
+ column.addSelectionListener(new SelectionAdapter()
+ {
+ @Override
+ public void widgetSelected(SelectionEvent e)
+ {
+ tableSorter.setColumn(index);
+ final TableViewer viewer = _tableViewer;
+ int dir = viewer .getTable().getSortDirection();
+ if (viewer.getTable().getSortColumn() == column)
+ {
+ dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
+ }
+ else
+ {
+ dir = SWT.UP;
+ }
+ viewer.getTable().setSortDirection(dir);
+ viewer.getTable().setSortColumn(column);
+ viewer.refresh();
+ }
+ });
+
+ }
+
+ _tableViewer.setContentProvider(new ContentProviderImpl());
+ _tableViewer.setLabelProvider(new LabelProviderImpl());
+ _tableViewer.setSorter(tableSorter);
+ _table.setSortColumn(_table.getColumn(0));
+ _table.setSortDirection(SWT.UP);
+
+ //Side Buttons
+ Composite buttonsComposite = _toolkit.createComposite(tableAndButtonsComposite);
+ gridData = new GridData(SWT.FILL, SWT.FILL, false, true);
+ buttonsComposite.setLayoutData(gridData);
+ buttonsComposite.setLayout(new GridLayout());
+
+ final Button viewSelectedMsgButton = _toolkit.createButton(buttonsComposite, "View Message Content ...", SWT.PUSH);
+ viewSelectedMsgButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
+ viewSelectedMsgButton.setEnabled(false);
+ viewSelectedMsgButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ if (_table.getSelectionIndex() == -1)
+ {
+ return;
+ }
+
+ viewMessageContent();
+ }
+ });
+
+ if(_ApiVersion.lessThan(1, 3)) //if the server predates Qpid JMX API 1.3
+ {
+ final Button deleteFirstMessageButton = _toolkit.createButton(buttonsComposite, "Delete 1st Unacquired Msg", SWT.PUSH);
+ deleteFirstMessageButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
+ deleteFirstMessageButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent se)
+ {
+ int response = ViewUtility.popupOkCancelConfirmationMessage("Delete 1st unacquired message",
+ "Delete 1st unacquired message on the queue?\n\n"
+ + "NOTE: Any ongoing consumer activity may mean this is "
+ + "not the first message listed in the table.");
+ if (response == SWT.OK)
+ {
+ try
+ {
+ _qmb.deleteMessageFromTop();
+ ViewUtility.operationResultFeedback(null, "Deleted 1st unacquired message on the queue", null);
+ }
+ catch (Exception e)
+ {
+ ViewUtility.operationFailedStatusBarMessage("Error deleting 1st unacquired message on queue");
+ MBeanUtility.handleException(_mbean, e);
+ }
+
+ refresh(_mbean);;
+ }
+ }
+ });
+ }
+
+ final Button moveMessagesButton;
+ if(_ApiVersion.greaterThanOrEqualTo(1, 3))
+ {
+ //If the server supports Qpid JMX API 1.3, show the move message button.
+ //This is being disabled for earlier brokers due to bugs affecting the result appearance
+ //and impacting on the ability of the source queues to deliver further messages.
+
+ moveMessagesButton = _toolkit.createButton(buttonsComposite, "Move Message(s) ...", SWT.PUSH);
+
+ moveMessagesButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
+ moveMessagesButton.setEnabled(false);
+ moveMessagesButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ if (_table.getSelectionIndex() == -1)
+ {
+ return;
+ }
+
+ moveOrCopyMessages(moveMessagesButton.getShell(), QueueOperations.MOVE);
+ }
+ });
+ }
+ else
+ {
+ moveMessagesButton = null;
+ }
+
+ final Button copyMessagesButton;
+ if(_ApiVersion.greaterThanOrEqualTo(1, 3))//if the server supports Qpid JMX API 1.3
+ {
+ copyMessagesButton= _toolkit.createButton(buttonsComposite, "Copy Message(s) ...", SWT.PUSH);
+ copyMessagesButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
+ copyMessagesButton.setEnabled(false);
+ copyMessagesButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ if (_table.getSelectionIndex() == -1)
+ {
+ return;
+ }
+
+ moveOrCopyMessages(copyMessagesButton.getShell(), QueueOperations.COPY);
+ }
+ });
+ }
+ else
+ {
+ copyMessagesButton = null;
+ }
+
+ final Button deleteMessagesButton;
+ if(_ApiVersion.greaterThanOrEqualTo(1, 3))//if the server supports Qpid JMX API 1.3
+ {
+ deleteMessagesButton = _toolkit.createButton(buttonsComposite, "Delete Message(s) ...", SWT.PUSH);
+ deleteMessagesButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
+ deleteMessagesButton.setEnabled(false);
+ deleteMessagesButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ if (_table.getSelectionIndex() == -1)
+ {
+ return;
+ }
+
+ deleteMessages(deleteMessagesButton.getShell());
+ }
+ });
+ }
+ else
+ {
+ deleteMessagesButton = null;
+ }
+
+ final Button clearQueueButton = _toolkit.createButton(buttonsComposite, "Clear Queue", SWT.PUSH);
+ clearQueueButton.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false));
+ clearQueueButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ int response = ViewUtility.popupOkCancelConfirmationMessage("Clear Queue",
+ "Clear queue ?");
+ if (response == SWT.OK)
+ {
+ try
+ {
+ if(_ApiVersion.greaterThanOrEqualTo(1, 3))
+ {
+ //Qpid JMX API 1.3+, returns the number of messages deleted
+ Long numDeleted = _qmb.clearQueue();
+ String message = "Queue cleared of " + numDeleted +
+ " non-acquired message" + (numDeleted == 1 ? "": "s");
+
+ ViewUtility.operationResultFeedback(null, message, null);
+ }
+ else
+ {
+ //Qpid JMX API 1.2 or below, void return
+ _qmb.clearQueue();
+ ViewUtility.operationResultFeedback(null, "Queue cleared of non-acquired messages", null);
+ }
+ }
+ catch (Exception e2)
+ {
+ ViewUtility.operationFailedStatusBarMessage("Error clearing Queue");
+ MBeanUtility.handleException(_mbean, e2);
+ }
+
+ refresh(_mbean);;
+ }
+ }
+ });
+
+ _toolkit.createLabel(messagesGroup, "Message Header: ");
+
+ //Redelivered status and header
+ Composite headerEtcComposite = _toolkit.createComposite(messagesGroup);
+ gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
+ headerEtcComposite.setLayoutData(gridData);
+ headerEtcComposite.setLayout(new GridLayout());
+
+ final Text headerText = new Text(headerEtcComposite, SWT.WRAP | SWT.BORDER | SWT.V_SCROLL);
+ headerText.setText("Select a message to view its header.");
+ headerText.setEditable(false);
+ data = new GridData(SWT.LEFT, SWT.TOP, false, false);
+ data.minimumHeight = 210;
+ data.heightHint = 210;
+ data.minimumWidth = 500;
+ data.widthHint = 500;
+ headerText.setLayoutData(data);
+
+ Composite redeliveryComposite = _toolkit.createComposite(headerEtcComposite);
+ redeliveryComposite.setLayout(new GridLayout(2,false));
+ data = new GridData(SWT.LEFT, SWT.FILL, false, false);
+ data.minimumWidth = 150;
+ data.widthHint = 150;
+ redeliveryComposite.setLayoutData(data);
+
+ _toolkit.createLabel(redeliveryComposite, "Redelivered: ");
+ final Text redeliveredText = new Text(redeliveryComposite, SWT.BORDER);
+ redeliveredText.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
+ redeliveredText.setText("-");
+ redeliveredText.setEditable(false);
+
+ //listener for double clicking to view message content
+ _table.addMouseListener(new MouseListener()
+ {
+ // MouseListener implementation
+ public void mouseDoubleClick(MouseEvent event)
+ {
+ viewMessageContent();
+ }
+
+ public void mouseDown(MouseEvent e){}
+ public void mouseUp(MouseEvent e){}
+ });
+
+ //selection listener to enable and disable buttons, update header and redelivered info
+ _tableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
+ public void selectionChanged(SelectionChangedEvent evt)
+ {
+ int selectionIndex = _table.getSelectionIndex();
+
+ if (selectionIndex == -1)
+ {
+ headerText.setText("Select a message to view its header.");
+ redeliveredText.setText("-");
+ viewSelectedMsgButton.setEnabled(false);
+ if(moveMessagesButton != null)
+ {
+ moveMessagesButton.setEnabled(false);
+ }
+ if(copyMessagesButton != null)
+ {
+ copyMessagesButton.setEnabled(false);
+ }
+ if(deleteMessagesButton != null)
+ {
+ deleteMessagesButton.setEnabled(false);
+ }
+
+ return;
+ }
+ else
+ {
+ if(moveMessagesButton != null)
+ {
+ moveMessagesButton.setEnabled(true);
+ }
+ if(copyMessagesButton != null)
+ {
+ copyMessagesButton.setEnabled(true);
+ }
+ if(deleteMessagesButton != null)
+ {
+ deleteMessagesButton.setEnabled(true);
+ }
+
+ final CompositeData selectedMsg = (CompositeData)_table.getItem(selectionIndex).getData();
+ Boolean redelivered = (Boolean) selectedMsg.get(MSG_REDELIVERED);
+ redeliveredText.setText(redelivered.toString());
+
+ String[] msgHeader = (String[]) selectedMsg.get(MSG_HEADER);
+ headerText.setText("");
+ String lineSeperator = System.getProperty("line.separator");
+ int size = msgHeader.length;
+ for(int i=0; i < size; i++)
+ {
+ headerText.append(msgHeader[i]);
+ if(!(i == size - 1))
+ {
+ headerText.append(lineSeperator);
+ }
+ }
+ headerText.setSelection(0);
+ }
+
+ if (_table.getSelectionCount() > 1)
+ {
+ viewSelectedMsgButton.setEnabled(false);
+ }
+ else
+ {
+ viewSelectedMsgButton.setEnabled(true);
+ }
+
+ }
+ });
+
+ }
+
+ /**
+ * Content Provider class for the table viewer
+ */
+ private static class ContentProviderImpl implements IStructuredContentProvider
+ {
+
+ public void inputChanged(Viewer v, Object oldInput, Object newInput)
+ {
+
+ }
+
+ public void dispose()
+ {
+
+ }
+
+ public Object[] getElements(Object parent)
+ {
+ Collection<Object> rowCollection = ((TabularDataSupport) parent).values();
+
+ return rowCollection.toArray();
+ }
+ }
+
+ /**
+ * Label Provider class for the table viewer
+ */
+ private static class LabelProviderImpl extends LabelProvider implements ITableLabelProvider
+ {
+ public String getColumnText(Object element, int columnIndex)
+ {
+ switch (columnIndex)
+ {
+ case 0 : // msg id column
+ return String.valueOf(((CompositeDataSupport) element).get(MSG_AMQ_ID));
+ case 1 : // msg size column
+ return String.valueOf(((CompositeDataSupport) element).get(MSG_SIZE));
+ case 2 : // msg position in queue
+ return String.valueOf(((CompositeDataSupport) element).get(MSG_QUEUE_POS));
+ default :
+ return "-";
+ }
+ }
+
+ public Image getColumnImage(Object element, int columnIndex)
+ {
+ return null;
+ }
+
+ }
+
+ /**
+ * Sorter class for the table viewer.
+ *
+ */
+ public static class TableSorter extends ViewerSorter
+ {
+ private int column;
+ private static final int ASCENDING = 0;
+ private static final int DESCENDING = 1;
+
+ private int direction = DESCENDING;
+
+ public TableSorter()
+ {
+ this.column = 0;
+ direction = ASCENDING;
+ }
+
+ public void setColumn(int column)
+ {
+ if (column == this.column)
+ {
+ // Same column as last sort; toggle the direction
+ direction = 1 - direction;
+ }
+ else
+ {
+ // New column; do an ascending sort
+ this.column = column;
+ direction = ASCENDING;
+ }
+ }
+
+ @Override
+ public int compare(Viewer viewer, Object e1, Object e2)
+ {
+ CompositeData msg1 = (CompositeData) e1;
+ CompositeData msg2 = (CompositeData) e2;
+
+ int comparison = 0;
+ switch(column)
+ {
+ case 0:
+ comparison = ((Long) msg1.get(MSG_AMQ_ID)).compareTo((Long)msg2.get(MSG_AMQ_ID));
+ break;
+ case 1:
+ comparison = ((Long) msg1.get(MSG_SIZE)).compareTo((Long)msg2.get(MSG_SIZE));
+ break;
+ case 2:
+ comparison = ((Long) msg1.get(MSG_QUEUE_POS)).compareTo((Long)msg2.get(MSG_QUEUE_POS));
+ break;
+ default:
+ comparison = 0;
+ }
+ // If descending order, flip the direction
+ if(direction == DESCENDING)
+ {
+ comparison = -comparison;
+ }
+ return comparison;
+ }
+ }
+
+ private void updateMessageInterval()
+ {
+ Long from;
+ try
+ {
+ from = Long.valueOf(_fromMsgText.getText());
+ }
+ catch(Exception e1)
+ {
+ ViewUtility.popupErrorMessage("Invalid Value", "Please enter a valid 'from' number");
+ return;
+ }
+
+ Long to;
+ try
+ {
+ to = Long.valueOf(_toMsgText.getText());
+ }
+ catch(Exception e1)
+ {
+ ViewUtility.popupErrorMessage("Invalid Value", "Please enter a valid 'to' number");
+ return;
+ }
+
+ _fromMsg = from;
+ _toMsg = to;
+
+ _interval = (to - from) + 1;
+ _previousButton.setText("< Prev " + _interval);
+ _nextButton.setText("Next " + _interval + " >");
+
+ refresh(_mbean);
+ }
+
+ private void viewMessageContent()
+ {
+ int selectionIndex = _table.getSelectionIndex();
+
+ if (selectionIndex != -1)
+ {
+ try
+ {
+ final CompositeData selectedMsg = (CompositeData)_table.getItem(selectionIndex).getData();
+ Long msgId = (Long) selectedMsg.get(MSG_AMQ_ID);
+
+ Object result = _qmb.viewMessageContent(msgId);
+
+ populateResults(result);
+ }
+ catch (Exception e3)
+ {
+ MBeanUtility.handleException(_mbean, e3);
+ }
+ }
+ }
+
+ private void populateResults(Object result)
+ {
+ Display display = Display.getCurrent();
+ int width = 610;
+ int height = 400;
+ Shell shell = ViewUtility.createPopupShell(RESULT, width, height);
+ shell.setImage(ApplicationRegistry.getImage(CONSOLE_IMAGE));
+ ViewUtility.populateCompositeWithData(_toolkit, shell, result);
+
+ shell.open();
+ while (!shell.isDisposed())
+ {
+ if (!display.readAndDispatch())
+ {
+ display.sleep();
+ }
+ }
+ shell.dispose();
+ }
+
+ private void moveOrCopyMessages(final Shell parent, final QueueOperations op)
+ {
+ final ArrayList<Long> rangeStarts = new ArrayList<Long>();
+ final ArrayList<Long> rangeEnds = new ArrayList<Long>();
+
+ gatherSelectedAMQMsgIDRanges(rangeStarts,rangeEnds);
+ String rangeString = getRangesString(rangeStarts,rangeEnds);
+
+ String windowTitle;
+ String dialogueMessage;
+ final String feedBackMessage;
+ final String failureFeedBackMessage;
+
+ if(op.equals(QueueOperations.MOVE))
+ {
+ windowTitle = "Move Messages";
+ dialogueMessage = "Move message(s) with AMQ ID:";
+ feedBackMessage = "Messages moved";
+ failureFeedBackMessage = "Error moving messages";
+ }
+ else
+ {
+ windowTitle = "Copy Messages";
+ dialogueMessage = "Copy message(s) with AMQ ID:";
+ feedBackMessage = "Messages copied";
+ failureFeedBackMessage = "Error copying messages";
+ }
+
+ final Shell shell = ViewUtility.createModalDialogShell(parent, windowTitle);
+
+ Composite idComposite = _toolkit.createComposite(shell, SWT.NONE);
+ idComposite.setBackground(shell.getBackground());
+ idComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ idComposite.setLayout(new GridLayout());
+
+ _toolkit.createLabel(idComposite,dialogueMessage).setBackground(shell.getBackground());
+ _toolkit.createLabel(idComposite,rangeString).setBackground(shell.getBackground());
+
+ Composite destinationComposite = _toolkit.createComposite(shell, SWT.NONE);
+ destinationComposite.setBackground(shell.getBackground());
+ destinationComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ destinationComposite.setLayout(new GridLayout(2,false));
+
+ _toolkit.createLabel(destinationComposite,"To Queue:").setBackground(shell.getBackground());
+ final Combo destinationCombo = new Combo(destinationComposite,SWT.NONE | SWT.READ_ONLY);
+ destinationCombo.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+
+ Composite okCancelButtonsComp = _toolkit.createComposite(shell);
+ okCancelButtonsComp.setBackground(shell.getBackground());
+ okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
+ okCancelButtonsComp.setLayout(new GridLayout(2,false));
+
+ Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
+ okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+ Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
+ cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+
+ List<String> queueList = ApplicationRegistry.getServerRegistry(_mbean).getQueueNames(_mbean.getVirtualHostName());
+ queueList.remove(_mbean.getName());
+
+ if(queueList.size() == 0)
+ {
+ destinationCombo.setItems(new String[]{"No other queues available"});
+ okButton.setEnabled(false);
+ }
+ else
+ {
+ Collections.sort(queueList);
+ destinationCombo.setItems(queueList.toArray(new String[0]));
+ }
+ destinationCombo.select(0);
+
+ okButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ String destQueue = destinationCombo.getItem(destinationCombo.getSelectionIndex()).toString();
+ shell.dispose();
+
+ try
+ {
+ for(int i=0 ; i < rangeStarts.size() ; i++)
+ {
+ Long from = rangeStarts.get(i);
+ Long to = rangeEnds.get(i);
+
+ switch(op)
+ {
+ case COPY:
+ _qmb.copyMessages(Long.valueOf(from), Long.valueOf(to), destQueue);
+ break;
+ case MOVE:
+ _qmb.moveMessages(Long.valueOf(from), Long.valueOf(to), destQueue);
+ break;
+ }
+ }
+
+ ViewUtility.operationResultFeedback(null, feedBackMessage, null);
+ }
+ catch (Exception e4)
+ {
+ ViewUtility.operationFailedStatusBarMessage(failureFeedBackMessage);
+ MBeanUtility.handleException(_mbean, e4);
+ }
+
+ refresh(_mbean);
+ }
+ });
+
+ cancelButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ shell.dispose();
+ }
+ });
+
+ shell.setDefaultButton(okButton);
+ shell.pack();
+ ViewUtility.centerChildInParentShell(parent, shell);
+
+ shell.open();
+ }
+
+ private void deleteMessages(final Shell parent)
+ {
+ final ArrayList<Long> rangeStarts = new ArrayList<Long>();
+ final ArrayList<Long> rangeEnds = new ArrayList<Long>();
+
+ gatherSelectedAMQMsgIDRanges(rangeStarts,rangeEnds);
+ String rangeString = getRangesString(rangeStarts,rangeEnds);
+
+ final Shell shell = ViewUtility.createModalDialogShell(parent, "Delete Messages");
+
+ Composite idComposite = _toolkit.createComposite(shell, SWT.NONE);
+ idComposite.setBackground(shell.getBackground());
+ idComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ idComposite.setLayout(new GridLayout());
+
+ _toolkit.createLabel(idComposite,"Delete message(s) with AMQ ID:").setBackground(shell.getBackground());
+ _toolkit.createLabel(idComposite,rangeString).setBackground(shell.getBackground());
+
+ Composite okCancelButtonsComp = _toolkit.createComposite(shell);
+ okCancelButtonsComp.setBackground(shell.getBackground());
+ okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
+ okCancelButtonsComp.setLayout(new GridLayout(2,false));
+
+ Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
+ okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+ Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
+ cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+
+ okButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ shell.dispose();
+
+ try
+ {
+ for(int i=0 ; i < rangeStarts.size() ; i++)
+ {
+ Long from = rangeStarts.get(i);
+ Long to = rangeEnds.get(i);
+
+ _qmb.deleteMessages(Long.valueOf(from), Long.valueOf(to));
+ }
+
+ ViewUtility.operationResultFeedback(null, "Messages deleted", null);
+ }
+ catch (Exception e4)
+ {
+ ViewUtility.operationFailedStatusBarMessage("Error deleting messages");
+ MBeanUtility.handleException(_mbean, e4);
+ }
+
+ refresh(_mbean);
+ }
+ });
+
+ cancelButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ shell.dispose();
+ }
+ });
+
+ shell.setDefaultButton(okButton);
+ shell.pack();
+ ViewUtility.centerChildInParentShell(parent, shell);
+
+ shell.open();
+ }
+
+ private void gatherSelectedAMQMsgIDRanges(ArrayList<Long> starts, ArrayList<Long> ends)
+ {
+ SortedSet<Long> amqIDs = new TreeSet<Long>();
+
+ for(Integer i : _table.getSelectionIndices())
+ {
+ CompositeData selectedMsg = (CompositeData)_table.getItem(i).getData();
+ amqIDs.add((Long)selectedMsg.get(MSG_AMQ_ID));
+ }
+
+ //initialise the first range
+ Long start = amqIDs.first();
+ Long end = amqIDs.first();
+
+ for(Long id : amqIDs)
+ {
+ if(id == amqIDs.first())
+ {
+ //skip first check, already initialised range
+ continue;
+ }
+
+ if(id == end +1)
+ {
+ //part of previous range, append
+ end = id;
+ }
+ else
+ {
+ //not in previous range, record existing start and end msg id values
+ starts.add(start);
+ ends.add(end);
+
+ //begin new range with this msg id
+ start = id;
+ end = id;
+ }
+ }
+
+ //record the last range created
+ starts.add(start);
+ ends.add(end);
+ }
+
+ private String getRangesString(ArrayList<Long> starts, ArrayList<Long> ends)
+ {
+ String idRangesString = "";
+
+ for(int i=0 ; i < starts.size() ; i++)
+ {
+ long start = starts.get(i);
+ long end = ends.get(i);
+
+ if(i != 0)
+ {
+ idRangesString = idRangesString.concat(", ");
+ }
+
+ if(start == end)
+ {
+ idRangesString = idRangesString.concat(String.valueOf(starts.get(i)));
+ }
+ else
+ {
+ idRangesString = idRangesString.concat(starts.get(i) + "-" + ends.get(i));
+ }
+ }
+
+ return idRangesString.concat(".");
+ }
+
+ private enum QueueOperations
+ {
+ MOVE,
+ COPY;
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/ConnectionTypeTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/ConnectionTypeTabControl.java
new file mode 100644
index 0000000000..f1f7b07b6f
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/ConnectionTypeTabControl.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.views.type;
+
+import java.util.List;
+
+import static org.apache.qpid.management.ui.Constants.CONNECTION;
+
+import org.apache.qpid.management.ui.ManagedBean;
+import org.apache.qpid.management.ui.ManagedServer;
+import org.eclipse.swt.widgets.TabFolder;
+
+/**
+ * Controller class, which takes care of displaying appropriate information and widgets for Connections.
+ * This allows user to select Connections and add those to the navigation view
+ */
+
+public class ConnectionTypeTabControl extends MBeanTypeTabControl
+{
+
+ public ConnectionTypeTabControl(TabFolder tabFolder, ManagedServer server, String virtualHost)
+ {
+ super(tabFolder, server, virtualHost, CONNECTION);
+ }
+
+ @Override
+ protected List<ManagedBean> getMbeans()
+ {
+ return _serverRegistry.getConnections(_virtualHost);
+ }
+
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/ExchangeTypeTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/ExchangeTypeTabControl.java
new file mode 100644
index 0000000000..5d587c7158
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/ExchangeTypeTabControl.java
@@ -0,0 +1,45 @@
+/*
+ *
+ * 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.type;
+
+import java.util.List;
+
+import static org.apache.qpid.management.ui.Constants.EXCHANGE;
+
+import org.apache.qpid.management.ui.ManagedBean;
+import org.apache.qpid.management.ui.ManagedServer;
+import org.eclipse.swt.widgets.TabFolder;
+
+public class ExchangeTypeTabControl extends MBeanTypeTabControl
+{
+
+ public ExchangeTypeTabControl(TabFolder tabFolder, ManagedServer server, String virtualHost)
+ {
+ super(tabFolder, server, virtualHost, EXCHANGE);
+ }
+
+ @Override
+ protected List<ManagedBean> getMbeans()
+ {
+ return _serverRegistry.getExchanges(_virtualHost);
+ }
+
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/MBeanTypeTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/MBeanTypeTabControl.java
new file mode 100644
index 0000000000..a4574b8d22
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/MBeanTypeTabControl.java
@@ -0,0 +1,456 @@
+/*
+ *
+ * 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.type;
+
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.qpid.management.ui.ApiVersion;
+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.jmx.JMXManagedObject;
+import org.apache.qpid.management.ui.jmx.JMXServerRegistry;
+import org.apache.qpid.management.ui.jmx.MBeanUtility;
+import org.apache.qpid.management.ui.views.MBeanView;
+import org.apache.qpid.management.ui.views.NavigationView;
+import org.apache.qpid.management.ui.views.TabControl;
+
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+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.TableViewerColumn;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+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.TabFolder;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.forms.widgets.Form;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+public abstract class MBeanTypeTabControl extends TabControl
+{
+ protected FormToolkit _toolkit;
+ protected Form _form;
+ protected Table _table = null;
+ protected TableViewer _tableViewer = null;
+
+ protected List<ManagedBean> _mbeans = null;
+ protected String _type;
+ protected ApiVersion _ApiVersion;
+ protected JMXManagedObject _vhostMbean;
+ protected String _virtualHost;
+ protected JMXServerRegistry _serverRegistry;
+ protected Composite _tableComposite;
+ protected Button _favouritesButton;
+ protected Button _openButton;
+
+ public MBeanTypeTabControl(TabFolder tabFolder, ManagedServer server, String virtualHost, String type)
+ {
+ super(tabFolder);
+ _virtualHost = virtualHost;
+ _serverRegistry = (JMXServerRegistry) ApplicationRegistry.getServerRegistry(server);
+ _ApiVersion = _serverRegistry.getManagementApiVersion();
+ _vhostMbean = (JMXManagedObject) _serverRegistry.getVirtualHostManagerMBean(_virtualHost);
+ _type = type;
+ _toolkit = new FormToolkit(_tabFolder.getDisplay());
+ _form = _toolkit.createForm(_tabFolder);
+ _form.getBody().setLayout(new GridLayout());
+ init();
+ createWidgets();
+ }
+
+ protected void init()
+ {
+
+ }
+
+ /**
+ * @see TabControl#getControl()
+ */
+ public Control getControl()
+ {
+ return _form;
+ }
+
+ /**
+ * @see TabControl#setFocus()
+ */
+ public void setFocus()
+ {
+ _table.setFocus();
+ }
+
+ public void refresh()
+ {
+ refresh(null);
+ }
+
+
+ @Override
+ public void refresh(ManagedBean mbean)
+ {
+ _mbeans = getMbeans();
+
+ _tableViewer.setInput(_mbeans);
+
+ layout();
+ }
+
+ public void layout()
+ {
+ _form.layout(true);
+ _form.getBody().layout(true, true);
+ }
+
+ protected abstract List<ManagedBean> getMbeans();
+
+ protected void createTable()
+ {
+ _table = new Table (_tableComposite, SWT.MULTI | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION);
+ _table.setLinesVisible (true);
+ _table.setHeaderVisible (true);
+ GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
+ _table.setLayoutData(data);
+
+ _tableViewer = new TableViewer(_table);
+ final TableSorter tableSorter = new TableSorter();
+
+ String[] titles = { "Name"};
+ int[] bounds = { 310};
+ for (int i = 0; i < titles.length; i++)
+ {
+ final int index = i;
+ final TableViewerColumn viewerColumn = new TableViewerColumn(_tableViewer, SWT.NONE);
+ final TableColumn column = viewerColumn.getColumn();
+
+ column.setText(titles[i]);
+ column.setWidth(bounds[i]);
+ column.setResizable(true);
+
+ //Setting the right sorter
+ column.addSelectionListener(new SelectionAdapter()
+ {
+ @Override
+ public void widgetSelected(SelectionEvent e)
+ {
+ tableSorter.setColumn(index);
+ final TableViewer viewer = _tableViewer;
+ int dir = viewer .getTable().getSortDirection();
+ if (viewer.getTable().getSortColumn() == column)
+ {
+ dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
+ }
+ else
+ {
+ dir = SWT.UP;
+ }
+ viewer.getTable().setSortDirection(dir);
+ viewer.getTable().setSortColumn(column);
+ viewer.refresh();
+ }
+ });
+
+ }
+
+ _tableViewer.setContentProvider(new ContentProviderImpl());
+ _tableViewer.setLabelProvider(new LabelProviderImpl());
+ _tableViewer.setSorter(tableSorter);
+ _table.setSortColumn(_table.getColumn(0));
+ _table.setSortDirection(SWT.UP);
+
+ addTableListeners();
+ }
+
+ protected void addTableListeners()
+ {
+ _favouritesButton.setEnabled(false);
+ _openButton.setEnabled(false);
+
+ _tableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
+ public void selectionChanged(SelectionChangedEvent evt)
+ {
+ int selectionIndex = _table.getSelectionIndex();
+
+ if (selectionIndex == -1)
+ {
+ _favouritesButton.setEnabled(false);
+ _openButton.setEnabled(false);
+ return;
+ }
+ else
+ {
+ _favouritesButton.setEnabled(true);
+ }
+
+ if(_table.getSelectionCount() > 1)
+ {
+ _openButton.setEnabled(false);
+ }
+ else
+ {
+ _openButton.setEnabled(true);
+ }
+ }
+ });
+
+ _table.addMouseListener(new MouseListener()
+ {
+ // MouseListener implementation
+ public void mouseDoubleClick(MouseEvent event)
+ {
+ openMBean();
+ }
+
+ public void mouseDown(MouseEvent e){}
+ public void mouseUp(MouseEvent e){}
+ });
+ }
+
+
+ private void createWidgets()
+ {
+ Composite mainComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
+ mainComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ mainComposite.setLayout(new GridLayout());
+
+ Composite buttonComposite = _toolkit.createComposite(mainComposite, SWT.NONE);
+ GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
+ buttonComposite.setLayoutData(gridData);
+ buttonComposite.setLayout(new GridLayout(2,true));
+
+ _favouritesButton = _toolkit.createButton(buttonComposite,
+ "<-- Add " + _type + "(s) to favourites", SWT.PUSH);
+ gridData = new GridData(SWT.LEFT, SWT.CENTER, true, false);
+ _favouritesButton.setLayoutData(gridData);
+ _favouritesButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ addMBeanToFavourites();
+ }
+ });
+
+ _openButton = _toolkit.createButton(buttonComposite, "Open selected " + _type, SWT.PUSH);
+ gridData = new GridData(SWT.RIGHT, SWT.CENTER, true, false);
+ _openButton.setLayoutData(gridData);
+ _openButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ openMBean();
+ }
+ });
+
+ _tableComposite = _toolkit.createComposite(mainComposite);
+ gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+ _tableComposite.setLayoutData(gridData);
+ _tableComposite.setLayout(new GridLayout(1,false));
+
+ createTable();
+
+ createLowerAreaButton(mainComposite);
+ }
+
+ protected void createLowerAreaButton(Composite parent)
+ {
+
+ }
+
+ /**
+ * Content Provider class for the table viewer
+ */
+ private static class ContentProviderImpl implements IStructuredContentProvider
+ {
+
+ public void inputChanged(Viewer v, Object oldInput, Object newInput)
+ {
+
+ }
+
+ public void dispose()
+ {
+
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object[] getElements(Object parent)
+ {
+ return ((List<ManagedBean>) parent).toArray();
+ }
+ }
+
+ /**
+ * Label Provider class for the table viewer
+ */
+ private static class LabelProviderImpl extends LabelProvider implements ITableLabelProvider
+ {
+ public String getColumnText(Object element, int columnIndex)
+ {
+ switch (columnIndex)
+ {
+ case 0 : // name column
+ return ((ManagedBean) element).getName();
+ default:
+ return "-";
+ }
+ }
+
+ public Image getColumnImage(Object element, int columnIndex)
+ {
+ return null;
+ }
+
+ }
+
+ /**
+ * Sorter class for the table viewer.
+ *
+ */
+ private static class TableSorter extends ViewerSorter
+ {
+ private int column;
+ private static final int ASCENDING = 0;
+ private static final int DESCENDING = 1;
+
+ private int direction;
+
+ public TableSorter()
+ {
+ this.column = 0;
+ direction = ASCENDING;
+ }
+
+ public void setColumn(int column)
+ {
+ if(column == this.column)
+ {
+ // Same column as last sort; toggle the direction
+ direction = 1 - direction;
+ }
+ else
+ {
+ // New column; do an ascending sort
+ this.column = column;
+ direction = ASCENDING;
+ }
+ }
+
+ @Override
+ public int compare(Viewer viewer, Object e1, Object e2)
+ {
+ ManagedBean mbean1 = (ManagedBean) e1;
+ ManagedBean mbean2 = (ManagedBean) e2;
+
+ int comparison = 0;
+ switch(column)
+ {
+ case 0:
+ comparison = mbean1.getName().compareTo(mbean2.getName());
+ break;
+ default:
+ comparison = 0;
+ }
+ // If descending order, flip the direction
+ if(direction == DESCENDING)
+ {
+ comparison = -comparison;
+ }
+ return comparison;
+ }
+ }
+
+ protected void addMBeanToFavourites()
+ {
+ int selectionIndex = _table.getSelectionIndex();
+
+ if (selectionIndex == -1)
+ {
+ return;
+ }
+
+ int[] selectedIndices = _table.getSelectionIndices();
+
+ ArrayList<ManagedBean> selectedMBeans = new ArrayList<ManagedBean>();
+
+ for(int index = 0; index < selectedIndices.length ; index++)
+ {
+ ManagedBean selectedMBean = (ManagedBean)_table.getItem(selectedIndices[index]).getData();
+ selectedMBeans.add(selectedMBean);
+ }
+
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ NavigationView view = (NavigationView)window.getActivePage().findView(NavigationView.ID);
+
+ ManagedBean bean = null;
+ try
+ {
+ for(ManagedBean mbean: selectedMBeans)
+ {
+ view.addManagedBean(mbean);
+ }
+ }
+ catch (Exception ex)
+ {
+ MBeanUtility.handleException(bean, ex);
+ }
+ }
+
+ protected void openMBean()
+ {
+ int selectionIndex = _table.getSelectionIndex();
+
+ if (selectionIndex == -1)
+ {
+ return;
+ }
+
+ final ManagedBean selectedMBean = (ManagedBean)_table.getItem(selectionIndex).getData();
+
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ MBeanView view = (MBeanView) window.getActivePage().findView(MBeanView.ID);
+ try
+ {
+ view.openMBean(selectedMBean);
+ }
+ catch (Exception ex)
+ {
+ MBeanUtility.handleException(selectedMBean, ex);
+ }
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/QueueTypeTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/QueueTypeTabControl.java
new file mode 100644
index 0000000000..406ef08326
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/type/QueueTypeTabControl.java
@@ -0,0 +1,786 @@
+/*
+ *
+ * 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.type;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.Semaphore;
+
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerInvocationHandler;
+
+import static org.apache.qpid.management.ui.ApplicationRegistry.DATA_DIR;
+import static org.apache.qpid.management.ui.Constants.QUEUE;
+import static org.apache.qpid.management.common.mbeans.ManagedQueue.ATTR_NAME;
+import static org.apache.qpid.management.common.mbeans.ManagedQueue.ATTR_ACTIVE_CONSUMER_COUNT;
+import static org.apache.qpid.management.common.mbeans.ManagedQueue.ATTR_AUTODELETE;
+import static org.apache.qpid.management.common.mbeans.ManagedQueue.ATTR_CONSUMER_COUNT;
+import static org.apache.qpid.management.common.mbeans.ManagedQueue.ATTR_DURABLE;
+import static org.apache.qpid.management.common.mbeans.ManagedQueue.ATTR_MAX_MSG_AGE;
+import static org.apache.qpid.management.common.mbeans.ManagedQueue.ATTR_MAX_MSG_COUNT;
+import static org.apache.qpid.management.common.mbeans.ManagedQueue.ATTR_MAX_MSG_SIZE;
+import static org.apache.qpid.management.common.mbeans.ManagedQueue.ATTR_MAX_QUEUE_DEPTH;
+import static org.apache.qpid.management.common.mbeans.ManagedQueue.ATTR_MSG_COUNT;
+import static org.apache.qpid.management.common.mbeans.ManagedQueue.ATTR_OWNER;
+import static org.apache.qpid.management.common.mbeans.ManagedQueue.ATTR_QUEUE_DEPTH;
+import static org.apache.qpid.management.common.mbeans.ManagedQueue.ATTR_RCVD_MSG_COUNT;
+
+import org.apache.qpid.management.common.mbeans.ManagedBroker;
+import org.apache.qpid.management.common.mbeans.ManagedQueue;
+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.jmx.MBeanUtility;
+import org.apache.qpid.management.ui.views.MBeanView;
+import org.apache.qpid.management.ui.views.NavigationView;
+import org.apache.qpid.management.ui.views.ViewUtility;
+import org.eclipse.jface.preference.PreferenceStore;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.ITableLabelProvider;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.jface.viewers.TableViewer;
+import org.eclipse.jface.viewers.TableViewerColumn;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+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.Shell;
+import org.eclipse.swt.widgets.TabFolder;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.ui.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+
+public class QueueTypeTabControl extends MBeanTypeTabControl
+{
+ private MBeanServerConnection _mbsc;
+ private ManagedBroker _vhmb;
+
+ private List<String> _selectedAttributes;
+ private PreferenceStore _preferences;
+ private Semaphore _tableViewerSemaphore = new Semaphore(1);
+
+ private static final String APP_DIR = ApplicationRegistry.DATA_DIR;
+ private static final String INI_FILENAME = APP_DIR + File.separator + "qpidmc_queue_attributes.ini";
+ private static final String INI_QUEUE_ATTRIBUES = "QueueAttributesSelection";
+
+ private static final ArrayList<String> FALLBACK_ATTRIBUTES_LIST = new ArrayList<String>();
+ static
+ {
+ FALLBACK_ATTRIBUTES_LIST.add(ATTR_NAME);
+ FALLBACK_ATTRIBUTES_LIST.add(ATTR_ACTIVE_CONSUMER_COUNT);
+ FALLBACK_ATTRIBUTES_LIST.add(ATTR_AUTODELETE);
+ FALLBACK_ATTRIBUTES_LIST.add(ATTR_CONSUMER_COUNT);
+ FALLBACK_ATTRIBUTES_LIST.add(ATTR_DURABLE);
+ FALLBACK_ATTRIBUTES_LIST.add(ATTR_MAX_MSG_AGE);
+ FALLBACK_ATTRIBUTES_LIST.add(ATTR_MAX_MSG_COUNT);
+ FALLBACK_ATTRIBUTES_LIST.add(ATTR_MAX_MSG_SIZE);
+ FALLBACK_ATTRIBUTES_LIST.add(ATTR_MAX_QUEUE_DEPTH);
+ FALLBACK_ATTRIBUTES_LIST.add(ATTR_MSG_COUNT);
+ FALLBACK_ATTRIBUTES_LIST.add(ATTR_OWNER);
+ FALLBACK_ATTRIBUTES_LIST.add(ATTR_QUEUE_DEPTH);
+ FALLBACK_ATTRIBUTES_LIST.add(ATTR_RCVD_MSG_COUNT);
+ }
+
+ private static final Map<String, Integer> DEFAULT_COLUMN_WIDTHS = new HashMap<String,Integer>();
+ static
+ {
+ DEFAULT_COLUMN_WIDTHS.put(ATTR_NAME, 215);
+ DEFAULT_COLUMN_WIDTHS.put(ATTR_OWNER,125);
+ DEFAULT_COLUMN_WIDTHS.put(ATTR_QUEUE_DEPTH,125);
+ }
+
+ public QueueTypeTabControl(TabFolder tabFolder, ManagedServer server, String virtualHost)
+ {
+ super(tabFolder,server,virtualHost,QUEUE);
+ _mbsc = (MBeanServerConnection) _serverRegistry.getServerConnection();
+
+ //create a proxy for the VirtualHostManager mbean to use in retrieving the attribute names/values
+ _vhmb = MBeanServerInvocationHandler.newProxyInstance(_mbsc,
+ _vhostMbean.getObjectName(), ManagedBroker.class, false);
+
+ }
+
+ @Override
+ protected void init()
+ {
+ createIniFileIfNecessary();
+ loadAttributePreferences();
+ }
+
+ /**
+ * Create the ini file if it doesn't already exist.
+ */
+ public static void createIniFileIfNecessary()
+ {
+ File dir = new File(DATA_DIR);
+ if (!dir.exists())
+ {
+ if(!dir.mkdir())
+ {
+ System.err.println("Could not create application data directory " + DATA_DIR);
+ ViewUtility.popupErrorMessage("Error", "Fatal Error: Unable to create the application data directory: " + DATA_DIR);
+ System.exit(1);
+ }
+ }
+
+ File file = new File(INI_FILENAME);
+ try
+ {
+ if (!file.exists())
+ {
+ file.createNewFile();
+ }
+ }
+ catch (IOException ex)
+ {
+ System.err.println("Error creating the configuration file " + INI_FILENAME);
+ ViewUtility.popupErrorMessage("Error", "Fatal Error: Unable to create the configuration file: " + INI_FILENAME);
+ System.exit(1);
+ }
+ }
+
+ private void loadAttributePreferences()
+ {
+ _preferences = new PreferenceStore(INI_FILENAME);
+ List<String> attributesList = new ArrayList<String>();
+
+ //ensure the name is present, and first
+ attributesList.add(ManagedQueue.ATTR_NAME);
+
+ //add any others from the file
+ try
+ {
+ _preferences.load();
+
+ String selectedAttributes = _preferences.getString(INI_QUEUE_ATTRIBUES);
+ if (selectedAttributes.length() != 0)
+ {
+ String[] attributes = selectedAttributes.split(",");
+ for (String attr : attributes)
+ {
+ if(attr.equals(ManagedQueue.ATTR_NAME))
+ {
+ //the Name attribute is already present
+ continue;
+ }
+
+ attributesList.add(attr);
+ }
+ }
+ }
+ catch (IOException e)
+ {
+ ViewUtility.popupErrorMessage("Error", "Unable to load previous attribute selections, defaulting to Name only");
+ System.err.println(e);
+ }
+
+ _selectedAttributes = attributesList;
+ }
+
+ private void saveAttributePreferences()
+ {
+ String chosenAttributes = new String();
+
+ for(String attr : _selectedAttributes)
+ {
+ chosenAttributes = chosenAttributes.concat(attr) + ",";
+ }
+ //cut off last ","
+ int lastIndex = chosenAttributes.lastIndexOf(',');
+ if (lastIndex != -1)
+ {
+ chosenAttributes = chosenAttributes.substring(0,lastIndex);
+ }
+
+ _preferences.putValue(INI_QUEUE_ATTRIBUES, chosenAttributes);
+
+ try
+ {
+ _preferences.save();
+ }
+ catch (IOException e)
+ {
+ ViewUtility.popupErrorMessage("Error", "Unable to save the attribute selection, choices will be lost at shutdown");
+ System.err.println(e);
+ }
+ }
+
+ @Override
+ public void refresh(ManagedBean mbean)
+ {
+ //Try locking. If we cant aquire the lock, dont bother getting new values.
+ //Either the attributes are being changed and these values would be out of date,
+ //or another thread is still in the process of refreshing
+ if(_tableViewerSemaphore.tryAcquire())
+ {
+ try
+ {
+ List<List<Object>> values = null;
+
+ if(_ApiVersion.greaterThanOrEqualTo(1, 3))
+ {
+ //Qpid JMX API 1.3+, use this virtualhosts VirtualHostManager MBean
+ //to retrieve the attributes values requested for all queues at once
+ try
+ {
+ values = _vhmb.retrieveQueueAttributeValues(_selectedAttributes.toArray(new String[0]));
+ }
+ catch(Exception e)
+ {
+ MBeanUtility.handleException(_vhostMbean, e);
+ }
+ }
+ else
+ {
+ //Qpid JMX API 1.2 or below, use the local ManagedBeans and look
+ //up the attribute values for each queue individually
+ _mbeans = getMbeans();
+ values = MBeanUtility.getQueueAttributes(_mbeans, _selectedAttributes.toArray(new String[0]));
+ }
+
+ _tableViewer.setInput(values);
+ layout();
+ }
+ finally
+ {
+ _tableViewerSemaphore.release();
+ }
+ }
+
+ }
+
+ @Override
+ protected List<ManagedBean> getMbeans()
+ {
+ return _serverRegistry.getQueues(_virtualHost);
+ }
+
+ private void clearTableComposite()
+ {
+ ViewUtility.disposeChildren(_tableComposite);
+ }
+
+ @Override
+ protected void createTable()
+ {
+ _table = new Table (_tableComposite, SWT.MULTI | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION);
+ _table.setLinesVisible (true);
+ _table.setHeaderVisible (true);
+ GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
+ _table.setLayoutData(data);
+
+ _tableViewer = new TableViewer(_table);
+
+ final QueueTableSorter tableSorter = new QueueTableSorter();
+
+ for (int i = 0; i < _selectedAttributes.size(); i++)
+ {
+ final int index = i;
+ final TableViewerColumn viewerColumn = new TableViewerColumn(_tableViewer, SWT.NONE);
+ final TableColumn column = viewerColumn.getColumn();
+
+ String attrName = _selectedAttributes.get(i);
+ column.setMoveable(true);
+ column.setText(attrName);
+ column.pack();
+ if(DEFAULT_COLUMN_WIDTHS.containsKey(attrName))
+ {
+ //retrieve the desired default width
+ column.setWidth(DEFAULT_COLUMN_WIDTHS.get(attrName));
+ }
+ else
+ {
+ //add padding for sort direction indicator
+ column.setWidth(column.getWidth() + 15);
+ }
+ column.setResizable(true);
+
+ //Setting the right sorter
+ column.addSelectionListener(new SelectionAdapter()
+ {
+ @Override
+ public void widgetSelected(SelectionEvent e)
+ {
+ tableSorter.setColumn(index);
+ final TableViewer viewer = _tableViewer;
+ int dir = viewer .getTable().getSortDirection();
+ if (viewer.getTable().getSortColumn() == column)
+ {
+ dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
+ }
+ else
+ {
+ dir = SWT.UP;
+ }
+ viewer.getTable().setSortDirection(dir);
+ viewer.getTable().setSortColumn(column);
+ viewer.refresh();
+ }
+ });
+
+ }
+
+ _tableViewer.setContentProvider(new QueueContentProviderImpl());
+ _tableViewer.setLabelProvider(new QueueLabelProviderImpl());
+
+ _tableViewer.setUseHashlookup(true);
+ _tableViewer.setSorter(tableSorter);
+ _table.setSortColumn(_table.getColumn(0));
+ _table.setSortDirection(SWT.UP);
+
+ addTableListeners();
+ }
+
+ protected void createLowerAreaButton(Composite parent)
+ {
+ Composite lowerButtonComposite = _toolkit.createComposite(parent, SWT.NONE);
+ GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, false);
+ lowerButtonComposite.setLayoutData(gridData);
+ lowerButtonComposite.setLayout(new GridLayout());
+
+ final Button attributesButton = _toolkit.createButton(lowerButtonComposite, "Select Attributes ...", SWT.PUSH);
+ gridData = new GridData(SWT.RIGHT, SWT.CENTER, true, false);
+ attributesButton.setLayoutData(gridData);
+ attributesButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ chooseAttributes(attributesButton.getShell());
+ }
+ });
+ }
+
+ private void chooseAttributes(final Shell parent)
+ {
+
+ List<String> availableAttributes;
+ if(_ApiVersion.greaterThanOrEqualTo(1, 3))
+ {
+ //Qpid JMX API 1.3+, request the current queue attributes names from the broker
+ try
+ {
+ availableAttributes = _vhmb.retrieveQueueAttributeNames();
+ }
+ catch (IOException e)
+ {
+ availableAttributes = new ArrayList<String>(FALLBACK_ATTRIBUTES_LIST);
+ }
+ }
+ else
+ {
+ //Qpid JMX API 1.2 or below, use the falllback list of names.
+ availableAttributes = new ArrayList<String>(FALLBACK_ATTRIBUTES_LIST);
+ }
+
+
+ final List<String> chosenAttributes = new ArrayList<String>();
+
+ final Shell shell = ViewUtility.createModalDialogShell(parent, "Select Attributes");
+
+ Composite attributesComposite = _toolkit.createComposite(shell, SWT.NONE);
+ attributesComposite.setBackground(shell.getBackground());
+ attributesComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ attributesComposite.setLayout(new GridLayout(2,false));
+
+ //add a selected-but-disabled check box for the Name attribute (its a mandatory attribute)
+ final Button nameCheckbox = new Button(attributesComposite, SWT.CHECK);
+ nameCheckbox.setText(ManagedQueue.ATTR_NAME);
+ nameCheckbox.setSelection(true);
+ nameCheckbox.setEnabled(false);
+
+ for(String attr : availableAttributes)
+ {
+ if(attr.equals(ManagedQueue.ATTR_NAME))
+ {
+ //Name attribute is mandatory and gets added to the front of the list later
+ continue;
+ }
+
+ final Button attrButton = new Button(attributesComposite, SWT.CHECK);
+ attrButton.setText(attr);
+
+ //if it was checked before, select it again now
+ if(_selectedAttributes.contains(attr))
+ {
+ attrButton.setSelection(true);
+ chosenAttributes.add(attr);
+ }
+
+ //add a selection listener to update the selected attribute list
+ attrButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ if(attrButton.getSelection())
+ {
+ chosenAttributes.add(attrButton.getText());
+ }
+ else
+ {
+ chosenAttributes.remove(attrButton.getText());
+ }
+ }
+ });
+ }
+
+ Composite okCancelButtonsComp = _toolkit.createComposite(shell);
+ okCancelButtonsComp.setBackground(shell.getBackground());
+ okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
+ okCancelButtonsComp.setLayout(new GridLayout(2,false));
+
+ Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
+ okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+ Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
+ cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+
+ okButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ shell.dispose();
+
+ //The Name attribute is mandatory, add it now, also
+ //ensuring it is left-most by placing it first in the list
+ List<String> newSelection = new ArrayList<String>();
+ newSelection.add(ManagedQueue.ATTR_NAME);
+
+ //now add all remaining choices in alphabetical order
+ Collections.sort(chosenAttributes);
+ newSelection.addAll(chosenAttributes);
+
+ _tableViewerSemaphore.acquireUninterruptibly();
+ try
+ {
+ _selectedAttributes = newSelection;
+
+ clearTableComposite();
+ createTable();
+ saveAttributePreferences();
+ }
+ finally
+ {
+ _tableViewerSemaphore.release();
+ }
+
+ refresh(_mbean);
+ }
+ });
+
+ cancelButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ shell.dispose();
+ }
+ });
+
+ shell.setDefaultButton(okButton);
+ shell.pack();
+ ViewUtility.centerChildInParentShell(parent, shell);
+
+ shell.open();
+ }
+
+ private String getQueueDepthString(Long value)
+ {
+ if(value == null)
+ {
+ return "-";
+ }
+
+ if (_ApiVersion.greaterThanOrEqualTo(1,2))
+ {
+ //Qpid JMX API 1.2 or above, returns Bytes
+ return convertLongBytesToText(value);
+ }
+ else
+ {
+ //Qpid JMX API 1.1 or below, returns KB
+ double mb = 1024.0;
+
+ if(value > mb) //MB
+ {
+ return String.format("%.3f", (Double)(value / mb)) + " MB";
+ }
+ else //KB
+ {
+ return value + " KB";
+ }
+ }
+ }
+
+ private String convertLongBytesToText(Long value)
+ {
+ if(value == null)
+ {
+ return "-";
+ }
+
+ double mb = 1024.0 * 1024.0;
+ double kb = 1024.0;
+
+ if(value >= mb) //MB
+ {
+ return String.format("%.3f", (Double)((double)value / mb)) + " MB";
+ }
+ else if (value >= kb) //KB
+ {
+ return String.format("%.3f", (Double)((double)value / kb)) + " KB";
+ }
+ else //Bytes
+ {
+ return value + " Bytes";
+ }
+ }
+
+ /**
+ * sorter class for the table viewer.
+ *
+ */
+ private static class QueueTableSorter extends ViewerSorter
+ {
+ protected int column;
+ protected static final int ASCENDING = 0;
+ protected static final int DESCENDING = 1;
+
+ protected int direction;
+
+ public QueueTableSorter()
+ {
+ this.column = 0;
+ direction = ASCENDING;
+ }
+
+ public void setColumn(int column)
+ {
+ if(column == this.column)
+ {
+ // Same column as last sort; toggle the direction
+ direction = 1 - direction;
+ }
+ else
+ {
+ // New column; do an ascending sort
+ this.column = column;
+ direction = ASCENDING;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public int compare(Viewer viewer, Object e1, Object e2)
+ {
+ List<Object> queue1 = (List<Object>) e1;
+ List<Object> queue2 = (List<Object>) e2;
+
+ int comparison = 0;
+ switch(column)
+ {
+ default:
+ if(queue1.get(column) instanceof Comparable)
+ {
+ comparison = ((Comparable)queue1.get(column)).compareTo((Comparable) queue2.get(column));
+ }
+ }
+ // If descending order, flip the direction
+ if(direction == DESCENDING)
+ {
+ comparison = -comparison;
+ }
+ return comparison;
+ }
+ }
+
+ /**
+ * Content Provider class for the table viewer for Qpid JMX API 1.3 and above.
+ */
+ private static class QueueContentProviderImpl implements IStructuredContentProvider
+ {
+
+ public void inputChanged(Viewer v, Object oldInput, Object newInput)
+ {
+
+ }
+
+ public void dispose()
+ {
+
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object[] getElements(Object parent)
+ {
+ return ((List<List<Object>>) parent).toArray();
+ }
+ }
+
+ /**
+ * Label Provider class for the table viewer for for Qpid JMX API 1.3 and above.
+ */
+ private class QueueLabelProviderImpl extends LabelProvider implements ITableLabelProvider
+ {
+ @SuppressWarnings("unchecked")
+ public String getColumnText(Object element, int columnIndex)
+ {
+ List<Object> attributes = (List<Object>) element;
+
+ switch (columnIndex)
+ {
+ default :
+ String attrName = _selectedAttributes.get(columnIndex);
+
+ if(ATTR_QUEUE_DEPTH.equals(attrName))
+ {
+ return getQueueDepthString((Long) attributes.get(columnIndex));
+ }
+ else if(ATTR_MAX_QUEUE_DEPTH.equals(attrName) || ATTR_MAX_MSG_SIZE.equals(attrName))
+ {
+ Number val = (Number)attributes.get(columnIndex);
+ return convertLongBytesToText(val.longValue());
+ }
+ else if(ATTR_MAX_MSG_AGE.equals(attrName))
+ {
+ return String.valueOf(attributes.get(columnIndex) + "ms");
+ }
+
+ return String.valueOf(attributes.get(columnIndex));
+ }
+ }
+
+ public Image getColumnImage(Object element, int columnIndex)
+ {
+ return null;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected void addMBeanToFavourites()
+ {
+ int selectionIndex = _table.getSelectionIndex();
+
+ if (selectionIndex == -1)
+ {
+ return;
+ }
+
+ int[] selectedIndices = _table.getSelectionIndices();
+
+ ArrayList<ManagedBean> selectedMBeans = new ArrayList<ManagedBean>();
+
+ boolean allSucceded = true;
+ //the entries are created from an List<Object> with the attribute values (name first)
+ for(int index = 0; index < selectedIndices.length ; index++)
+ {
+ List<Object> queueEntry = (List<Object>) _table.getItem(selectedIndices[index]).getData();
+ String queueName = (String) queueEntry.get(0);
+
+ ManagedBean queueMBean = _serverRegistry.getQueue(queueName, _virtualHost);
+
+ //check queue had not already been unregistered before trying to add it
+ if(queueMBean != null)
+ {
+ selectedMBeans.add(queueMBean);
+ }
+ else
+ {
+ allSucceded = false;
+ }
+ }
+
+ if(allSucceded)
+ {
+ //ensure the status bar is cleared of any previous failures added by the below
+ ViewUtility.clearStatusBar();
+ }
+ else
+ {
+ ViewUtility.operationFailedStatusBarMessage("A selected queue could not be added as it was no longer registered");
+ refresh();
+ }
+
+
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ NavigationView view = (NavigationView)window.getActivePage().findView(NavigationView.ID);
+
+ ManagedBean bean = null;
+ try
+ {
+ for(ManagedBean mbean: selectedMBeans)
+ {
+ bean = mbean;
+ view.addManagedBean(mbean);
+ }
+ }
+ catch (Exception ex)
+ {
+ MBeanUtility.handleException(bean, ex);
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ protected void openMBean()
+ {
+ int selectionIndex = _table.getSelectionIndex();
+
+ if (selectionIndex == -1)
+ {
+ return;
+ }
+
+ ManagedBean selectedMBean;
+
+ //the entries are created from an List<Object> with the attribute values (name first)
+ List<Object> queueEntry = (List<Object>) _table.getItem(selectionIndex).getData();
+ String queueName = (String) queueEntry.get(0);
+ selectedMBean = _serverRegistry.getQueue(queueName, _virtualHost);
+
+ if(selectedMBean == null)
+ {
+ ViewUtility.popupErrorMessage("Error", "Unable to retrieve the selected MBean to open it");
+ return;
+ }
+
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ MBeanView view = (MBeanView) window.getActivePage().findView(MBeanView.ID);
+ try
+ {
+ view.openMBean(selectedMBean);
+ }
+ catch (Exception ex)
+ {
+ MBeanUtility.handleException(selectedMBean, ex);
+ }
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/users/UserManagementTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/users/UserManagementTabControl.java
new file mode 100644
index 0000000000..fdcc25d337
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/users/UserManagementTabControl.java
@@ -0,0 +1,925 @@
+/*
+ *
+ * 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.users;
+
+import static org.apache.qpid.management.common.mbeans.UserManagement.RIGHTS_ADMIN;
+import static org.apache.qpid.management.common.mbeans.UserManagement.RIGHTS_READ_ONLY;
+import static org.apache.qpid.management.common.mbeans.UserManagement.RIGHTS_READ_WRITE;
+import static org.apache.qpid.management.common.mbeans.UserManagement.USERNAME;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerInvocationHandler;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularDataSupport;
+
+import org.apache.qpid.management.ui.ApiVersion;
+import org.apache.qpid.management.ui.ApplicationRegistry;
+import org.apache.qpid.management.ui.ManagedBean;
+import org.apache.qpid.management.common.mbeans.UserManagement;
+import org.apache.qpid.management.ui.jmx.JMXManagedObject;
+import org.apache.qpid.management.ui.jmx.MBeanUtility;
+import org.apache.qpid.management.ui.views.TabControl;
+import org.apache.qpid.management.ui.views.ViewUtility;
+import org.eclipse.jface.dialogs.InputDialog;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+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.TableViewerColumn;
+import org.eclipse.jface.viewers.Viewer;
+import org.eclipse.jface.viewers.ViewerSorter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+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.Group;
+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.FormToolkit;
+import org.eclipse.ui.forms.widgets.ScrolledForm;
+
+
+/**
+ * Control class for the UserManagement mbean.
+ */
+public class UserManagementTabControl extends TabControl
+{
+ private FormToolkit _toolkit;
+ private ScrolledForm _form;
+ private Table _table = null;
+ private TableViewer _tableViewer = null;
+
+ private TabularDataSupport _userDetails = null;
+ private UserManagement _ummb;
+ private ApiVersion _ApiVersion;
+
+ public UserManagementTabControl(TabFolder tabFolder, JMXManagedObject mbean, MBeanServerConnection mbsc)
+ {
+ super(tabFolder);
+ _mbean = mbean;
+ _ApiVersion = ApplicationRegistry.getServerRegistry(mbean).getManagementApiVersion();
+ _ummb = (UserManagement)
+ MBeanServerInvocationHandler.newProxyInstance(mbsc, mbean.getObjectName(),
+ UserManagement.class, false);
+ _toolkit = new FormToolkit(_tabFolder.getDisplay());
+ _form = _toolkit.createScrolledForm(_tabFolder);
+ _form.getBody().setLayout(new GridLayout());
+ createWidgets();
+ }
+
+ /**
+ * @see TabControl#getControl()
+ */
+ public Control getControl()
+ {
+ return _form;
+ }
+
+ /**
+ * @see TabControl#setFocus()
+ */
+ public void setFocus()
+ {
+ _table.setFocus();
+ }
+
+ @Override
+ public void refresh(ManagedBean mbean)
+ {
+ _userDetails = null;
+ try
+ {
+ _userDetails = (TabularDataSupport) _ummb.viewUsers();
+ }
+ catch(Exception e)
+ {
+ MBeanUtility.handleException(_mbean, e);
+
+ }
+
+ _tableViewer.setInput(_userDetails);
+
+ layout();
+ }
+
+ public void layout()
+ {
+ _form.layout(true);
+ _form.getBody().layout(true, true);
+ }
+
+ private void createWidgets()
+ {
+ Composite paramsComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
+ paramsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ paramsComposite.setLayout(new GridLayout());
+
+ Group viewUsersGroup = new Group(paramsComposite, SWT.SHADOW_NONE);
+ viewUsersGroup.setBackground(paramsComposite.getBackground());
+ viewUsersGroup.setText("Users");
+ viewUsersGroup.setLayout(new GridLayout(2,false));
+ viewUsersGroup.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+
+ Composite tableComposite = _toolkit.createComposite(viewUsersGroup);
+ GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+ gridData.heightHint = 250;
+ gridData.minimumHeight = 250;
+ tableComposite.setLayoutData(gridData);
+ tableComposite.setLayout(new GridLayout(2,false));
+
+ _table = new Table (tableComposite, SWT.MULTI | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION);
+ _table.setLinesVisible (true);
+ _table.setHeaderVisible (true);
+ gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+ _table.setLayoutData(gridData);
+
+ _tableViewer = new TableViewer(_table);
+ final TableSorter tableSorter = new TableSorter();
+
+ String[] titles = { "Username", "JMX Management Rights" };
+ int[] bounds = { 310, 200 };
+ for (int i = 0; i < titles.length; i++)
+ {
+ final int index = i;
+ final TableViewerColumn viewerColumn = new TableViewerColumn(_tableViewer, SWT.NONE);
+ final TableColumn column = viewerColumn.getColumn();
+
+ column.setText(titles[i]);
+ column.setWidth(bounds[i]);
+ column.setResizable(true);
+
+ //Setting the right sorter
+ column.addSelectionListener(new SelectionAdapter()
+ {
+ @Override
+ public void widgetSelected(SelectionEvent e)
+ {
+ tableSorter.setColumn(index);
+ final TableViewer viewer = _tableViewer;
+ int dir = viewer .getTable().getSortDirection();
+ if (viewer.getTable().getSortColumn() == column)
+ {
+ dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
+ }
+ else
+ {
+ dir = SWT.UP;
+ }
+ viewer.getTable().setSortDirection(dir);
+ viewer.getTable().setSortColumn(column);
+ viewer.refresh();
+ }
+ });
+
+ }
+
+ _tableViewer.setContentProvider(new ContentProviderImpl());
+ _tableViewer.setLabelProvider(new LabelProviderImpl());
+ _tableViewer.setSorter(tableSorter);
+ _table.setSortColumn(_table.getColumn(0));
+ _table.setSortDirection(SWT.UP);
+
+ Composite buttonsComposite = _toolkit.createComposite(tableComposite);
+ gridData = new GridData(SWT.FILL, SWT.TOP, false, false);
+ gridData.heightHint = 165;
+ buttonsComposite.setLayoutData(gridData);
+ buttonsComposite.setLayout(new GridLayout());
+
+ final Button addUserButton = _toolkit.createButton(buttonsComposite, "Add New User ...", SWT.PUSH);
+ gridData = new GridData(SWT.CENTER, SWT.TOP, false, true);
+ gridData.widthHint = 125;
+ addUserButton.setLayoutData(gridData);
+ addUserButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ addUser(addUserButton.getShell());
+ }
+ });
+
+ final Button deleteUsersButton = _toolkit.createButton(buttonsComposite, "Delete User(s)", SWT.PUSH);
+ gridData = new GridData(SWT.CENTER, SWT.BOTTOM, false, false);
+ gridData.widthHint = 125;
+ deleteUsersButton.setLayoutData(gridData);
+ deleteUsersButton.setEnabled(false);
+ deleteUsersButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ int selectionIndex = _table.getSelectionIndex();
+
+ if (selectionIndex != -1)
+ {
+ deleteUsers();
+ }
+ }
+ });
+
+ final Button setPasswordButton = _toolkit.createButton(buttonsComposite, "Set Password ...", SWT.PUSH);
+ gridData = new GridData(SWT.CENTER, SWT.BOTTOM, false, false);
+ gridData.widthHint = 125;
+ setPasswordButton.setLayoutData(gridData);
+ setPasswordButton.setEnabled(false);
+ setPasswordButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ int selectionIndex = _table.getSelectionIndex();
+
+ if (selectionIndex != -1)
+ {
+ final CompositeData selectedLogger = (CompositeData)_table.getItem(
+ selectionIndex).getData();
+ String user = selectedLogger.get(USERNAME).toString();
+ InputDialog id = new InputDialog(setPasswordButton.getShell(),"Set Password",
+ "Please enter the new password for '" + user + "':",null,null){
+ @Override
+ protected Control createDialogArea(Composite parent)
+ {
+ Control control = super.createDialogArea(parent);
+ //set the Text field echo char to '*' to mask the password
+ getText().setEchoChar('*');
+ //return the normal result
+ return control;
+ }
+ };
+
+ int returnValue;
+ while((returnValue = id.open()) == InputDialog.OK)
+ {
+ if (id.getValue() == null || id.getValue().toString().length() == 0)
+ {
+ ViewUtility.popupErrorMessage("Set Password", "Please enter a valid password");
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (returnValue == InputDialog.OK)
+ {
+ char[] password = id.getValue().toCharArray();
+
+ // Qpid JMX API 1.1 and below expects the password to be sent as a hashed value.
+ if (_ApiVersion.lessThanOrEqualTo(1,1))
+ {
+ try
+ {
+ password = ViewUtility.getHash(id.getValue());
+ }
+ catch (Exception hashException)
+ {
+ ViewUtility.popupErrorMessage("Set Password",
+ "Unable to calculate hash for Password:"
+ + hashException.getMessage());
+ return;
+ }
+ }
+
+ try
+ {
+ boolean result = _ummb.setPassword(user, password);
+ ViewUtility.operationResultFeedback(result, "Updated user password", "Failed to update user password");
+ }
+ catch(Exception e2)
+ {
+ ViewUtility.operationFailedStatusBarMessage("Error updating user password");
+ MBeanUtility.handleException(_mbean, e2);
+ }
+ }
+ }
+ }
+ });
+
+ final Button setRightsButton = _toolkit.createButton(buttonsComposite, "Set Rights ...", SWT.PUSH);
+ gridData = new GridData(SWT.CENTER, SWT.BOTTOM, false, false);
+ gridData.widthHint = 125;
+ setRightsButton.setLayoutData(gridData);
+ setRightsButton.setEnabled(false);
+ setRightsButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ int selectionIndex = _table.getSelectionIndex();
+
+ if (selectionIndex != -1)
+ {
+ setRights(setRightsButton.getShell());
+ }
+ }
+ });
+
+ _tableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
+ public void selectionChanged(SelectionChangedEvent evt)
+ {
+ int selectionIndex = _table.getSelectionIndex();
+
+ if (selectionIndex == -1)
+ {
+ deleteUsersButton.setEnabled(false);
+ setRightsButton.setEnabled(false);
+ setPasswordButton.setEnabled(false);
+ return;
+ }
+ else
+ {
+ deleteUsersButton.setEnabled(true);
+ setRightsButton.setEnabled(true);
+ }
+
+ if (_table.getSelectionCount() > 1)
+ {
+ setPasswordButton.setEnabled(false);
+ }
+ else
+ {
+ setPasswordButton.setEnabled(true);
+ }
+ }
+ });
+
+ Group miscGroup = new Group(paramsComposite, SWT.SHADOW_NONE);
+ miscGroup.setBackground(paramsComposite.getBackground());
+ miscGroup.setText("Misc");
+ gridData = new GridData(SWT.LEFT, SWT.TOP, true, true);
+ miscGroup.setLayoutData(gridData);
+ miscGroup.setLayout(new GridLayout(2,false));
+
+ final Button reloadUserDetails = _toolkit.createButton(miscGroup,
+ "Reload User Details", SWT.PUSH);
+ if(_ApiVersion.lessThan(1, 2))
+ {
+ //this only reloaded the JMX rights file before Qpid JMX API 1.2
+ _toolkit.createLabel(miscGroup, " Loads the current management rights file from disk");
+ }
+ else
+ {
+ //since Qpid JMX API 1.2 it also reloads the password file
+ _toolkit.createLabel(miscGroup, " Loads the current password and management rights files from disk");
+ }
+ reloadUserDetails.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ int response = ViewUtility.popupOkCancelConfirmationMessage("Reload User Data",
+ "Do you want to reload user data ?");
+ if (response == SWT.OK)
+ {
+ try
+ {
+ boolean result = _ummb.reloadData();
+ ViewUtility.operationResultFeedback(result, "Reloaded user data", "Failed to reload user data");
+ }
+ catch(Exception e3)
+ {
+ ViewUtility.operationFailedStatusBarMessage("Error reloading user data");
+ MBeanUtility.handleException(_mbean, e3);
+ }
+ refresh(_mbean);
+ }
+ }
+ });
+
+ }
+
+
+ /**
+ * Content Provider class for the table viewer
+ */
+ private static class ContentProviderImpl implements IStructuredContentProvider
+ {
+
+ public void inputChanged(Viewer v, Object oldInput, Object newInput)
+ {
+
+ }
+
+ public void dispose()
+ {
+
+ }
+
+ public Object[] getElements(Object parent)
+ {
+ Collection<Object> rowCollection = ((TabularDataSupport) parent).values();
+
+ return rowCollection.toArray();
+ }
+ }
+
+ /**
+ * Label Provider class for the table viewer
+ */
+ private class LabelProviderImpl extends LabelProvider implements ITableLabelProvider
+ {
+ @Override
+ public String getColumnText(Object element, int columnIndex)
+ {
+ switch (columnIndex)
+ {
+ case 0 : // username column
+ return (String) ((CompositeData) element).get(USERNAME);
+ case 1 : // rights column
+ return classifyUserRights((CompositeData) element);
+ default :
+ return "-";
+ }
+ }
+
+ @Override
+ public Image getColumnImage(Object element, int columnIndex)
+ {
+ return null;
+ }
+
+ }
+
+ /**
+ * Sorter class for the table viewer.
+ *
+ */
+ private class TableSorter extends ViewerSorter
+ {
+ private int column;
+ private static final int ASCENDING = 0;
+ private static final int DESCENDING = 1;
+
+ private int direction;
+
+ public TableSorter()
+ {
+ this.column = 0;
+ direction = ASCENDING;
+ }
+
+ public void setColumn(int column)
+ {
+ if(column == this.column)
+ {
+ // Same column as last sort; toggle the direction
+ direction = 1 - direction;
+ }
+ else
+ {
+ // New column; do an ascending sort
+ this.column = column;
+ direction = ASCENDING;
+ }
+ }
+
+ @Override
+ public int compare(Viewer viewer, Object e1, Object e2)
+ {
+ CompositeData user1 = (CompositeData) e1;
+ CompositeData user2 = (CompositeData) e2;
+
+ int comparison = 0;
+ switch(column)
+ {
+ case 0:
+ comparison = String.valueOf(user1.get(USERNAME)).compareTo(
+ String.valueOf(user2.get(USERNAME)));
+ break;
+ case 1:
+ comparison = classifyUserRights(user1).compareTo(classifyUserRights(user2));
+ break;
+ default:
+ comparison = 0;
+ }
+ // If descending order, flip the direction
+ if(direction == DESCENDING)
+ {
+ comparison = -comparison;
+ }
+ return comparison;
+ }
+ }
+
+ private String classifyUserRights(CompositeData user)
+ {
+ Boolean read = (Boolean)user.get(RIGHTS_READ_ONLY);
+ Boolean write = (Boolean)user.get(RIGHTS_READ_WRITE);
+ Boolean admin = (Boolean)user.get(RIGHTS_ADMIN);
+
+ if(admin)
+ {
+ return "Admin";
+ }
+ else if(write)
+ {
+ return "Read & Write";
+ }
+ else if(read)
+ {
+ return "Read Only";
+ }
+ else
+ {
+ return "No Access";
+ }
+ }
+
+ private void setRights(final Shell parent)
+ {
+
+ int selectionIndex = _table.getSelectionIndex();
+
+ if (selectionIndex == -1)
+ {
+ return;
+ }
+
+ int[] selectedIndices = _table.getSelectionIndices();
+
+ final ArrayList<String> selectedUsers = new ArrayList<String>();
+
+ for(int index = 0; index < selectedIndices.length ; index++)
+ {
+ CompositeData selectedUser = (CompositeData)_table.getItem(selectedIndices[index]).getData();
+ String user = selectedUser.get(USERNAME).toString();
+ selectedUsers.add(user);
+ }
+
+ String selectedUsersString = "";
+ for(String user : selectedUsers)
+ {
+ selectedUsersString = selectedUsersString.concat(user + ", ");
+ }
+ //cut off last ", "
+ int lastIndex = selectedUsersString.lastIndexOf(',');
+ if (lastIndex != -1)
+ {
+ selectedUsersString = selectedUsersString.substring(0,lastIndex);
+ }
+
+
+
+ final Shell shell = ViewUtility.createModalDialogShell(parent, "Set Rights");
+
+ Label overview = _toolkit.createLabel(shell,"Select rights for user(s): ");
+ overview.setBackground(shell.getBackground());
+ Label userNamesLabel= _toolkit.createLabel(shell,selectedUsersString);
+ userNamesLabel.setBackground(shell.getBackground());
+
+ Composite buttons = _toolkit.createComposite(shell, SWT.NONE);
+ buttons.setBackground(shell.getBackground());
+ buttons.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ buttons.setLayout(new GridLayout(4,false));
+
+ final Button noneButton = new Button(buttons, SWT.RADIO);
+ noneButton.setText("No Access");
+ noneButton.setSelection(true);
+ final Button readButton = new Button(buttons, SWT.RADIO);
+ readButton.setText("Read Only");
+ final Button writeButton = new Button(buttons, SWT.RADIO);
+ writeButton.setText("Read + Write");
+ final Button adminButton = new Button(buttons, SWT.RADIO);
+ adminButton.setText("Admin");
+
+ Composite okCancelButtonsComp = _toolkit.createComposite(shell);
+ okCancelButtonsComp.setBackground(shell.getBackground());
+ okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
+ okCancelButtonsComp.setLayout(new GridLayout(2,false));
+
+ Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
+ okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+ Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
+ cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+
+ okButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ boolean read = readButton.getSelection();
+ boolean write = writeButton.getSelection();
+ boolean admin = adminButton.getSelection();
+
+ shell.dispose();
+
+ HashMap<String,Boolean> results = new HashMap<String,Boolean>();
+ try
+ {
+ //perform the rights updates, save the results.
+ for(String user : selectedUsers)
+ {
+ boolean result = _ummb.setRights(user,read,write,admin);
+ results.put(user, result);
+ }
+
+ //categorise the overall result
+ boolean overallResult = true;
+ for(boolean result : results.values())
+ {
+ if (!result)
+ {
+ overallResult = false;
+ }
+ }
+
+ //output the result to status bar if all success, and dialogue if not
+ if(overallResult)
+ {
+ ViewUtility.operationResultFeedback(overallResult, "Updated user rights", null);
+ }
+ else
+ {
+ String failedToUpdateRightsUsers = "";
+ for(String user : results.keySet())
+ {
+ if(!results.get(user))
+ {
+ failedToUpdateRightsUsers = failedToUpdateRightsUsers.concat(user + ", ");
+ }
+ }
+
+ //cut off last ", "
+ int lastIndex2 = failedToUpdateRightsUsers.lastIndexOf(',');
+ if (lastIndex2 != -1)
+ {
+ failedToUpdateRightsUsers = failedToUpdateRightsUsers.substring(0, lastIndex2);
+ }
+
+ ViewUtility.operationResultFeedback(overallResult, null, "Failed to update user(s) rights: " + failedToUpdateRightsUsers);
+ }
+ }
+ catch(Exception e4)
+ {
+ ViewUtility.operationFailedStatusBarMessage("Error updating user rights");
+ MBeanUtility.handleException(_mbean, e4);
+ }
+ refresh(_mbean);
+ }
+ });
+
+ cancelButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ shell.dispose();
+ }
+ });
+
+ shell.setDefaultButton(okButton);
+ shell.pack();
+ ViewUtility.centerChildInParentShell(parent, shell);
+
+ shell.open();
+ }
+
+ private void addUser(final Shell parent)
+ {
+ final Shell shell = ViewUtility.createModalDialogShell(parent, "Add New User");
+
+ Composite usernameComposite = _toolkit.createComposite(shell, SWT.NONE);
+ usernameComposite.setBackground(shell.getBackground());
+ usernameComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ usernameComposite.setLayout(new GridLayout(2,false));
+
+ _toolkit.createLabel(usernameComposite,"Username:").setBackground(shell.getBackground());
+ final Text usernameText = new Text(usernameComposite, SWT.BORDER);
+ usernameText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+
+ Composite passwordComposite = _toolkit.createComposite(shell, SWT.NONE);
+ passwordComposite.setBackground(shell.getBackground());
+ passwordComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ passwordComposite.setLayout(new GridLayout(2,false));
+
+ _toolkit.createLabel(passwordComposite,"Password:").setBackground(shell.getBackground());
+ final Text passwordText = new Text(passwordComposite, SWT.BORDER | SWT.PASSWORD);
+ passwordText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+
+ Group buttonGroup = new Group(shell, SWT.NONE);
+ buttonGroup.setText("JMX Management Rights");
+ buttonGroup.setBackground(shell.getBackground());
+ buttonGroup.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ buttonGroup.setLayout(new GridLayout(4,false));
+
+ final Button noneButton = new Button(buttonGroup, SWT.RADIO);
+ noneButton.setText("No Access");
+ noneButton.setSelection(true);
+ final Button readButton = new Button(buttonGroup, SWT.RADIO);
+ readButton.setText("Read Only");
+ final Button writeButton = new Button(buttonGroup, SWT.RADIO);
+ writeButton.setText("Read + Write");
+ final Button adminButton = new Button(buttonGroup, SWT.RADIO);
+ adminButton.setText("Admin");
+
+ Composite okCancelButtonsComp = _toolkit.createComposite(shell);
+ okCancelButtonsComp.setBackground(shell.getBackground());
+ okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
+ okCancelButtonsComp.setLayout(new GridLayout(2,false));
+
+ Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
+ okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+ Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
+ cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+
+ okButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ String username = usernameText.getText();
+ String password = passwordText.getText();
+
+ if (username == null || username.length() == 0)
+ {
+ ViewUtility.popupErrorMessage("Add New User", "Please enter a valid username");
+ return;
+ }
+
+ if (password == null || password.length() == 0)
+ {
+ ViewUtility.popupErrorMessage("Add New User", "Please enter a valid password");
+ return;
+ }
+
+ char[] passwordChars = password.toCharArray();
+
+ // Qpid JMX API 1.1 and below expects the password to be sent as a hashed value.
+ if (_ApiVersion.lessThanOrEqualTo(1,1))
+ {
+ try
+ {
+ passwordChars = ViewUtility.getHash(password);
+ }
+ catch (Exception hashException)
+ {
+ ViewUtility.popupErrorMessage("Set Password",
+ "Unable to calculate hash for Password:"
+ + hashException.getMessage());
+ return;
+ }
+ }
+
+ boolean read = readButton.getSelection();
+ boolean write = writeButton.getSelection();
+ boolean admin = adminButton.getSelection();
+
+ shell.dispose();
+ try
+ {
+ boolean result = false;
+ // If we have Qpid JMX API 1.7 or above, use newer createUser method with String based password.
+ if (_ApiVersion.greaterThanOrEqualTo(1,7))
+ {
+ result = _ummb.createUser(username, password, read, write, admin);
+ }
+ else
+ {
+ result = _ummb.createUser(username, passwordChars, read, write, admin);
+ }
+
+ ViewUtility.operationResultFeedback(result, "Created user", "Failed to create user");
+ }
+ catch(Exception e5)
+ {
+ ViewUtility.operationFailedStatusBarMessage("Error creating user");
+ MBeanUtility.handleException(_mbean, e5);
+ }
+
+ refresh(_mbean);
+ }
+ });
+
+ cancelButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ shell.dispose();
+ }
+ });
+
+ shell.setDefaultButton(okButton);
+ shell.pack();
+ ViewUtility.centerChildInParentShell(parent, shell);
+
+ shell.open();
+ }
+
+ private void deleteUsers()
+ {
+ int selectionIndex = _table.getSelectionIndex();
+ if (selectionIndex == -1)
+ {
+ return;
+ }
+
+ int[] selectedIndices = _table.getSelectionIndices();
+
+ ArrayList<String> selectedUsers = new ArrayList<String>();
+
+ for(int index = 0; index < selectedIndices.length ; index++)
+ {
+ CompositeData selectedUser = (CompositeData)_table.getItem(selectedIndices[index]).getData();
+ String user = selectedUser.get(USERNAME).toString();
+ selectedUsers.add(user);
+ }
+
+ String selectedUsersString = "";
+ for(String user : selectedUsers)
+ {
+ selectedUsersString = selectedUsersString.concat(user + ", ");
+ }
+ //cut off last ", "
+ int lastIndex = selectedUsersString.lastIndexOf(',');
+ if (lastIndex != -1)
+ {
+ selectedUsersString = selectedUsersString.substring(0,lastIndex);
+ }
+
+ int response = ViewUtility.popupOkCancelConfirmationMessage(
+ "User Management", "Delete user(s): " + selectedUsersString + " ?");
+
+ if (response == SWT.OK)
+ {
+ HashMap<String,Boolean> results = new HashMap<String,Boolean>();
+ try
+ {
+ //perform the deletes, save the results.
+ for(String user : selectedUsers)
+ {
+ boolean result = _ummb.deleteUser(user);
+ results.put(user, result);
+ }
+
+ //categorise the overall result
+ boolean overallResult = true;
+ for(boolean result : results.values())
+ {
+ if (!result)
+ {
+ overallResult = false;
+ }
+ }
+
+ //output the result to status bar if all success, and dialogue if not
+ if(overallResult)
+ {
+ ViewUtility.operationResultFeedback(overallResult, "Deleted user(s)", null);
+ }
+ else
+ {
+ String failedToDeleteUsers = "";
+ for(String user : results.keySet())
+ {
+ if(!results.get(user))
+ {
+ failedToDeleteUsers = failedToDeleteUsers.concat(user + ", ");
+ }
+ }
+
+ //cut off last ", "
+ lastIndex = failedToDeleteUsers.lastIndexOf(',');
+ if (lastIndex != -1)
+ {
+ failedToDeleteUsers = failedToDeleteUsers.substring(0, lastIndex);
+ }
+
+ ViewUtility.operationResultFeedback(overallResult, null, "Failed to delete user(s): " + failedToDeleteUsers);
+ }
+
+ }
+ catch(Exception e1)
+ {
+ ViewUtility.operationFailedStatusBarMessage("Error deleting user(s)");
+ MBeanUtility.handleException(_mbean, e1);
+ }
+
+ refresh(_mbean);;
+ }
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/vhost/VHostTabControl.java b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/vhost/VHostTabControl.java
new file mode 100644
index 0000000000..0cbb1389d8
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/java/org/apache/qpid/management/ui/views/vhost/VHostTabControl.java
@@ -0,0 +1,871 @@
+/*
+ *
+ * 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.vhost;
+
+import static org.apache.qpid.management.ui.Constants.DEFAULT_EXCHANGE_TYPE_VALUES;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerInvocationHandler;
+
+import org.apache.qpid.management.ui.ApiVersion;
+import org.apache.qpid.management.ui.ApplicationRegistry;
+import org.apache.qpid.management.ui.ManagedBean;
+import org.apache.qpid.management.ui.ServerRegistry;
+import org.apache.qpid.management.common.mbeans.ManagedBroker;
+import org.apache.qpid.management.ui.jmx.JMXManagedObject;
+import org.apache.qpid.management.ui.jmx.MBeanUtility;
+import org.apache.qpid.management.ui.views.MBeanView;
+import org.apache.qpid.management.ui.views.TabControl;
+import org.apache.qpid.management.ui.views.ViewUtility;
+import org.eclipse.jface.viewers.ISelectionChangedListener;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+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.jface.viewers.ViewerSorter;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Image;
+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.Group;
+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.IWorkbenchWindow;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.forms.widgets.Form;
+import org.eclipse.ui.forms.widgets.FormToolkit;
+
+
+/**
+ * Control class for the VirtualHostManager mbean operations tab.
+ */
+public class VHostTabControl extends TabControl
+{
+ private FormToolkit _toolkit;
+ private Form _form;
+ private Table _queueTable = null;
+ private TableViewer _queueTableViewer = null;
+ private Table _exchangeTable = null;
+ private TableViewer _exchangeTableViewer = null;
+
+ private Composite _paramsComposite = null;
+
+ private ManagedBroker _vhmb;
+ private ApiVersion _ApiVersion;
+ private List<ManagedBean> _queues;
+ private List<ManagedBean> _exchanges;
+ private ServerRegistry _serverRegistry;
+
+ public VHostTabControl(TabFolder tabFolder, JMXManagedObject mbean, MBeanServerConnection mbsc)
+ {
+ super(tabFolder);
+ _mbean = mbean;
+ _serverRegistry = ApplicationRegistry.getServerRegistry(mbean);
+ _ApiVersion = _serverRegistry.getManagementApiVersion();
+ _vhmb = (ManagedBroker) MBeanServerInvocationHandler.newProxyInstance(mbsc,
+ mbean.getObjectName(), ManagedBroker.class, false);
+ _toolkit = new FormToolkit(_tabFolder.getDisplay());
+ _form = _toolkit.createForm(_tabFolder);
+ _form.getBody().setLayout(new GridLayout());
+ createComposites();
+ createWidgets();
+ }
+
+ private void createComposites()
+ {
+ _paramsComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE);
+ _paramsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ _paramsComposite.setLayout(new GridLayout(2, true));
+ }
+
+ /**
+ * @see TabControl#getControl()
+ */
+ public Control getControl()
+ {
+ return _form;
+ }
+
+ /**
+ * @see TabControl#setFocus()
+ */
+ public void setFocus()
+ {
+
+ }
+
+ @Override
+ public void refresh(ManagedBean mbean)
+ {
+ ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(MBeanView.getServer());
+ _queues = serverRegistry.getQueues(MBeanView.getVirtualHost());
+ _exchanges = serverRegistry.getExchanges(MBeanView.getVirtualHost());
+
+ _queueTableViewer.setInput(_queues);
+ _exchangeTableViewer.setInput(_exchanges);
+
+ layout();
+ }
+
+ public void layout()
+ {
+ _form.layout(true);
+ _form.getBody().layout(true, true);
+ }
+
+ private void createWidgets()
+ {
+ Group queuesGroup = new Group(_paramsComposite, SWT.SHADOW_NONE);
+ queuesGroup.setBackground(_paramsComposite.getBackground());
+ queuesGroup.setText("Queues");
+ queuesGroup.setLayout(new GridLayout(2,false));
+ GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+ queuesGroup.setLayoutData(gridData);
+
+ _queueTable = new Table (queuesGroup, SWT.MULTI | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION);
+ _queueTable.setLinesVisible (true);
+ _queueTable.setHeaderVisible (true);
+ GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
+ _queueTable.setLayoutData(data);
+
+ _queueTableViewer = new TableViewer(_queueTable);
+ final TableSorter tableSorter = new TableSorter();
+
+ String[] titles = {"Name"};
+ int[] bounds = { 250 };
+ for (int i = 0; i < titles.length; i++)
+ {
+ final int index = i;
+ final TableColumn column = new TableColumn (_queueTable, SWT.NONE);
+
+ column.setText(titles[i]);
+ column.setWidth(bounds[i]);
+ column.setResizable(true);
+
+ //Setting the right sorter
+ column.addSelectionListener(new SelectionAdapter()
+ {
+ @Override
+ public void widgetSelected(SelectionEvent e)
+ {
+ tableSorter.setColumn(index);
+ final TableViewer viewer = _queueTableViewer;
+ int dir = viewer .getTable().getSortDirection();
+ if (viewer.getTable().getSortColumn() == column)
+ {
+ dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
+ }
+ else
+ {
+ dir = SWT.UP;
+ }
+ viewer.getTable().setSortDirection(dir);
+ viewer.getTable().setSortColumn(column);
+ viewer.refresh();
+ }
+ });
+
+ }
+
+ _queueTableViewer.setContentProvider(new ContentProviderImpl());
+ _queueTableViewer.setLabelProvider(new LabelProviderImpl());
+ _queueTableViewer.setSorter(tableSorter);
+ _queueTable.setSortColumn(_queueTable.getColumn(0));
+ _queueTable.setSortDirection(SWT.UP);
+
+ Composite queuesRightComposite = _toolkit.createComposite(queuesGroup);
+ gridData = new GridData(SWT.FILL, SWT.FILL, false, true);
+ queuesRightComposite.setLayoutData(gridData);
+ queuesRightComposite.setLayout(new GridLayout());
+
+ final Button createQueueButton = _toolkit.createButton(queuesRightComposite, "Create ...", SWT.PUSH);
+ createQueueButton.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
+ createQueueButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ createQueue(createQueueButton.getShell());
+ }
+ });
+
+ final Button deleteQueueButton = _toolkit.createButton(queuesRightComposite, "Delete", SWT.PUSH);
+ deleteQueueButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ deleteQueueButton.setEnabled(false);
+ deleteQueueButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ deleteQueuesOrExchanges(deleteQueueButton.getShell(), VhostOperations.DELETE_QUEUE);
+ }
+ });
+
+ _queueTableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
+ public void selectionChanged(SelectionChangedEvent evt)
+ {
+ int selectionIndex = _queueTable.getSelectionIndex();
+
+ if (selectionIndex != -1)
+ {
+ deleteQueueButton.setEnabled(true);
+ }
+ else
+ {
+ deleteQueueButton.setEnabled(false);
+ }
+ }
+ });
+
+ //listener for double clicking to open the selection mbean
+ _queueTable.addMouseListener(new MouseListener()
+ {
+ // MouseListener implementation
+ public void mouseDoubleClick(MouseEvent event)
+ {
+ openMBean(_queueTable);
+ }
+
+ public void mouseDown(MouseEvent e){}
+ public void mouseUp(MouseEvent e){}
+ });
+
+ Group exchangesGroup = new Group(_paramsComposite, SWT.SHADOW_NONE);
+ exchangesGroup.setBackground(_paramsComposite.getBackground());
+ exchangesGroup.setText("Exchanges");
+ exchangesGroup.setLayout(new GridLayout(2,false));
+ gridData = new GridData(SWT.FILL, SWT.FILL, true, true);
+ exchangesGroup.setLayoutData(gridData);
+
+ _exchangeTable = new Table (exchangesGroup, SWT.MULTI | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION);
+ _exchangeTable.setLinesVisible (true);
+ _exchangeTable.setHeaderVisible (true);
+ data = new GridData(SWT.FILL, SWT.FILL, true, true);
+ _exchangeTable.setLayoutData(data);
+
+ _exchangeTableViewer = new TableViewer(_exchangeTable);
+ final TableSorter exchangeTableSorter = new TableSorter();
+
+ for (int i = 0; i < titles.length; i++)
+ {
+ final int index = i;
+ final TableColumn column = new TableColumn (_exchangeTable, SWT.NONE);
+
+ column.setText(titles[i]);
+ column.setWidth(bounds[i]);
+ column.setResizable(true);
+
+ //Setting the right sorter
+ column.addSelectionListener(new SelectionAdapter()
+ {
+ @Override
+ public void widgetSelected(SelectionEvent e)
+ {
+ exchangeTableSorter.setColumn(index);
+ final TableViewer viewer = _exchangeTableViewer;
+ int dir = viewer .getTable().getSortDirection();
+ if (viewer.getTable().getSortColumn() == column)
+ {
+ dir = dir == SWT.UP ? SWT.DOWN : SWT.UP;
+ }
+ else
+ {
+ dir = SWT.UP;
+ }
+ viewer.getTable().setSortDirection(dir);
+ viewer.getTable().setSortColumn(column);
+ viewer.refresh();
+ }
+ });
+
+ }
+
+ _exchangeTableViewer.setContentProvider(new ContentProviderImpl());
+ _exchangeTableViewer.setLabelProvider(new LabelProviderImpl());
+ _exchangeTableViewer.setSorter(exchangeTableSorter);
+ _exchangeTable.setSortColumn(_exchangeTable.getColumn(0));
+ _exchangeTable.setSortDirection(SWT.UP);
+
+ Composite exchangesRightComposite = _toolkit.createComposite(exchangesGroup);
+ gridData = new GridData(SWT.FILL, SWT.FILL, false, true);
+ exchangesRightComposite.setLayoutData(gridData);
+ exchangesRightComposite.setLayout(new GridLayout());
+
+ final Button createExchangeButton = _toolkit.createButton(exchangesRightComposite, "Create ...", SWT.PUSH);
+ createExchangeButton.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, false, false));
+ createExchangeButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ createExchange(createQueueButton.getShell());
+ }
+ });
+
+ final Button deleteExchangeButton = _toolkit.createButton(exchangesRightComposite, "Delete", SWT.PUSH);
+ deleteExchangeButton.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ deleteExchangeButton.setEnabled(false);
+ deleteExchangeButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ deleteQueuesOrExchanges(deleteExchangeButton.getShell(), VhostOperations.DELETE_EXCHANGE);
+ }
+ });
+
+ _exchangeTableViewer.addSelectionChangedListener(new ISelectionChangedListener(){
+ public void selectionChanged(SelectionChangedEvent evt)
+ {
+ int selectionIndex = _exchangeTable.getSelectionIndex();
+
+ if (selectionIndex != -1)
+ {
+ deleteExchangeButton.setEnabled(true);
+ }
+ else
+ {
+ deleteExchangeButton.setEnabled(false);
+ }
+ }
+ });
+
+ //listener for double clicking to open the selection mbean
+ _exchangeTable.addMouseListener(new MouseListener()
+ {
+ // MouseListener implementation
+ public void mouseDoubleClick(MouseEvent event)
+ {
+ openMBean(_exchangeTable);
+ }
+
+ public void mouseDown(MouseEvent e){}
+ public void mouseUp(MouseEvent e){}
+ });
+ }
+
+
+ /**
+ * Content Provider class for the table viewer
+ */
+ private static class ContentProviderImpl implements IStructuredContentProvider
+ {
+
+ public void inputChanged(Viewer v, Object oldInput, Object newInput)
+ {
+
+ }
+
+ public void dispose()
+ {
+
+ }
+
+ @SuppressWarnings("unchecked")
+ public Object[] getElements(Object parent)
+ {
+ return ((List<ManagedBean>) parent).toArray();
+ }
+ }
+
+ /**
+ * Label Provider class for the table viewer
+ */
+ private static class LabelProviderImpl extends LabelProvider implements ITableLabelProvider
+ {
+ @Override
+ public String getColumnText(Object element, int columnIndex)
+ {
+ switch (columnIndex)
+ {
+ case 0 : // name column
+ return ((ManagedBean) element).getName();
+ default :
+ return "-";
+ }
+ }
+
+ @Override
+ public Image getColumnImage(Object element, int columnIndex)
+ {
+ return null;
+ }
+
+ }
+
+ /**
+ * Sorter class for the table viewer.
+ *
+ */
+ public static class TableSorter extends ViewerSorter
+ {
+ private int column;
+ private static final int ASCENDING = 0;
+ private static final int DESCENDING = 1;
+
+ private int direction = DESCENDING;
+
+ public TableSorter()
+ {
+ this.column = 0;
+ direction = ASCENDING;
+ }
+
+ public void setColumn(int column)
+ {
+ if (column == this.column)
+ {
+ // Same column as last sort; toggle the direction
+ direction = 1 - direction;
+ }
+ else
+ {
+ // New column; do an ascending sort
+ this.column = column;
+ direction = ASCENDING;
+ }
+ }
+
+ @Override
+ public int compare(Viewer viewer, Object e1, Object e2)
+ {
+ ManagedBean mbean1 = (ManagedBean ) e1;
+ ManagedBean mbean2 = (ManagedBean ) e2;
+
+ int comparison = 0;
+ switch(column)
+ {
+ case 0:
+ comparison = mbean1.getName().compareTo(mbean2.getName());
+ break;
+ default:
+ comparison = 0;
+ }
+ // If descending order, flip the direction
+ if(direction == DESCENDING)
+ {
+ comparison = -comparison;
+ }
+ return comparison;
+ }
+ }
+
+ private void createQueue(final Shell parent)
+ {
+ final Shell shell = ViewUtility.createModalDialogShell(parent, "Create Queue");
+
+ Composite nameComposite = _toolkit.createComposite(shell, SWT.NONE);
+ nameComposite.setBackground(shell.getBackground());
+ nameComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ nameComposite.setLayout(new GridLayout(2,false));
+
+ _toolkit.createLabel(nameComposite,"Name:").setBackground(shell.getBackground());
+ final Text nameText = new Text(nameComposite, SWT.BORDER);
+ nameText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+
+ Composite ownerComposite = _toolkit.createComposite(shell, SWT.NONE);
+ ownerComposite.setBackground(shell.getBackground());
+ ownerComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ ownerComposite.setLayout(new GridLayout(2,false));
+
+ _toolkit.createLabel(ownerComposite,"Owner (optional):").setBackground(shell.getBackground());
+ final Text ownerText = new Text(ownerComposite, SWT.BORDER);
+ ownerText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+
+ Composite durableComposite = _toolkit.createComposite(shell, SWT.NONE);
+ durableComposite.setBackground(shell.getBackground());
+ GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
+ gridData.minimumWidth = 220;
+ durableComposite.setLayoutData(gridData);
+ durableComposite.setLayout(new GridLayout(2,false));
+
+ _toolkit.createLabel(durableComposite,"Durable:").setBackground(shell.getBackground());
+ final Button durableButton = new Button(durableComposite, SWT.CHECK);
+ durableButton.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, false));
+
+ Composite okCancelButtonsComp = _toolkit.createComposite(shell);
+ okCancelButtonsComp.setBackground(shell.getBackground());
+ okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
+ okCancelButtonsComp.setLayout(new GridLayout(2,false));
+
+ Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
+ okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+ Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
+ cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+
+ okButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ String name = nameText.getText();
+
+ if (name == null || name.length() == 0)
+ {
+ ViewUtility.popupErrorMessage("Create Queue", "Please enter a valid name");
+ return;
+ }
+
+ String owner = ownerText.getText();
+
+ if (owner != null && owner.length() == 0)
+ {
+ owner = null;
+ }
+
+ boolean durable = durableButton.getSelection();
+
+ shell.dispose();
+
+ try
+ {
+ _vhmb.createNewQueue(name, owner, durable);
+
+ ViewUtility.operationResultFeedback(null, "Created Queue", null);
+ try
+ {
+ //delay to allow mbean registration notification processing
+ Thread.sleep(250);
+ }
+ catch(InterruptedException ie)
+ {
+ //ignore
+ }
+ }
+ catch(Exception e5)
+ {
+ ViewUtility.operationFailedStatusBarMessage("Error creating Queue");
+ MBeanUtility.handleException(_mbean, e5);
+ }
+
+ refresh(_mbean);
+ }
+ });
+
+ cancelButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ shell.dispose();
+ }
+ });
+
+ shell.setDefaultButton(okButton);
+ shell.pack();
+ ViewUtility.centerChildInParentShell(parent, shell);
+
+ shell.open();
+ }
+
+ private void createExchange(final Shell parent)
+ {
+ final Shell shell = ViewUtility.createModalDialogShell(parent, "Create Exchange");
+
+ Composite nameComposite = _toolkit.createComposite(shell, SWT.NONE);
+ nameComposite.setBackground(shell.getBackground());
+ nameComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ nameComposite.setLayout(new GridLayout(2,false));
+
+ _toolkit.createLabel(nameComposite,"Name:").setBackground(shell.getBackground());
+ final Text nameText = new Text(nameComposite, SWT.BORDER);
+ nameText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+
+ Composite typeComposite = _toolkit.createComposite(shell, SWT.NONE);
+ typeComposite.setBackground(shell.getBackground());
+ typeComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ typeComposite.setLayout(new GridLayout(2,false));
+
+ String[] exchangeTypes;
+ if(_ApiVersion.greaterThanOrEqualTo(1, 3))//if the server supports Qpid JMX API 1.3
+ {//request the current exchange types from the broker
+ try
+ {
+ exchangeTypes = _vhmb.getExchangeTypes();
+ }
+ catch (IOException e1)
+ {
+ exchangeTypes = DEFAULT_EXCHANGE_TYPE_VALUES.toArray(new String[DEFAULT_EXCHANGE_TYPE_VALUES.size()]);
+ }
+ }
+ else //use the fallback defaults.
+ {
+ exchangeTypes = DEFAULT_EXCHANGE_TYPE_VALUES.toArray(new String[DEFAULT_EXCHANGE_TYPE_VALUES.size()]);
+ }
+
+ _toolkit.createLabel(typeComposite,"Type:").setBackground(shell.getBackground());
+ final org.eclipse.swt.widgets.List typeList = new org.eclipse.swt.widgets.List(typeComposite, SWT.SINGLE | SWT.BORDER);
+ typeList.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ typeList.setItems(exchangeTypes);
+
+ Composite durableComposite = _toolkit.createComposite(shell, SWT.NONE);
+ durableComposite.setBackground(shell.getBackground());
+ GridData gridData = new GridData(SWT.FILL, SWT.TOP, true, false);
+ gridData.minimumWidth = 220;
+ durableComposite.setLayoutData(gridData);
+ durableComposite.setLayout(new GridLayout(2,false));
+
+ _toolkit.createLabel(durableComposite,"Durable:").setBackground(shell.getBackground());
+ final Button durableButton = new Button(durableComposite, SWT.CHECK);
+ durableButton.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, false));
+
+
+ Composite okCancelButtonsComp = _toolkit.createComposite(shell);
+ okCancelButtonsComp.setBackground(shell.getBackground());
+ okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
+ okCancelButtonsComp.setLayout(new GridLayout(2,false));
+
+ Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
+ okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+ Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
+ cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+
+ okButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ String name = nameText.getText();
+
+ if (name == null || name.length() == 0)
+ {
+ ViewUtility.popupErrorMessage("Create Exchange", "Please enter a valid name");
+ return;
+ }
+
+ int selectedTypeIndex = typeList.getSelectionIndex();
+
+ if (selectedTypeIndex == -1)
+ {
+ ViewUtility.popupErrorMessage("Create Exchange", "Please select an Exchange type");
+ return;
+ }
+
+ String type = typeList.getItem(selectedTypeIndex);
+
+ boolean durable = durableButton.getSelection();
+
+ shell.dispose();
+
+ try
+ {
+ _vhmb.createNewExchange(name, type, durable);
+
+ ViewUtility.operationResultFeedback(null, "Created Exchange", null);
+ try
+ {
+ //delay to allow mbean registration notification processing
+ Thread.sleep(250);
+ }
+ catch(InterruptedException ie)
+ {
+ //ignore
+ }
+ }
+ catch(Exception e5)
+ {
+ ViewUtility.operationFailedStatusBarMessage("Error creating Exchange");
+ MBeanUtility.handleException(_mbean, e5);
+ }
+
+ refresh(_mbean);
+ }
+ });
+
+ cancelButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ shell.dispose();
+ }
+ });
+
+ shell.setDefaultButton(okButton);
+ shell.pack();
+ ViewUtility.centerChildInParentShell(parent, shell);
+
+ shell.open();
+ }
+
+ private void deleteQueuesOrExchanges(Shell parent, final VhostOperations op)
+ {
+ Table table;
+ String windowTitle;
+ String dialogueMessage;
+ final String feedBackMessage;
+ final String failureFeedBackMessage;
+
+ if(op.equals(VhostOperations.DELETE_QUEUE))
+ {
+ table = _queueTable;
+ windowTitle = "Delete Queue(s)";
+ dialogueMessage = "Delete Queue(s): ";
+ feedBackMessage = "Queue(s) deleted";
+ failureFeedBackMessage = "Error deleting Queue(s)";
+ }
+ else
+ {
+ table = _exchangeTable;
+ windowTitle = "Delete Exchange(s)";
+ dialogueMessage = "Delete Exchange(s): ";
+ feedBackMessage = "Exchange(s) deleted";
+ failureFeedBackMessage = "Error deleting Exchange(s)";
+ }
+
+ int selectionIndex = table.getSelectionIndex();
+ if (selectionIndex == -1)
+ {
+ return;
+ }
+
+ int[] selectedIndices = table.getSelectionIndices();
+
+ final ArrayList<ManagedBean> selectedMBeans = new ArrayList<ManagedBean>();
+
+ for(int index = 0; index < selectedIndices.length ; index++)
+ {
+ ManagedBean selectedMBean = (ManagedBean)table.getItem(selectedIndices[index]).getData();
+ selectedMBeans.add(selectedMBean);
+ }
+
+
+ final Shell shell = ViewUtility.createModalDialogShell(parent, windowTitle);
+
+ _toolkit.createLabel(shell, dialogueMessage).setBackground(shell.getBackground());
+
+ final Text headerText = new Text(shell, SWT.WRAP | SWT.V_SCROLL | SWT.BORDER );
+ headerText.setEditable(false);
+ GridData data = new GridData(SWT.FILL, SWT.FILL, false, false);
+ data.minimumHeight = 150;
+ data.heightHint = 150;
+ data.minimumWidth = 400;
+ data.widthHint = 400;
+ headerText.setLayoutData(data);
+
+ String lineSeperator = System.getProperty("line.separator");
+ for(ManagedBean mbean : selectedMBeans)
+ {
+ headerText.append(mbean.getName() + lineSeperator);
+ }
+ headerText.setSelection(0);
+
+ Composite okCancelButtonsComp = _toolkit.createComposite(shell);
+ okCancelButtonsComp.setBackground(shell.getBackground());
+ okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true));
+ okCancelButtonsComp.setLayout(new GridLayout(2,false));
+
+ Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH);
+ okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+ Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH);
+ cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false));
+
+ okButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ shell.dispose();
+
+ try
+ {
+ //perform the deletes
+ for(ManagedBean mbean : selectedMBeans)
+ {
+ switch(op)
+ {
+ case DELETE_QUEUE:
+ _vhmb.deleteQueue(mbean.getName());
+ _serverRegistry.removeManagedObject(mbean);
+ break;
+ case DELETE_EXCHANGE:
+ _vhmb.unregisterExchange(mbean.getName());
+ break;
+ }
+ //remove the mbean from the server registry now instead of
+ //waiting for an mbean Unregistration Notification to do it
+ _serverRegistry.removeManagedObject(mbean);
+ }
+
+ ViewUtility.operationResultFeedback(null, feedBackMessage, null);
+ }
+ catch(Exception e1)
+ {
+ ViewUtility.operationFailedStatusBarMessage(failureFeedBackMessage);
+ MBeanUtility.handleException(_mbean, e1);
+ }
+
+ refresh(_mbean);;
+ }
+ });
+
+ cancelButton.addSelectionListener(new SelectionAdapter()
+ {
+ public void widgetSelected(SelectionEvent e)
+ {
+ shell.dispose();
+ }
+ });
+
+ shell.setDefaultButton(okButton);
+ shell.pack();
+ ViewUtility.centerChildInParentShell(parent, shell);
+
+ shell.open();
+ }
+
+ private enum VhostOperations
+ {
+ DELETE_QUEUE,
+ DELETE_EXCHANGE;
+ }
+
+ private void openMBean(Table table)
+ {
+ int selectionIndex = table.getSelectionIndex();
+
+ if (selectionIndex == -1)
+ {
+ return;
+ }
+
+ ManagedBean selectedMBean = (ManagedBean) table.getItem(selectionIndex).getData();
+
+ IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
+ MBeanView view = (MBeanView) window.getActivePage().findView(MBeanView.ID);
+ try
+ {
+ view.openMBean(selectedMBean);
+ }
+ catch (Exception ex)
+ {
+ MBeanUtility.handleException(selectedMBean, ex);
+ }
+ }
+}
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/.eclipseproduct b/qpid/java/management/eclipse-plugin/src/main/resources/.eclipseproduct
new file mode 100644
index 0000000000..28ee27ca17
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/.eclipseproduct
@@ -0,0 +1,23 @@
+#Eclipse Product File
+#Fri Nov 03 14:47:54 GMT 2006
+#
+# 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.
+#
+version=1.0-incubating-M2-SNAPSHOT
+name=Qpid Management Console
+id=org.apache.qpid.manager.gui.product
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/jmxremote.sasl-plugin/MANIFEST.MF b/qpid/java/management/eclipse-plugin/src/main/resources/jmxremote.sasl-plugin/MANIFEST.MF
new file mode 100644
index 0000000000..83c7c9f435
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/jmxremote.sasl-plugin/MANIFEST.MF
@@ -0,0 +1,20 @@
+Manifest-Version: 1.0
+Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
+Bundle-ManifestVersion: 2
+Bundle-Name: jmx sasl Plug-in
+Bundle-SymbolicName: jmxremote.sasl
+Bundle-Version: 1.0.1
+Bundle-ClassPath: jmxremote_optional.jar
+Export-Package: com.sun.jmx.remote.generic,
+ com.sun.jmx.remote.opt.internal,
+ com.sun.jmx.remote.opt.security,
+ com.sun.jmx.remote.opt.util,
+ com.sun.jmx.remote.profile.sasl,
+ com.sun.jmx.remote.profile.tls,
+ com.sun.jmx.remote.protocol.jmxmp,
+ com.sun.jmx.remote.socket,
+ javax.management.remote.generic,
+ javax.management.remote.jmxmp,
+ javax.management.remote.message
+Bundle-Vendor:
+Bundle-Localization: plugin
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/Configuration/config.ini b/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/Configuration/config.ini
new file mode 100644
index 0000000000..dc15366740
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/Configuration/config.ini
@@ -0,0 +1,49 @@
+###############################################################################
+# 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.defaultStartLevel=4
+osgi.bundles=jmxremote.sasl, \
+qpid-management-common, \
+org.apache.qpid.management.ui, \
+com.ibm.icu, \
+org.eclipse.core.commands, \
+org.eclipse.core.contenttype, \
+org.eclipse.core.databinding, \
+org.eclipse.core.expressions, \
+org.eclipse.core.jobs, \
+org.eclipse.core.runtime@start, \
+org.eclipse.core.runtime.compatibility.registry, \
+org.eclipse.equinox.app,org.eclipse.equinox.common, \
+org.eclipse.equinox.preferences, \
+org.eclipse.equinox.registry, \
+org.eclipse.help, \
+org.eclipse.jface, \
+org.eclipse.jface.databinding, \
+org.eclipse.swt, \
+org.eclipse.swt.gtk.linux.x86, \
+org.eclipse.ui, \
+org.eclipse.ui.forms, \
+org.eclipse.ui.workbench, \
+org.eclipse.equinox.launcher, \
+org.eclipse.equinox.launcher.gtk.linux.x86, \
+org.apache.commons.codec
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/libcairo-swt.so b/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/libcairo-swt.so
new file mode 100644
index 0000000000..b66f95814e
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/libcairo-swt.so
Binary files differ
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/qpidmc b/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/qpidmc
new file mode 100644
index 0000000000..0cc5c65455
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/qpidmc
Binary files differ
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/qpidmc.ini b/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/qpidmc.ini
new file mode 100644
index 0000000000..19ceb6f717
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86/qpidmc.ini
@@ -0,0 +1,37 @@
+###############################################################################
+# 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.
+###############################################################################
+
+-vmargs
+-Xms40m
+-Xmx256m
+-XX:MaxPermSize=256m
+-Dosgi.requiredJavaVersion=1.5
+-Declipse.consoleLog=true
+
+#===============================================
+# SSL trust store configuration options.
+#===============================================
+
+# Uncomment lines below to specify custom truststore for server SSL
+# certificate verification, eg when using self-signed server certs.
+#
+#-Djavax.net.ssl.trustStore=<path.to.truststore>
+#-Djavax.net.ssl.trustStorePassword=<truststore.password>
+
+
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/Configuration/config.ini b/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/Configuration/config.ini
new file mode 100644
index 0000000000..f437e830b5
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/Configuration/config.ini
@@ -0,0 +1,49 @@
+###############################################################################
+# 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.defaultStartLevel=4
+osgi.bundles=jmxremote.sasl, \
+qpid-management-common, \
+org.apache.qpid.management.ui, \
+com.ibm.icu, \
+org.eclipse.core.commands, \
+org.eclipse.core.contenttype, \
+org.eclipse.core.databinding, \
+org.eclipse.core.expressions, \
+org.eclipse.core.jobs, \
+org.eclipse.core.runtime@start, \
+org.eclipse.core.runtime.compatibility.registry, \
+org.eclipse.equinox.app,org.eclipse.equinox.common, \
+org.eclipse.equinox.preferences, \
+org.eclipse.equinox.registry, \
+org.eclipse.help, \
+org.eclipse.jface, \
+org.eclipse.jface.databinding, \
+org.eclipse.swt, \
+org.eclipse.swt.gtk.linux.x86_64, \
+org.eclipse.ui, \
+org.eclipse.ui.forms, \
+org.eclipse.ui.workbench, \
+org.eclipse.equinox.launcher, \
+org.eclipse.equinox.launcher.gtk.linux.x86_64, \
+org.apache.commons.codec
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/libcairo-swt.so b/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/libcairo-swt.so
new file mode 100644
index 0000000000..5734427fb8
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/libcairo-swt.so
Binary files differ
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/qpidmc b/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/qpidmc
new file mode 100644
index 0000000000..ff1f3a7507
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/qpidmc
Binary files differ
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/qpidmc.ini b/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/qpidmc.ini
new file mode 100644
index 0000000000..19ceb6f717
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/linux-gtk-x86_64/qpidmc.ini
@@ -0,0 +1,37 @@
+###############################################################################
+# 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.
+###############################################################################
+
+-vmargs
+-Xms40m
+-Xmx256m
+-XX:MaxPermSize=256m
+-Dosgi.requiredJavaVersion=1.5
+-Declipse.consoleLog=true
+
+#===============================================
+# SSL trust store configuration options.
+#===============================================
+
+# Uncomment lines below to specify custom truststore for server SSL
+# certificate verification, eg when using self-signed server certs.
+#
+#-Djavax.net.ssl.trustStore=<path.to.truststore>
+#-Djavax.net.ssl.trustStorePassword=<truststore.password>
+
+
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/macosx/Configuration/config.ini b/qpid/java/management/eclipse-plugin/src/main/resources/macosx/Configuration/config.ini
new file mode 100644
index 0000000000..3ac3aa20f3
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/macosx/Configuration/config.ini
@@ -0,0 +1,49 @@
+###############################################################################
+# 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.defaultStartLevel=4
+osgi.bundles=jmxremote.sasl, \
+qpid-management-common, \
+org.apache.qpid.management.ui, \
+com.ibm.icu, \
+org.eclipse.core.commands, \
+org.eclipse.core.contenttype, \
+org.eclipse.core.databinding, \
+org.eclipse.core.expressions, \
+org.eclipse.core.jobs, \
+org.eclipse.core.runtime@start, \
+org.eclipse.core.runtime.compatibility.registry, \
+org.eclipse.equinox.app,org.eclipse.equinox.common, \
+org.eclipse.equinox.preferences, \
+org.eclipse.equinox.registry, \
+org.eclipse.help, \
+org.eclipse.jface, \
+org.eclipse.jface.databinding, \
+org.eclipse.swt, \
+org.eclipse.swt.carbon.macosx, \
+org.eclipse.ui, \
+org.eclipse.ui.forms, \
+org.eclipse.ui.workbench, \
+org.eclipse.equinox.launcher, \
+org.eclipse.equinox.launcher.carbon.macosx, \
+org.apache.commons.codec
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/macosx/Contents/Info.plist b/qpid/java/management/eclipse-plugin/src/main/resources/macosx/Contents/Info.plist
new file mode 100644
index 0000000000..c6482a9254
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/macosx/Contents/Info.plist
@@ -0,0 +1,55 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<!--
+ -
+ - 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.
+ -
+ -->
+<plist version="1.0">
+<dict>
+ <key>CFBundleExecutable</key>
+ <string>qpidmc</string>
+ <key>CFBundleGetInfoString</key>
+ <string>Apache Qpid Management Console for Mac OS X</string>
+ <key>CFBundleIconFile</key>
+ <string>Console.icns</string>
+ <key>CFBundleIdentifier</key>
+ <string>org.apache.qpid.management.ui</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>Qpid Management Console</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>3.4</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>3.4</string>
+ <key>Qpid Management Console</key>
+ <array>
+ <string>-consoleLog</string>
+ <string>-showlocation</string>
+ <!-- WARNING:
+ If you try to add a single VM argument (-vmargs) here,
+ *all* vmargs specified in qpidmc.ini will be ignored.
+ We recommend to add all arguments in MacOS/qpidmc.ini -->
+ </array>
+</dict>
+</plist>
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/macosx/Contents/MacOS/qpidmc b/qpid/java/management/eclipse-plugin/src/main/resources/macosx/Contents/MacOS/qpidmc
new file mode 100755
index 0000000000..36247a08e4
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/macosx/Contents/MacOS/qpidmc
Binary files differ
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/macosx/Contents/MacOS/qpidmc.ini b/qpid/java/management/eclipse-plugin/src/main/resources/macosx/Contents/MacOS/qpidmc.ini
new file mode 100644
index 0000000000..2a31b9b2c7
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/macosx/Contents/MacOS/qpidmc.ini
@@ -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.
+###############################################################################
+
+-startup
+../../plugins/org.eclipse.equinox.launcher_1.0.101.R34x_v20080819.jar
+--launcher.library
+../../plugins/org.eclipse.equinox.launcher.carbon.macosx_1.0.101.R34x_v20080731
+-vmargs
+-XstartOnFirstThread
+-Xms40m
+-Xmx512m
+-XX:MaxPermSize=256m
+-Dosgi.requiredJavaVersion=1.5
+-Declipse.consoleLog=true
+-Dorg.eclipse.swt.internal.carbon.smallFonts
+
+#===============================================
+# SSL trust store configuration options.
+#===============================================
+
+# Uncomment lines below to specify custom truststore for server SSL
+# certificate verification, eg when using self-signed server certs.
+#
+#-Djavax.net.ssl.trustStore=<path.to.truststore>
+#-Djavax.net.ssl.trustStorePassword=<truststore.password>
+
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/macosx/Contents/Resources/Console.icns b/qpid/java/management/eclipse-plugin/src/main/resources/macosx/Contents/Resources/Console.icns
new file mode 100644
index 0000000000..610976efab
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/macosx/Contents/Resources/Console.icns
Binary files differ
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Configuration/config.ini b/qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Configuration/config.ini
new file mode 100644
index 0000000000..a99a8b3f7d
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Configuration/config.ini
@@ -0,0 +1,49 @@
+###############################################################################
+# 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.defaultStartLevel=4
+osgi.bundles=jmxremote.sasl, \
+qpid-management-common, \
+org.apache.qpid.management.ui, \
+com.ibm.icu, \
+org.eclipse.core.commands, \
+org.eclipse.core.contenttype, \
+org.eclipse.core.databinding, \
+org.eclipse.core.expressions, \
+org.eclipse.core.jobs, \
+org.eclipse.core.runtime@start, \
+org.eclipse.core.runtime.compatibility.registry, \
+org.eclipse.equinox.app,org.eclipse.equinox.common, \
+org.eclipse.equinox.preferences, \
+org.eclipse.equinox.registry, \
+org.eclipse.help, \
+org.eclipse.jface, \
+org.eclipse.jface.databinding, \
+org.eclipse.swt, \
+org.eclipse.swt.gtk.solaris.sparc, \
+org.eclipse.ui, \
+org.eclipse.ui.forms, \
+org.eclipse.ui.workbench, \
+org.eclipse.equinox.launcher, \
+org.eclipse.equinox.launcher.gtk.solaris.sparc, \
+org.apache.commons.codec
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.l.pm b/qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.l.pm
new file mode 100644
index 0000000000..995d7c9bb0
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.l.pm
@@ -0,0 +1,311 @@
+/* XPM */
+static char *ProductIcon48[] = {
+/* columns rows colors chars-per-pixel */
+"48 48 257 2",
+" c black",
+". c gray100",
+"X c #69695A5AE8E8",
+"o c #494949499191",
+"O c #CECE9292BFBF",
+"+ c #E7E7CACAE0E0",
+"@ c #C8C88C8CBBBB",
+"# c #C2C28A8ABABA",
+"$ c #EAEAD7D7E8E8",
+"% c #CFCFA9A9CCCC",
+"& c #D9D9BCBCD8D8",
+"* c #B6B68787B9B9",
+"= c #C3C39999C7C7",
+"- c #A7A77D7DB5B5",
+"; c #BDBDA3A3CDCD",
+": c #D8D8CACAE3E3",
+"> c #A8A88D8DC4C4",
+", c #92927575B2B2",
+"< c #87876C6CAAAA",
+"1 c #9A9A8383BABA",
+"2 c #7B7B6363A3A3",
+"3 c #666654549595",
+"4 c #73735F5FADAD",
+"5 c #626251519292",
+"6 c #7F7F7272A7A7",
+"7 c #6D6D5E5E9E9E",
+"8 c #64645454A9A9",
+"9 c #77776969B1B1",
+"0 c #49493E3E8282",
+"q c #7D7D7373B6B6",
+"w c #5B5B4E4EADAD",
+"e c #55554949BABA",
+"r c #56564949BABA",
+"t c #56564A4ABABA",
+"y c #56564949B9B9",
+"u c #55554949B8B8",
+"i c #4F4F4444ACAC",
+"p c #53534848B4B4",
+"a c #53534848B3B3",
+"s c #54544949B5B5",
+"d c #52524747B0B0",
+"f c #52524747AFAF",
+"g c #54544949B3B3",
+"h c #DEDEDCDCEEEE",
+"j c #3E3E36369898",
+"k c #43433B3B9F9F",
+"l c #33332C2C7777",
+"z c #42423A3A9C9C",
+"x c #4A4A4040A8A8",
+"c c #55554A4ABABA",
+"v c #55554A4AB9B9",
+"b c #54544949B7B7",
+"n c #52524848B1B1",
+"m c #51514747AEAE",
+"M c #4E4E4545A9A9",
+"N c #49494141A0A0",
+"B c #52524848AFAF",
+"V c #51514848AEAE",
+"C c #50504747ACAC",
+"Z c #4F4F4646AAAA",
+"A c #51514848ADAD",
+"S c #50504747ABAB",
+"D c #50504848ACAC",
+"F c #50504747A9A9",
+"G c #4E4E4646A7A7",
+"H c #4E4E4545A4A4",
+"J c #4D4D4545A4A4",
+"K c #4F4F4747A8A8",
+"L c #4E4E4646A5A5",
+"P c #4D4D4545A3A3",
+"I c #3B3B35357D7D",
+"U c #4E4E4646A3A3",
+"Y c #55554D4D9F9F",
+"T c #4A4A43438989",
+"R c #51514B4B9090",
+"E c #67676060A5A5",
+"W c #1D1D18186A6A",
+"Q c #272722227D7D",
+"! c #282823237D7D",
+"~ c #2B2B26268181",
+"^ c #33332C2C8989",
+"/ c #3B3B36368E8E",
+"( c #454540409797",
+") c #4D4D4646A4A4",
+"_ c #4C4C4545A1A1",
+"` c #4D4D4646A2A2",
+"' c #4B4B4545A0A0",
+"] c #4D4D4646A1A1",
+"[ c #4C4C45459F9F",
+"{ c #4B4B45459E9E",
+"} c #4A4A44449C9C",
+"| c #494944449898",
+" . c #484843439696",
+".. c #4A4A45459999",
+"X. c #4F4F4A4AA0A0",
+"o. c #68686363AAAA",
+"O. c #21211D1D7676",
+"+. c #242420207575",
+"@. c #2D2D2A2A7F7F",
+"#. c #2D2D2A2A7B7B",
+"$. c #3D3D39398F8F",
+"%. c #484844449696",
+"&. c #474743439393",
+"*. c #464643439191",
+"=. c #454542428E8E",
+"-. c #4D4D4A4A9C9C",
+";. c #57575454A3A3",
+":. c #5A5A58589797",
+">. c #5F5F5D5D9999",
+",. c #85858282C1C1",
+"<. c #95959292C9C9",
+"1. c #B8B8B6B6DCDC",
+"2. c #070705055353",
+"3. c #080807075555",
+"4. c #0A0A09095757",
+"5. c #0C0C0B0B5858",
+"6. c #0F0F0D0D5C5C",
+"7. c #10100F0F5C5C",
+"8. c #131311116464",
+"9. c #141413136060",
+"0. c #141413135F5F",
+"q. c #171715156767",
+"w. c #161615156262",
+"e. c #161615156161",
+"r. c #181817176464",
+"t. c #1A1A19196666",
+"y. c #1C1C1A1A6464",
+"u. c #1D1D1C1C6868",
+"i. c #1F1F1E1E6A6A",
+"p. c #222221216C6C",
+"a. c #242423236F6F",
+"s. c #272725257171",
+"d. c #272726267272",
+"f. c #272726267171",
+"g. c #292928287474",
+"h. c #2A2A29297474",
+"j. c #2C2C2B2B7777",
+"k. c #2F2F2E2E7C7C",
+"l. c #2E2E2D2D7979",
+"z. c #343433337E7E",
+"x. c #393937378686",
+"c. c #373736368181",
+"v. c #3A3A39398484",
+"b. c #3A3A39398383",
+"n. c #3D3D3B3B8686",
+"m. c #424241418C8C",
+"M. c #424241418B8B",
+"N. c #444442428B8B",
+"B. c #434341418989",
+"V. c #454544448E8E",
+"C. c #454544448D8D",
+"Z. c #424241418787",
+"A. c #434342428888",
+"S. c #444442428787",
+"D. c #424241418585",
+"F. c #414140408383",
+"G. c #484847479090",
+"H. c #434342428686",
+"J. c #4A4A49499393",
+"K. c #464645458A8A",
+"L. c #4D4D4C4C9595",
+"P. c #54545252A0A0",
+"I. c #50504F4F9898",
+"U. c #58585757A0A0",
+"Y. c #525250509393",
+"T. c #5B5B5959A2A2",
+"R. c #585857579F9F",
+"E. c #62626161A9A9",
+"W. c #64646363ACAC",
+"Q. c #6B6B6A6AB2B2",
+"!. c #6B6B6A6AB1B1",
+"~. c #75757474B8B8",
+"^. c #7F7F7D7DBDBD",
+"/. c #9C9C9B9BCFCF",
+"(. c #0B0B0B0B5858",
+"). c #0D0D0D0D5A5A",
+"_. c #111111115E5E",
+"`. c #131313136060",
+"'. c #212121216D6D",
+"]. c #242424246F6F",
+"[. c #2B2B2C2C7777",
+"{. c #2B2B2B2B7777",
+"}. c #2C2C2C2C7777",
+"|. c #2E2E2E2E7979",
+" X c #313131317C7C",
+".X c #313131317B7B",
+"XX c #343434347E7E",
+"oX c #3C3C3C3C8686",
+"OX c #3F3F3F3F8989",
+"+X c #414142428B8B",
+"@X c #424242428B8B",
+"#X c #474747479090",
+"$X c #414141418484",
+"%X c #404040408181",
+"&X c #4A4A4A4A9494",
+"*X c #4A4A4A4A9393",
+"=X c #4D4D4D4D9696",
+"-X c #4F4F4F4F9898",
+";X c #505050509898",
+":X c #525252529B9B",
+">X c #555555559E9E",
+",X c #555555559D9D",
+"<X c #57575858A0A0",
+"1X c #58585858A0A0",
+"2X c #575758589F9F",
+"3X c #575757579F9F",
+"4X c #5A5A5A5AA2A2",
+"5X c #5D5D5D5DA5A5",
+"6X c #5F5F5F5FA7A7",
+"7X c #61616262AAAA",
+"8X c #61616161A9A9",
+"9X c #61616262A9A9",
+"0X c #62626262AAAA",
+"qX c #64646464ACAC",
+"wX c #62626262A9A9",
+"eX c #64646464ABAB",
+"rX c #66666666AEAE",
+"tX c #66666666ADAD",
+"yX c #68686868B0B0",
+"uX c #69696969AFAF",
+"iX c #6D6D6D6DB4B4",
+"pX c #6F6F6F6FB5B5",
+"aX c #73737373BABA",
+"sX c #71717171B7B7",
+"dX c #76767676BCBC",
+"fX c #79797979BFBF",
+"gX c #77777777B9B9",
+"hX c #80808080C1C1",
+"jX c #8C8C8C8CC5C5",
+"kX c #90909090C9C9",
+"lX c #98989898CBCB",
+"zX c #A0A0A0A0CFCF",
+"xX c #A5A5A5A5D3D3",
+"cX c #ABABABABD6D6",
+"vX c #C4C4C4C4E3E3",
+"bX c #D1D1D1D1E9E9",
+"nX c #E5E5E5E5F3F3",
+"mX c #9F9FA0A0D1D1",
+"MX c #B6B6C5C5E5E5",
+"NX c #8E8EA6A6D6D6",
+"BX c #9090A7A7D7D7",
+"VX c #9191A9A9D7D7",
+"CX c #9595ABABD8D8",
+"ZX c #9999AFAFDADA",
+"AX c #9D9DB2B2DCDC",
+"SX c #A1A1B5B5DDDD",
+"DX c #A5A5B8B8DEDE",
+"FX c #A9A9BBBBE0E0",
+"GX c #ACACBDBDE1E1",
+"HX c #B0B0C1C1E3E3",
+"JX c #B4B4C4C4E4E4",
+"KX c #B8B8C7C7E5E5",
+"LX c #BBBBC9C9E6E6",
+"PX c #AEAEC0C0E2E2",
+"IX c #B2B2C3C3E3E3",
+"UX c gray100",
+"YX c None",
+/* pixels */
+"YXX X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X X YX",
+"X %X%X%XF.F.F.F.$XD.Z.Z.Z.B.B.B.N.N.=.=.=.*.*.*.&.&. . .| ....} } { { _ _ P P H G G G K S S C o ",
+"X %X%X%X%XF.F.$XD.D.Z.Z.B.A.B.N.N.N.=.=.=.*.*.&.&.%.%.%.| | ..} { { [ _ _ ` U J L G K F Z S C o ",
+"X %X%X%X%XF.F.F.D.D.H.Z.Z.A.B.N.N.N.C.=.=.*.*.&.&. . .%.| | ..} } { [ [ _ P P H G G K F S S C o ",
+"X %XF.%XF.F.$XF.$XZ.Z.Z.B.A.K.Y.7 , - - 1 1 ^.^.~.aX~.q 9 6XY { } { ' _ ] P P H L G K F Z S C o ",
+"X %XF.F.F.F.F.D.D.Z.Z.Z.K.:.1 ; % ; <.hXfXfXdXaXaXsXpXiX!.yXrXo.;.X.[ _ _ ` H H G K K F S S C o ",
+"X F.F.F.F.F.D.D.D.Z.H.Y.1 & & 1.cXmX/.kXfXdXaXaXsXpXiXQ.yXtXeXE.6X5XP.X._ ` J L G G K F Z S C o ",
+"X D.$XF.$XD.D.Z.Z.S.>.% + : vX1.1.cXmX/.dXaXaXsXpXiXQ.uXrXqX8X6X5XT.R.P.X.P ) H G K K S S S m o ",
+"X D.$XD.D.D.D.D.S.6 & $ h bXvXvX1.xX/.kXfXaXsXpXiXQ.yXrXW.E.6X5X4XU.,X:XI.-.` L G G K F Z C C o ",
+"X D.D.D.D.D.Z.H.6 & $ h h h bXvX1.cXmXkX,.dXpXiXQ.yXtXqXwX6X5XT.U.,X:XI.=X*X..` G K K Z S S m o ",
+"X Z.D.Z.H.Z.Z.7 & $ h h nXh bXvX1.cXmXkX,.gXiXQ.uXrXW.E.6X5X4XU.,X:X-XL.J.#XV. .P G F S S C m o ",
+"X Z.Z.Z.H.Z.R % + : bXh h h bXvX1.cX/.kXhX~.Q.yXrXqX9X6X5X4X2X,X:X;X=X*X#XV.M.OX( K Z S S C m o ",
+"X Z.Z.Z.A.A.* & & vXvXbXbXbXvXvX1.xXlXjX^.pXuXrXeXwX6X5X4XU.,X:X-XL.*XG.V.@XOXoXb.( Z S C C V o ",
+"X B.B.B.A.2 % % 1.1.vXvXvXvXvX1.cXzX<.,.gXiXrXW.E.6X5X4XU.,X:XI.=X*X#XV.@XOXn.b.c.x.N S S C m o ",
+"X B.B.B.S.* % ; xX1.1.1.1.1.cXcXzXlXjX^.pXrXeX7X6X5X4XR.,X:X-XL.J.#XV.@XOXn.b.c.XX X$.S C C m o ",
+"X N.N.N.2 O = /.mXxXcXcXcXcXxXzXlXjXhX~.uXeXE.6X5X4XU.,X:X-XL.J.#XV.M.OXn.v.c.z. X|.k.N D V f o ",
+"X N.N.N.- @ > kX<././.mXzXzXlX<.jXhXgXuXeXE.6X5X4X1X,X:XI.L.*X#XV.m.OXn.b.c.z. Xl.j.g./ C m V o ",
+"X N.N.R @ # ,.,.jXkXkX<.kXkXjX,.^.~.uXwXE.6X5X4X1X,X:XI.=XJ.#XC.M.OXn.v.c.z..X|.j.g.d.#.M m B o ",
+"X =.M.< @ * fXfXhXhX,.,.,.hX^.gXpXuXqX9X6X5X4XU.,X:XI.L.*XG.V.+XOXn.b.c.z..X|.[.g.d.a.p.z V B o ",
+"X =.N.- @ NXNXBXBXBXVXCXCXCXCXZXZXZXZXAXAXSXSXSXDXDXDXFXFXFXGXPXPXHXHXIXJXMXMXMXKXKXLXLXLXB d o ",
+"X =.=.* @ 1 dXdXaXaXsXpXiX!.yXrXeXwX6X5X4X<X,X:XI.=X*XG.V.M.OXn.v.c.XX.X|.j.g.d.a.p.i.u.@.f d o ",
+"X *.=.# @ ^.dXaXaXsXpXiXQ.yXrXeXwX6X5XT.U.,X:X-XL.&XG.C.m.OXoXv.c.z..X|.j.g.f.a.p.i.u.t.+.d d o ",
+"X *.*.@ @ NXNXNXBXVXVXCXCXCXCXZXZXZXZXAXAXAXSXSXDXDXDXFXFXGXGXPXPXHXHXJXJXJXMXKXKXKXLXLXLXd n o ",
+"X &.*.@ @ dXaXsXpXiXQ.yXtXeXE.6X5X4XU.>X:XI.L.*XG.V.m.OXoXv.c.z. X|.j.g.d.a.'.i.u.t.r.w.9.d n o ",
+"X &.&.@ @ ~.sXpXiXQ.yXtXW.E.6X5X4X1X,X:XI.=X*X#XC.m.OXn.b.c.z. X|.[.g.f.a.p.i.u.t.r.w.9.0.n a o ",
+"X &.&.@ @ NXNXBXBXVXVXVXCXCXCXZXZXZXZXAXAXSXSXSXDXDXDXFXFXGXGXPXPXHXIXIXJXMXMXKXKXKXLXLXLXn n o ",
+"X %. .# @ q iXQ.yXrXW.0X6X5X4XU.>X:XI.L.*X#XV.@XOXn.b.c.XX.X|.{.g.f.].'.i.u.t.r.w.0._.7.W n a o ",
+"X %. .* # , Q.yXtXeX7X6X5X4XU.,X:X-XL.*X#XV.@XOXn.b.c.XX Xl.{.g.d.a.p.i.u.t.r.e.0._.7.).+.a a o ",
+"X | | - # NXNXNXBXVXVXCXCXCXCXZXZXZXAXAXAXAXSXSXDXDXDXFXFXGXGXPXPXHXHXIXJXMXMXMXKXKXLXLXLXa a o ",
+"X | | < # - rXeX9X6X5X4XU.,X:X-XL.*X#XC.@XOXoXb.c.z. X|.j.h.s.a.'.i.u.t.r.w.9._.7.).5.4.j a p o ",
+"X | } Y # * 9 8X6X5X4X3X,X:XI.=X*XG.V.@XOXn.v.c.XX X|.j.g.f.a.p.i.u.t.r.e.0._.7.).5.4.q.i g p o ",
+"X } } | - # , 6X5X4XR.,X:XI.=X*XG.V.m.OXoXb.c.XX X|.j.g.f.a.p.i.u.t.r.e.9._.7.).5.4.3.~ a s s o ",
+"X } } } 4 # - E 4XU.>X:X-X=XJ.#XV.M.OXoXb.c.XX X|.{.h.d.a.'.i.u.t.r.e.9._.7.).5.4.3.6.z p s s o ",
+"X { { } } - # < U.,X:XI.=X*XG.V.+XOXoXb.c.z. X|.}.g.d.a.'.i.u.t.r.w.0._.7.).5.4.3.2.! g p s s o ",
+"X [ { ' [ 4 * - E :X;XL.J.#XV.m.OXoXb.c.z..X|.j.h.f.a.'.i.u.t.r.w.9._.6.).(.4.3.2.8.k p s s s o ",
+"X [ [ ' _ [ , * , ;XL.J.#XV.@XOXoXv.c.z..X|.{.g.f.a.p.i.u.t.r.w.`._.7.).(.4.3.2.2.^ s p s s s o ",
+"X _ _ _ _ P ] - * 2 *X#XV.m.OXn.v.c.XX X|.j.h.f.a.p.i.u.t.r.w.`._.7.).(.4.3.2.2.Q p s s s b u o ",
+"X ` ` ` ` ` ` 8 - - 7 V.@XOXoXv.c.XX.X|.j.g.d.a.'.i.u.t.r.w.0._.7.).5.4.3.2.2.O.x p s s s u u o ",
+"X P P ) P U U ) 8 - - 7 OXn.v.c.XX X|.j.h.f.a.p.i.u.t.r.w.0._.7.).5.4.3.2.2.O.x s s s s b u u o ",
+"X L L ) H ) L L L 8 1 - 7 b.c.z. X|.j.h.f.a.'.i.u.t.r.w.0._.7.).5.4.3.2.2.Q x p s s s b b u e o ",
+"X L G L G G G G G G G , * 2 T .Xl.j.h.f.a.p.i.u.t.r.e.0._.7.).5.4.3.2.8.^ p p s s s s u u e e o ",
+"X G G G G G G G K K M M 4 , , 3 I g.d.a.p.i.u.t.r.e.`._.7.).5.4.3.7.! k p s p s s s u u u e v o ",
+"X K G K K K K K K Z Z M F F 4 , < 3 I p.i.u.t.r.w.9._.7.).5.4.W ~ z a p p s s b s u u u e e e o ",
+"X F Z F F F F Z Z F F S S S S S w 9 < 2 5 0 l p.e.9.y.a.l ^ j i a p p p s s b b b u e v y r e o ",
+"X S Z Z S Z S Z S S S S S C C C A m d V f m B m B d d n d a a a p s p s s b u u u u e v e r t o ",
+"X S S S S S S S S S S C C C m m A V V B B B d d d n n a a a p p s p s s b u u u e e e c t r t o ",
+"X C C C C C C C C m C A m A m f V f f B d d d n n n a a a a s s s s s u b u u u u v t t r t t o ",
+"YXo o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o o YX"
+};
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.m.pm b/qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.m.pm
new file mode 100644
index 0000000000..e64aa0cc06
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.m.pm
@@ -0,0 +1,295 @@
+/* XPM */
+static char *ProductIcon32[] = {
+/* columns rows colors chars-per-pixel */
+"32 32 257 2",
+" c black",
+". c gray100",
+"X c #69695A5AE8E8",
+"o c #494949499191",
+"O c #E8E8CBCBE0E0",
+"+ c #DDDDB3B3D2D2",
+"@ c #F0F0DDDDEBEB",
+"# c #CDCD9191BEBE",
+"$ c #C8C88B8BBBBB",
+"% c #CACA9898C2C2",
+"& c #C3C38A8ABBBB",
+"* c #BABA8787B9B9",
+"= c #DCDCC4C4DEDE",
+"- c #C5C5A3A3CACA",
+"; c #ADAD8181B8B8",
+": c #A3A37A7AB5B5",
+"> c #E2E2D6D6E9E9",
+", c #B3B39A9AC4C4",
+"< c #EBEBE3E3F0F0",
+"1 c #C9C9B6B6D6D6",
+"2 c #96967676B8B8",
+"3 c #8C8C7171ABAB",
+"4 c #A4A49292BEBE",
+"5 c #7D7D6565A6A6",
+"6 c #83836D6DABAB",
+"7 c #9A9A8787C2C2",
+"8 c #7B7B6464B7B7",
+"9 c #5E5E50509191",
+"0 c #646457579A9A",
+"q c #85857B7BBEBE",
+"w c #7C7C7373B6B6",
+"e c #62625353D5D5",
+"r c #61615353D4D4",
+"t c #60605252D1D1",
+"y c #5F5F5252D0D0",
+"u c #5F5F5151CFCF",
+"i c #60605353D2D2",
+"p c #5F5F5252CFCF",
+"a c #5E5E5151CDCD",
+"s c #5C5C4F4FC7C7",
+"d c #5F5F5252CDCD",
+"f c #5E5E5151CBCB",
+"g c #5B5B4F4FC4C4",
+"h c #5A5A4E4EC1C1",
+"j c #71716969B0B0",
+"k c #48483E3EADAD",
+"l c #5D5D5151CDCD",
+"z c #5C5C5050C9C9",
+"x c #5D5D5151CBCB",
+"c c #5C5C5050C7C7",
+"v c #5B5B4F4FC6C6",
+"b c #5B5B5050C6C6",
+"n c #59594E4EC1C1",
+"m c #58584D4DBFBF",
+"M c #59594F4FC2C2",
+"N c #5A5A4F4FC2C2",
+"B c #58584D4DBCBC",
+"V c #57574D4DBCBC",
+"C c #59594E4EBEBE",
+"Z c #58584E4EBDBD",
+"A c #58584D4DBBBB",
+"S c #57574D4DBABA",
+"D c #56564D4DB9B9",
+"F c #56564C4CB6B6",
+"G c #55554C4CB6B6",
+"H c #54544B4BB4B4",
+"J c #54544B4BB1B1",
+"K c #53534B4BB1B1",
+"L c #52524A4AAEAE",
+"P c #51514949ACAC",
+"I c #51514949ABAB",
+"U c #474741418787",
+"Y c #32322C2C8F8F",
+"T c #2B2B25257777",
+"R c #36362F2F9696",
+"E c #2B2B26266E6E",
+"W c #4D4D4545ACAC",
+"Q c #55554D4DB8B8",
+"! c #54544C4CB4B4",
+"~ c #54544C4CB3B3",
+"^ c #51514A4AACAC",
+"/ c #51514A4AABAB",
+"( c #50504949A9A9",
+") c #4F4F4949A6A6",
+"_ c #4C4C4747A1A1",
+"` c #4E4E4848A3A3",
+"' c #4D4D4848A1A1",
+"] c #4B4B46469C9C",
+"[ c #4C4C47479E9E",
+"{ c #51514C4CA6A6",
+"} c #A9A9A6A6D5D5",
+"| c #1E1E1A1A6666",
+" . c #292925258181",
+".. c #3D3D39399292",
+"X. c #4A4A46469B9B",
+"o. c #53534E4EABAB",
+"O. c #494945459797",
+"+. c #4A4A46469999",
+"@. c #474744449494",
+"#. c #484845459494",
+"$. c #474744449292",
+"%. c #464643439090",
+"&. c #464642428D8D",
+"*. c #54545050A9A9",
+"=. c #474744448F8F",
+"-. c #4C4C49499999",
+";. c #57575454A6A6",
+":. c #5B5B5757AAAA",
+">. c #545451519B9B",
+",. c #5A5A57579C9C",
+"<. c #65656262A7A7",
+"1. c #68686666A2A2",
+"2. c #CACAC9C9E5E5",
+"3. c #050504045151",
+"4. c #080807075454",
+"5. c #0A0A09095858",
+"6. c #0C0C0A0A5858",
+"7. c #10100E0E6262",
+"8. c #0E0E0D0D5A5A",
+"9. c #121211115D5D",
+"0. c #131312125D5D",
+"q. c #161615156161",
+"w. c #171716166161",
+"e. c #1A1A19196565",
+"r. c #20201E1E7070",
+"t. c #1E1E1D1D6969",
+"y. c #2A2A29297676",
+"u. c #2F2F2D2D7676",
+"i. c #3A3A39398787",
+"p. c #3A3A39398383",
+"a. c #3F3F3E3E8888",
+"s. c #414140408989",
+"d. c #454543438D8D",
+"f. c #444442428B8B",
+"g. c #444443438C8C",
+"h. c #434342428A8A",
+"j. c #434341418888",
+"k. c #434342428989",
+"l. c #424241418787",
+"z. c #434342428787",
+"x. c #424241418585",
+"c. c #41413F3F8181",
+"v. c #414140408282",
+"b. c #484846468D8D",
+"n. c #494948489090",
+"m. c #4B4B4A4A9191",
+"M. c #4B4B49498E8E",
+"N. c #525251519A9A",
+"B. c #525251519999",
+"V. c #565654549A9A",
+"C. c #545453539494",
+"Z. c #60605F5FA7A7",
+"A. c #64646363ABAB",
+"S. c #5A5A59599797",
+"D. c #68686767ADAD",
+"F. c #6C6C6B6BB2B2",
+"G. c #5E5E5D5D9A9A",
+"H. c #76767575BABA",
+"J. c #78787777BBBB",
+"K. c #76767474B5B5",
+"L. c #7E7E7D7DBABA",
+"P. c #A5A5A4A4D2D2",
+"I. c #040404045252",
+"U. c #070707075454",
+"Y. c #070708085353",
+"T. c #080808085454",
+"R. c #0A0A0B0B5757",
+"E. c #0E0E0E0E5A5A",
+"W. c #111112125E5E",
+"Q. c #111111115E5E",
+"!. c #111111115D5D",
+"~. c #111112125D5D",
+"^. c #161616166868",
+"/. c #151516166161",
+"(. c #151515156161",
+"). c #19191A1A6565",
+"_. c #191919196565",
+"`. c #1A1A1A1A6464",
+"'. c #1D1D1E1E6969",
+"]. c #1E1E1E1E6969",
+"[. c #222222226D6D",
+"{. c #272727277171",
+"}. c #2B2B2C2C7676",
+"|. c #2B2B2B2B7676",
+" X c #2B2B2B2B7575",
+".X c #303030307A7A",
+"XX c #303030307979",
+"oX c #353535357F7F",
+"OX c #393939398383",
+"+X c #3A3A3A3A8383",
+"@X c #3F3F3F3F8787",
+"#X c #434343438C8C",
+"$X c #434344448C8C",
+"%X c #424242428686",
+"&X c #414141418484",
+"*X c #484848489191",
+"=X c #484849499090",
+"-X c #4D4D4D4D9696",
+";X c #515151519D9D",
+":X c #4D4D4D4D9595",
+">X c #515152529A9A",
+",X c #515152529999",
+"<X c #525252529A9A",
+"1X c #525252529999",
+"2X c #565657579E9E",
+"3X c #575757579D9D",
+"4X c #5B5B5B5BA2A2",
+"5X c #5F5F6060A6A6",
+"6X c #5F5F5F5FA6A6",
+"7X c #63636464AAAA",
+"8X c #64646464AAAA",
+"9X c #67676767AEAE",
+"0X c #67676868AEAE",
+"qX c #68686868AEAE",
+"wX c #6F6F6F6FB5B5",
+"eX c #6C6C6C6CB1B1",
+"rX c #73737373B8B8",
+"tX c #82828282BEBE",
+"yX c #86868686C2C2",
+"uX c #89898989C4C4",
+"iX c #98989898CBCB",
+"pX c #A0A0A0A0CFCF",
+"aX c #A9A9A9A9D5D5",
+"sX c #B0B0B0B0D8D8",
+"dX c #B8B8B8B8DDDD",
+"fX c #BDBDBDBDE0E0",
+"gX c #D9D9D9D9EDED",
+"hX c #90909191C6C6",
+"jX c #71718989BCBC",
+"kX c #73738B8BBFBF",
+"lX c #72728989BCBC",
+"zX c #79799090C3C3",
+"xX c #7E7E9595C7C7",
+"cX c #81819898CACA",
+"vX c #84849B9BCCCC",
+"bX c #8C8CA3A3D4D4",
+"nX c #71718A8ABCBC",
+"mX c #73738B8BBDBD",
+"MX c #75758D8DBFBF",
+"NX c #74748C8CBEBE",
+"BX c #76768E8EC0C0",
+"VX c #7C7C9494C6C6",
+"CX c #7B7B9393C4C4",
+"ZX c #7F7F9797C9C9",
+"AX c #82829A9ACBCB",
+"SX c #85859E9ECECE",
+"DX c #8888A0A0D1D1",
+"FX c #87879F9FD0D0",
+"GX c #8B8BA4A4D4D4",
+"HX c #8B8BA3A3D4D4",
+"JX c #8989A1A1D2D2",
+"KX c #8D8DA5A5D6D6",
+"LX c #8B8BA3A3D3D3",
+"PX c #8E8EA6A6D6D6",
+"IX c #8D8DA5A5D5D5",
+"UX c gray100",
+"YX c None",
+/* pixels */
+"YXX X X X X X X X X X X X X X X X X X X X X X X X X X X X X X YX",
+"X v.v.v.v.&Xl.z.k.&.d.%.$.@.O.+.] [ _ ` ) ( ^ L K ! G D V m m o ",
+"X c.c.c.v.&Xx.z.f.f.d.%.$.#.O.+.X.[ _ ` ) ( / L K H F D V C n o ",
+"X v.c.v.v.x.x.z.k.f.n.V.,.>.-.+.] [ _ ` ) ( ^ L K H G D V C h o ",
+"X &Xv.&Xx.x.l.j.M.1.4 - - , 7 q J.H.K.j :.*.P L K H F S B C n o ",
+"X x.&Xx.x.z.j.S., = = 1 } iXuXH.rXwXF.qX7XZ.;.o.J ! F S B m n o ",
+"X x.l.z.%Xz.G.1 @ > 2.dXaXiXuXrXwXF.qX8X5X4X2X;X{ H F S V C n o ",
+"X z.j.j.j.C.1 @ < gX2.fXaXpXuXwXeX9X7X5X4X2XN.:X*X_ D S Z m h o ",
+"X k.k.h.b., O > gXgX2.dXaXiXyXF.D.A.Z.4X3X1X:Xn.g.a._ V B m N o ",
+"X f.f.f.3 + = 2.2.2.fXsXpXhXtXD.8XZ.4X2X1X:X*X$X@Xp.i.W C n N o ",
+"X d.&.%.% + 1 dXdXdXsXP.iXyXK.8X5X4X2X>X:X*Xg.a.+XoX.X..m n N o ",
+"X %.=.5 % - P.} aXP.pXiXyXK.D.Z.4X3X1X-Xn.$X@X+XoX.X Xy.W h g o ",
+"X $.$.: # PXIXGXGXLXJXFXFXSXvXAXcXZXxXVXCXzXzXBXMXkXmXnXjXh g o ",
+"X #.@.* $ 7 yXuXyXtXL.K.D.6X4X2X1X:Xo g.a.OXoX.X|.{.[.t. .g v o ",
+"X O.#.$ $ q H.rXwXF.0XA.6X4X2X1X:Xo $Xa.p.oX.X|.{.[.'.`.r.g b o ",
+"X X.+.$ $ PXKXbXbXLXJXDXFXSXvXAXcXZXxXCXCXzXBXBXMXNXmXlXjXb c o ",
+"X ] ] $ $ H.wXF.0X7X6X4X2X<X:Xo #Xa.+XoX.X|.{.[.].)./.~.Q.c z o ",
+"X [ [ & & w F.qX7XZ.4X2X,X:Xo #Xa.+XoX.X}.{.[.'.e./.9.E.^.c z o ",
+"X ' _ * & PXKXbXHXLXJXDXSXSXvXAXcXZXxXVXCXzXzXBXMXNXkXjXjXz x o ",
+"X ` ` : & 2 8XZ.4X2XB.:X*Xg.@Xp.oX.X|.{.[.].).q.!.E.R.U.Y z f o ",
+"X ) ) 5 & ; <.4X2X>X:Xo #Xa.+XoXXX|.{.[.t._.q.~.E.R.4.5.k x a o ",
+"X ( ( I ; * 6 2X>X:X=X$X@X+XoX.X|.{.[.t.e./.W.E.R.Y.3. .z a a o ",
+"X I ^ / 8 * : 0 :X*X#X@X+XoX.X|.{.[.'._.(.~.E.R.T.3.7.k x a p o ",
+"X L L L ^ 2 * 3 m.$Xa.p.oX.X}.{.[.t.).(.~.E.6.T.3.I.R x a a y o ",
+"X J K K K K 2 * 5 s.OXoX.X}.{.[.'._.(.9.8.R.4.3.I.Y x l a p t o ",
+"X ~ H H ! ! ! 2 ; 5 U XX}.{.[.].e.(.W.E.R.U.3.7.R x l u u y t o ",
+"X G F G G G Q Q 8 : 3 9 u.[.]._./.Q.E.R.T.6. .k x a a u t t t o ",
+"X D S D S D S S S V 8 2 6 9 c.E w.0.| T Y k z z a a p t t i r o ",
+"X A V B V V V B B m m n n h h g g g c z z z l l d p y t i r r o ",
+"X m C C C C C C C n n n M N g g b c z z x a a a u y t t r r e o ",
+"X n n n n n h h h N N g g v b s z z z x a p p u t t r r r e e o ",
+"YXo o o o o o o o o o o o o o o o o o o o o o o o o o o o o o YX"
+};
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.s.pm b/qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.s.pm
new file mode 100644
index 0000000000..e2b9379f3a
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.s.pm
@@ -0,0 +1,287 @@
+/* XPM */
+static char *ProductIcon24[] = {
+/* columns rows colors chars-per-pixel */
+"24 24 257 2",
+" c black",
+". c gray100",
+"X c #69695A5AE8E8",
+"o c #494949499191",
+"O c #F1F1DFDFECEC",
+"+ c #D7D7ACACCDCD",
+"@ c #DFDFBBBBD6D6",
+"# c #E2E2C4C4DBDB",
+"$ c #CECE9C9CC4C4",
+"% c #C4C48B8BBABA",
+"& c #C2C28A8ABABA",
+"* c #C4C48E8EBCBC",
+"= c #BFBF8A8AB9B9",
+"- c #EBEBD9D9E9E9",
+"; c #BFBF8888B9B9",
+": c #D8D8B9B9D6D6",
+"> c #B9B98686B9B9",
+", c #B8B88989B9B9",
+"< c #BBBB9393BFBF",
+"1 c #A9A97B7BB2B2",
+"2 c #E4E4D4D4E7E7",
+"3 c #C6C6AFAFCECE",
+"4 c #A6A68080B6B6",
+"5 c #A2A27E7EB4B4",
+"6 c #9E9E7E7EB1B1",
+"7 c #ABAB9090BBBB",
+"8 c #B7B7A0A0C5C5",
+"9 c #9D9D7C7CB2B2",
+"0 c #AAAA8B8BBEBE",
+"q c #AAAA9090BCBC",
+"w c #8C8C6B6BABAB",
+"e c #90907070B1B1",
+"r c #C4C4B3B3D7D7",
+"t c #CDCDBFBFDDDD",
+"y c #EAEAE4E4F1F1",
+"u c #88886A6AADAD",
+"i c #9E9E8585C1C1",
+"p c #84846A6AAFAF",
+"a c #81816B6BAAAA",
+"s c #D7D7CFCFE6E6",
+"d c #81816969B1B1",
+"f c #78786363A5A5",
+"g c #6E6E5D5D9C9C",
+"h c #717160609D9D",
+"j c #83837474AAAA",
+"k c #6A6A5757A3A3",
+"l c #6E6E5E5EA0A0",
+"z c #5E5E50509292",
+"x c #88887B7BBCBC",
+"c c #68685858ABAB",
+"v c #5A5A4D4DA2A2",
+"b c #7D7D7373B4B4",
+"n c #5A5A4E4EA6A6",
+"m c #5F5F56569595",
+"M c #56564A4ABBBB",
+"N c #56564949B9B9",
+"B c #55554949B8B8",
+"V c #53534848B3B3",
+"C c #54544949B4B4",
+"Z c #52524747B0B0",
+"A c #52524747AFAF",
+"S c #5B5B53539393",
+"D c #3E3E36369797",
+"F c #49494040A6A6",
+"G c #48484040A5A5",
+"H c #55554A4ABABA",
+"J c #54544949B7B7",
+"K c #53534949B4B4",
+"L c #51514747AFAF",
+"P c #52524848B1B1",
+"I c #51514848B0B0",
+"U c #51514848AEAE",
+"Y c #51514747ADAD",
+"T c #51514848ADAD",
+"R c #4F4F4747ABAB",
+"E c #50504747ABAB",
+"W c #50504646A9A9",
+"Q c #4F4F4646A8A8",
+"! c #4E4E4646A7A7",
+"~ c #4E4E4545A4A4",
+"^ c #4D4D4545A4A4",
+"/ c #4E4E4646A5A5",
+"( c #4D4D4545A1A1",
+") c #3D3D36367E7E",
+"_ c #4B4B44449C9C",
+"` c #2A2A25257F7F",
+"' c #3E3E37379898",
+"] c #474740409C9C",
+"[ c #4D4D4646A4A4",
+"{ c #4C4C4545A2A2",
+"} c #4D4D4646A2A2",
+"| c #4D4D4646A1A1",
+" . c #4B4B45459F9F",
+".. c #4C4C45459F9F",
+"X. c #4C4C46469F9F",
+"o. c #4B4B45459D9D",
+"O. c #494943439898",
+"+. c #494944449A9A",
+"@. c #4A4A45459A9A",
+"#. c #494944449898",
+"$. c #484843439696",
+"%. c #494944449797",
+"&. c #484843439595",
+"*. c #51514C4CA1A1",
+"=. c #6B6B6767AEAE",
+"-. c #95959191C9C9",
+";. c #23231F1F7676",
+":. c #21211E1E7070",
+">. c #292925257F7F",
+",. c #252521217070",
+"<. c #242421216D6D",
+"1. c #2B2B27278080",
+"2. c #393935358C8C",
+"3. c #444440409494",
+"4. c #3B3B38388282",
+"5. c #474743439494",
+"6. c #484844449595",
+"7. c #474743439393",
+"8. c #474744449393",
+"9. c #464643439191",
+"0. c #454542428F8F",
+"q. c #4A4A47479898",
+"w. c #464643438F8F",
+"e. c #454542428D8D",
+"r. c #444441418B8B",
+"t. c #484844449191",
+"y. c #444441418989",
+"u. c #494946469090",
+"i. c #4C4C48489393",
+"p. c #51514E4E9E9E",
+"a. c #73737070B6B6",
+"s. c #77777474BBBB",
+"d. c #A0A09E9ED1D1",
+"f. c #D6D6D5D5EBEB",
+"g. c #0E0E0D0D5A5A",
+"h. c #11110F0F5E5E",
+"j. c #121211115E5E",
+"k. c #131312125F5F",
+"l. c #171716166363",
+"z. c #1D1D1B1B6868",
+"x. c #1D1D1C1C6868",
+"c. c #222221216E6E",
+"v. c #222221216D6D",
+"b. c #282827277474",
+"n. c #282827277373",
+"m. c #292928287373",
+"M. c #2F2F2E2E7979",
+"N. c #353534347F7F",
+"B. c #363635358181",
+"V. c #3C3C3B3B8585",
+"C. c #424241418C8C",
+"Z. c #424241418B8B",
+"A. c #444442428B8B",
+"S. c #434341418989",
+"D. c #434342428989",
+"F. c #424241418787",
+"G. c #414140408484",
+"H. c #474745458D8D",
+"J. c #434342428787",
+"K. c #424241418585",
+"L. c #414140408282",
+"P. c #494948489191",
+"I. c #4F4F4E4E9797",
+"U. c #59595757A6A6",
+"Y. c #5F5F5D5DA4A4",
+"T. c #6C6C6B6BB3B3",
+"R. c #7C7C7B7BB9B9",
+"E. c #A8A8A7A7D3D3",
+"W. c #0D0D0D0D5A5A",
+"Q. c #1F1F1F1F6C6C",
+"!. c #222222226E6E",
+"~. c #3B3B3B3B8585",
+"^. c #414141418C8C",
+"/. c #414141418B8B",
+"(. c #424242428B8B",
+"). c #484848489292",
+"_. c #404040408181",
+"`. c #4E4E4E4E9898",
+"'. c #555555559E9E",
+"]. c #555555559D9D",
+"[. c #5B5B5B5BA3A3",
+"{. c #5C5C5C5CA3A3",
+"}. c #61616161A9A9",
+"|. c #66666666AEAE",
+" X c #66666666ADAD",
+".X c #6B6B6B6BB2B2",
+"XX c #70707070B7B7",
+"oX c #6A6A6A6AADAD",
+"OX c #74747474BBBB",
+"+X c #89898989C2C2",
+"@X c #90909090C8C8",
+"#X c #8F8F8F8FC6C6",
+"$X c #92929292C6C6",
+"%X c #9F9F9F9FCFCF",
+"&X c #A5A5A5A5D2D2",
+"*X c #B5B5B5B5DBDB",
+"=X c #B8B8B8B8DEDE",
+"-X c #B7B7B7B7DCDC",
+";X c #BBBBBBBBDEDE",
+":X c #BDBDBDBDDFDF",
+">X c #C9C9C9C9E5E5",
+",X c #D1D1D1D1EAEA",
+"<X c #7C7C7D7DBABA",
+"1X c #89898A8AC7C7",
+"2X c #8F8F9090C7C7",
+"3X c #A3A3A4A4D3D3",
+"4X c #A2A2B5B5DEDE",
+"5X c #ADADBDBDE1E1",
+"6X c #B9B9C7C7E5E5",
+"7X c #BABAC8C8E6E6",
+"8X c #8E8EA6A6D6D6",
+"9X c #9090A7A7D7D7",
+"0X c #9191A9A9D7D7",
+"qX c #9292A9A9D8D8",
+"wX c #9494ABABD8D8",
+"eX c #9898AEAED9D9",
+"rX c #9B9BB0B0DADA",
+"tX c #9E9EB3B3DCDC",
+"yX c #A1A1B5B5DDDD",
+"uX c #A5A5B8B8DEDE",
+"iX c #A8A8BBBBE0E0",
+"pX c #ACACBEBEE1E1",
+"aX c #AFAFC0C0E3E3",
+"sX c #B3B3C3C3E4E4",
+"dX c #B2B2C2C2E3E3",
+"fX c #B5B5C5C5E5E5",
+"gX c #B8B8C7C7E6E6",
+"hX c #B6B6C5C5E4E4",
+"jX c #9797AEAED9D9",
+"kX c #A1A1B6B6DDDD",
+"lX c #A8A8BBBBDFDF",
+"zX c gray100",
+"xX c black",
+"cX c black",
+"vX c black",
+"bX c black",
+"nX c black",
+"mX c black",
+"MX c black",
+"NX c black",
+"BX c black",
+"VX c black",
+"CX c black",
+"ZX c black",
+"AX c black",
+"SX c black",
+"DX c black",
+"FX c black",
+"GX c black",
+"HX c black",
+"JX c black",
+"KX c black",
+"LX c black",
+"PX c black",
+"IX c black",
+"UX c black",
+"YX c None",
+/* pixels */
+"YXX X X X X X X X X X X X X X X X X X X X X X YX",
+"X _._.L.G.K.F.D.A.e.0.9.&.$.%.+._ ..{ ^ ! W E o ",
+"X L.L.L.G.F.F.D.r.e.0.9.7.&.O.@.o. .{ ~ ! Q E o ",
+"X L.G.G.K.F.S.y.r.e.w.9.5.$.+.@.o...( ~ ! W E o ",
+"X G.K.K.F.J.D.h 6 0 i x s.a.=.U.*...} ~ ! W E o ",
+"X K.F.F.F.S 7 : r d.1XOXXX.X|.}.[.p.| / ! W E o ",
+"X F.F.F.m 3 - s =X3X@XXXT. X}.[.].I.q.{ Q E T o ",
+"X S.D.H.8 O y ,X;X&X2X.X|.}.[.].I.P.C.3.Q E Y o ",
+"X A.r.j # 2 f.>X*X%X+X|.}.[.].I.P.^.~.B.] E Y o ",
+"X e.u.q @ t :X-XE.$X<X}.[.].`.P.Z.V.N.M.2.Y L o ",
+"X 0.i.< + 8X8XqXwXeXrXtX4XuXlXpXaXsXfXgX7XY A o ",
+"X 9.t.* $ -.#X+XR.oX{.'.`.P.(.~.N.M.m.c.Q.T Z o ",
+"X 8.7.; % 8X9X0XwXeXrXtXyXuXiXpXaXdXfXgX7XL Z o ",
+"X 6.&.1 & b X}.[.'.I.P./.~.N.M.n.!.x.l.:.I P o ",
+"X #.#.w = 8X9XqXwXjXrXtXkXuXiX5XaXsXhX6X7XP V o ",
+"X +.+.k > 5 Y.].I.)./.~.N.M.b.v.x.l.k.h.' V C o ",
+"X o.o.o.u , a I.).Z.V.N.M.n.c.z.l.j.W.` P V C o ",
+"X .. .X.v e 4 l ^.V.N.M.m.!.x.l.j.g.;.F V C J o ",
+"X ( | ( ( n p 9 g 4.M.n.c.x.l.j.h.>.G V K C J o ",
+"X ~ [ [ ^ / / c d f z ) <.z.,.1.D P V C C B B o ",
+"X ! Q ! Q Q Q Q W E E Y T A Z P V V K C J B B o ",
+"X Q W Q W R W E E T T T L Z P V V K J J J B N o ",
+"X R E E E E E Y Y U L Z P P P C V J J B B H M o ",
+"YXo o o o o o o o o o o o o o o o o o o o o o YX"
+};
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.t.pm b/qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.t.pm
new file mode 100644
index 0000000000..3f6b21f428
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/Qpidmc.t.pm
@@ -0,0 +1,279 @@
+/* XPM */
+static char *ProductIcon16[] = {
+/* columns rows colors chars-per-pixel */
+"16 16 257 2",
+" c black",
+". c gray100",
+"X c #E2E2C0C0D9D9",
+"o c #EDEDD9D9E8E8",
+"O c #D5D5ABABCDCD",
+"+ c #E2E2C3C3DCDC",
+"@ c #C5C58E8EBCBC",
+"# c #D4D4ABABCDCD",
+"$ c #CACA9F9FC6C6",
+"% c #D6D6B4B4D3D3",
+"& c #CACAA0A0C8C8",
+"* c #C6C69D9DC6C6",
+"= c #C5C59F9FC8C8",
+"- c #CCCCACACCECE",
+"; c #CCCCB0B0D3D3",
+": c #A6A68383B3B3",
+"> c #BABA9A9AC6C6",
+", c #B7B79A9AC2C2",
+"< c #E3E3D5D5E9E9",
+"1 c #B0B08E8EC0C0",
+"2 c #9F9F8080B8B8",
+"3 c #AFAF9898C1C1",
+"4 c #DBDBCFCFE5E5",
+"5 c #96967878B2B2",
+"6 c #9A9A7E7EBABA",
+"7 c #8E8E7878AFAF",
+"8 c #91917F7FBDBD",
+"9 c #D3D3CCCCE4E4",
+"0 c #535348488B8B",
+"q c #69695A5AE8E8",
+"w c #55554949B9B9",
+"e c #55554949B8B8",
+"r c #54544848B6B6",
+"t c #53534848B4B4",
+"y c #54544848B4B4",
+"u c #53534848B3B3",
+"i c #53534848B2B2",
+"p c #52524747AFAF",
+"a c #53534848B1B1",
+"s c #54544949B8B8",
+"d c #54544949B6B6",
+"f c #52524848B3B3",
+"g c #52524848B2B2",
+"h c #53534949B3B3",
+"j c #52524848B1B1",
+"k c #52524848B0B0",
+"l c #51514747AEAE",
+"z c #52524848AFAF",
+"x c #51514848AEAE",
+"c c #51514747ADAD",
+"v c #51514747ACAC",
+"b c #4F4F4646AAAA",
+"n c #51514848ADAD",
+"m c #50504747ABAB",
+"M c #50504747AAAA",
+"N c #4F4F4646A8A8",
+"B c #50504747A9A9",
+"V c #4E4E4646A7A7",
+"C c #4E4E4646A6A6",
+"Z c #4F4F4646A6A6",
+"A c #4F4F4747A7A7",
+"S c #4D4D4545A3A3",
+"D c #4D4D4545A2A2",
+"F c #4C4C45459E9E",
+"G c #74746E6EB3B3",
+"H c #2E2E29298383",
+"J c #383832329090",
+"K c #464640409999",
+"L c #4D4D4646A2A2",
+"P c #4E4E4747A3A3",
+"I c #4B4B45459F9F",
+"U c #4B4B45459E9E",
+"Y c #4C4C46469F9F",
+"T c #4A4A44449B9B",
+"R c #4A4A44449A9A",
+"E c #494943439797",
+"W c #494944449797",
+"Q c #484843439494",
+"! c #78787474B8B8",
+"~ c #272724247878",
+"^ c #2D2D2A2A7575",
+"/ c #484844449797",
+"( c #474743439393",
+") c #454542429090",
+"_ c #4B4B48489A9A",
+"` c #464643438F8F",
+"' c #464643438E8E",
+"] c #454542428C8C",
+"[ c #51514D4DA0A0",
+"{ c #5C5C5959A5A5",
+"} c #535350509090",
+"| c #C8C8C7C7E3E3",
+" . c #121211115D5D",
+".. c #1A1A19196565",
+"X. c #242422226D6D",
+"o. c #3F3F3E3E8888",
+"O. c #444442428D8D",
+"+. c #444442428989",
+"@. c #424241418787",
+"#. c #454543438A8A",
+"$. c #434342428888",
+"%. c #424241418686",
+"&. c #414140408484",
+"*. c #414140408383",
+"=. c #424240408383",
+"-. c #414140408282",
+";. c #474746468D8D",
+":. c #464644448989",
+">. c #525251519999",
+",. c #64646363AAAA",
+"<. c #61615F5FA2A2",
+"1. c #6E6E6C6CB2B2",
+"2. c #A5A5A4A4D3D3",
+"3. c #B0B0AFAFD6D6",
+"4. c #111112125D5D",
+"5. c #19191A1A6565",
+"6. c #1E1E1E1E6C6C",
+"7. c #222222226D6D",
+"8. c #2B2B2B2B7676",
+"9. c #2B2B2B2B7575",
+"0. c #2B2B2C2C7575",
+"q. c #343435357F7F",
+"w. c #343435357E7E",
+"e. c #353535357F7F",
+"r. c #3E3E3E3E8888",
+"t. c #3E3E3E3E8787",
+"y. c #414141418484",
+"u. c #404040408282",
+"i. c #484849499191",
+"p. c #494949499191",
+"a. c #484848489090",
+"s. c #484849499090",
+"d. c #404040408080",
+"f. c #525252529A9A",
+"g. c #525252529999",
+"h. c #5B5B5B5BA3A3",
+"j. c #5B5B5B5BA2A2",
+"k. c #64646464ABAB",
+"l. c #63636464AAAA",
+"z. c #6B6B6C6CB2B2",
+"x. c #72727373B9B9",
+"c. c #71717171A4A4",
+"v. c #78787878ABAB",
+"b. c #7F7F7F7FB1B1",
+"n. c #8C8C8C8CBEBE",
+"m. c #A5A5A5A5D2D2",
+"M. c #C9C9C9C9E5E5",
+"N. c #85858686B7B7",
+"B. c #91919292C4C4",
+"V. c #71718989BCBC",
+"C. c #73738B8BBEBE",
+"Z. c #75758D8DC0C0",
+"A. c #78789090C3C3",
+"S. c #7A7A9292C5C5",
+"D. c #71718A8ABDBD",
+"F. c #76768E8EC0C0",
+"G. c #78789090C2C2",
+"H. c #7B7B9393C5C5",
+"J. c #7D7D9595C7C7",
+"K. c #80809999CACA",
+"L. c #7E7E9696C7C7",
+"P. c #83839B9BCDCD",
+"I. c #83839B9BCCCC",
+"U. c #86869E9ECFCF",
+"Y. c #8888A1A1D1D1",
+"T. c #8A8AA2A2D3D3",
+"R. c #8989A1A1D1D1",
+"E. c #8B8BA3A3D3D3",
+"W. c gray100",
+"Q. c black",
+"!. c black",
+"~. c black",
+"^. c black",
+"/. c black",
+"(. c black",
+"). c black",
+"_. c black",
+"`. c black",
+"'. c black",
+"]. c black",
+"[. c black",
+"{. c black",
+"}. c black",
+"|. c black",
+" X c black",
+".X c black",
+"XX c black",
+"oX c black",
+"OX c black",
+"+X c black",
+"@X c black",
+"#X c black",
+"$X c black",
+"%X c black",
+"&X c black",
+"*X c black",
+"=X c black",
+"-X c black",
+";X c black",
+":X c black",
+">X c black",
+",X c black",
+"<X c black",
+"1X c black",
+"2X c black",
+"3X c black",
+"4X c black",
+"5X c black",
+"6X c black",
+"7X c black",
+"8X c black",
+"9X c black",
+"0X c black",
+"qX c black",
+"wX c black",
+"eX c black",
+"rX c black",
+"tX c black",
+"yX c black",
+"uX c black",
+"iX c black",
+"pX c black",
+"aX c black",
+"sX c black",
+"dX c black",
+"fX c black",
+"gX c black",
+"hX c black",
+"jX c black",
+"kX c black",
+"lX c black",
+"zX c black",
+"xX c black",
+"cX c black",
+"vX c black",
+"bX c black",
+"nX c black",
+"mX c black",
+"MX c black",
+"NX c black",
+"BX c black",
+"VX c black",
+"CX c black",
+"ZX c black",
+"AX c black",
+"SX c black",
+"DX c black",
+"FX c black",
+"GX c black",
+"HX c black",
+"JX c black",
+"KX c black",
+"LX c black",
+"PX c black",
+"IX c black",
+"UX c black",
+"YX c None",
+/* pixels */
+"YXq q q q q q q q q q q q q q YX",
+"q d.-.y.%.+.O.` ( E R U D C B p.",
+"q u.*.&.$.#.] ) Q W T F L V M p.",
+"q =.y.} , % ; 8 ! 1.{ [ S Z b p.",
+"q @.:.- o 4 2.x.z.,.j.>._ A m p.",
+"q +.: X < M.m.z.l.j.g.s.r.K v p.",
+"q ' $ + 9 | 3.B.n.N.b.v.c.<.n p.",
+"q ` O T.Y.U.P.K.L.S.G.F.C.D.l p.",
+"q ( # @ G k.h.g.i.t.e.9.7.6.z p.",
+"q / * E.R.U.I.K.J.H.A.Z.C.V.a p.",
+"q T 2 & 5 f.a.o.q.8.7...4.J u p.",
+"q I Y 1 = 7 ;.w.0.7.5. .H f y p.",
+"q L D P 6 > 3 0 ^ X.~ J i t d p.",
+"q C C V A N M m n p k g y r e p.",
+"q M b M m m c x p j h y d s w p.",
+"YXp.p.p.p.p.p.p.p.p.p.p.p.p.p.YX"
+};
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/qpidmc b/qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/qpidmc
new file mode 100755
index 0000000000..b88ff49e8e
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/qpidmc
Binary files differ
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/qpidmc.ini b/qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/qpidmc.ini
new file mode 100644
index 0000000000..cfa715e5a8
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/solaris-gtk-sparc/qpidmc.ini
@@ -0,0 +1,40 @@
+###############################################################################
+# 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.
+###############################################################################
+-startup
+plugins/org.eclipse.equinox.launcher_1.0.101.R34x_v20080819.jar
+--launcher.library
+plugins/org.eclipse.equinox.launcher.gtk.solaris.sparc_1.0.101.R34x_v20080731
+-vmargs
+-Xms40m
+-Xmx256m
+-XX:MaxPermSize=256m
+-Dosgi.requiredJavaVersion=1.5
+-Declipse.consoleLog=true
+
+#===============================================
+# SSL trust store configuration options.
+#===============================================
+
+# Uncomment lines below to specify custom truststore for server SSL
+# certificate verification, eg when using self-signed server certs.
+#
+#-Djavax.net.ssl.trustStore=<path.to.truststore>
+#-Djavax.net.ssl.trustStorePassword=<truststore.password>
+
+
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/Configuration/config.ini b/qpid/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/Configuration/config.ini
new file mode 100644
index 0000000000..a61bea2fa8
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/Configuration/config.ini
@@ -0,0 +1,49 @@
+###############################################################################
+# 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.defaultStartLevel=4
+osgi.bundles=jmxremote.sasl, \
+qpid-management-common, \
+org.apache.qpid.management.ui, \
+com.ibm.icu, \
+org.eclipse.core.commands, \
+org.eclipse.core.contenttype, \
+org.eclipse.core.databinding, \
+org.eclipse.core.expressions, \
+org.eclipse.core.jobs, \
+org.eclipse.core.runtime@start, \
+org.eclipse.core.runtime.compatibility.registry, \
+org.eclipse.equinox.app,org.eclipse.equinox.common, \
+org.eclipse.equinox.preferences, \
+org.eclipse.equinox.registry, \
+org.eclipse.help, \
+org.eclipse.jface, \
+org.eclipse.jface.databinding, \
+org.eclipse.swt, \
+org.eclipse.swt.win32.win32.x86, \
+org.eclipse.ui, \
+org.eclipse.ui.forms, \
+org.eclipse.ui.workbench, \
+org.eclipse.equinox.launcher, \
+org.eclipse.equinox.launcher.win32.win32.x86, \
+org.apache.commons.codec
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.exe b/qpid/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.exe
new file mode 100644
index 0000000000..3999884bfb
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.exe
Binary files differ
diff --git a/qpid/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.ini b/qpid/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.ini
new file mode 100644
index 0000000000..312580769e
--- /dev/null
+++ b/qpid/java/management/eclipse-plugin/src/main/resources/win32-win32-x86/qpidmc.ini
@@ -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.
+###############################################################################
+
+-vmargs
+-Xms40m
+-Xmx256m
+-XX:MaxPermSize=256m
+-Dosgi.requiredJavaVersion=1.5
+-Declipse.consoleLog=true
+
+#===============================================
+# SSL trust store configuration options.
+#===============================================
+
+# Uncomment lines below to specify custom truststore for server SSL
+# certificate verification, eg when using self-signed server certs.
+#
+#-Djavax.net.ssl.trustStore=<path.to.truststore>
+#-Djavax.net.ssl.trustStorePassword=<truststore.password>
+