From 9dc57fe738f366d875c2319dafdfa2c50ce2f20b Mon Sep 17 00:00:00 2001 From: Keith Wall Date: Tue, 3 Mar 2015 14:56:40 +0000 Subject: merge from trunk git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/QPID-6262-JavaBrokerNIO@1663717 13f79535-47bb-0310-9956-ffa450edef68 --- .../protocol/v0_10/ServerConnectionDelegate.java | 24 +- .../protocol/v0_10/ServerSessionDelegate.java | 41 +++ .../qpid/server/protocol/v0_8/AMQChannel.java | 65 +++- .../server/protocol/v0_8/AMQProtocolEngine.java | 42 ++- .../qpid/server/protocol/v1_0/SendingLink_1_0.java | 22 +- .../js/qpid/management/virtualhost/derby/add.js | 9 +- .../js/qpid/management/virtualhost/derby/edit.js | 10 +- .../qpid/management/virtualhostnode/derby/edit.js | 7 +- .../js/qpid/management/store/pool/bonecp/show.js | 14 +- .../js/qpid/management/virtualhost/jdbc/add.js | 12 +- .../js/qpid/management/virtualhost/jdbc/edit.js | 9 +- .../js/qpid/management/virtualhost/jdbc/show.js | 9 +- .../js/qpid/management/virtualhostnode/jdbc/add.js | 11 +- .../qpid/management/virtualhostnode/jdbc/edit.js | 8 +- .../qpid/management/virtualhostnode/jdbc/show.js | 11 +- .../server/management/plugin/HttpManagement.java | 3 + .../plugin/report/QueueBinaryReport.java | 28 ++ .../management/plugin/report/QueueReport.java | 161 ++++++++ .../management/plugin/report/QueueTextReport.java | 28 ++ .../management/plugin/report/ReportRunner.java | 408 +++++++++++++++++++++ .../plugin/report/ReportableMessage.java | 42 +++ .../plugin/report/ReportableMessageHeader.java | 58 +++ .../rest/ConfiguredObjectToMapConverter.java | 4 +- .../plugin/servlet/rest/QueueReportServlet.java | 103 ++++++ .../src/main/java/resources/addPort.html | 17 + .../main/java/resources/editVirtualHostNode.html | 33 +- .../resources/js/qpid/common/ResourceWidget.js | 38 +- .../js/qpid/common/grid/ColumnDefDialog.js | 11 +- .../js/qpid/common/grid/RowNumberLimitDialog.js | 14 +- .../src/main/java/resources/js/qpid/common/util.js | 52 +-- .../js/qpid/management/AccessControlProvider.js | 12 +- .../js/qpid/management/AuthenticationProvider.js | 4 +- .../java/resources/js/qpid/management/Broker.js | 12 +- .../resources/js/qpid/management/Connection.js | 14 +- .../java/resources/js/qpid/management/Exchange.js | 5 +- .../resources/js/qpid/management/GroupProvider.js | 7 +- .../java/resources/js/qpid/management/KeyStore.js | 4 +- .../java/resources/js/qpid/management/Plugin.js | 7 +- .../main/java/resources/js/qpid/management/Port.js | 18 +- .../resources/js/qpid/management/Preferences.js | 11 +- .../js/qpid/management/PreferencesProvider.js | 5 +- .../java/resources/js/qpid/management/Queue.js | 5 +- .../resources/js/qpid/management/TrustStore.js | 4 +- .../resources/js/qpid/management/VirtualHost.js | 5 +- .../js/qpid/management/VirtualHostNode.js | 6 +- .../management/accesscontrolprovider/AclFile.js | 6 +- .../accesscontrolprovider/aclfile/add.js | 7 +- .../js/qpid/management/addAccessControlProvider.js | 7 +- .../qpid/management/addAuthenticationProvider.js | 7 +- .../js/qpid/management/addGroupProvider.js | 7 +- .../java/resources/js/qpid/management/addPort.js | 15 +- .../js/qpid/management/addPreferencesProvider.js | 7 +- .../java/resources/js/qpid/management/addStore.js | 14 +- .../management/addVirtualHostNodeAndVirtualHost.js | 7 +- .../PrincipalDatabaseAuthenticationManager.js | 6 +- .../base64md5passwordfile/add.js | 13 +- .../authenticationprovider/external/add.js | 13 +- .../plainpasswordfile/add.js | 13 +- .../authenticationprovider/simpleldap/add.js | 7 +- .../resources/js/qpid/management/editBroker.js | 7 +- .../java/resources/js/qpid/management/editQueue.js | 6 +- .../js/qpid/management/editVirtualHost.js | 6 +- .../js/qpid/management/editVirtualHostNode.js | 9 +- .../resources/js/qpid/management/group/Group.js | 5 +- .../groupprovider/GroupManagingGroupProvider.js | 15 +- .../qpid/management/groupprovider/groupfile/add.js | 13 +- .../qpid/management/logs/LogFileDownloadDialog.js | 8 +- .../resources/js/qpid/management/logs/LogViewer.js | 8 +- .../js/qpid/management/plugin/managementhttp.js | 5 +- .../js/qpid/management/plugin/managementjmx.js | 5 +- .../filesystempreferences/add.js | 13 +- .../filesystempreferences/show.js | 6 +- .../js/qpid/management/store/filekeystore/add.js | 79 ++-- .../js/qpid/management/store/filetruststore/add.js | 74 ++-- .../qpid/management/store/nonjavakeystore/add.js | 93 +++-- .../qpid/management/store/nonjavatruststore/add.js | 85 +++-- .../management/store/nonjavatruststore/show.js | 11 +- .../management/virtualhost/providedstore/add.js | 8 +- .../management/virtualhost/providedstore/edit.js | 11 +- .../qpid/management/virtualhostnode/json/edit.js | 7 +- .../src/main/java/resources/showPort.html | 81 ++-- .../src/main/java/resources/showQueue.html | 2 +- .../management/plugin/report/ReportRunnerTest.java | 186 ++++++++++ .../management/plugin/report/TestBinaryReport.java | 114 ++++++ .../management/plugin/report/TestTextReport.java | 84 +++++ .../rest/ConfiguredObjectToMapConverterTest.java | 1 + ...pid.server.management.plugin.report.QueueReport | 2 + .../qpid/server/jmx/mbeans/ConnectionMBean.java | 2 +- .../server/jmx/mbeans/ConnectionMBeanTest.java | 6 +- 89 files changed, 2062 insertions(+), 432 deletions(-) create mode 100644 qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/report/QueueBinaryReport.java create mode 100644 qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/report/QueueReport.java create mode 100644 qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/report/QueueTextReport.java create mode 100644 qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/report/ReportRunner.java create mode 100644 qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/report/ReportableMessage.java create mode 100644 qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/report/ReportableMessageHeader.java create mode 100644 qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueReportServlet.java create mode 100644 qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/report/ReportRunnerTest.java create mode 100644 qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/report/TestBinaryReport.java create mode 100644 qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/report/TestTextReport.java create mode 100644 qpid/java/broker-plugins/management-http/src/test/resources/META-INF/services/org.apache.qpid.server.management.plugin.report.QueueReport (limited to 'qpid/java/broker-plugins') diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnectionDelegate.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnectionDelegate.java index 78228c209f..6e2a6cac7d 100644 --- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnectionDelegate.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerConnectionDelegate.java @@ -184,7 +184,8 @@ public class ServerConnectionDelegate extends ServerDelegate vhostName = ""; } - vhost = ((AmqpPort)sconn.getPort()).getVirtualHost(vhostName); + AmqpPort port = (AmqpPort) sconn.getPort(); + vhost = port.getVirtualHost(vhostName); @@ -193,14 +194,28 @@ public class ServerConnectionDelegate extends ServerDelegate if (vhost.getState() != State.ACTIVE) { sconn.setState(Connection.State.CLOSING); - sconn.invoke(new ConnectionClose(ConnectionCloseCode.CONNECTION_FORCED, "Virtual host '"+vhostName+"' is not active")); + final String redirectHost = vhost.getRedirectHost(port); + if(redirectHost == null) + { + sconn.invoke(new ConnectionClose(ConnectionCloseCode.CONNECTION_FORCED, + "Virtual host '" + vhostName + "' is not active")); + } + else + { + sconn.invoke(new ConnectionRedirect(redirectHost, new ArrayList())); + } return; } sconn.setVirtualHost(vhost); try { - vhost.getSecurityManager().authoriseCreateConnection(sconn); + if(!vhost.authoriseCreateConnection(sconn)) + { + sconn.setState(Connection.State.CLOSING); + sconn.invoke(new ConnectionClose(ConnectionCloseCode.CONNECTION_FORCED, "Connection not authorized")); + return; + } } catch (AccessControlException e) { @@ -215,7 +230,8 @@ public class ServerConnectionDelegate extends ServerDelegate else { sconn.setState(Connection.State.CLOSING); - sconn.invoke(new ConnectionClose(ConnectionCloseCode.INVALID_PATH, "Unknown virtualhost '"+vhostName+"'")); + sconn.invoke(new ConnectionClose(ConnectionCloseCode.INVALID_PATH, + "Unknown virtualhost '" + vhostName + "'")); } } diff --git a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java index c42630d0c6..dd634c36ff 100644 --- a/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java +++ b/qpid/java/broker-plugins/amqp-0-10-protocol/src/main/java/org/apache/qpid/server/protocol/v0_10/ServerSessionDelegate.java @@ -33,6 +33,7 @@ import java.util.UUID; import org.apache.log4j.Logger; +import org.apache.qpid.common.AMQPFilterTypes; import org.apache.qpid.exchange.ExchangeDefaults; import org.apache.qpid.protocol.AMQConstant; import org.apache.qpid.server.protocol.ServerProtocolEngine; @@ -40,8 +41,10 @@ import org.apache.qpid.server.consumer.ConsumerImpl; import org.apache.qpid.server.exchange.ExchangeImpl; import org.apache.qpid.server.virtualhost.VirtualHostUnavailableException; import org.apache.qpid.server.filter.AMQInvalidArgumentException; +import org.apache.qpid.server.filter.ArrivalTimeFilter; import org.apache.qpid.server.filter.FilterManager; import org.apache.qpid.server.filter.FilterManagerFactory; +import org.apache.qpid.server.filter.MessageFilter; import org.apache.qpid.server.logging.messages.ChannelMessages; import org.apache.qpid.server.logging.messages.ExchangeMessages; import org.apache.qpid.server.message.InstanceProperties; @@ -259,6 +262,43 @@ public class ServerSessionDelegate extends SessionDelegate return; } + + if(method.hasArguments() && method.getArguments().containsKey(AMQPFilterTypes.REPLAY_PERIOD.toString())) + { + Object value = method.getArguments().get(AMQPFilterTypes.REPLAY_PERIOD.toString()); + final long period; + if(value instanceof Number) + { + period = ((Number)value).longValue(); + } + else if(value instanceof String) + { + try + { + period = Long.parseLong(value.toString()); + } + catch (NumberFormatException e) + { + exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "Cannot parse value " + value + " as a number for filter " + AMQPFilterTypes.REPLAY_PERIOD.toString()); + return; + } + } + else + { + exception(session, method, ExecutionErrorCode.ILLEGAL_ARGUMENT, "Cannot parse value " + value + " as a number for filter " + AMQPFilterTypes.REPLAY_PERIOD.toString()); + return; + } + final long startingFrom = System.currentTimeMillis() - (1000l * period); + if(filterManager == null) + { + filterManager = new FilterManager(); + } + MessageFilter filter = new ArrivalTimeFilter(startingFrom); + filterManager.add(filter.getName(), filter); + + } + + ConsumerTarget_0_10 target = new ConsumerTarget_0_10((ServerSession)session, destination, method.getAcceptMode(), method.getAcquireMode(), @@ -1609,4 +1649,5 @@ public class ServerSessionDelegate extends SessionDelegate { } } + } diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java index 9631530f90..18ebc94187 100644 --- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQChannel.java @@ -59,11 +59,11 @@ import org.apache.qpid.server.consumer.ConsumerImpl; import org.apache.qpid.server.consumer.ConsumerTarget; import org.apache.qpid.server.exchange.ExchangeImpl; import org.apache.qpid.server.filter.AMQInvalidArgumentException; +import org.apache.qpid.server.filter.ArrivalTimeFilter; import org.apache.qpid.server.filter.FilterManager; import org.apache.qpid.server.filter.FilterManagerFactory; import org.apache.qpid.server.filter.Filterable; import org.apache.qpid.server.filter.MessageFilter; -import org.apache.qpid.server.filter.SimpleFilterManager; import org.apache.qpid.server.flow.FlowCreditManager; import org.apache.qpid.server.logging.LogMessage; import org.apache.qpid.server.logging.LogSubject; @@ -673,7 +673,7 @@ public class AMQChannel * @param tag the tag chosen by the client (if null, server will generate one) * @param sources the queues to subscribe to * @param acks Are acks enabled for this subscriber - * @param filters Filters to apply to this subscriber + * @param arguments Filters to apply to this subscriber * * @param exclusive Flag requesting exclusive access to the queue * @return the consumer tag. This is returned to the subscriber and used in subsequent unsubscribe requests @@ -681,7 +681,7 @@ public class AMQChannel * @throws org.apache.qpid.AMQException if something goes wrong */ public AMQShortString consumeFromSource(AMQShortString tag, Collection sources, boolean acks, - FieldTable filters, boolean exclusive, boolean noLocal) + FieldTable arguments, boolean exclusive, boolean noLocal) throws MessageSource.ExistingConsumerPreventsExclusive, MessageSource.ExistingExclusiveConsumer, AMQInvalidArgumentException, @@ -700,19 +700,19 @@ public class AMQChannel ConsumerTarget_0_8 target; EnumSet options = EnumSet.noneOf(ConsumerImpl.Option.class); - if(filters != null && Boolean.TRUE.equals(filters.get(AMQPFilterTypes.NO_CONSUME.getValue()))) + if(arguments != null && Boolean.TRUE.equals(arguments.get(AMQPFilterTypes.NO_CONSUME.getValue()))) { - target = ConsumerTarget_0_8.createBrowserTarget(this, tag, filters, _noAckCreditManager); + target = ConsumerTarget_0_8.createBrowserTarget(this, tag, arguments, _noAckCreditManager); } else if(acks) { - target = ConsumerTarget_0_8.createAckTarget(this, tag, filters, _creditManager); + target = ConsumerTarget_0_8.createAckTarget(this, tag, arguments, _creditManager); options.add(ConsumerImpl.Option.ACQUIRES); options.add(ConsumerImpl.Option.SEES_REQUEUES); } else { - target = ConsumerTarget_0_8.createNoAckTarget(this, tag, filters, _noAckCreditManager); + target = ConsumerTarget_0_8.createNoAckTarget(this, tag, arguments, _noAckCreditManager); options.add(ConsumerImpl.Option.ACQUIRES); options.add(ConsumerImpl.Option.SEES_REQUEUES); } @@ -732,23 +732,66 @@ public class AMQChannel try { - FilterManager filterManager = FilterManagerFactory.createManager(FieldTable.convertToMap(filters)); + FilterManager filterManager = FilterManagerFactory.createManager(FieldTable.convertToMap(arguments)); if(noLocal) { if(filterManager == null) { - filterManager = new SimpleFilterManager(); + filterManager = new FilterManager(); } final Object connectionReference = getConnectionReference(); - filterManager.add(new MessageFilter() + MessageFilter filter = new MessageFilter() { + + @Override + public String getName() + { + return AMQPFilterTypes.NO_LOCAL.toString(); + } + @Override public boolean matches(final Filterable message) { return message.getConnectionReference() != connectionReference; } - }); + }; + filterManager.add(filter.getName(), filter); + } + + if(arguments != null && arguments.containsKey(AMQPFilterTypes.REPLAY_PERIOD.toString())) + { + Object value = arguments.get(AMQPFilterTypes.REPLAY_PERIOD.toString()); + final long period; + if(value instanceof Number) + { + period = ((Number)value).longValue(); + } + else if(value instanceof String) + { + try + { + period = Long.parseLong(value.toString()); + } + catch (NumberFormatException e) + { + throw new AMQInvalidArgumentException("Cannot parse value " + value + " as a number for filter " + AMQPFilterTypes.REPLAY_PERIOD.toString()); + } + } + else + { + throw new AMQInvalidArgumentException("Cannot parse value " + value + " as a number for filter " + AMQPFilterTypes.REPLAY_PERIOD.toString()); + } + + final long startingFrom = System.currentTimeMillis() - (1000l * period); + if(filterManager == null) + { + filterManager = new FilterManager(); + } + MessageFilter filter = new ArrivalTimeFilter(startingFrom); + filterManager.add(filter.getName(), filter); + } + for(MessageSource source : sources) { ConsumerImpl sub = diff --git a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java index 659207d9e8..d58ac36ff5 100644 --- a/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java +++ b/qpid/java/broker-plugins/amqp-0-8-protocol/src/main/java/org/apache/qpid/server/protocol/v0_8/AMQProtocolEngine.java @@ -1565,7 +1565,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, virtualHostStr = virtualHostName == null ? null : virtualHostName.toString(); } - VirtualHostImpl virtualHost = ((AmqpPort)getPort()).getVirtualHost(virtualHostStr); + VirtualHostImpl virtualHost = ((AmqpPort)getPort()).getVirtualHost(virtualHostStr); if (virtualHost == null) { @@ -1578,8 +1578,16 @@ public class AMQProtocolEngine implements ServerProtocolEngine, // Check virtualhost access if (virtualHost.getState() != State.ACTIVE) { - closeConnection(AMQConstant.CONNECTION_FORCED, - "Virtual host '" + virtualHost.getName() + "' is not active",0); + String redirectHost = virtualHost.getRedirectHost(getPort()); + if(redirectHost != null) + { + closeConnection(0, new AMQFrame(0,new ConnectionRedirectBody(getProtocolVersion(),AMQShortString.valueOf(redirectHost), null))); + } + else + { + closeConnection(AMQConstant.CONNECTION_FORCED, + "Virtual host '" + virtualHost.getName() + "' is not active", 0); + } } else @@ -1587,21 +1595,29 @@ public class AMQProtocolEngine implements ServerProtocolEngine, setVirtualHost(virtualHost); try { - virtualHost.getSecurityManager().authoriseCreateConnection(this); - if (getContextKey() == null) + + if(virtualHost.authoriseCreateConnection(this)) { - setContextKey(new AMQShortString(Long.toString(System.currentTimeMillis()))); - } + if (getContextKey() == null) + { + setContextKey(new AMQShortString(Long.toString(System.currentTimeMillis()))); + } + + MethodRegistry methodRegistry = getMethodRegistry(); + AMQMethodBody responseBody = methodRegistry.createConnectionOpenOkBody(virtualHostName); - MethodRegistry methodRegistry = getMethodRegistry(); - AMQMethodBody responseBody = methodRegistry.createConnectionOpenOkBody(virtualHostName); + writeFrame(responseBody.generateFrame(0)); + _state = ConnectionState.OPEN; - writeFrame(responseBody.generateFrame(0)); - _state = ConnectionState.OPEN; + } + else + { + closeConnection(AMQConstant.ACCESS_REFUSED, "Connection refused",0); + } } catch (AccessControlException e) { - closeConnection(AMQConstant.ACCESS_REFUSED, e.getMessage(),0); + closeConnection(AMQConstant.ACCESS_REFUSED, e.getMessage(), 0); } } } @@ -1767,7 +1783,7 @@ public class AMQProtocolEngine implements ServerProtocolEngine, _logger.info("Locale selected: " + locale); SubjectCreator subjectCreator = getSubjectCreator(); - SaslServer ss = null; + SaslServer ss; try { ss = subjectCreator.createSaslServer(String.valueOf(mechanism), diff --git a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java index 6a202998f4..fe36ba91cb 100644 --- a/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java +++ b/qpid/java/broker-plugins/amqp-1-0-protocol/src/main/java/org/apache/qpid/server/protocol/v1_0/SendingLink_1_0.java @@ -65,8 +65,8 @@ import org.apache.qpid.filter.selector.ParseException; import org.apache.qpid.server.binding.BindingImpl; import org.apache.qpid.server.consumer.ConsumerImpl; import org.apache.qpid.server.exchange.ExchangeImpl; +import org.apache.qpid.server.filter.FilterManager; import org.apache.qpid.server.filter.JMSSelectorFilter; -import org.apache.qpid.server.filter.SimpleFilterManager; import org.apache.qpid.server.message.MessageInstance; import org.apache.qpid.server.message.MessageSource; import org.apache.qpid.server.model.ExclusivityPolicy; @@ -154,15 +154,7 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS actualFilters.put(entry.getKey(), entry.getValue()); } - catch (ParseException e) - { - Error error = new Error(); - error.setCondition(AmqpError.INVALID_FIELD); - error.setDescription("Invalid JMS Selector: " + selectorFilter.getValue()); - error.setInfo(Collections.singletonMap(Symbol.valueOf("field"), Symbol.valueOf("filter"))); - throw new AmqpErrorException(error); - } - catch (SelectorParsingException e) + catch (ParseException | SelectorParsingException e) { Error error = new Error(); error.setCondition(AmqpError.INVALID_FIELD); @@ -374,8 +366,16 @@ public class SendingLink_1_0 implements SendingLinkListener, Link_1_0, DeliveryS { name = getEndpoint().getName(); } + + FilterManager filters = null; + if(messageFilter != null) + { + filters = new FilterManager(); + filters.add(messageFilter.getName(), messageFilter); + } + _consumer = _queue.addConsumer(_target, - messageFilter == null ? null : new SimpleFilterManager(messageFilter), + filters, Message_1_0.class, name, options); } catch (MessageSource.ExistingExclusiveConsumer e) diff --git a/qpid/java/broker-plugins/derby-store/src/main/java/resources/js/qpid/management/virtualhost/derby/add.js b/qpid/java/broker-plugins/derby-store/src/main/java/resources/js/qpid/management/virtualhost/derby/add.js index 7b12d10343..323b8e9750 100644 --- a/qpid/java/broker-plugins/derby-store/src/main/java/resources/js/qpid/management/virtualhost/derby/add.js +++ b/qpid/java/broker-plugins/derby-store/src/main/java/resources/js/qpid/management/virtualhost/derby/add.js @@ -34,10 +34,11 @@ define(["dojo/_base/xhr", show: function (data) { this.containerNode = domConstruct.create("div", {innerHTML: template}, data.containerNode); - parser.parse(this.containerNode); - - registry.byId("addVirtualHost.storeUnderfullSize").set("regExpGen", util.numericOrContextVarRegexp); - registry.byId("addVirtualHost.storeOverfullSize").set("regExpGen", util.numericOrContextVarRegexp); + parser.parse(this.containerNode).then(function(instances) + { + registry.byId("addVirtualHost.storeUnderfullSize").set("regExpGen", util.numericOrContextVarRegexp); + registry.byId("addVirtualHost.storeOverfullSize").set("regExpGen", util.numericOrContextVarRegexp); + }); } }; } diff --git a/qpid/java/broker-plugins/derby-store/src/main/java/resources/js/qpid/management/virtualhost/derby/edit.js b/qpid/java/broker-plugins/derby-store/src/main/java/resources/js/qpid/management/virtualhost/derby/edit.js index a8b68a0c16..c1018313b8 100644 --- a/qpid/java/broker-plugins/derby-store/src/main/java/resources/js/qpid/management/virtualhost/derby/edit.js +++ b/qpid/java/broker-plugins/derby-store/src/main/java/resources/js/qpid/management/virtualhost/derby/edit.js @@ -22,10 +22,12 @@ define(["qpid/common/util", "dijit/registry", "dojo/domReady!"], return { show: function(data) { - util.buildEditUI(data.containerNode, "virtualhost/sizemonitoring/edit.html", "editVirtualHost.", null, null); - - registry.byId("editVirtualHost.storeUnderfullSize").set("regExpGen", util.numericOrContextVarRegexp); - registry.byId("editVirtualHost.storeOverfullSize").set("regExpGen", util.numericOrContextVarRegexp); + util.parseHtmlIntoDiv(data.containerNode, "virtualhost/sizemonitoring/edit.html", + function() + { + registry.byId("editVirtualHost.storeUnderfullSize").set("regExpGen", util.numericOrContextVarRegexp); + registry.byId("editVirtualHost.storeOverfullSize").set("regExpGen", util.numericOrContextVarRegexp); + }); } }; } diff --git a/qpid/java/broker-plugins/derby-store/src/main/java/resources/js/qpid/management/virtualhostnode/derby/edit.js b/qpid/java/broker-plugins/derby-store/src/main/java/resources/js/qpid/management/virtualhostnode/derby/edit.js index 5fa0443185..a7f5d05719 100644 --- a/qpid/java/broker-plugins/derby-store/src/main/java/resources/js/qpid/management/virtualhostnode/derby/edit.js +++ b/qpid/java/broker-plugins/derby-store/src/main/java/resources/js/qpid/management/virtualhostnode/derby/edit.js @@ -22,8 +22,11 @@ define(["qpid/common/util", "dijit/registry", "dojo/domReady!"], return { show: function(data) { - util.buildEditUI(data.containerNode, "virtualhostnode/filebased/edit.html", "editVirtualHostNode.", ["storePath"], data.data); - registry.byId("editVirtualHostNode.storePath").set("disabled", data.data.state != "STOPPED"); + util.parseHtmlIntoDiv(data.containerNode, "virtualhostnode/filebased/edit.html", + function() + { + registry.byId("editVirtualHostNode.storePath").set("disabled", data.data.state != "STOPPED"); + }); } }; } diff --git a/qpid/java/broker-plugins/jdbc-provider-bone/src/main/java/resources/js/qpid/management/store/pool/bonecp/show.js b/qpid/java/broker-plugins/jdbc-provider-bone/src/main/java/resources/js/qpid/management/store/pool/bonecp/show.js index 31e5db5035..3d15cdbc37 100644 --- a/qpid/java/broker-plugins/jdbc-provider-bone/src/main/java/resources/js/qpid/management/store/pool/bonecp/show.js +++ b/qpid/java/broker-plugins/jdbc-provider-bone/src/main/java/resources/js/qpid/management/store/pool/bonecp/show.js @@ -40,13 +40,15 @@ define(["dojo/_base/xhr", sync: true, load: function(template) { containerNode.innerHTML = template; - parser.parse(containerNode); + parser.parse(containerNode).then(function(instances) + { + for(var i=0; i implem root.addServlet(new ServletHolder(new StructureServlet()), "/service/structure"); root.addServlet(new ServletHolder(new MessageServlet()), "/service/message/*"); root.addServlet(new ServletHolder(new MessageContentServlet()), "/service/message-content/*"); + root.addServlet(new ServletHolder(new QueueReportServlet()), "/service/queuereport/*"); + root.addServlet(new ServletHolder(new LogRecordsServlet()), "/service/logrecords"); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/report/QueueBinaryReport.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/report/QueueBinaryReport.java new file mode 100644 index 0000000000..d842de3f1b --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/report/QueueBinaryReport.java @@ -0,0 +1,28 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.management.plugin.report; + +public abstract class QueueBinaryReport extends QueueReport +{ + public QueueBinaryReport() + { + } +} diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/report/QueueReport.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/report/QueueReport.java new file mode 100644 index 0000000000..23b24aaf8d --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/report/QueueReport.java @@ -0,0 +1,161 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.management.plugin.report; + +import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.model.VirtualHost; + +/** + *

+ * The QueueReport class provides an extension point for installations to provide custom management reporting on + * queues through the REST API. + *

+ * + *

+ * A custom QueueReport must extend either {@link org.apache.qpid.server.management.plugin.report.QueueTextReport} + * or {@link org.apache.qpid.server.management.plugin.report.QueueBinaryReport}. The report implementation must + * define a {@link #getName() name} which is unique amongst all installed reports. The report class must be present + * in the classpath of the broker, and a provider-configuration file named + * org.apache.qpid.server.management.plugin.report.QueueReport must be added in the resource directory + * META-INF/services directory with the binary name of the implementation (as described in + * {@link java.util.ServiceLoader ServiceLoader}). + *

+ * + *

Running reports

+ *

+ * The report can be run using the URL: + * {@code http:///service/queuereport///[?param1=x¶m2=y...]} + *

+ * + *

Report Parameters

+ * + *

+ * Reports can take parameters from the query string of the HTTP request. For every parameter in the query string + * the system will look for a setter on the report object with either a String or String[] parameter. Thus if + * the query string contains {@code foo=bar}, then the system will look for a setter {@code setFoo(String value)} or + * {@code setFoo(String[] value)}. If the same parameter occurs multiple times in the query string then only the + * array variant of the setter will be called. + *

+ *

+ * Setters for the parameters are guaranteed to be called before the first message is added to the report. + *

+ * + *

+ * NOTE: In order to comply with the requirements of the {@link java.util.ServiceLoader ServiceLoader} api, all + * implementations of QueueReport MUST provide a public no-args constructor. + *

+ * @param + */ +public abstract class QueueReport +{ + private Queue _queue; + + QueueReport() + { + + } + + /** + * Gets the name of the report. + *

+ * The name of the report must be unique amongst all installed implementations. The name of the report + * is examined by the Qpid immediately upon construction. The name should not change during + * the lifetime of the object (the value is only meaningful to the system at the time of initial construction) + * and all instances of the same concrete implementation should have the same name. + *

+ * @return the name of the report + */ + public abstract String getName(); + + /** + * Get the name of the queue against which the report is being run. + * + * @return the name of the queue + */ + public final String getQueueName() + { + return _queue.getName(); + } + + final void setQueue(final Queue queue) + { + _queue = queue; + } + + /** + * Get the name of the virtual host against which the report is being run. + * + * @return the name of the virtual host + */ + public final String getVirtualHostName() + { + return _queue.getParent(VirtualHost.class).getName(); + } + + /** + * + * The value returned by getContentType() will be used to set the Content-Type HTTP header field + * + * @return the value to use for the content-type HTTP header field + */ + public abstract String getContentType(); + + /** + * Called by the system to add a message to the report. + * + *

+ * The method is called by the system for every message on the queue, or until {@link #isComplete()} returns true. + *

+ * @param reportableMessage the message to add to the report + */ + public abstract void addMessage(final ReportableMessage reportableMessage); + + /** + * Informs the system if the report is complete (i.e. does not need to report on any more messages). + * + *

+ * This method will be called by the system after each message is {@link #addMessage(ReportableMessage) added} + * to the report. If a report is only interested in some messages, and can determine that the addition of more + * messages will not vary the content of the report, then it can return true. + *

+ *

+ * If this method always returns false, then all messages from the queue will be added to the report. + *

+ *

+ * NOTE: Retrieving content or properties of the message may require it to be reloaded from disk, and so care + * should be taken by reports to only access properties/content of the message if it is going to be required + * for the report production. + *

+ * + * @return true if the report does not want to report on any more messages in the queue + */ + public abstract boolean isComplete(); + + /** + * Called by the system to get the content of the report to retrun to the user. + *

+ * The system guarantees to only call this method once + *

+ * @return the report content. + */ + public abstract T getReport(); + +} diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/report/QueueTextReport.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/report/QueueTextReport.java new file mode 100644 index 0000000000..09bc5c4229 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/report/QueueTextReport.java @@ -0,0 +1,28 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.management.plugin.report; + +public abstract class QueueTextReport extends QueueReport +{ + public QueueTextReport() + { + } +} diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/report/ReportRunner.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/report/ReportRunner.java new file mode 100644 index 0000000000..2a05cfc9a1 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/report/ReportRunner.java @@ -0,0 +1,408 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.management.plugin.report; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.ServiceLoader; +import java.util.Set; +import java.util.UUID; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.queue.QueueEntry; +import org.apache.qpid.server.queue.QueueEntryVisitor; + +public class ReportRunner +{ + private static final Logger LOGGER = LoggerFactory.getLogger(ReportRunner.class); + + private static final Set IMMUTABLE_CLASSES = new HashSet<>(Arrays.asList( + Boolean.class, + Byte.class, + Short.class, + Character.class, + Integer.class, + Long.class, + Float.class, + Double.class, + UUID.class, + Date.class, + String.class + )); + + private ReportRunner(final QueueReport report) + { + _report = report; + } + + public boolean isBinaryReport() + { + return _report instanceof QueueBinaryReport; + } + + public static ReportRunner createRunner(final String reportName, final Map parameterMap) + { + QueueReport report = getReport(reportName); + setReportParameters(report, parameterMap); + return new ReportRunner<>(report); + } + + private static void setReportParameters(final QueueReport report, final Map parameterMap) + { + if(parameterMap != null && !parameterMap.isEmpty()) + { + Class clazz = report.getClass(); + for(Map.Entry entry : parameterMap.entrySet()) + { + String key = entry.getKey(); + String[] value = entry.getValue(); + if(isValidName(key)) + { + + StringBuilder setterName = new StringBuilder("set"); + setterName.append(key.substring(0,1).toUpperCase()); + if(key.length()>1) + { + setterName.append(key.substring(1)); + } + Method method = null; + try + { + + if (value == null || value.length == 0 || value.length == 1) + { + try + { + method = clazz.getMethod(setterName.toString(), String.class); + method.invoke(report, value == null || value.length == 0 ? null : value[0]); + } + catch (NoSuchMethodException | IllegalAccessException e) + { + method = null; + } + } + if (method == null) + { + try + { + method = clazz.getMethod(setterName.toString(), String[].class); + method.invoke(report, new Object[] { value }); + } + catch (NoSuchMethodException | IllegalAccessException e) + { + LOGGER.info("Unknown parameter '" + + key + + "' (no setter) for report " + + report.getName()); + } + } + } + catch (InvocationTargetException e) + { + LOGGER.info("Error setting parameter '" + key + "' for report " + report.getName(), e); + } + } + else + { + LOGGER.info("Invalid parameter name '" + key + "' running report " + report.getName()); + } + } + } + } + + private static boolean isValidName(final String key) + { + if(key != null && key.length() != 0) + { + if(Character.isJavaIdentifierStart(key.charAt(0))) + { + for(int i = 1; i < key.length(); i++) + { + if(!Character.isJavaIdentifierPart(key.charAt(i))) + { + return false; + } + } + return true; + } + + } + return false; + + } + + private static QueueReport getReport(final String reportName) + { + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + for (final QueueReport report : ServiceLoader.load(QueueReport.class, classLoader)) + { + if (report.getName().equals(reportName)) + { + try + { + return report.getClass().newInstance(); + } + catch (InstantiationException | IllegalAccessException e) + { + // can't happen as by definition must have public noargs constructor + } + } + } + throw new IllegalArgumentException("Unknown report: " + reportName); + } + + public String getContentType() + { + return _report.getContentType(); + } + + + private static class ReportVisitor implements QueueEntryVisitor + { + + private final QueueReport _report; + + public ReportVisitor(final QueueReport report) + { + _report = report; + } + + @Override + public boolean visit(final QueueEntry entry) + { + _report.addMessage(convertMessage(entry.getMessage())); + return _report.isComplete(); + } + + + } + + + private static ReportableMessage convertMessage(final ServerMessage message) + { + return new ReportableMessage() + { + @Override + public String getInitialRoutingAddress() + { + return message.getInitialRoutingAddress(); + } + + @Override + public ReportableMessageHeader getMessageHeader() + { + return convertMessageHeader(message.getMessageHeader()); + } + + @Override + public ByteBuffer getContent() + { + ByteBuffer content = message.getContent(0, (int) getSize()); + + return content.asReadOnlyBuffer(); + } + + @Override + public boolean isPersistent() + { + return message.isPersistent(); + } + + @Override + public long getSize() + { + return message.getSize(); + } + + @Override + public long getExpiration() + { + return message.getExpiration(); + } + + @Override + public long getMessageNumber() + { + return message.getMessageNumber(); + } + + @Override + public long getArrivalTime() + { + return message.getArrivalTime(); + } + }; + } + + private static ReportableMessageHeader convertMessageHeader(final AMQMessageHeader messageHeader) + { + return new ReportableMessageHeader() + { + @Override + public String getCorrelationId() + { + return messageHeader.getCorrelationId(); + } + + @Override + public long getExpiration() + { + return messageHeader.getExpiration(); + } + + @Override + public String getUserId() + { + return messageHeader.getUserId(); + } + + @Override + public String getAppId() + { + return messageHeader.getAppId(); + } + + @Override + public String getMessageId() + { + return messageHeader.getMessageId(); + } + + @Override + public String getMimeType() + { + return messageHeader.getMimeType(); + } + + @Override + public String getEncoding() + { + return messageHeader.getEncoding(); + } + + @Override + public byte getPriority() + { + return messageHeader.getPriority(); + } + + @Override + public long getTimestamp() + { + return messageHeader.getTimestamp(); + } + + @Override + public String getType() + { + return messageHeader.getType(); + } + + @Override + public String getReplyTo() + { + return messageHeader.getReplyTo(); + } + + @Override + public Object getHeader(final String name) + { + return makeImmutable(messageHeader.getHeader(name)); + } + + @Override + public boolean containsHeaders(final Set names) + { + return messageHeader.containsHeaders(names); + } + + @Override + public boolean containsHeader(final String name) + { + return messageHeader.containsHeader(name); + } + + @Override + public Collection getHeaderNames() + { + return Collections.unmodifiableCollection(messageHeader.getHeaderNames()); + } + }; + } + + private static Object makeImmutable(final Object value) + { + if(value == null || IMMUTABLE_CLASSES.contains(value.getClass())) + { + return value; + } + else if(value instanceof byte[]) + { + return ByteBuffer.wrap((byte[])value).asReadOnlyBuffer(); + } + else if(value instanceof List) + { + List orig = (List) value; + List copy = new ArrayList<>(orig.size()); + for(Object element : orig) + { + copy.add(makeImmutable(element)); + } + return copy; + } + else if(value instanceof Map) + { + Map orig = (Map) value; + LinkedHashMap copy = new LinkedHashMap<>(); + for(Map.Entry entry : orig.entrySet()) + { + copy.put(makeImmutable(entry.getKey()),makeImmutable(entry.getValue())); + } + return copy; + } + else return null; + } + + private final QueueReport _report; + + public final T runReport(Queue queue) + { + _report.setQueue(queue); + ReportVisitor visitor = new ReportVisitor(_report); + queue.visit(visitor); + return _report.getReport(); + } +} diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/report/ReportableMessage.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/report/ReportableMessage.java new file mode 100644 index 0000000000..00b6c4abeb --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/report/ReportableMessage.java @@ -0,0 +1,42 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.management.plugin.report; + +import java.nio.ByteBuffer; + +public interface ReportableMessage +{ + String getInitialRoutingAddress(); + + ReportableMessageHeader getMessageHeader(); + + public ByteBuffer getContent(); + + boolean isPersistent(); + + long getSize(); + + long getExpiration(); + + long getMessageNumber(); + + long getArrivalTime(); +} diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/report/ReportableMessageHeader.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/report/ReportableMessageHeader.java new file mode 100644 index 0000000000..e78415f8d0 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/report/ReportableMessageHeader.java @@ -0,0 +1,58 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.management.plugin.report; + +import java.util.Collection; +import java.util.Set; + +public interface ReportableMessageHeader +{ + String getCorrelationId(); + + long getExpiration(); + + String getUserId(); + + String getAppId(); + + String getMessageId(); + + String getMimeType(); + + String getEncoding(); + + byte getPriority(); + + long getTimestamp(); + + String getType(); + + String getReplyTo(); + + Object getHeader(String name); + + boolean containsHeaders(Set names); + + boolean containsHeader(String name); + + Collection getHeaderNames(); + +} diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ConfiguredObjectToMapConverter.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ConfiguredObjectToMapConverter.java index 331b50ea7c..0f1b7d03e9 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ConfiguredObjectToMapConverter.java +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/ConfiguredObjectToMapConverter.java @@ -162,14 +162,14 @@ public class ConfiguredObjectToMapConverter .getAttributeTypes(confObject.getClass()) .get(name); - if (attribute.isSecure() && !(isSecureTransport && extractAsConfig)) + if (attribute.isSecureValue(value) && !(isSecureTransport && extractAsConfig)) { // do not expose actual secure attribute value // getAttribute() returns encoded value value = confObject.getAttribute(name); } - if(attribute.isOversized() && !extractAsConfig) + if(attribute.isOversized() && !extractAsConfig && !useActualValues) { String valueString = String.valueOf(value); if(valueString.length() > oversizeThreshold) diff --git a/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueReportServlet.java b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueReportServlet.java new file mode 100644 index 0000000000..2b3def2dab --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/main/java/org/apache/qpid/server/management/plugin/servlet/rest/QueueReportServlet.java @@ -0,0 +1,103 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.management.plugin.servlet.rest; + +import java.io.IOException; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.apache.qpid.server.management.plugin.report.ReportRunner; +import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.model.VirtualHost; + +public class QueueReportServlet extends AbstractServlet +{ + @Override + protected void doGetWithSubjectAndActor(HttpServletRequest request, HttpServletResponse response) throws + IOException, + ServletException + { + String[] pathInfoElements = getPathInfoElements(request); + if(pathInfoElements != null && pathInfoElements.length == 3) + { + Queue queue = getQueueFromRequest(request); + ReportRunner reportRunner = ReportRunner.createRunner(pathInfoElements[2],request.getParameterMap()); + Object output = reportRunner.runReport(queue); + response.setContentType(reportRunner.getContentType()); + if(reportRunner.isBinaryReport()) + { + response.getOutputStream().write((byte[])output); + } + else + { + response.getWriter().write((String)output); + } + } + else + { + throw new IllegalArgumentException("Invalid path is specified"); + } + + } + + private Queue getQueueFromRequest(HttpServletRequest request) + { + String[] pathInfoElements = getPathInfoElements(request); + if(pathInfoElements == null || pathInfoElements.length < 2) + { + throw new IllegalArgumentException("Invalid path is specified"); + } + String vhostName = pathInfoElements[0]; + String queueName = pathInfoElements[1]; + + VirtualHost vhost = getBroker().findVirtualHostByName(vhostName); + if (vhost == null) + { + throw new IllegalArgumentException("Could not find virtual host with name '" + vhostName + "'"); + } + + Queue queueFromVirtualHost = getQueueFromVirtualHost(queueName, vhost); + if (queueFromVirtualHost == null) + { + throw new IllegalArgumentException("Could not find queue with name '" + queueName + "' on virtual host '" + vhost.getName() + "'"); + } + return queueFromVirtualHost; + } + + private Queue getQueueFromVirtualHost(String queueName, VirtualHost vhost) + { + Queue queue = null; + + for(Queue q : vhost.getQueues()) + { + + if(q.getName().equals(queueName)) + { + queue = q; + break; + } + } + return queue; + } + +} diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/addPort.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/addPort.html index b787e701ec..10b79987a5 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/addPort.html +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/addPort.html @@ -159,6 +159,23 @@ +
+
+
+ +
+
+ +
+
+
+
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/editVirtualHostNode.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/editVirtualHostNode.html index cee18f7185..59597845a2 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/editVirtualHostNode.html +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/editVirtualHostNode.html @@ -19,31 +19,34 @@
-
-
NOTE: All changes will only take effect after Virtual Host Node restart.
-
-
Name*:
-
- +
+
NOTE: All changes will only take effect after Virtual Host Node restart.
+
+
Name*:
+
+ -
-
+
+
-
+
-
+
-
-
+
+
+
+
-
+
diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/ResourceWidget.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/ResourceWidget.js index f603c96ff3..bee38149da 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/ResourceWidget.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/ResourceWidget.js @@ -44,6 +44,7 @@ function (declare, array, lang, util, _WidgetBase, _TemplatedMixin, _WidgetsInTe fileReaderSupported: window.FileReader ? true : false, displayWarningWhenFileReaderUnsupported: false, isDebug: false, + uploaded: false, buildRendering: function() { @@ -74,7 +75,7 @@ function (declare, array, lang, util, _WidgetBase, _TemplatedMixin, _WidgetsInTe { // Fall back for IE8/9 which do not support FileReader this.uploadFields.style.display = "none"; - if (displayWarningWhenFileReaderUnsupported) + if (this.displayWarningWhenFileReaderUnsupported) { this.unsupportedWarning.className = this.unsupportedWarning.className.replace("hidden", ""); } @@ -127,6 +128,7 @@ function (declare, array, lang, util, _WidgetBase, _TemplatedMixin, _WidgetsInTe }, _fileClearButtonClicked: function(event) { + this.uploaded = false; this.uploader.reset(); this.set("value", this._resetValue); }, @@ -134,20 +136,17 @@ function (declare, array, lang, util, _WidgetBase, _TemplatedMixin, _WidgetsInTe { var serverPathValue = this.resourceLocation.get("value") || this._resetValue; this.set("value", serverPathValue); + if (this.uploaded ) + { + this.uploaded = !serverPathValue; + } }, _setValueAttr: function(newValue, priorityChange) { - var isDataUrl = newValue && newValue.indexOf("data:") == 0; + var isDataUrl = this.uploaded || ( newValue && newValue.indexOf("data:") == 0 ); if (isDataUrl) { - this.uploadData.style.display = "block"; - this.selectedFileStatus.className = "loadedIcon"; - this.selectedFile.innerHTML = this.selectedFileName || "uploaded data"; - this.resourceLocation.set("value", ""); - this.resourceLocation.setDisabled(true); - this.resourceLocation.set("required", false); - this.clearButton.setDisabled(false); - this.selectedFileStatus.className = "loadedIcon"; + this._initUploaded(true); } else { @@ -172,6 +171,25 @@ function (declare, array, lang, util, _WidgetBase, _TemplatedMixin, _WidgetsInTe _setPlaceHolderAttr: function(newValue) { this.resourceLocation.set("placeHolder", newValue); + }, + _setUploadedAttr: function(uploaded) + { + this.uploaded = uploaded; + this._initUploaded(uploaded); + }, + _initUploaded: function(uploaded) + { + if (uploaded) + { + this.uploadData.style.display = "block"; + this.selectedFileStatus.className = "loadedIcon"; + this.selectedFile.innerHTML = this.selectedFileName || "uploaded data"; + this.resourceLocation.set("value", ""); + this.resourceLocation.setDisabled(true); + this.resourceLocation.set("required", false); + this.clearButton.setDisabled(false); + this.selectedFileStatus.className = "loadedIcon"; + } } } ); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/ColumnDefDialog.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/ColumnDefDialog.js index d285dfaad6..a0b62082cb 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/ColumnDefDialog.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/ColumnDefDialog.js @@ -45,10 +45,15 @@ return declare("qpid.common.grid.ColumnDefDialog", null, { constructor: function(args){ var grid = this.grid = args.grid; - + var that = this; this.containerNode = dom.create("div", {innerHTML: template}); - parser.parse(this.containerNode); - + parser.parse(this.containerNode).then(function(instances) + { + that._postParse(); + }); + }, + _postParse: function() + { var submitButton = registry.byNode(query(".displayButton", this.containerNode)[0]); this.closeButton = registry.byNode(query(".cancelButton", this.containerNode)[0]); var columnsContainer = query(".columnList", this.containerNode)[0]; diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/RowNumberLimitDialog.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/RowNumberLimitDialog.js index db3ae5a2ea..e78670bf57 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/RowNumberLimitDialog.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/grid/RowNumberLimitDialog.js @@ -41,11 +41,17 @@ return declare("qpid.management.logs.RowNumberLimitDialog", null, { grid: null, dialog: null, - constructor: function(domNode, limitChangedCallback){ - + constructor: function(domNode, limitChangedCallback) + { + var that = this; this.containerNode = dom.create("div", {innerHTML: template}); - parser.parse(this.containerNode); - + parser.parse(this.containerNode).then(function(instances) + { + that._postParse(domNode, limitChangedCallback); + }); + }, + _postParse: function(domNode, limitChangedCallback) + { this.rowNumberLimit = registry.byNode(query(".rowNumberLimit", this.containerNode)[0]) this.submitButton = registry.byNode(query(".submitButton", this.containerNode)[0]); this.closeButton = registry.byNode(query(".cancelButton", this.containerNode)[0]); diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js index 60be40b62b..746eb4bbbc 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/common/util.js @@ -528,40 +528,41 @@ define(["dojo/_base/xhr", return object1 === object2; } - util.parseHtmlIntoDiv = function(containerNode, htmlTemplateLocation) + util.parseHtmlIntoDiv = function(containerNode, htmlTemplateLocation, postParseCallback) { xhr.get({url: htmlTemplateLocation, sync: true, load: function(template) { containerNode.innerHTML = template; - parser.parse(containerNode); + parser.parse(containerNode).then(function(instances) + { + if (postParseCallback && typeof postParseCallback == "function") + { + postParseCallback(); + } + }); }}); } - util.buildUI = function(containerNode, parent, htmlTemplateLocation, fieldNames, obj) + util.buildUI = function(containerNode, parent, htmlTemplateLocation, fieldNames, obj, postParseCallback) { - this.parseHtmlIntoDiv(containerNode, htmlTemplateLocation); - if (fieldNames && obj) - { - for(var i=0; i= 0) ? entities.encode(String(this.portData[ "maxOpenConnections" ])) : "(no limit)" ; + this.keyStoreValue.innerHTML = this.portData[ "keyStore" ] ? entities.encode(String(this.portData[ "keyStore" ])) : ""; this.needClientAuthValue.innerHTML = "" ; this.wantClientAuthValue.innerHTML = "" ; @@ -190,6 +198,9 @@ define(["dojo/dom", this.needClientAuth.style.display = "needClientAuth" in typeMetaData.attributes ? "block" : "none"; this.wantClientAuth.style.display = "wantClientAuth" in typeMetaData.attributes ? "block" : "none"; this.trustStores.style.display = "trustStores" in typeMetaData.attributes ? "block" : "none"; + + this.maxOpenConnections.style.display = "maxOpenConnections" in typeMetaData.attributes ? "block" : "none"; + }; PortUpdater.prototype.update = function() @@ -200,6 +211,7 @@ define(["dojo/dom", xhr.get({url: this.query, sync: properties.useSyncGet, handleAs: "json"}).then(function(data) { thisObj.portData = data[0]; + util.flattenStatistics( thisObj.portData ); thisObj.updateHeader(); }); }; diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Preferences.js b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Preferences.js index f9982a1699..c8e1d17e06 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Preferences.js +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/js/qpid/management/Preferences.js @@ -65,8 +65,15 @@ function (declare, xhr, event, connect, dom, domConstruct, parser, json, Memory, this.userPreferences = {}; this.domNode = domConstruct.create("div", {innerHTML: markup}); - this.preferencesDialog = parser.parse(this.domNode)[0]; - + parser.parse(this.domNode).then(function(instances) + { + that._postParse(); + }); + }, + _postParse: function() + { + var that = this; + this.preferencesDialog = registry.byId("preferences.preferencesDialog"); for(var i=0; iName:
- -
-
Port Type:
-
+
+
+
+
Port Type:
+
+
+
+
+
Open connections (current/maximum):
+
+ / +
+
+
-
+
State:
-
-
+
+
-
+
Port Number:
-
-
+
+
-
+
Protocols:
-
-
+
+
-
Authentication Provider:
-
+
Authentication Provider:
+
-
Binding address:
-
+
Binding address:
+
Transports:
-
-
+
+
-
-
Key Store:
-
-
+
+
Key Store:
+
+
-
-
Need SSL Client Certificate:
-
-
+
+
Need SSL Client Certificate:
+
+
-
-
Want SSL Client Certificate:
-
-
+
+
Want SSL Client Certificate:
+
+
+ +
+
Trust Stores:
+
+
-
-
Trust Stores:
-
-

diff --git a/qpid/java/broker-plugins/management-http/src/main/java/resources/showQueue.html b/qpid/java/broker-plugins/management-http/src/main/java/resources/showQueue.html index a068868e7f..7132dd8105 100644 --- a/qpid/java/broker-plugins/management-http/src/main/java/resources/showQueue.html +++ b/qpid/java/broker-plugins/management-http/src/main/java/resources/showQueue.html @@ -25,7 +25,7 @@
Name:
-
+
Type:
diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/report/ReportRunnerTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/report/ReportRunnerTest.java new file mode 100644 index 0000000000..38432a26f4 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/report/ReportRunnerTest.java @@ -0,0 +1,186 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.management.plugin.report; + +import static org.mockito.Mockito.doAnswer; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.io.ByteArrayOutputStream; +import java.io.ObjectOutputStream; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.mockito.ArgumentCaptor; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; + +import org.apache.qpid.server.message.AMQMessageHeader; +import org.apache.qpid.server.message.ServerMessage; +import org.apache.qpid.server.model.Queue; +import org.apache.qpid.server.queue.AMQQueue; +import org.apache.qpid.server.queue.QueueEntry; +import org.apache.qpid.server.queue.QueueEntryVisitor; +import org.apache.qpid.test.utils.QpidTestCase; + +public class ReportRunnerTest extends QpidTestCase +{ + public void testTextReportCountsMessages() + { + ReportRunner runner = (ReportRunner) ReportRunner.createRunner(TestTextReport.NAME, + Collections.emptyMap()); + Queue queue = createMockQueue(); + assertEquals("There are 0 messages on the queue.", runner.runReport(queue)); + + runner = (ReportRunner) ReportRunner.createRunner(TestTextReport.NAME, + Collections.emptyMap()); + Queue queue1 = createMockQueue(mock(ServerMessage.class)); + assertEquals("There are 1 messages on the queue.", runner.runReport(queue1)); + + runner = (ReportRunner) ReportRunner.createRunner(TestTextReport.NAME, + Collections.emptyMap()); + Queue queue2 = createMockQueue(mock(ServerMessage.class), mock(ServerMessage.class)); + assertEquals("There are 2 messages on the queue.", runner.runReport(queue2)); + } + + public void testTextReportSingleStringParam() + { + Queue queue2 = createMockQueue(mock(ServerMessage.class), mock(ServerMessage.class)); + + Map parameterMap = new HashMap<>(); + parameterMap.put("stringParam", new String[]{"hello world"}); + ReportRunner runner = + (ReportRunner) ReportRunner.createRunner(TestTextReport.NAME, parameterMap); + assertEquals("There are 2 messages on the queue. stringParam = hello world.", runner.runReport(queue2)); + } + + public void testTextReportSingleStringArrayParam() + { + Queue queue = createMockQueue(); + + Map parameterMap = new HashMap<>(); + parameterMap.put("stringArrayParam", new String[] { "hello world", "goodbye"}); + ReportRunner runner = (ReportRunner) ReportRunner.createRunner(TestTextReport.NAME, parameterMap); + assertEquals("There are 0 messages on the queue. stringArrayParam = [hello world, goodbye].", runner.runReport(queue)); + + } + + + public void testTextReportBothParams() + { + Queue queue = createMockQueue(); + + Map parameterMap = new HashMap<>(); + parameterMap.put("stringParam", new String[]{"hello world"}); + parameterMap.put("stringArrayParam", new String[] { "hello world", "goodbye"}); + ReportRunner runner = (ReportRunner) ReportRunner.createRunner(TestTextReport.NAME, parameterMap); + assertEquals("There are 0 messages on the queue. stringParam = hello world. stringArrayParam = [hello world, goodbye].", runner.runReport(queue)); + + } + + public void testInvalidReportName() + { + try + { + ReportRunner.createRunner("unknown", Collections.emptyMap()); + fail("Unknown report name should throw exception"); + } + catch(IllegalArgumentException e) + { + assertEquals("Unknown report: unknown", e.getMessage()); + } + } + + public void testBinaryReportWithLimit() throws Exception + { + Queue queue = createMockQueue(createMessageWithAppProperties(Collections.singletonMap("key",1)), + createMessageWithAppProperties(Collections.singletonMap("key",2)), + createMessageWithAppProperties(Collections.singletonMap("key", 3)), + createMessageWithAppProperties(Collections.singletonMap("key", 4))); + Map parameterMap = new HashMap<>(); + parameterMap.put("propertyName", new String[]{"key"}); + parameterMap.put("limit", new String[] { "3" }); + + ReportRunner runner = (ReportRunner) ReportRunner.createRunner(TestBinaryReport.NAME, parameterMap); + + ByteArrayOutputStream bytes = new ByteArrayOutputStream(); + ObjectOutputStream objects = new ObjectOutputStream(bytes); + objects.writeObject(Integer.valueOf(1)); + objects.writeObject(Integer.valueOf(2)); + objects.writeObject(Integer.valueOf(3)); + objects.flush(); + byte[] expected = bytes.toByteArray(); + byte[] actual = runner.runReport(queue); + assertTrue("Output not as expected", Arrays.equals(expected, actual)); + } + + private ServerMessage createMessageWithAppProperties(final Map props) + { + ServerMessage message = mock(ServerMessage.class); + final AMQMessageHeader header = mock(AMQMessageHeader.class); + when(message.getMessageHeader()).thenReturn(header); + final ArgumentCaptor headerNameCaptor = ArgumentCaptor.forClass(String.class); + when(header.getHeader(headerNameCaptor.capture())).thenAnswer(new Answer() + { + @Override + public Object answer(final InvocationOnMock invocation) throws Throwable + { + String header = headerNameCaptor.getValue(); + return props.get(header); + } + }); + when(header.getHeaderNames()).thenReturn(props.keySet()); + return message; + } + + private Queue createMockQueue(final ServerMessage... messages) + { + final AMQQueue queue = mock(AMQQueue.class); + final ArgumentCaptor captor = ArgumentCaptor.forClass(QueueEntryVisitor.class); + doAnswer(new Answer() + { + @Override + public Object answer(final InvocationOnMock invocation) throws Throwable + { + QueueEntryVisitor visitor = captor.getValue(); + for(ServerMessage message : messages) + { + if(visitor.visit(makeEntry(queue, message))) + { + break; + } + } + return null; + } + }).when(queue).visit(captor.capture()); + return queue; + } + + private QueueEntry makeEntry(final AMQQueue queue, final ServerMessage message) + { + QueueEntry entry = mock(QueueEntry.class); + when(entry.getQueue()).thenReturn(queue); + when(entry.getMessage()).thenReturn(message); + return entry; + } +} diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/report/TestBinaryReport.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/report/TestBinaryReport.java new file mode 100644 index 0000000000..fc5e93631e --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/report/TestBinaryReport.java @@ -0,0 +1,114 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.management.plugin.report; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectOutputStream; + +public class TestBinaryReport extends QueueBinaryReport +{ + + + private int _limit; + private String _propertyName; + private int _count; + private final ByteArrayOutputStream _bytesOutputStream = new ByteArrayOutputStream(); + private final ObjectOutputStream _objectOutputStream; + public static final String NAME = "testBinary"; + + public TestBinaryReport() + { + try + { + _objectOutputStream = new ObjectOutputStream(_bytesOutputStream); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + ; + } + + @Override + public String getName() + { + return NAME; + } + + @Override + public String getContentType() + { + return "application/octet-stream"; + } + + @Override + public void addMessage(final ReportableMessage reportableMessage) + { + if(_propertyName != null) + { + Object value = reportableMessage.getMessageHeader().getHeader(_propertyName); + if(value != null) + { + try + { + _objectOutputStream.writeObject(value); + } + catch (IOException e) + { + // ignore + } + } + } + _count++; + } + + @Override + public boolean isComplete() + { + return _limit != 0 && _count >= _limit; + } + + @Override + public byte[] getReport() + { + try + { + _objectOutputStream.flush(); + + return _bytesOutputStream.toByteArray(); + } + catch (IOException e) + { + throw new RuntimeException(e); + } + } + + public void setLimit(final String limit) + { + _limit = Integer.parseInt(limit); + } + + public void setPropertyName(final String propertyName) + { + this._propertyName = propertyName; + } +} diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/report/TestTextReport.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/report/TestTextReport.java new file mode 100644 index 0000000000..7f9e1e2962 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/report/TestTextReport.java @@ -0,0 +1,84 @@ +/* + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * + */ +package org.apache.qpid.server.management.plugin.report; + +import java.util.Arrays; + +public class TestTextReport extends QueueTextReport +{ + public static final String NAME = "testText"; + private int _count; + private String _stringParam; + private String[] _stringArrayParam; + + @Override + public String getName() + { + return NAME; + } + + @Override + public String getContentType() + { + return "text/plain"; + } + + @Override + public void addMessage(final ReportableMessage reportableMessage) + { + _count++; + } + + @Override + public boolean isComplete() + { + return false; + } + + @Override + public String getReport() + { + StringBuilder result = new StringBuilder("There are " + _count + " messages on the queue."); + if(_stringParam != null) + { + result.append(" stringParam = " + _stringParam + "."); + } + if(_stringArrayParam != null) + { + result.append(" stringArrayParam = " + Arrays.asList(_stringArrayParam) + "."); + } + return result.toString(); + } + + @SuppressWarnings("unused") + public void setStringParam(final String value) + { + _stringParam = value; + } + + @SuppressWarnings("unused") + public void setStringArrayParam(final String[] value) + { + _stringArrayParam = value; + } + + +} diff --git a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ConfiguredObjectToMapConverterTest.java b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ConfiguredObjectToMapConverterTest.java index b3c9bd911f..5fb73c8ee4 100644 --- a/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ConfiguredObjectToMapConverterTest.java +++ b/qpid/java/broker-plugins/management-http/src/test/java/org/apache/qpid/server/management/plugin/servlet/rest/ConfiguredObjectToMapConverterTest.java @@ -313,6 +313,7 @@ public class ConfiguredObjectToMapConverterTest extends TestCase Map> attributeTypes = typeRegistry.getAttributeTypes(TestChild.class); ConfiguredObjectAttribute secureAttribute = mock(ConfiguredObjectAttribute.class); when(secureAttribute.isSecure()).thenReturn(true); + when(secureAttribute.isSecureValue(any())).thenReturn(true); when(attributeTypes.get(eq("secureAttribute"))).thenReturn(secureAttribute); TestChild mockChild = mock(TestChild.class); diff --git a/qpid/java/broker-plugins/management-http/src/test/resources/META-INF/services/org.apache.qpid.server.management.plugin.report.QueueReport b/qpid/java/broker-plugins/management-http/src/test/resources/META-INF/services/org.apache.qpid.server.management.plugin.report.QueueReport new file mode 100644 index 0000000000..7d25ec4378 --- /dev/null +++ b/qpid/java/broker-plugins/management-http/src/test/resources/META-INF/services/org.apache.qpid.server.management.plugin.report.QueueReport @@ -0,0 +1,2 @@ +org.apache.qpid.server.management.plugin.report.TestTextReport +org.apache.qpid.server.management.plugin.report.TestBinaryReport diff --git a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBean.java b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBean.java index a016ff9d9d..0787e404fa 100644 --- a/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBean.java +++ b/qpid/java/broker-plugins/management-jmx/src/main/java/org/apache/qpid/server/jmx/mbeans/ConnectionMBean.java @@ -100,7 +100,7 @@ public class ConnectionMBean extends AbstractStatisticsGatheringMBean