diff options
author | Robert Godfrey <rgodfrey@apache.org> | 2009-10-05 10:29:26 +0000 |
---|---|---|
committer | Robert Godfrey <rgodfrey@apache.org> | 2009-10-05 10:29:26 +0000 |
commit | 8de1fa8dc5fd1ad3e1efd464320f2fd019bdbef4 (patch) | |
tree | cf51f96eb23c45a827222b13753411796d65c865 | |
parent | cd4111bf751210e9e5009d9c5452126e6039a4b4 (diff) | |
download | qpid-python-8de1fa8dc5fd1ad3e1efd464320f2fd019bdbef4.tar.gz |
Merged from trunk up to r797511
git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/java-broker-0-10@821741 13f79535-47bb-0310-9956-ffa450edef68
34 files changed, 2087 insertions, 449 deletions
diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java index d7583d9c59..306dce1057 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/AMQBrokerManagerMBean.java @@ -39,6 +39,8 @@ package org.apache.qpid.server; import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; import javax.management.JMException; import javax.management.MBeanException; @@ -75,7 +77,7 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr private final MessageStore _messageStore; private final VirtualHost.VirtualHostMBean _virtualHostMBean; - + @MBeanConstructor("Creates the Broker Manager MBean") public AMQBrokerManagerMBean(VirtualHost.VirtualHostMBean virtualHostMBean) throws JMException { @@ -112,6 +114,29 @@ public class AMQBrokerManagerMBean extends AMQManagedObject implements ManagedBr } /** + * Returns a Map keyed by QueueName, detailing its associated QueueDepth in bytes. + * @since Qpid JMX API 1.3 + * @throws IOException + */ + public Map<String,Long> viewQueueNamesDepths() throws IOException + { + Map<String,Long> queueDepthMap = new HashMap<String,Long>(_queueRegistry.getQueues().size()); + + String queueName; + Long queueDepth; + + for(AMQQueue queue : _queueRegistry.getQueues()) + { + queueName = queue.getName().toString(); + queueDepth = queue.getQueueDepth(); + + queueDepthMap.put(queueName,queueDepth); + } + + return queueDepthMap; + } + + /** * Creates new exchange and registers it with the registry. * * @param exchangeName diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java index 2a037782eb..b1855e0a40 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/exchange/FanoutExchange.java @@ -59,6 +59,8 @@ public class FanoutExchange extends AbstractExchange @MBeanDescription("Management Bean for Fanout Exchange") private final class FanoutExchangeMBean extends ExchangeMBean { + private static final String BINDING_KEY_SUBSTITUTE = "*"; + @MBeanConstructor("Creates an MBean for AMQ fanout exchange") public FanoutExchangeMBean() throws JMException { @@ -71,15 +73,23 @@ public class FanoutExchange extends AbstractExchange { _bindingList = new TabularDataSupport(_bindinglistDataType); + + if(_queues.isEmpty()) + { + return _bindingList; + } + + ArrayList<String> queueNames = new ArrayList<String>(); for (AMQQueue queue : _queues) { String queueName = queue.getName().toString(); - - Object[] bindingItemValues = {queueName, new String[]{queueName}}; - CompositeData bindingData = new CompositeDataSupport(_bindingDataType, COMPOSITE_ITEM_NAMES, bindingItemValues); - _bindingList.put(bindingData); + queueNames.add(queueName); } + + Object[] bindingItemValues = {BINDING_KEY_SUBSTITUTE, queueNames.toArray(new String[0])}; + CompositeData bindingData = new CompositeDataSupport(_bindingDataType, COMPOSITE_ITEM_NAMES, bindingItemValues); + _bindingList.put(bindingData); return _bindingList; } @@ -94,7 +104,7 @@ public class FanoutExchange extends AbstractExchange try { - queue.bind(FanoutExchange.this, new AMQShortString(binding), null); + queue.bind(FanoutExchange.this, new AMQShortString(BINDING_KEY_SUBSTITUTE), null); } catch (AMQException ex) { diff --git a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/LogMessages_en_US.properties b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/LogMessages_en_US.properties index d393614191..8e9ee3720c 100644 --- a/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/LogMessages_en_US.properties +++ b/qpid/java/broker/src/main/java/org/apache/qpid/server/logging/messages/LogMessages_en_US.properties @@ -1,13 +1,198 @@ +# +# 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. +# +# LogMessages used within the Java Broker as originally defined on the wiki: +# +# http://cwiki.apache.org/confluence/display/qpid/Status+Update+Design#StatusUpdateDesign-InitialStatusMessages +# +# Technical Notes: +# This is a standard Java Properties file so white space is respected at the +# end of the lines. This file is processed in a number of ways. +# 1) ResourceBundle +# This file is loaded through a ResourceBundle named LogMessages. the en_US +# addition to the file is the localisation. Additional localisations can be +# provided and will automatically be selected based on the <locale> value in +# the config.xml. The default is en_US. +# +# 2) MessasgeFormat +# Each entry is prepared with the Java Core MessageFormat methods. Therefore +# most functionality you can do via MessageFormat can be done here: +# +# http://java.sun.com/javase/6/docs/api/java/text/MessageFormat.html +# +# The cavet here is that only default String and number FormatTypes can be used. +# This is due to the processing described in 3 below. If support for date, time +# or choice is requried then the GenerateLogMessages class should be updated to +# provide support. +# +# Format Note: +# As mentioned earlier white space in this file is very important. One thing +# in particular to note is the way MessageFormat peforms its replacements. +# The replacement text will totally replace the {xxx} section so there will be +# no addtion of white space or removal e.g. +# MSG = Text----{0}---- +# When given parameter 'Hello' result in text: +# Text----Hello---- +# +# For simple arguments this is expected however when using Style formats then +# it can be a little unexepcted. In particular a common pattern is used for +# number replacements : {0,number,#}. This is used in the Broker to display an +# Integer simply as the Integer with no formating. e.g new Integer(1234567) +# becomes the String "1234567" which is can be contrasted with the pattern +# without a style format field : {0,number} which becomes string "1,234,567". +# +# What you may not expect is that {0,number, #} would produce the String " 1234567" +# note the space after the ',' here /\ has resulted in a space /\ in +# the output. +# +# More details on the SubformatPattern can be found on the API link above. +# +# 3) GenerateLogMessage/Velocity Macro +# This is the first and final stage of processing that this file goes through. +# 1) Class Generation: +# The GenerateLogMessage processes this file and uses the velocity Macro +# to create classes with static methods to perform the logging and give us +# compile time validation. +# +# 2) Property Processing: +# During the class generation the message properties ({x}) are identified +# and used to create the method signature. +# +# 3) Option Processing: +# The Classes perform final formatting of the messages at runtime based on +# optional parameters that are defined within the message. Optional +# paramters are enclosed in square brackets e.g. [optional]. +# +# To provide fixed log messages as required by the Technical Specification: +# http://cwiki.apache.org/confluence/display/qpid/Operational+Logging+-+Status+Update+-+Technical+Specification#OperationalLogging-StatusUpdate-TechnicalSpecification-Howtoprovidefixedlogmessages +# +# This file is processed by Velocity to create a number of classes that contain +# static methods that provide LogMessages in the code to provide compile time +# validation. +# +# For details of what processing is done see GenerateLogMessages. +# +# What a localiser or developer need know is the following: +# +# The Property structure is important is it defines how the class and methods +# will be built. +# +# Class Generation: +# ================= +# +# Each class of messages will be split in to their own <Class>Messages.java +# Currently the following classes are created and are populated with the +# messages that bear their 3-digit type identifier: +# +# Class | Type +# ---------------------|-------- +# Broker | BKR +# ManagementConsole | MNG +# VirtualHost | VHT +# MessageStore | MST +# Connection | CON +# Channel | CHN +# Queue | QUE +# Exchange | EXH +# Binding | BND +# Subscription | SUB +# +# Property Processing: +# ==================== +# +# Each property is then processed by the GenerateLogMessages class to identify +# The number and type of parameters, {x} entries. Parameters are defaulted to +# String types but the use of FormatType number (e.g.{0,number}) will result +# in a Number type being used. These parameters are then used to build the +# method parameter list. e.g: +# Property: +# BRK-1003 = Shuting down : {0} port {1,number,#} +# becomes Method: +# public static LogMessage BRK_1003(String param1, Number param2) +# +# This improves our compile time validation of log message content and +# ensures that change in the message format does not accidentally cause +# erroneous messages. +# +# Option Processing: +# ==================== +# +# Options are identified in the log message as being surrounded by square +# brackets ([ ]). These optional values can themselves contain paramters +# however nesting of options is not permitted. Identification is performed on +# first matchings so give the message: +# Msg = Log Message [option1] [option2] +# Two options will be identifed and enabled to select text 'option1 and +# 'option2'. +# +# The nesting of a options is not supported and will provide +# unexpected results. e.g. Using Message: +# Msg = Log Message [option1 [sub-option2]] +# +# The options will be 'option1 [sub-option2' and 'sub-option2'. The first +# option includes the second option as the nesting is not detected. +# +# The detected options are presented in the method signature as boolean options +# numerically identified by their position in the message. e.g. +# Property: +# CON-1001 = Open : Client ID {0} [: Protocol Version : {1}] +# becomes Method: +# public static LogMessage CON_1001(String param1, String param2, boolean opt1) +# +# The value of 'opt1' will show/hide the option in the message. Note that +# 'param2' is still required however a null value can be used if the optional +# section is not desired. +# +# Again here the importance of white space needs to be highlighted. +# Looking at the QUE-1001 message as an example. The first thought on how this +# would look would be as follows: +# QUE-1001 = Create : Owner: {0} [AutoDelete] [Durable] [Transient] [Priority: {1,number,#}] +# Each option is correctly defined so the text that is defined will appear when +# selected. e.g. 'AutoDelete'. However, what may not be immediately apparent is +# the white space. Using the above definition of QUE-1001 if we were to print +# the message with only the Priority option displayed it would appear as this: +# "Create : Owner: guest Priority: 1" +# Note the spaces here /\ This is because only the text between the brackets +# has been removed. +# +# Each option needs to include white space to correctly format the message. So +# the correct definition of QUE-1001 is as follows: +# QUE-1001 = Create : Owner: {0}[ AutoDelete][ Durable][ Transient][ Priority: {1,number,#}] +# Note that white space is included with each option and there is no extra +# white space between the options. As a result the output with just Priority +# enabled is as follows: +# "Create : Owner: guest Priority: 1" +# +# The final processing that is done in the generation is the conversion of the +# property name. As a '-' is an illegal character in the method name it is +# converted to '_' This processing gives the final method signature as follows: +# <Class>Message.<Type>_<Number>(<parmaters>,<options>) +# #Broker # 0 - Version # 1 = Build BRK-1001 = Startup : Version: {0} Build: {1} # 0 - Transport # 1 - Port -BRK-1002 = Starting : Listening on {0} port {1, number, #} +BRK-1002 = Starting : Listening on {0} port {1,number,#} # 0 - Transport # 1 - Port -BRK-1003 = Shuting down : {0} port {1, number, #} +BRK-1003 = Shuting down : {0} port {1,number,#} BRK-1004 = Ready BRK-1005 = Stopped # 0 - path @@ -19,10 +204,10 @@ BRK-1007 = Using logging configuration : {0} MNG-1001 = Startup # 0 - Service # 1 - Port -MNG-1002 = Starting : {0} : Listening on port {1, number, #} +MNG-1002 = Starting : {0} : Listening on port {1,number,#} # 0 - Service # 1 - Port -MNG-1003 = Shuting down : {0} : port {1, number, #} +MNG-1003 = Shuting down : {0} : port {1,number,#} MNG-1004 = Ready MNG-1005 = Stopped # 0 - Path @@ -39,20 +224,18 @@ MST-1001 = Created : {0} # 0 - path MST-1002 = Store location : {0} MST-1003 = Closed -MST-1004 = Recovery Start # 0 - queue name -MST-1005 = Recovery Start : {0} +MST-1004 = Recovery Start[ : {0}] # 0 - count # 1 - queue count -MST-1006 = Recovered {0,number} messages for queue {1} -MST-1007 = Recovery Complete +MST-1005 = Recovered {0,number} messages for queue {1} # 0 - queue name -MST-1008 = Recovery Complete : {0} +MST-1006 = Recovery Complete[ : {0}] #Connection # 0 - Client id # 1 - Protocol Version -CON-1001 = Open : Client ID {0} : Protocol Version : {1} +CON-1001 = Open : Client ID {0}[ : Protocol Version : {1}] CON-1002 = Close #Channel @@ -64,19 +247,20 @@ CHN-1003 = Close #Queue # 0 - owner -QUE-1001 = Create : Owner:{0} [AutoDelete] [Durable|Transient] [Priority:<levels>] +# 1 - priority +QUE-1001 = Create : Owner: {0}[ AutoDelete][ Durable][ Transient][ Priority: {1,number,#}] QUE-1002 = Deleted #Exchange # 0 - type # 1 - name -EXH-1001 = Create : [Durable] Type:{0} Name:{1} +EXH-1001 = Create :[ Durable] Type: {0} Name: {1} EXH-1002 = Deleted #Binding -BND-1001 = Create [: Arguments : <key=value>] +BND-1001 = Create[ : Arguments : {0}] BND-1002 = Deleted #Subscription -SUB-1001 = Create : [Durable] [Arguments : <key=value>] +SUB-1001 = Create[ : Durable][ : Arguments : {0}] SUB-1002 = Close diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/AbstractTestMessages.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/AbstractTestMessages.java index 6589695146..17a9d6c591 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/AbstractTestMessages.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/AbstractTestMessages.java @@ -81,24 +81,35 @@ public abstract class AbstractTestMessages extends TestCase { assertEquals("Log has incorrect message count", 1, logs.size()); - String log = String.valueOf(logs.get(0)); + //We trim() here as we don't care about extra white space at the end of the log message + // but we do care about the ability to easily check we don't have unexpected text at + // the end. + String log = String.valueOf(logs.get(0)).trim(); - int index = log.indexOf(_logSubject.toString()); + // Simple switch to print out all the logged messages + //System.err.println(log); - assertTrue("Unable to locate Subject:" + log, index != -1); + int msgIndex = log.indexOf(_logSubject.toString())+_logSubject.toString().length(); - String message = log.substring(index + _logSubject.toString().length()); + assertTrue("Unable to locate Subject:" + log, msgIndex != -1); + + String message = log.substring(msgIndex); assertTrue("Message does not start with tag:" + tag + ":" + message, message.startsWith(tag)); // Test that the expected items occur in order. - index = 0; + int index = 0; for (String text : expected) { index = message.indexOf(text, index); assertTrue("Message does not contain expected (" + text + ") text :" + message, index != -1); + index = index + text.length(); } + + //Check there is nothing left on the log message + assertEquals("Message has more text. '" + log.substring(msgIndex + index) + "'", + log.length(), msgIndex + index); } } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/BindingMessagesTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/BindingMessagesTest.java index a12d14239d..b2182bb1b2 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/BindingMessagesTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/BindingMessagesTest.java @@ -25,9 +25,9 @@ import java.util.List; public class BindingMessagesTest extends AbstractTestMessages { - public void testMessage1001() + public void testMessage1001_NoArgs() { - _logMessage = BindingMessages.BND_1001(); + _logMessage = BindingMessages.BND_1001(null, false); List<Object> log = performLog(); String[] expected = {"Create"}; @@ -35,6 +35,18 @@ public class BindingMessagesTest extends AbstractTestMessages validateLogMessage(log, "BND-1001", expected); } + public void testMessage1001_Args() + { + String arguments = "arguments"; + + _logMessage = BindingMessages.BND_1001(arguments, true); + List<Object> log = performLog(); + + String[] expected = {"Create", ": Arguments :", arguments}; + + validateLogMessage(log, "BND-1001", expected); + } + public void testMessage1002() { _logMessage = BindingMessages.BND_1002(); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ConnectionMessagesTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ConnectionMessagesTest.java index 8723c48476..eb76029a5c 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ConnectionMessagesTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ConnectionMessagesTest.java @@ -24,12 +24,12 @@ import java.util.List; public class ConnectionMessagesTest extends AbstractTestMessages { - public void testMessage1001() + public void testMessage1001_WithProtocolVersion() { String clientID = "client"; String protocolVersion = "8-0"; - _logMessage = ConnectionMessages.CON_1001(clientID, protocolVersion); + _logMessage = ConnectionMessages.CON_1001(clientID, protocolVersion, true); List<Object> log = performLog(); String[] expected = {"Open :", "Client ID", clientID, @@ -38,6 +38,19 @@ public class ConnectionMessagesTest extends AbstractTestMessages validateLogMessage(log, "CON-1001", expected); } + public void testMessage1001_NoProtocolVersion() + { + String clientID = "client"; + + _logMessage = ConnectionMessages.CON_1001(clientID, null, false); + List<Object> log = performLog(); + + String[] expected = {"Open :", "Client ID", clientID}; + + validateLogMessage(log, "CON-1001", expected); + } + + public void testMessage1002() { _logMessage = ConnectionMessages.CON_1002(); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ExchangeMessagesTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ExchangeMessagesTest.java index 46a911fdc6..831ede3e0c 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ExchangeMessagesTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/ExchangeMessagesTest.java @@ -27,7 +27,7 @@ import java.util.List; public class ExchangeMessagesTest extends AbstractTestMessages { - public void testMessage1001() + public void testMessage1001_Transient() { // Get the Default Exchange on the Test Vhost for testing Exchange exchange = ApplicationRegistry.getInstance(). @@ -37,7 +37,7 @@ public class ExchangeMessagesTest extends AbstractTestMessages String type = exchange.getType().toString(); String name = exchange.getName().toString(); - _logMessage = ExchangeMessages.EXH_1001(type, name); + _logMessage = ExchangeMessages.EXH_1001(type, name, false); List<Object> log = performLog(); String[] expected = {"Create :", "Type:", type, "Name:", name}; @@ -45,6 +45,25 @@ public class ExchangeMessagesTest extends AbstractTestMessages validateLogMessage(log, "EXH-1001", expected); } + public void testMessage1001_Persistent() + { + // Get the Default Exchange on the Test Vhost for testing + Exchange exchange = ApplicationRegistry.getInstance(). + getVirtualHostRegistry().getVirtualHost("test"). + getExchangeRegistry().getDefaultExchange(); + + String type = exchange.getType().toString(); + String name = exchange.getName().toString(); + + _logMessage = ExchangeMessages.EXH_1001(type, name, true); + List<Object> log = performLog(); + + String[] expected = {"Create :", "Durable", "Type:", type, "Name:", name}; + + validateLogMessage(log, "EXH-1001", expected); + } + + public void testMessage1002() { _logMessage = ExchangeMessages.EXH_1002(); diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/MessageStoreMessagesTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/MessageStoreMessagesTest.java index e1ae93b869..e02993b840 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/MessageStoreMessagesTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/MessageStoreMessagesTest.java @@ -61,7 +61,7 @@ public class MessageStoreMessagesTest extends AbstractTestMessages public void testMessage1004() { - _logMessage = MessageStoreMessages.MST_1004(); + _logMessage = MessageStoreMessages.MST_1004(null,false); List<Object> log = performLog(); String[] expected = {"Recovery Start"}; @@ -69,24 +69,24 @@ public class MessageStoreMessagesTest extends AbstractTestMessages validateLogMessage(log, "MST-1004", expected); } - public void testMessage1005() + public void testMessage1004_withQueue() { String queueName = "testQueue"; - _logMessage = MessageStoreMessages.MST_1005(queueName); + _logMessage = MessageStoreMessages.MST_1004(queueName, true); List<Object> log = performLog(); String[] expected = {"Recovery Start :", queueName}; - validateLogMessage(log, "MST-1005", expected); + validateLogMessage(log, "MST-1004", expected); } - public void testMessage1006() + public void testMessage1005() { String queueName = "testQueue"; Integer messasgeCount = 2000; - _logMessage = MessageStoreMessages.MST_1006(messasgeCount, queueName); + _logMessage = MessageStoreMessages.MST_1005(messasgeCount, queueName); List<Object> log = performLog(); // Here we use MessageFormat to ensure the messasgeCount of 2000 is @@ -95,29 +95,29 @@ public class MessageStoreMessagesTest extends AbstractTestMessages MessageFormat.format("{0,number}", messasgeCount), "messages for queue", queueName}; - validateLogMessage(log, "MST-1006", expected); + validateLogMessage(log, "MST-1005", expected); } - public void testMessage1007() + public void testMessage1006() { - _logMessage = MessageStoreMessages.MST_1007(); + _logMessage = MessageStoreMessages.MST_1006(null,false); List<Object> log = performLog(); String[] expected = {"Recovery Complete"}; - validateLogMessage(log, "MST-1007", expected); + validateLogMessage(log, "MST-1006", expected); } - public void testMessage1008() + public void testMessage1006_withQueue() { String queueName = "testQueue"; - _logMessage = MessageStoreMessages.MST_1008(queueName); + _logMessage = MessageStoreMessages.MST_1006(queueName, true); List<Object> log = performLog(); String[] expected = {"Recovery Complete :", queueName}; - validateLogMessage(log, "MST-1008", expected); + validateLogMessage(log, "MST-1006", expected); } } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/QueueMessagesTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/QueueMessagesTest.java index 4ba00ea6e4..2f53d0aff5 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/QueueMessagesTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/QueueMessagesTest.java @@ -24,14 +24,114 @@ import java.util.List; public class QueueMessagesTest extends AbstractTestMessages { - public void testMessage1001() + public void testMessage1001ALL() { String owner = "guest"; + Integer priority = 3; - _logMessage = QueueMessages.QUE_1001(owner); + _logMessage = QueueMessages.QUE_1001(owner, priority, true, true, true, true); List<Object> log = performLog(); - String[] expected = {"Create :", "Owner:", owner}; + String[] expected = {"Create :", "Owner:", owner, "AutoDelete", + "Durable", "Transient", "Priority:", + String.valueOf(priority)}; + + validateLogMessage(log, "QUE-1001", expected); + } + + public void testMessage1001AutoDelete() + { + String owner = "guest"; + + _logMessage = QueueMessages.QUE_1001(owner, null, true, false, false, false); + List<Object> log = performLog(); + + String[] expected = {"Create :", "Owner:", owner, "AutoDelete"}; + + validateLogMessage(log, "QUE-1001", expected); + } + + public void testMessage1001Priority() + { + String owner = "guest"; + Integer priority = 3; + + _logMessage = QueueMessages.QUE_1001(owner, priority, false, false, false, true); + List<Object> log = performLog(); + + String[] expected = {"Create :", "Owner:", owner, "Priority:", + String.valueOf(priority)}; + + validateLogMessage(log, "QUE-1001", expected); + } + + public void testMessage1001AutoDeletePriority() + { + String owner = "guest"; + Integer priority = 3; + + _logMessage = QueueMessages.QUE_1001(owner, priority, true, false, false, true); + List<Object> log = performLog(); + + String[] expected = {"Create :", "Owner:", owner, "AutoDelete", + "Priority:", + String.valueOf(priority)}; + + validateLogMessage(log, "QUE-1001", expected); + } + + public void testMessage1001AutoDeleteTransient() + { + String owner = "guest"; + + _logMessage = QueueMessages.QUE_1001(owner, null, true, false, true, false); + List<Object> log = performLog(); + + String[] expected = {"Create :", "Owner:", owner, "AutoDelete", + "Transient"}; + + validateLogMessage(log, "QUE-1001", expected); + } + + public void testMessage1001AutoDeleteTransientPriority() + { + String owner = "guest"; + Integer priority = 3; + + _logMessage = QueueMessages.QUE_1001(owner, priority, true, false, true, true); + List<Object> log = performLog(); + + String[] expected = {"Create :", "Owner:", owner, "AutoDelete", + "Transient", "Priority:", + String.valueOf(priority)}; + + validateLogMessage(log, "QUE-1001", expected); + } + + public void testMessage1001AutoDeleteDurable() + { + String owner = "guest"; + + _logMessage = QueueMessages.QUE_1001(owner, null, true, true, false, false); + List<Object> log = performLog(); + + String[] expected = {"Create :", "Owner:", owner, "AutoDelete", + "Durable"}; + + validateLogMessage(log, "QUE-1001", expected); + } + + public void testMessage1001AutoDeleteDurablePriority() + { + String owner = "guest"; + Integer priority = 3; + + _logMessage = QueueMessages.QUE_1001(owner, priority, true, true, false, true); + List<Object> log = performLog(); + + String[] expected = {"Create :", "Owner:", owner, "AutoDelete", + "Durable", "Priority:", + String.valueOf(priority)}; validateLogMessage(log, "QUE-1001", expected); } diff --git a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/SubscriptionMessagesTest.java b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/SubscriptionMessagesTest.java index 1bb96e1e33..80ebcc79cd 100644 --- a/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/SubscriptionMessagesTest.java +++ b/qpid/java/broker/src/test/java/org/apache/qpid/server/logging/messages/SubscriptionMessagesTest.java @@ -24,17 +24,41 @@ import java.util.List; public class SubscriptionMessagesTest extends AbstractTestMessages { - public void testMessage1001() + public void testMessage1001ALL() { + String arguments = "arguments"; - _logMessage = SubscriptionMessages.SUB_1001(); + _logMessage = SubscriptionMessages.SUB_1001(arguments, true, true); List<Object> log = performLog(); - String[] expected = {"Create :"}; + String[] expected = {"Create :", "Durable", "Arguments :", arguments}; validateLogMessage(log, "SUB-1001", expected); } + public void testMessage1001Durable() + { + _logMessage = SubscriptionMessages.SUB_1001(null, true, false); + List<Object> log = performLog(); + + String[] expected = {"Create :", "Durable"}; + + validateLogMessage(log, "SUB-1001", expected); + } + + public void testMessage1001Arguments() + { + String arguments = "arguments"; + + _logMessage = SubscriptionMessages.SUB_1001(arguments, false, true); + List<Object> log = performLog(); + + String[] expected = {"Create :","Arguments :", arguments}; + + validateLogMessage(log, "SUB-1001", expected); + } + + public void testMessage1002() { _logMessage = SubscriptionMessages.SUB_1002(); diff --git a/qpid/java/broker/src/velocity/java/org/apache/qpid/server/logging/GenerateLogMessages.java b/qpid/java/broker/src/velocity/java/org/apache/qpid/server/logging/GenerateLogMessages.java index cc0565031f..ea0946f6d6 100644 --- a/qpid/java/broker/src/velocity/java/org/apache/qpid/server/logging/GenerateLogMessages.java +++ b/qpid/java/broker/src/velocity/java/org/apache/qpid/server/logging/GenerateLogMessages.java @@ -30,6 +30,7 @@ import java.util.Enumeration; import java.util.HashMap; import java.util.LinkedList; import java.util.List; +import java.util.Locale; import java.util.Properties; import java.util.ResourceBundle; @@ -210,15 +211,20 @@ public class GenerateLogMessages * type checking during compilation whilst allowing the log message to * maintain formatting controls. * + * OPTIONS + * * The returned hashMap contains the following structured data: * * - name - ClassName ('Broker') - * list - methodName ('BRK_1001') - * - name ('BRK-1001') - * - format ('Startup : Version: {0} Build: {1}') - * - parameters (list) - * - type ('String'|'Number') - * - name ('param1') + * - list[logEntryData] - methodName ('BRK_1001') + * - name ('BRK-1001') + * - format ('Startup : Version: {0} Build: {1}') + * - parameters (list) + * - type ('String'|'Number') + * - name ('param1') + * - options (list) + * - name ('opt1') + * - value ('AutoDelete') * * @param messsageName the name to give the Class e.g. 'Broker' * @param messageKey the 3-digit key to extract the messages e.g. 'BRK' @@ -228,7 +234,7 @@ public class GenerateLogMessages private HashMap<String, Object> prepareType(String messsageName, String messageKey) throws InvalidTypeException { // Load the LogMessages Resource Bundle - ResourceBundle _messages = ResourceBundle.getBundle("org.apache.qpid.server.logging.messages.LogMessages"); + ResourceBundle _messages = ResourceBundle.getBundle("org.apache.qpid.server.logging.messages.LogMessages", Locale.US); Enumeration<String> messageKeys = _messages.getKeys(); @@ -265,79 +271,187 @@ public class GenerateLogMessages // Javadoc of the method. logEntryData.put("format", logMessage); - // Split the string on the start brace '{' this will give us the - // details for each parameter that this message contains. - String[] parametersString = logMessage.split("\\{"); - // Taking an example of 'Text {n[,type]} text {m} more text {p}' - // This would give us: - // 0 - Text - // 1 - n[,type]} text - // 2 - m} more text - // 3 - p} - - // Create the parameter list for this item - List<HashMap<String, String>> parameters = new LinkedList<HashMap<String, String>>(); + // Add the parameters for this message + logEntryData.put("parameters", extractParameters(logMessage)); - // Add the parameter list to this log entry data - logEntryData.put("parameters", parameters); + //Add the options for this messagse + logEntryData.put("options", extractOptions(logMessage)); - // Add the data to the list of messages + //Add this entry to the list for this class logMessageList.add(logEntryData); + } + } - // Check that we have some parameters to process - // Skip 0 as that will not be the first entry - // Text {n[,type]} text {m} more text {p} - if (parametersString.length > 1) - { - for (int index = 1; index < parametersString.length; index++) - { - // Use a HashMap to store the type,name of the parameter - // for easy retrieval in the macro template - HashMap<String, String> parameter = new HashMap<String, String>(); + return messageTypeData; + } - // Check for any properties of the parameter : - // e.g. {0} vs {0,number} vs {0,number,xxxx} - int typeIndex = parametersString[index].indexOf(","); + /** + * This method is responsible for extracting the options form the given log + * message and providing a HashMap with the expected data: + * - options (list) + * - name ('opt1') + * - value ('AutoDelete') + * + * The options list that this method provides must contain HashMaps that + * have two entries. A 'name' and a 'value' these strings are important as + * they are used in LogMessage.vm to extract the stored String during + * processing of the template. + * + * The 'name' is a unique string that is used to name the boolean parameter + * and refer to it later in the method body. + * + * The 'value' is used to provide documentation in the generated class to + * aid readability. + * + * @param logMessage the message from the properties file + * @return list of option data + */ + private List<HashMap<String, String>> extractOptions(String logMessage) + { + // Split the string on the start brace '{' this will give us the + // details for each parameter that this message contains. + // NOTE: Simply splitting on '[' prevents the use of nested options. + // Currently there is no demand for nested options + String[] optionString = logMessage.split("\\["); + // Taking an example of: + // 'Text {n,type,format} [option] text {m} [option with param{p}] more' + // This would give us: + // 0 - Text {n,type,format} + // 1 - option] text {m} + // 2 - option with param{p}] more + + // Create the parameter list for this item + List<HashMap<String, String>> options = new LinkedList<HashMap<String, String>>(); + + // Check that we have some parameters to process + // Skip 0 as that will not be the first entry + // Text {n,type,format} [option] text {m} [option with param{p}] more + if (optionString.length > 1) + { + for (int index = 1; index < optionString.length; index++) + { + // Use a HashMap to store the type,name of the parameter + // for easy retrieval in the macro template + HashMap<String, String> option = new HashMap<String, String>(); - // The parameter type - String type; + // Locate the end of the Option + // NOTE: it is this simple matching on the first ']' that + // prevents the nesting of options. + // Currently there is no demand for nested options + int end = optionString[index].indexOf("]"); - //Be default all types are Strings - if (typeIndex == -1) - { - type = "String"; - } - else - { - //Check string ',....}' for existence of number - // to identify this parameter as an integer - // This allows for a style value to be present - // Only check the text inside the braces '{}' - int typeIndexEnd = parametersString[index].indexOf("}", typeIndex); - String typeString = parametersString[index].substring(typeIndex, typeIndexEnd); - if (typeString.contains("number")) - { - type = "Number"; - } - else - { - throw new InvalidTypeException("Invalid type(" + typeString + ") index (" + parameter.size() + ") in message:" + logMessage); - } + // The parameter type + String value = optionString[index].substring(0, end); - } + // Simply name the parameters by index. + option.put("name", "opt" + index); + + //Store the value e.g. AutoDelete + // We trim as we don't need to include any whitespace that is + // used for formating. This is only used to aid readability of + // of the generated code. + option.put("value", value.trim()); - //Store the data - parameter.put("type", type); - // Simply name the parameters by index. - parameter.put("name", "param" + index); + options.add(option); + } + } - parameters.add(parameter); + return options; + } + + /** + * This method is responsible for extract the parameters that are requried + * for this log message. The data is returned in a HashMap that has the + * following structure: + * - parameters (list) + * - type ('String'|'Number') + * - name ('param1') + * + * The parameters list that is provided must contain HashMaps that have the + * two named entries. A 'type' and a 'name' these strings are importans as + * they are used in LogMessage.vm to extract and the stored String during + * processing of the template + * + * The 'type' and 'name' values are used to populate the method signature. + * This is what gives us the compile time validation of log messages. + * + * The 'name' must be unique as there may be many parameters. The value is + * also used in the method body to pass the values through to the + * MessageFormat class for formating the log message. + * + * @param logMessage the message from the properties file + * @return list of option data + * @throws InvalidTypeException if the FormatType is specified and is not 'number' + */ + private List<HashMap<String, String>> extractParameters(String logMessage) + throws InvalidTypeException + { + // Split the string on the start brace '{' this will give us the + // details for each parameter that this message contains. + String[] parametersString = logMessage.split("\\{"); + // Taking an example of 'Text {n[,type]} text {m} more text {p}' + // This would give us: + // 0 - Text + // 1 - n[,type]} text + // 2 - m} more text + // 3 - p} + + // Create the parameter list for this item + List<HashMap<String, String>> parameters = new LinkedList<HashMap<String, String>>(); + + // Check that we have some parameters to process + // Skip 0 as that will not be the first entry + // Text {n[,type]} text {m} more text {p} + if (parametersString.length > 1) + { + for (int index = 1; index < parametersString.length; index++) + { + // Use a HashMap to store the type,name of the parameter + // for easy retrieval in the macro template + HashMap<String, String> parameter = new HashMap<String, String>(); + + // Check for any properties of the parameter : + // e.g. {0} vs {0,number} vs {0,number,xxxx} + int typeIndex = parametersString[index].indexOf(","); + + + // The parameter type + String type; + + //Be default all types are Strings + if (typeIndex == -1) + { + type = "String"; + } + else + { + //Check string ',....}' for existence of number + // to identify this parameter as an integer + // This allows for a style value to be present + // Only check the text inside the braces '{}' + int typeIndexEnd = parametersString[index].indexOf("}", typeIndex); + String typeString = parametersString[index].substring(typeIndex, typeIndexEnd); + if (typeString.contains("number")) + { + type = "Number"; } + else + { + throw new InvalidTypeException("Invalid type(" + typeString + ") index (" + parameter.size() + ") in message:" + logMessage); + } + } + + //Store the data + parameter.put("type", type); + // Simply name the parameters by index. + parameter.put("name", "param" + index); + + parameters.add(parameter); } } - return messageTypeData; + return parameters; } /** diff --git a/qpid/java/broker/src/velocity/templates/org/apache/qpid/server/logging/messages/LogMessages.vm b/qpid/java/broker/src/velocity/templates/org/apache/qpid/server/logging/messages/LogMessages.vm index 6656763ab9..917901a18b 100644 --- a/qpid/java/broker/src/velocity/templates/org/apache/qpid/server/logging/messages/LogMessages.vm +++ b/qpid/java/broker/src/velocity/templates/org/apache/qpid/server/logging/messages/LogMessages.vm @@ -33,7 +33,10 @@ import java.util.ResourceBundle; * This file is based on the content of LogMessages.properties * * It is generated so that we can provide compile time validation of the - * message parameters + * message parameters. + * + * DO NOT EDIT DIRECTLY THIS FILE IS GENERATED. + * */ public class ${type.name}Messages { @@ -51,25 +54,105 @@ public class ${type.name}Messages _formatter.setLocale(currentLocale); } +## +## The list stored under key 'list' in the 'type' HashMap contains all the +## log messages that this class should contain. So for each entry in the list +## this template will create a new log method. +## #foreach( $message in ${type.list} ) /** * Log a ${type.name} message of the Format: - * <pre>${message.format}</pre> + * <pre>${message.format}</pre> + * Optional values are contained in [square brackets] and are numbered + * sequentially in the method call. + * */ +## There is a lot in the method header here. To make it more readable/understandable +## This is the same text laid out to be easier to read: +## public static LogMessage ${message.methodName} ( +## #foreach($parameter in ${message.parameters}) +## ${parameter.type} ${parameter.name} +## #if (${velocityCount} != ${message.parameters.size()} ) +## , +## #end +## #end +## #if(${message.parameters.size()} > 0 && ${message.options.size()} > 0) +## , +## #end +## #foreach($option in ${message.options}) +## boolean ${option.name} +## #if (${velocityCount} != ${message.options.size()} ) +## , +## #end +## #end +## ) +## +## What is going on is that we set the method name based on the HashMap lookup +## for 'methodName' Then for each entry(another HashMap) in the list stored +## in the HashMap under 'parameters' build the argument list of from the 'type' +## and 'name' values. Ensuring that we add a ', ' between each entry. +## +## However, check that we are not at the last entry of the list as we don't +## want to add ', ' at then end. +## +## Before we go on to the options we perform a check to see if we had any +## parameters. If we did and we have options to add then we add ', ' to keep +## the syntax correct. +## +## We then go on to the options that are again retrieved from the top HashMap +## with key 'options'. For each option a boolean argument is created and the +## name is retrieved from the option HashMap with key 'name' +## public static LogMessage ${message.methodName}(#foreach($parameter in ${message.parameters})${parameter.type} ${parameter.name}#if (${velocityCount} != ${message.parameters.size()} ), #end -#end) +#end#if(${message.parameters.size()} > 0 && ${message.options.size()} > 0), #end#foreach($option in ${message.options})boolean ${option.name}#if (${velocityCount} != ${message.options.size()} ), #end#end) { final Object[] messageArguments = {#foreach($parameter in ${message.parameters})${parameter.name}#if (${velocityCount} != ${message.parameters.size()} ), #end#end}; - _formatter.applyPattern(_messages.getString("${message.name}")); + + ## If we have some options then we need to build the message based + ## on those values so only provide that logic if we need it. +#if(${message.options.size()} > 0) + String rawMessage = _formatter.format(messageArguments); + + StringBuffer msg =new StringBuffer("${message.name} : "); + + // Split the formatted message up on the option values so we can + // rebuild the message based on the configured options. + String[] parts = rawMessage.split("\\["); + msg.append(parts[0]); + + int end; + if (parts.length > 1) + { + ## For Each Optional value check if it has been enabled and then + ## append it to the log. +#foreach($option in ${message.options}) + + // Add Option : ${option.value} + end = parts[${velocityCount}].indexOf(']'); + if (${option.name}) + { + msg.append(parts[${velocityCount}].substring(0, end)); + } + + // Use 'end + 1' to remove the ']' from the output + msg.append(parts[${velocityCount}].substring(end + 1)); +#end + } + + final String message = msg.toString(); +#else + ## If we have no options then we can just format and set the log + final String message = "${message.name} : " + _formatter.format(messageArguments); +#end + return new LogMessage() { public String toString() { - return "${message.name} : " + _formatter.format(messageArguments); + return message; } }; - } #end diff --git a/qpid/java/doc/Qpid-architecture.dia b/qpid/java/doc/Qpid-architecture.dia Binary files differnew file mode 100644 index 0000000000..4bdfd2ee93 --- /dev/null +++ b/qpid/java/doc/Qpid-architecture.dia diff --git a/qpid/java/doc/broker-0.5-network.dia b/qpid/java/doc/broker-0.5-network.dia Binary files differnew file mode 100644 index 0000000000..425ea2249e --- /dev/null +++ b/qpid/java/doc/broker-0.5-network.dia diff --git a/qpid/java/doc/client-0.5-connection-creation.dia b/qpid/java/doc/client-0.5-connection-creation.dia Binary files differnew file mode 100644 index 0000000000..b7c6d185a1 --- /dev/null +++ b/qpid/java/doc/client-0.5-connection-creation.dia diff --git a/qpid/java/doc/client-0.5-network-processing.dia b/qpid/java/doc/client-0.5-network-processing.dia Binary files differnew file mode 100644 index 0000000000..9bb009d0ab --- /dev/null +++ b/qpid/java/doc/client-0.5-network-processing.dia diff --git a/qpid/java/doc/noddy-network-blocks.dia b/qpid/java/doc/noddy-network-blocks.dia Binary files differnew file mode 100644 index 0000000000..06abc109b1 --- /dev/null +++ b/qpid/java/doc/noddy-network-blocks.dia diff --git a/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ManagedBroker.java b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ManagedBroker.java index 224bf8de2c..e376033bad 100644 --- a/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ManagedBroker.java +++ b/qpid/java/management/common/src/main/java/org/apache/qpid/management/common/mbeans/ManagedBroker.java @@ -22,9 +22,12 @@ package org.apache.qpid.management.common.mbeans; import java.io.IOException; +import java.util.Map; import javax.management.JMException; import javax.management.MBeanOperationInfo; +import javax.management.openmbean.OpenDataException; +import javax.management.openmbean.TabularData; import org.apache.qpid.management.common.mbeans.annotations.MBeanAttribute; import org.apache.qpid.management.common.mbeans.annotations.MBeanOperation; @@ -52,6 +55,15 @@ public interface ManagedBroker String[] getExchangeTypes() throws IOException; /** + * Returns a Map keyed by QueueName, detailing its associated QueueDepth in bytes. + * @since Qpid JMX API 1.3 + * @throws IOException + */ + @MBeanOperation(name = "viewQueueNamesDepths", description = "View the queue names and depths in this virtualhost", + impact = MBeanOperationInfo.INFO) + Map<String,Long> viewQueueNamesDepths() throws IOException; + + /** * Creates a new Exchange. * @param name * @param type 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 index ae01f30f32..8ded3f35c6 100644 --- 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 @@ -29,6 +29,8 @@ 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 */ @@ -157,6 +159,11 @@ public abstract class ManagedBean extends ManagedObject return _type.endsWith(EXCHANGE); } + public boolean isVirtualHostManager() + { + return _type.endsWith(ManagedBroker.TYPE); + } + public boolean isTempQueue() { return (isQueue() && getName().startsWith("tmp_")); 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 index 23879a779c..6c0b51e584 100644 --- 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 @@ -46,6 +46,8 @@ public abstract class ServerRegistry 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>(); public ServerRegistry() { @@ -98,6 +100,22 @@ public abstract class ServerRegistry _queues.get(vHost).add(mbean); } + protected void addVirtualHostManagerMBean(ManagedBean mbean) + { + String vHost = mbean.getVirtualHostName(); + _vhostManagers.put(vHost, mbean); + } + + protected void removeVirtualHostManagerMBean(ManagedBean mbean) + { + _vhostManagers.remove(mbean); + } + + public ManagedBean getVirtualHostManagerMBean(String virtualHost) + { + return _vhostManagers.get(virtualHost); + } + protected void removeConnectionMBean(ManagedBean mbean) { _connections.get(mbean.getVirtualHostName()).remove(mbean); @@ -128,6 +146,23 @@ public abstract class ServerRegistry return _queues.get(virtualHost); } + //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)) 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 index 575b98d48a..2b459c858f 100644 --- 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 @@ -157,6 +157,10 @@ public class JMXServerRegistry extends ServerRegistry { addConnectionMBean(mbean); } + else if (mbean.isVirtualHostManager()) + { + addVirtualHostManagerMBean(mbean); + } addVirtualHost(mbean.getVirtualHostName()); _mbeansMap.put(mbean.getUniqueName(), mbean); @@ -183,6 +187,10 @@ public class JMXServerRegistry extends ServerRegistry { removeConnectionMBean(mbean); } + else if (mbean.isVirtualHostManager()) + { + removeVirtualHostManagerMBean(mbean); + } } public void putMBeanInfo(ManagedBean mbean, MBeanInfo mbeanInfo) 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 index a185467e2d..1fef89d6b5 100644 --- 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 @@ -34,6 +34,7 @@ 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; @@ -242,9 +243,9 @@ public class MBeanTabFolderFactory } /** - * Creates TabFolder and tabs for each mbeantype (eg Connection, Queue, Exchange) + * Creates TabFolder and tabs for all mbeantype (Connection, Queue, and Exchange) */ - public static TabFolder generateMBeanTypeTabFolder(final Composite parent) + public static TabFolder generateMBeanTypeTabFolder(final Composite parent, ManagedServer server, String virtualHost) { TabFolder tabFolder = new TabFolder(parent, SWT.NONE); FormData layoutData = new FormData(); @@ -254,24 +255,101 @@ public class MBeanTabFolderFactory 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); + 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); + 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); + 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()); @@ -290,7 +368,45 @@ public class MBeanTabFolderFactory 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), 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 index d92e8ef49d..35d1b4a34f 100644 --- 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 @@ -173,11 +173,11 @@ public class MBeanView extends ViewPart if (NODE_TYPE_TYPEINSTANCE.equals(mbeanType)) { // An virtual host instance is selected - refreshTypeTabFolder(_typeTabFolder.getItem(0)); + generateTypeTabFolder(); } else if (NODE_TYPE_MBEANTYPE.equals(mbeanType)) { - refreshTypeTabFolder(_selectedNode.getName()); + showTypeTabFolder(_selectedNode.getName()); } else if (NOTIFICATIONS.equals(mbeanType)) { @@ -307,12 +307,7 @@ public class MBeanView extends ViewPart // Add selection listener for selection events in the Navigation view getSite().getPage().addSelectionListener(NavigationView.ID, _selectionListener); - - // Add mbeantype TabFolder. This will list all the mbeans under a mbeantype (eg Queue, Exchange). - // Using this list mbeans will be added in the navigation view - _typeTabFolder = MBeanTabFolderFactory.generateMBeanTypeTabFolder(_form.getBody()); - _typeTabFolder.setVisible(false); - + createNotificationsTabFolder(); ViewUtility.setMBeanView(this); @@ -370,32 +365,48 @@ public class MBeanView extends ViewPart _notificationTabFolder.setVisible(true); } - /** - * Refreshes the Selected mbeantype tab. The control lists all the available mbeans - * for an mbeantype(eg Queue, Exchange etc) - * @param tab - * @throws Exception - */ - private void refreshTypeTabFolder(TabItem tab) throws Exception + + + private void generateTypeTabFolder() throws Exception { - refreshTab(tab); - _typeTabFolder.setSelection(tab); - _typeTabFolder.setVisible(true); + 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 refreshTypeTabFolder(String type) throws Exception + private void showTypeTabFolder(String type) throws Exception { + if (_typeTabFolder != null && !_typeTabFolder.isDisposed()) + { + _typeTabFolder.dispose(); + } + if (CONNECTION.equals(type)) { - refreshTypeTabFolder(_typeTabFolder.getItem(0)); + //Generates the Connection selection tab + _typeTabFolder = MBeanTabFolderFactory.generateConnectionTypeTabFolder( + _form.getBody(), getServer(), getVirtualHost()); + refreshTab(_typeTabFolder.getItem(0)); } else if (EXCHANGE.equals(type)) { - refreshTypeTabFolder(_typeTabFolder.getItem(1)); + //Generates the Exchange selection tab + _typeTabFolder = MBeanTabFolderFactory.generateExchangeTypeTabFolder( + _form.getBody(), getServer(), getVirtualHost()); + refreshTab(_typeTabFolder.getItem(0)); } else if (QUEUE.equals(type)) { - refreshTypeTabFolder(_typeTabFolder.getItem(2)); + //Generates the Queue selection tab + _typeTabFolder = MBeanTabFolderFactory.generateQueueTypeTabFolder( + _form.getBody(), getServer(), getVirtualHost()); + refreshTab(_typeTabFolder.getItem(0)); } } 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 index 43744c99df..dcdd199a7d 100644 --- 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 @@ -20,6 +20,9 @@ */ package org.apache.qpid.management.ui.views.exchange; +import static org.apache.qpid.management.ui.Constants.EXCHANGE_TYPE; +import static org.apache.qpid.management.ui.Constants.DEFAULT_EXCHANGE_TYPE_VALUES; + import java.util.Collection; import java.util.List; @@ -29,11 +32,14 @@ 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; @@ -45,6 +51,8 @@ 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; @@ -60,6 +68,8 @@ 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; @@ -79,6 +89,7 @@ public class ExchangeOperationsTabControl extends TabControl private TabularDataSupport _bindings = null; private ManagedExchange _emb; + private ApiVersion _ApiVersion; static final String BINDING_KEY = ManagedExchange.COMPOSITE_ITEM_NAMES[0]; static final String QUEUES = ManagedExchange.COMPOSITE_ITEM_NAMES[1]; @@ -87,6 +98,7 @@ public class ExchangeOperationsTabControl extends TabControl { super(tabFolder); _mbean = mbean; + _ApiVersion = ApplicationRegistry.getServerRegistry(mbean).getManagementApiVersion(); _emb = (ManagedExchange) MBeanServerInvocationHandler.newProxyInstance(mbsc, mbean.getObjectName(), ManagedExchange.class, false); _toolkit = new FormToolkit(_tabFolder.getDisplay()); @@ -130,10 +142,26 @@ public class ExchangeOperationsTabControl extends TabControl } catch (Exception e) { - MBeanUtility.handleException(mbean,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(); } @@ -260,22 +288,23 @@ public class ExchangeOperationsTabControl extends TabControl _queuesTableViewer.setSorter(queuesTableSorter); _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) { - int selectionIndex = _keysTable.getSelectionIndex(); - - if (selectionIndex != -1) - { - final CompositeData selectedMsg = (CompositeData)_keysTable.getItem(selectionIndex).getData(); - - String[] queues = (String[]) selectedMsg.get(QUEUES); - _queuesTableViewer.setInput(queues); - } - else - { - _queuesTableViewer.setInput(new String[]{"Select a binding key to view queues"}); - } + updateQueuesTable(); } }); @@ -296,6 +325,28 @@ public class ExchangeOperationsTabControl extends TabControl } + private void updateQueuesTable() + { + int selectionIndex = _keysTable.getSelectionIndex(); + + if (selectionIndex != -1) + { + final CompositeData selectedMsg = (CompositeData)_keysTable.getItem(selectionIndex).getData(); + + String[] queues = (String[]) selectedMsg.get(QUEUES); + _queuesTableViewer.setInput(queues); + } + else + { + _queuesTableViewer.setInput(new String[]{"Select a binding key to view queues"}); + } + } + + private boolean isFanoutExchange() + { + return _mbean.getProperty(EXCHANGE_TYPE).equalsIgnoreCase(DEFAULT_EXCHANGE_TYPE_VALUES[1]); + + } /** * Content Provider class for the table viewer @@ -477,6 +528,10 @@ public class ExchangeOperationsTabControl extends TabControl _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()); @@ -507,7 +562,7 @@ public class ExchangeOperationsTabControl extends TabControl { String binding = bindingText.getText(); - if (binding == null || binding.length() == 0) + if (!isFanoutExchange() && (binding == null || binding.length() == 0)) { ViewUtility.popupErrorMessage("Create New Binding", "Please enter a valid binding"); return; @@ -544,4 +599,35 @@ public class ExchangeOperationsTabControl extends TabControl shell.pack(); shell.open(); } + + 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 index 54135202db..e7ab034094 100644 --- 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 @@ -31,9 +31,11 @@ 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; @@ -45,6 +47,8 @@ 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; @@ -60,6 +64,8 @@ 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; @@ -82,7 +88,7 @@ public class HeadersExchangeOperationsTabControl extends TabControl static final String BINDING_NUM = ManagedExchange.HEADERS_COMPOSITE_ITEM_NAMES[0]; static final String QUEUE_NAME = ManagedExchange.HEADERS_COMPOSITE_ITEM_NAMES[1]; - static final String QUEUE_BINDINGS = ManagedExchange.HEADERS_COMPOSITE_ITEM_NAMES[2]; + static final String HEADER_BINDINGS = ManagedExchange.HEADERS_COMPOSITE_ITEM_NAMES[2]; public HeadersExchangeOperationsTabControl(TabFolder tabFolder, JMXManagedObject mbean, MBeanServerConnection mbsc) { @@ -132,7 +138,7 @@ public class HeadersExchangeOperationsTabControl extends TabControl } catch (Exception e) { - MBeanUtility.handleException(mbean,e); + MBeanUtility.handleException(_mbean,e); } _bindingNumberTableViewer.setInput(_bindings); @@ -224,7 +230,7 @@ public class HeadersExchangeOperationsTabControl extends TabControl _headersTable.setLayoutData(data); _headersTableViewer = new TableViewer(_headersTable); - final TableSorter queuesTableSorter = new TableSorter(QUEUE_BINDINGS); + final TableSorter queuesTableSorter = new TableSorter(HEADER_BINDINGS); titles = new String[]{"Header Bindings"}; bounds = new int[]{225}; @@ -262,8 +268,8 @@ public class HeadersExchangeOperationsTabControl extends TabControl } - _headersTableViewer.setContentProvider(new ContentProviderImpl(QUEUE_BINDINGS)); - _headersTableViewer.setLabelProvider(new LabelProviderImpl(QUEUE_BINDINGS)); + _headersTableViewer.setContentProvider(new ContentProviderImpl(HEADER_BINDINGS)); + _headersTableViewer.setLabelProvider(new LabelProviderImpl(HEADER_BINDINGS)); _headersTableViewer.setSorter(queuesTableSorter); _headersTableViewer.setInput(new String[]{"Select a binding to view key-value pairs"}); @@ -276,7 +282,7 @@ public class HeadersExchangeOperationsTabControl extends TabControl { final CompositeData selectedMsg = (CompositeData)_bindingNumberTable.getItem(selectionIndex).getData(); - String[] bindings = (String[]) selectedMsg.get(QUEUE_BINDINGS); + String[] bindings = (String[]) selectedMsg.get(HEADER_BINDINGS); _headersTableViewer.setInput(bindings); } else @@ -286,6 +292,19 @@ public class HeadersExchangeOperationsTabControl extends TabControl } }); + //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); @@ -555,4 +574,36 @@ public class HeadersExchangeOperationsTabControl extends TabControl shell.pack(); 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(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 index e86faed1fd..0214607a21 100644 --- 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 @@ -20,6 +20,9 @@ */ package org.apache.qpid.management.ui.views.logging; +import java.util.ArrayList; +import java.util.HashMap; + import javax.management.MBeanServerConnection; import javax.management.MBeanServerInvocationHandler; import javax.management.openmbean.CompositeData; @@ -55,6 +58,7 @@ 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; @@ -209,7 +213,7 @@ public class ConfigurationFileTabControl extends TabControl tableComposite.setLayout(gridLayout); - _table = new Table (tableComposite, SWT.SINGLE | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION); + _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); @@ -347,18 +351,36 @@ public class ConfigurationFileTabControl extends TabControl if (selectionIndex != -1) { - final CompositeData selectedLogger = (CompositeData)_table.getItem(selectionIndex).getData(); - String loggerName = selectedLogger.get(LOGGER_NAME).toString(); + 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"); - - Composite loggerComp = _toolkit.createComposite(shell); - loggerComp.setBackground(shell.getBackground()); - loggerComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - loggerComp.setLayout(new GridLayout(2,false)); - - _toolkit.createLabel(loggerComp, "Logger: ").setBackground(shell.getBackground()); - _toolkit.createLabel(loggerComp, loggerName).setBackground(shell.getBackground()); + + _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()); @@ -384,21 +406,63 @@ public class ConfigurationFileTabControl extends TabControl { public void widgetSelected(SelectionEvent e) { - String logger = selectedLogger.get(LOGGER_NAME).toString(); String level = levelCombo.getItem(levelCombo.getSelectionIndex()).toString(); shell.close(); try { - boolean result = _lmmb.setConfigFileLoggerLevel(logger, level); - ViewUtility.operationResultFeedback(result, - "Updated ConfigFile Logger Level", "Failed to update ConfigFile Logger Level"); + 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) + catch(Exception e4) { + ViewUtility.operationFailedStatusBarMessage("Error updating Config File Logger Level(s)"); MBeanUtility.handleException(_mbean, e4); - ViewUtility.operationFailedStatusBarMessage("Error updating ConfigFile Logger Level"); } refresh(_mbean); 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 index af4a17695c..5013d8f734 100644 --- 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 @@ -20,6 +20,9 @@ */ package org.apache.qpid.management.ui.views.logging; +import java.util.ArrayList; +import java.util.HashMap; + import javax.management.MBeanServerConnection; import javax.management.MBeanServerInvocationHandler; import javax.management.openmbean.CompositeData; @@ -55,6 +58,7 @@ 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; @@ -188,7 +192,7 @@ public class RuntimeTabControl extends TabControl GridLayout gridLayout = new GridLayout(); tableComposite.setLayout(gridLayout); - _table = new Table (tableComposite, SWT.SINGLE | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION); + _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); @@ -311,18 +315,36 @@ public class RuntimeTabControl extends TabControl if (selectionIndex != -1) { - final CompositeData selectedLogger = (CompositeData)_table.getItem(selectionIndex).getData(); - String loggerName = selectedLogger.get(LOGGER_NAME).toString(); + 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"); - Composite loggerComp = _toolkit.createComposite(shell); - loggerComp.setBackground(shell.getBackground()); - loggerComp.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); - loggerComp.setLayout(new GridLayout(2,false)); + _toolkit.createLabel(shell, "Logger(s): ").setBackground(shell.getBackground()); - _toolkit.createLabel(loggerComp, "Logger: ").setBackground(shell.getBackground()); - _toolkit.createLabel(loggerComp, loggerName).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()); @@ -348,20 +370,62 @@ public class RuntimeTabControl extends TabControl { public void widgetSelected(SelectionEvent e) { - String logger = selectedLogger.get(LOGGER_NAME).toString(); String level = levelCombo.getItem(levelCombo.getSelectionIndex()).toString(); shell.close(); - + try { - boolean result = _lmmb.setRuntimeLoggerLevel(logger, level); - ViewUtility.operationResultFeedback(result, - "Updated Runtime Logger Level", "Failed to update Runtime Logger Level"); + 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"); + ViewUtility.operationFailedStatusBarMessage("Error updating Runtime Logger Level(s)"); MBeanUtility.handleException(_mbean, e3); } 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 index 00c5b3326b..5623c3cb51 100644 --- 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 @@ -553,9 +553,10 @@ public class QueueOperationsTabControl extends TabControl String[] msgHeader = (String[]) selectedMsg.get(MSG_HEADER); headerText.setText(""); + String lineSeperator = System.getProperty("line.separator"); for(String s: msgHeader) { - headerText.append(s + "\n"); + headerText.append(s + lineSeperator); } } 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 index e0d850bd1e..f1f7b07b6f 100644 --- 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 @@ -24,10 +24,8 @@ import java.util.List; import static org.apache.qpid.management.ui.Constants.CONNECTION; -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.views.MBeanView; +import org.apache.qpid.management.ui.ManagedServer; import org.eclipse.swt.widgets.TabFolder; /** @@ -38,16 +36,15 @@ import org.eclipse.swt.widgets.TabFolder; public class ConnectionTypeTabControl extends MBeanTypeTabControl { - public ConnectionTypeTabControl(TabFolder tabFolder) + public ConnectionTypeTabControl(TabFolder tabFolder, ManagedServer server, String virtualHost) { - super(tabFolder,CONNECTION); + super(tabFolder, server, virtualHost, CONNECTION); } - @Override - protected List<ManagedBean> getMbeans() - { - ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(MBeanView.getServer()); - return serverRegistry.getConnections(MBeanView.getVirtualHost()); - } + @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 index 710422ab6e..5d587c7158 100644 --- 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 @@ -24,25 +24,22 @@ import java.util.List; import static org.apache.qpid.management.ui.Constants.EXCHANGE; -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.views.MBeanView; +import org.apache.qpid.management.ui.ManagedServer; import org.eclipse.swt.widgets.TabFolder; public class ExchangeTypeTabControl extends MBeanTypeTabControl { - public ExchangeTypeTabControl(TabFolder tabFolder) + public ExchangeTypeTabControl(TabFolder tabFolder, ManagedServer server, String virtualHost) { - super(tabFolder,EXCHANGE); + super(tabFolder, server, virtualHost, EXCHANGE); } @Override protected List<ManagedBean> getMbeans() { - ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(MBeanView.getServer()); - return serverRegistry.getExchanges(MBeanView.getVirtualHost()); + 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 index a16fbf8c98..94b69e1231 100644 --- 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 @@ -21,9 +21,15 @@ 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; @@ -64,13 +70,20 @@ public abstract class MBeanTypeTabControl extends TabControl protected Table _table = null; protected TableViewer _tableViewer = null; - private List<ManagedBean> _mbeans = null; + protected List<ManagedBean> _mbeans = null; private String _type; + protected ApiVersion _ApiVersion; + protected JMXManagedObject _vhostMbean; + protected String _virtualHost; + protected JMXServerRegistry _serverRegistry; - - public MBeanTypeTabControl(TabFolder tabFolder, String type) + 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); @@ -120,7 +133,7 @@ public abstract class MBeanTypeTabControl extends TabControl protected void createTable(Composite tableComposite) { - _table = new Table (tableComposite, SWT.SINGLE | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION); + _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); @@ -187,31 +200,14 @@ public abstract class MBeanTypeTabControl extends TabControl buttonComposite.setLayout(new GridLayout(2,true)); final Button favouritesButton = _toolkit.createButton(buttonComposite, - "<-- Add " + _type + " to favourites", SWT.PUSH); + "<-- 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) { - int selectionIndex = _table.getSelectionIndex(); - - if (selectionIndex != -1) - { - final ManagedBean selectedMBean = (ManagedBean)_table.getItem(selectionIndex).getData(); - - IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); - NavigationView view = (NavigationView)window.getActivePage().findView(NavigationView.ID); - try - { - view.addManagedBean(selectedMBean); - } - catch (Exception ex) - { - MBeanUtility.handleException(selectedMBean, ex); - } - - } + addMBeanToFavourites(); } }); @@ -222,23 +218,7 @@ public abstract class MBeanTypeTabControl extends TabControl { public void widgetSelected(SelectionEvent e) { - int selectionIndex = _table.getSelectionIndex(); - - if (selectionIndex != -1) - { - 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); - } - } + openMBean(); } }); @@ -257,16 +237,25 @@ public abstract class MBeanTypeTabControl extends TabControl { int selectionIndex = _table.getSelectionIndex(); - if (selectionIndex != -1) + if (selectionIndex == -1) { - favouritesButton.setEnabled(true); - openButton.setEnabled(true); + favouritesButton.setEnabled(false); + openButton.setEnabled(false); + return; } else { - favouritesButton.setEnabled(false); + favouritesButton.setEnabled(true); + } + + if(_table.getSelectionCount() > 1) + { openButton.setEnabled(false); } + else + { + openButton.setEnabled(true); + } } }); @@ -275,23 +264,7 @@ public abstract class MBeanTypeTabControl extends TabControl // MouseListener implementation public void mouseDoubleClick(MouseEvent event) { - int selectionIndex = _table.getSelectionIndex(); - - if (selectionIndex != -1) - { - 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); - } - } + openMBean(); } public void mouseDown(MouseEvent e){} @@ -403,4 +376,63 @@ public abstract class MBeanTypeTabControl extends TabControl 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 index 0e48c80a79..8f80426af8 100644 --- 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 @@ -23,16 +23,24 @@ package org.apache.qpid.management.ui.views.type; import java.util.ArrayList; import java.util.HashMap; import java.util.List; +import java.util.Map; + +import javax.management.MBeanServerConnection; +import javax.management.MBeanServerInvocationHandler; import static org.apache.qpid.management.ui.Constants.QUEUE; +import static org.apache.qpid.management.ui.Constants.ATTRIBUTE_QUEUE_DEPTH; +import org.apache.qpid.management.common.mbeans.ManagedBroker; import org.apache.qpid.management.ui.ApplicationRegistry; -import org.apache.qpid.management.ui.Constants; import org.apache.qpid.management.ui.ManagedBean; +import org.apache.qpid.management.ui.ManagedServer; import org.apache.qpid.management.ui.ServerRegistry; import org.apache.qpid.management.ui.jmx.MBeanUtility; import org.apache.qpid.management.ui.model.AttributeData; 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.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.LabelProvider; @@ -49,22 +57,60 @@ import org.eclipse.swt.widgets.Composite; 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 HashMap<ManagedBean, Long> _queueDepths = new HashMap<ManagedBean, Long>(); - private HashMap<ManagedBean, Long> _activeConsumerCounts = new HashMap<ManagedBean, Long>(); - + private MBeanServerConnection _mbsc; + private ManagedBroker _vhmb; + //Map for storing queue depths for servers using Qpid JMX API 1.2 and below + private Map<ManagedBean,Long> _queueDepths = new HashMap<ManagedBean, Long>(); + + public QueueTypeTabControl(TabFolder tabFolder, ManagedServer server, String virtualHost) + { + super(tabFolder,server,virtualHost,QUEUE); + _mbsc = (MBeanServerConnection) _serverRegistry.getServerConnection(); + _vhmb = (ManagedBroker) MBeanServerInvocationHandler.newProxyInstance(_mbsc, + _vhostMbean.getObjectName(), ManagedBroker.class, false); + } - public QueueTypeTabControl(TabFolder tabFolder) + @Override + public void refresh(ManagedBean mbean) { - super(tabFolder,QUEUE); + if(_ApiVersion.greaterThanOrEqualTo(1, 3)) + { + //Qpid JMX API 1.3+, use this virtualhosts VirtualHostManager MBean + //to retrieve the Queue Name and Queue Depth + + Map<String,Long> queueNamesDepths = null; + try + { + queueNamesDepths = _vhmb.viewQueueNamesDepths(); + } + catch(Exception e) + { + MBeanUtility.handleException(_vhostMbean, e); + } + + _tableViewer.setInput(queueNamesDepths); + } + else + { + //Qpid JMX API 1.2 or below, use the ManagedBeans and look + //up the attribute value for each + _mbeans = getMbeans(); + _tableViewer.setInput(_mbeans); + } + + layout(); } @Override protected List<ManagedBean> getMbeans() { ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(MBeanView.getServer()); + try { return extractQueueDetails(serverRegistry.getQueues(MBeanView.getVirtualHost())); @@ -80,36 +126,47 @@ public class QueueTypeTabControl extends MBeanTypeTabControl private List<ManagedBean> extractQueueDetails(List<ManagedBean> list) throws Exception { _queueDepths.clear(); - _activeConsumerCounts.clear(); - + List<ManagedBean> items = new ArrayList<ManagedBean>(); for (ManagedBean mbean : list) { - AttributeData data = MBeanUtility.getAttributeData(mbean, Constants.ATTRIBUTE_QUEUE_DEPTH); + AttributeData data = MBeanUtility.getAttributeData(mbean, ATTRIBUTE_QUEUE_DEPTH); _queueDepths.put(mbean, Long.valueOf(data.getValue().toString())); - data = MBeanUtility.getAttributeData(mbean, Constants.ATTRIBUTE_QUEUE_CONSUMERCOUNT); - _activeConsumerCounts.put(mbean, Long.valueOf(data.getValue().toString())); - + items.add(mbean); } return items; } - + @Override protected void createTable(Composite tableComposite) { - _table = new Table (tableComposite, SWT.SINGLE | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION); + _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 = new String[]{"Queue Name", "Queue Depth"}; + int[] bounds = new int[]{325, 200}; - String[] titles = { "Name", "QueueDepth", "Active Consumer Count"}; - int[] bounds = { 250, 175, 175}; + final TableSorter tableSorter; + + if(_ApiVersion.greaterThanOrEqualTo(1, 3)) + { + //QpidJMX API 1.3+ using the new getQueueNamesDepths method in VHostManager MBean. + //requires sorting Map.Entry elements + tableSorter = new NewerTableSorter(); + } + else + { + //QpidJMX API 1.2 or below. Requires sorting ManagedBeans and using the _queueDepths map + tableSorter = new OlderTableSorter(); + } + for (int i = 0; i < titles.length; i++) { final int index = i; @@ -145,17 +202,27 @@ public class QueueTypeTabControl extends MBeanTypeTabControl } - _tableViewer.setContentProvider(new ContentProviderImpl()); - _tableViewer.setLabelProvider(new LabelProviderImpl()); + if(_ApiVersion.greaterThanOrEqualTo(1, 3)) + { + _tableViewer.setContentProvider(new NewerContentProviderImpl()); + _tableViewer.setLabelProvider(new NewerLabelProviderImpl()); + } + else + { + _tableViewer.setContentProvider(new OlderContentProviderImpl()); + _tableViewer.setLabelProvider(new OlderLabelProviderImpl()); + } + + _tableViewer.setUseHashlookup(true); _tableViewer.setSorter(tableSorter); _table.setSortColumn(_table.getColumn(0)); _table.setSortDirection(SWT.UP); } /** - * Content Provider class for the table viewer + * Content Provider class for the table viewer for Qpid JMX API 1.2 and below. */ - private class ContentProviderImpl implements IStructuredContentProvider + private class OlderContentProviderImpl implements IStructuredContentProvider { public void inputChanged(Viewer v, Object oldInput, Object newInput) @@ -176,9 +243,9 @@ public class QueueTypeTabControl extends MBeanTypeTabControl } /** - * Label Provider class for the table viewer + * Label Provider class for the table viewer for Qpid JMX API 1.2 and below. */ - private class LabelProviderImpl extends LabelProvider implements ITableLabelProvider + private class OlderLabelProviderImpl extends LabelProvider implements ITableLabelProvider { @Override public String getColumnText(Object element, int columnIndex) @@ -190,9 +257,7 @@ public class QueueTypeTabControl extends MBeanTypeTabControl case 0 : // name column return mbean.getName(); case 1 : // queue depth column - return getQueueDepthString(mbean, _queueDepths.get(mbean)); - case 2 : // consumer count column - return String.valueOf(_activeConsumerCounts.get(mbean)); + return getQueueDepthString(_queueDepths.get(mbean)); default: return "-"; } @@ -205,12 +270,18 @@ public class QueueTypeTabControl extends MBeanTypeTabControl } } - private String getQueueDepthString(ManagedBean mbean, Long value) + private String getQueueDepthString(Long value) { - if (mbean.getVersion() == 1) //mbean is v1 and returns KB - { - Double mb = 1024.0; - + if(value == null) + { + return "-"; + } + + if (_ApiVersion.lessThanOrEqualTo(1,1)) + { + //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"; @@ -220,11 +291,12 @@ public class QueueTypeTabControl extends MBeanTypeTabControl return value + " KB"; } } - else //mbean is v2+ and returns Bytes + else { + //Qpid JMX API 1.2 or above, returns Bytes double mb = 1024.0 * 1024.0; double kb = 1024.0; - + if(value >= mb) //MB { return String.format("%.3f", (Double)(value / mb)) + " MB"; @@ -239,18 +311,19 @@ public class QueueTypeTabControl extends MBeanTypeTabControl } } } + /** - * Sorter class for the table viewer. + * Abstract sorter class for the table viewer. * */ - private class TableSorter extends ViewerSorter + private abstract class TableSorter extends ViewerSorter { - private int column; - private static final int ASCENDING = 0; - private static final int DESCENDING = 1; + protected int column; + protected static final int ASCENDING = 0; + protected static final int DESCENDING = 1; - private int direction; + protected int direction; public TableSorter() { @@ -274,6 +347,21 @@ public class QueueTypeTabControl extends MBeanTypeTabControl } @Override + public abstract int compare(Viewer viewer, Object e1, Object e2); + } + + /** + * sorter class for the table viewer for Qpid JMX API 1.2 and below. + * + */ + private class OlderTableSorter extends TableSorter + { + public OlderTableSorter() + { + super(); + } + + @Override public int compare(Viewer viewer, Object e1, Object e2) { ManagedBean mbean1 = (ManagedBean) e1; @@ -287,9 +375,44 @@ public class QueueTypeTabControl extends MBeanTypeTabControl break; case 1: //queue depth comparison = _queueDepths.get(mbean1).compareTo(_queueDepths.get(mbean2)); + default: + comparison = 0; + } + // If descending order, flip the direction + if(direction == DESCENDING) + { + comparison = -comparison; + } + return comparison; + } + } + + /** + * sorter class for the table viewer for Qpid JMX API 1.3 and above. + * + */ + private class NewerTableSorter extends TableSorter + { + public NewerTableSorter() + { + super(); + } + + @SuppressWarnings("unchecked") + @Override + public int compare(Viewer viewer, Object e1, Object e2) + { + Map.Entry<String, Long> queue1 = (Map.Entry<String, Long>) e1; + Map.Entry<String, Long> queue2 = (Map.Entry<String, Long>) e2; + + int comparison = 0; + switch(column) + { + case 0://name + comparison = (queue1.getKey()).compareTo(queue2.getKey()); break; - case 2: //active consumer count - comparison = _activeConsumerCounts.get(mbean1).compareTo(_activeConsumerCounts.get(mbean2)); + case 1://queue depth + comparison = (queue1.getValue()).compareTo(queue2.getValue());; break; default: comparison = 0; @@ -303,4 +426,152 @@ public class QueueTypeTabControl extends MBeanTypeTabControl } } + /** + * Content Provider class for the table viewer for Qpid JMX API 1.3 and above. + */ + private class NewerContentProviderImpl implements IStructuredContentProvider + { + + public void inputChanged(Viewer v, Object oldInput, Object newInput) + { + + } + + public void dispose() + { + + } + + @SuppressWarnings("unchecked") + public Object[] getElements(Object parent) + { + Map<String, Long> map = (Map<String, Long>) parent; + return map.entrySet().toArray(new Map.Entry[0]); + } + } + + /** + * Label Provider class for the table viewer for for Qpid JMX API 1.3 and above. + */ + private class NewerLabelProviderImpl extends LabelProvider implements ITableLabelProvider + { + @SuppressWarnings("unchecked") + @Override + public String getColumnText(Object element, int columnIndex) + { + Map.Entry<String, Long> queue = (Map.Entry<String, Long>) element; + + switch (columnIndex) + { + case 0 : // name column + return queue.getKey(); + case 1 : // depth column + return getQueueDepthString(queue.getValue()); + default : + return "-"; + } + } + + @Override + public Image getColumnImage(Object element, int columnIndex) + { + return null; + } + } + + @Override + protected void addMBeanToFavourites() + { + int selectionIndex = _table.getSelectionIndex(); + + if (selectionIndex == -1) + { + return; + } + + int[] selectedIndices = _table.getSelectionIndices(); + + ArrayList<ManagedBean> selectedMBeans = new ArrayList<ManagedBean>(); + + if(_ApiVersion.greaterThanOrEqualTo(1, 3)) + { + //if we have Qpid JMX API 1.3+ the entries are created from Map.Entry<String,Long> + for(int index = 0; index < selectedIndices.length ; index++) + { + Map.Entry<String, Long> queueEntry = (Map.Entry<String, Long>) _table.getItem(selectedIndices[index]).getData(); + String queueName = queueEntry.getKey(); + selectedMBeans.add(_serverRegistry.getQueue(queueName, _virtualHost)); + } + } + else + { + //if we have a Qpid JMX API 1.2 or less server, entries are created from ManagedBeans directly + for(int index = 0; index < selectedIndices.length ; index++) + { + ManagedBean mbean = (ManagedBean) _table.getItem(selectedIndices[index]).getData(); + selectedMBeans.add(mbean); + } + } + + 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); + } + } + + @Override + protected void openMBean() + { + int selectionIndex = _table.getSelectionIndex(); + + if (selectionIndex == -1) + { + return; + } + + ManagedBean selectedMBean; + + if(_ApiVersion.greaterThanOrEqualTo(1, 3)) + { + //if we have Qpid JMX API 1.3+ the entries are created from Map.Entry<String,Long> + Map.Entry<String, Long> queueEntry = (Map.Entry<String, Long>) _table.getItem(selectionIndex).getData(); + + String queueName = queueEntry.getKey(); + selectedMBean = _serverRegistry.getQueue(queueName, _virtualHost); + } + else + { + //if we have a Qpid JMX API 1.2 or less server, entries are created from ManagedBeans directly + selectedMBean = (ManagedBean)_table.getItem(selectionIndex).getData(); + } + + 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 index 30b0da1ae1..3abc83d0d8 100644 --- 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 @@ -20,13 +20,17 @@ */ package org.apache.qpid.management.ui.views.users; +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; @@ -75,6 +79,7 @@ public class UserManagementTabControl extends TabControl private TabularDataSupport _userDetails = null; private UserManagement _ummb; + private ApiVersion _ApiVersion; static final String USERNAME = UserManagement.COMPOSITE_ITEM_NAMES[0]; static final String RIGHTS_READ_ONLY = UserManagement.COMPOSITE_ITEM_NAMES[1]; @@ -85,6 +90,7 @@ public class UserManagementTabControl extends TabControl { super(tabFolder); _mbean = mbean; + _ApiVersion = ApplicationRegistry.getServerRegistry(mbean).getManagementApiVersion(); _ummb = (UserManagement) MBeanServerInvocationHandler.newProxyInstance(mbsc, mbean.getObjectName(), UserManagement.class, false); @@ -154,7 +160,7 @@ public class UserManagementTabControl extends TabControl tableComposite.setLayoutData(gridData); tableComposite.setLayout(new GridLayout(2,false)); - _table = new Table (tableComposite, SWT.SINGLE | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION); + _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); @@ -207,16 +213,29 @@ public class UserManagementTabControl extends TabControl _table.setSortDirection(SWT.UP); Composite buttonsComposite = _toolkit.createComposite(tableComposite); - gridData = new GridData(SWT.FILL, SWT.FILL, false, true); + gridData = new GridData(SWT.FILL, SWT.TOP, false, false); + gridData.heightHint = 165; buttonsComposite.setLayoutData(gridData); buttonsComposite.setLayout(new GridLayout()); - final Button deleteUserButton = _toolkit.createButton(buttonsComposite, "Delete User", SWT.PUSH); - gridData = new GridData(SWT.CENTER, SWT.TOP, false, false); + final Button addUserButton = _toolkit.createButton(buttonsComposite, "Add New User ...", SWT.PUSH); + gridData = new GridData(SWT.CENTER, SWT.TOP, false, true); gridData.widthHint = 125; - deleteUserButton.setLayoutData(gridData); - deleteUserButton.setEnabled(false); - deleteUserButton.addSelectionListener(new SelectionAdapter() + 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) { @@ -224,32 +243,13 @@ public class UserManagementTabControl extends TabControl if (selectionIndex != -1) { - final CompositeData selectedLogger = (CompositeData)_table.getItem(selectionIndex).getData(); - String user = selectedLogger.get(USERNAME).toString(); - - int response = ViewUtility.popupOkCancelConfirmationMessage("User Management", - "Delete user: " + user + " ?"); - if (response == SWT.OK) - { - try - { - boolean result = _ummb.deleteUser(user); - ViewUtility.operationResultFeedback(result, "Deleted user", "Failed to delete user"); - } - catch(Exception e1) - { - ViewUtility.operationFailedStatusBarMessage("Error deleting user"); - MBeanUtility.handleException(_mbean, e1); - } - - refresh(_mbean);; - } + deleteUsers(); } } }); final Button setPasswordButton = _toolkit.createButton(buttonsComposite, "Set Password ...", SWT.PUSH); - gridData = new GridData(SWT.CENTER, SWT.TOP, false, false); + gridData = new GridData(SWT.CENTER, SWT.BOTTOM, false, false); gridData.widthHint = 125; setPasswordButton.setLayoutData(gridData); setPasswordButton.setEnabled(false); @@ -317,7 +317,7 @@ public class UserManagementTabControl extends TabControl }); final Button setRightsButton = _toolkit.createButton(buttonsComposite, "Set Rights ...", SWT.PUSH); - gridData = new GridData(SWT.CENTER, SWT.TOP, false, false); + gridData = new GridData(SWT.CENTER, SWT.BOTTOM, false, false); gridData.widthHint = 125; setRightsButton.setLayoutData(gridData); setRightsButton.setEnabled(false); @@ -329,43 +329,36 @@ public class UserManagementTabControl extends TabControl if (selectionIndex != -1) { - final CompositeData selectedLogger = (CompositeData)_table.getItem( - selectionIndex).getData(); - String user = selectedLogger.get(USERNAME).toString(); - - setRights(setRightsButton.getShell(), user); + setRights(setRightsButton.getShell()); } } }); - final Button addUserButton = _toolkit.createButton(buttonsComposite, "Add New User ...", SWT.PUSH); - gridData = new GridData(SWT.CENTER, SWT.BOTTOM, false, true); - gridData.widthHint = 125; - addUserButton.setLayoutData(gridData); - addUserButton.addSelectionListener(new SelectionAdapter() - { - public void widgetSelected(SelectionEvent e) - { - addUser(addUserButton.getShell()); - } - }); - _tableViewer.addSelectionChangedListener(new ISelectionChangedListener(){ public void selectionChanged(SelectionChangedEvent evt) { int selectionIndex = _table.getSelectionIndex(); - if (selectionIndex != -1) + if (selectionIndex == -1) { - deleteUserButton.setEnabled(true); - setPasswordButton.setEnabled(true); - setRightsButton.setEnabled(true); + deleteUsersButton.setEnabled(false); + setRightsButton.setEnabled(false); + setPasswordButton.setEnabled(false); + return; } else { - deleteUserButton.setEnabled(false); + deleteUsersButton.setEnabled(true); + setRightsButton.setEnabled(true); + } + + if (_table.getSelectionCount() > 1) + { setPasswordButton.setEnabled(false); - setRightsButton.setEnabled(false); + } + else + { + setPasswordButton.setEnabled(true); } } }); @@ -379,12 +372,14 @@ public class UserManagementTabControl extends TabControl final Button reloadUserDetails = _toolkit.createButton(miscGroup, "Reload User Details", SWT.PUSH); - if(_mbean.getVersion() == 1) + 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() @@ -549,13 +544,48 @@ public class UserManagementTabControl extends TabControl } } - private void setRights(final Shell parent, final String user) + 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 '" + user + "':"); + 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)); @@ -590,14 +620,56 @@ public class UserManagementTabControl extends TabControl boolean admin = adminButton.getSelection(); shell.dispose(); + + HashMap<String,Boolean> results = new HashMap<String,Boolean>(); try { - boolean result = _ummb.setRights(user,read,write,admin); - ViewUtility.operationResultFeedback(result, "Updated user rights", "Failed to update user rights"); + //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 setting user rights"); + ViewUtility.operationFailedStatusBarMessage("Error updating user rights"); MBeanUtility.handleException(_mbean, e4); } refresh(_mbean); @@ -716,4 +788,97 @@ public class UserManagementTabControl extends TabControl shell.pack(); 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 index 2d5d4dc0d3..dae8d8d067 100644 --- 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 @@ -23,7 +23,9 @@ 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; @@ -47,6 +49,8 @@ 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; @@ -61,6 +65,8 @@ 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; @@ -81,12 +87,16 @@ public class VHostTabControl extends TabControl 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; - _ApiVersion = ApplicationRegistry.getServerRegistry(mbean).getManagementApiVersion(); + _serverRegistry = ApplicationRegistry.getServerRegistry(mbean); + _ApiVersion = _serverRegistry.getManagementApiVersion(); _vhmb = (ManagedBroker) MBeanServerInvocationHandler.newProxyInstance(mbsc, mbean.getObjectName(), ManagedBroker.class, false); _toolkit = new FormToolkit(_tabFolder.getDisplay()); @@ -122,15 +132,12 @@ public class VHostTabControl extends TabControl @Override public void refresh(ManagedBean mbean) { - List<ManagedBean> queues = null; - List<ManagedBean> exchanges = null; - ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(MBeanView.getServer()); - queues = serverRegistry.getQueues(MBeanView.getVirtualHost()); - exchanges = serverRegistry.getExchanges(MBeanView.getVirtualHost()); + _queues = serverRegistry.getQueues(MBeanView.getVirtualHost()); + _exchanges = serverRegistry.getExchanges(MBeanView.getVirtualHost()); - _queueTableViewer.setInput(queues); - _exchangeTableViewer.setInput(exchanges); + _queueTableViewer.setInput(_queues); + _exchangeTableViewer.setInput(_exchanges); layout(); } @@ -150,7 +157,7 @@ public class VHostTabControl extends TabControl GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true); queuesGroup.setLayoutData(gridData); - _queueTable = new Table (queuesGroup, SWT.SINGLE | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION); + _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); @@ -221,35 +228,7 @@ public class VHostTabControl extends TabControl { public void widgetSelected(SelectionEvent e) { - int selectionIndex = _queueTable.getSelectionIndex(); - - if (selectionIndex != -1) - { - final ManagedBean selectedQueue = (ManagedBean)_queueTable.getItem(selectionIndex).getData(); - String queue = selectedQueue.getName(); - - int response = ViewUtility.popupOkCancelConfirmationMessage("VirtualHost Manager", - "Delete queue: " + queue + " ?"); - if (response == SWT.OK) - { - try - { - _vhmb.deleteQueue(queue); - - ViewUtility.operationResultFeedback(null, "Deleted Queue", null); - //remove queue from list of managed beans - ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(MBeanView.getServer()); - serverRegistry.removeManagedObject(selectedQueue); - } - catch(Exception e1) - { - ViewUtility.operationFailedStatusBarMessage("Error deleting Queue"); - MBeanUtility.handleException(_mbean, e1); - } - - refresh(_mbean);; - } - } + deleteQueuesOrExchanges(deleteQueueButton.getShell(), VhostOperations.DELETE_QUEUE); } }); @@ -269,6 +248,18 @@ public class VHostTabControl extends TabControl } }); + //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()); @@ -277,7 +268,7 @@ public class VHostTabControl extends TabControl gridData = new GridData(SWT.FILL, SWT.FILL, true, true); exchangesGroup.setLayoutData(gridData); - _exchangeTable = new Table (exchangesGroup, SWT.SINGLE | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION); + _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); @@ -346,35 +337,7 @@ public class VHostTabControl extends TabControl { public void widgetSelected(SelectionEvent e) { - int selectionIndex = _exchangeTable.getSelectionIndex(); - - if (selectionIndex != -1) - { - final ManagedBean selectedExchange = (ManagedBean)_exchangeTable.getItem(selectionIndex).getData(); - String exchange = selectedExchange.getName(); - - int response = ViewUtility.popupOkCancelConfirmationMessage("VirtualHost Manager", - "Delete exchange: " + exchange + " ?"); - if (response == SWT.OK) - { - try - { - _vhmb.unregisterExchange(exchange); - - ViewUtility.operationResultFeedback(null, "Deleted Exchange", null); - //remove exchange from list of managed beans - ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(MBeanView.getServer()); - serverRegistry.removeManagedObject(selectedExchange); - } - catch(Exception e1) - { - ViewUtility.operationFailedStatusBarMessage("Error deleting Exchange"); - MBeanUtility.handleException(_mbean, e1); - } - - refresh(_mbean);; - } - } + deleteQueuesOrExchanges(deleteExchangeButton.getShell(), VhostOperations.DELETE_EXCHANGE); } }); @@ -394,6 +357,18 @@ public class VHostTabControl extends TabControl } }); + //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){} + }); } @@ -732,4 +707,155 @@ public class VHostTabControl extends TabControl 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(); + 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); + } + } } |