From bb3965b7f7785287e9671c499476058e340ccebb Mon Sep 17 00:00:00 2001 From: Martyn Taylor Date: Mon, 14 Aug 2017 16:39:55 +0100 Subject: [PATCH 1/2] ARTEMIS-1349 Add management views for client objects --- .../management/ActiveMQServerControl.java | 30 ++++ .../core/impl/RemotingConnectionImpl.java | 19 +- .../protocol/AbstractRemotingConnection.java | 11 ++ .../spi/core/protocol/RemotingConnection.java | 18 ++ .../activemq/artemis/utils/StringUtil.java | 3 +- .../amqp/broker/AMQPSessionCallback.java | 9 + .../ActiveMQProtonRemotingConnection.java | 15 ++ .../broker/ProtonProtocolManagerFactory.java | 2 +- .../amqp/proton/AMQPSessionContext.java | 5 + .../core/protocol/mqtt/MQTTConnection.java | 33 ++++ .../protocol/mqtt/MQTTConnectionManager.java | 1 + .../protocol/mqtt/MQTTPublishManager.java | 1 + .../protocol/openwire/OpenWireConnection.java | 9 + .../core/protocol/stomp/StompConnection.java | 12 ++ .../impl/ActiveMQServerControlImpl.java | 111 ++++++++++++ .../impl/view/ActiveMQAbstractView.java | 164 ++++++++++++++++++ .../management/impl/view/AddressView.java | 63 +++++++ .../management/impl/view/ConnectionView.java | 67 +++++++ .../management/impl/view/ConsumerView.java | 56 ++++++ .../management/impl/view/ProducerView.java | 55 ++++++ .../core/management/impl/view/QueueView.java | 56 ++++++ .../management/impl/view/SessionView.java | 50 ++++++ .../predicate/ActiveMQFilterPredicate.java | 106 +++++++++++ .../predicate/AddressFilterPredicate.java | 69 ++++++++ .../predicate/ConnectionFilterPredicate.java | 79 +++++++++ .../predicate/ConsumerFilterPredicate.java | 71 ++++++++ .../predicate/ProducerFilterPredicate.java | 71 ++++++++ .../view/predicate/QueueFilterPredicate.java | 107 ++++++++++++ .../predicate/SessionFilterPredicate.java | 65 +++++++ .../core/impl/ActiveMQPacketHandler.java | 6 +- .../artemis/core/server/ServerProducer.java | 35 ++++ .../artemis/core/server/ServerSession.java | 9 + .../core/server/impl/ServerProducerImpl.java | 78 +++++++++ .../core/server/impl/ServerSessionImpl.java | 26 +++ .../ActiveMQServerControlUsingCoreTest.java | 41 +++++ 35 files changed, 1541 insertions(+), 12 deletions(-) create mode 100644 artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ActiveMQAbstractView.java create mode 100644 artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/AddressView.java create mode 100644 artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ConnectionView.java create mode 100644 artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ConsumerView.java create mode 100644 artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ProducerView.java create mode 100644 artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/QueueView.java create mode 100644 artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/SessionView.java create mode 100644 artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/ActiveMQFilterPredicate.java create mode 100644 artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/AddressFilterPredicate.java create mode 100644 artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/ConnectionFilterPredicate.java create mode 100644 artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/ConsumerFilterPredicate.java create mode 100644 artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/ProducerFilterPredicate.java create mode 100644 artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/QueueFilterPredicate.java create mode 100644 artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/SessionFilterPredicate.java create mode 100644 artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ServerProducer.java create mode 100644 artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerProducerImpl.java diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/ActiveMQServerControl.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/ActiveMQServerControl.java index d39e47028c..4e4fc95c59 100644 --- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/ActiveMQServerControl.java +++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/core/management/ActiveMQServerControl.java @@ -1075,5 +1075,35 @@ public interface ActiveMQServerControl { @Operation(desc = "List Addresses on the broker", impact = MBeanOperationInfo.INFO) String listAddresses(@Parameter(name = "separator", desc = "Separator used on the string listing") String separator) throws Exception; + + @Operation(desc = "Search for Connections", impact = MBeanOperationInfo.INFO) + String listConnections(@Parameter(name = "Options") String options, + @Parameter(name = "Page Number") int page, + @Parameter(name = "Page Size") int pageSize) throws Exception; + + @Operation(desc = "Search for Sessions", impact = MBeanOperationInfo.INFO) + String listSessions(@Parameter(name = "Options") String options, + @Parameter(name = "Page Number") int page, + @Parameter(name = "Page Size") int pageSize) throws Exception; + + @Operation(desc = "Search for Consumers", impact = MBeanOperationInfo.INFO) + String listConsumers(@Parameter(name = "Options") String options, + @Parameter(name = "Page Number") int page, + @Parameter(name = "Page Size") int pageSize) throws Exception; + + @Operation(desc = "Search for Consumers", impact = MBeanOperationInfo.INFO) + String listProducers(@Parameter(name = "Options") String options, + @Parameter(name = "Page Number") int page, + @Parameter(name = "Page Size") int pageSize) throws Exception; + + @Operation(desc = "Search for Addresses", impact = MBeanOperationInfo.INFO) + String listAddresses(@Parameter(name = "Options") String options, + @Parameter(name = "Page Number") int page, + @Parameter(name = "Page Size") int pageSize) throws Exception; + + @Operation(desc = "Search for Queues", impact = MBeanOperationInfo.INFO) + String listQueues(@Parameter(name = "Options") String options, + @Parameter(name = "Page Number") int page, + @Parameter(name = "Page Size") int pageSize) throws Exception; } diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/RemotingConnectionImpl.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/RemotingConnectionImpl.java index 28bd2f696d..937f061da3 100644 --- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/RemotingConnectionImpl.java +++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/RemotingConnectionImpl.java @@ -29,6 +29,7 @@ import org.apache.activemq.artemis.api.core.ActiveMQException; import org.apache.activemq.artemis.api.core.ActiveMQRemoteDisconnectException; import org.apache.activemq.artemis.api.core.Interceptor; import org.apache.activemq.artemis.api.core.SimpleString; +import org.apache.activemq.artemis.api.core.client.ActiveMQClient; import org.apache.activemq.artemis.core.client.ActiveMQClientLogger; import org.apache.activemq.artemis.core.protocol.core.Channel; import org.apache.activemq.artemis.core.protocol.core.CoreRemotingConnection; @@ -347,6 +348,16 @@ public class RemotingConnectionImpl extends AbstractRemotingConnection implement return false; } + /** + * Returns the name of the protocol for this Remoting Connection + * + * @return + */ + @Override + public String getProtocolName() { + return ActiveMQClient.DEFAULT_CORE_PROTOCOL; + } + // Buffer Handler implementation // ---------------------------------------------------- @Override @@ -400,14 +411,6 @@ public class RemotingConnectionImpl extends AbstractRemotingConnection implement } } - public void setClientID(String cID) { - clientID = cID; - } - - public String getClientID() { - return clientID; - } - @Override public void killMessage(SimpleString nodeID) { if (clientVersion < DisconnectConsumerWithKillMessage.VERSION_INTRODUCED) { diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/spi/core/protocol/AbstractRemotingConnection.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/spi/core/protocol/AbstractRemotingConnection.java index 3893902842..a92a695af7 100644 --- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/spi/core/protocol/AbstractRemotingConnection.java +++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/spi/core/protocol/AbstractRemotingConnection.java @@ -44,6 +44,7 @@ public abstract class AbstractRemotingConnection implements RemotingConnection { protected final Executor executor; protected final long creationTime; protected volatile boolean dataReceived; + private String clientId; public AbstractRemotingConnection(final Connection transportConnection, final Executor executor) { this.transportConnection = transportConnection; @@ -226,4 +227,14 @@ public abstract class AbstractRemotingConnection implements RemotingConnection { public Subject getSubject() { return null; } + + @Override + public void setClientID(String clientId) { + this.clientId = clientId; + } + + @Override + public String getClientID() { + return clientId; + } } diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/spi/core/protocol/RemotingConnection.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/spi/core/protocol/RemotingConnection.java index 4cda8c07cd..9fc40a3a9f 100644 --- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/spi/core/protocol/RemotingConnection.java +++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/spi/core/protocol/RemotingConnection.java @@ -214,4 +214,22 @@ public interface RemotingConnection extends BufferHandler { * @return */ Subject getSubject(); + + /** + * Returns the name of the protocol for this Remoting Connection + * @return + */ + String getProtocolName(); + + /** + * Sets the client ID associated with this connection + * @return + */ + void setClientID(String cID); + + /** + * Returns the Client ID associated with this connection + * @return + */ + String getClientID(); } diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/StringUtil.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/StringUtil.java index ac4d6411c2..878057b37c 100644 --- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/StringUtil.java +++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/utils/StringUtil.java @@ -18,6 +18,7 @@ package org.apache.activemq.artemis.utils; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collection; import java.util.Iterator; import java.util.List; @@ -30,7 +31,7 @@ public class StringUtil { * @param delimit the delimiter used to separate each string entry in the list * @return the converted string */ - public static String joinStringList(List strList, String delimit) { + public static String joinStringList(Collection strList, String delimit) { Iterator entries = strList.iterator(); StringBuilder builder = new StringBuilder(); diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPSessionCallback.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPSessionCallback.java index 98845cd1b0..6807adac56 100644 --- a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPSessionCallback.java +++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/AMQPSessionCallback.java @@ -38,6 +38,7 @@ import org.apache.activemq.artemis.core.server.BindingQueryResult; import org.apache.activemq.artemis.core.server.MessageReference; import org.apache.activemq.artemis.core.server.QueueQueryResult; import org.apache.activemq.artemis.core.server.ServerConsumer; +import org.apache.activemq.artemis.core.server.ServerProducer; import org.apache.activemq.artemis.core.server.ServerSession; import org.apache.activemq.artemis.core.server.impl.AddressInfo; import org.apache.activemq.artemis.core.server.impl.ServerConsumerImpl; @@ -673,4 +674,12 @@ public class AMQPSessionCallback implements SessionCallback { public void invokeOutgoing(AMQPMessage message, ActiveMQProtonRemotingConnection connection) { protonSPI.invokeOutgoingInterceptors(message, connection); } + + public void addProducer(ServerProducer serverProducer) { + serverSession.addProducer(serverProducer); + } + + public void removeProducer(String name) { + serverSession.removeProducer(name); + } } diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/ActiveMQProtonRemotingConnection.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/ActiveMQProtonRemotingConnection.java index 1441b96803..c3533ebcd9 100644 --- a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/ActiveMQProtonRemotingConnection.java +++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/ActiveMQProtonRemotingConnection.java @@ -160,4 +160,19 @@ public class ActiveMQProtonRemotingConnection extends AbstractRemotingConnection } return null; } + + /** + * Returns the name of the protocol for this Remoting Connection + * + * @return + */ + @Override + public String getProtocolName() { + return ProtonProtocolManagerFactory.AMQP_PROTOCOL_NAME; + } + + @Override + public String getClientID() { + return amqpConnection.getContainer(); + } } diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/ProtonProtocolManagerFactory.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/ProtonProtocolManagerFactory.java index 5cf846364c..3d5f694769 100644 --- a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/ProtonProtocolManagerFactory.java +++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/broker/ProtonProtocolManagerFactory.java @@ -34,7 +34,7 @@ public class ProtonProtocolManagerFactory extends AbstractProtocolManagerFactory public static final byte ID = 2; - private static final String AMQP_PROTOCOL_NAME = "AMQP"; + public static final String AMQP_PROTOCOL_NAME = "AMQP"; private static final String MODULE_NAME = "artemis-amqp-protocol"; diff --git a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/AMQPSessionContext.java b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/AMQPSessionContext.java index 72833e3711..bf60e17d8a 100644 --- a/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/AMQPSessionContext.java +++ b/artemis-protocols/artemis-amqp-protocol/src/main/java/org/apache/activemq/artemis/protocol/amqp/proton/AMQPSessionContext.java @@ -21,6 +21,8 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; +import org.apache.activemq.artemis.core.server.ServerProducer; +import org.apache.activemq.artemis.core.server.impl.ServerProducerImpl; import org.apache.activemq.artemis.protocol.amqp.broker.AMQPSessionCallback; import org.apache.activemq.artemis.protocol.amqp.client.ProtonClientSenderContext; import org.apache.activemq.artemis.protocol.amqp.exceptions.ActiveMQAMQPException; @@ -138,6 +140,7 @@ public class AMQPSessionContext extends ProtonInitializable { } public void removeReceiver(Receiver receiver) { + sessionSPI.removeProducer(receiver.getName()); receivers.remove(receiver); } @@ -200,6 +203,8 @@ public class AMQPSessionContext extends ProtonInitializable { ProtonServerReceiverContext protonReceiver = new ProtonServerReceiverContext(sessionSPI, connection, this, receiver); protonReceiver.initialise(); receivers.put(receiver, protonReceiver); + ServerProducer serverProducer = new ServerProducerImpl(receiver.getName(), "AMQP", receiver.getTarget().getAddress()); + sessionSPI.addProducer(serverProducer); receiver.setContext(protonReceiver); connection.lock(); try { diff --git a/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTConnection.java b/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTConnection.java index e1afcb00ae..94bf17c28b 100644 --- a/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTConnection.java +++ b/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTConnection.java @@ -45,6 +45,8 @@ public class MQTTConnection implements RemotingConnection { private boolean connected; + private String clientID; + private final List failureListeners = Collections.synchronizedList(new ArrayList()); private final List closeListeners = Collections.synchronizedList(new ArrayList()); @@ -233,4 +235,35 @@ public class MQTTConnection implements RemotingConnection { public Subject getSubject() { return null; } + + /** + * Returns the name of the protocol for this Remoting Connection + * + * @return + */ + @Override + public String getProtocolName() { + return MQTTProtocolManagerFactory.MQTT_PROTOCOL_NAME; + } + + /** + * Sets the client ID associated with this connection + * + * @param cID + * @return + */ + @Override + public void setClientID(String cID) { + this.clientID = cID; + } + + /** + * Returns the Client ID associated with this connection + * + * @return + */ + @Override + public String getClientID() { + return clientID; + } } diff --git a/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTConnectionManager.java b/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTConnectionManager.java index e550e67c92..02e1c66965 100644 --- a/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTConnectionManager.java +++ b/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTConnectionManager.java @@ -98,6 +98,7 @@ public class MQTTConnectionManager { session.getConnection().setConnected(true); session.start(); + session.getConnection().setClientID(clientId); session.getProtocolHandler().sendConnack(MqttConnectReturnCode.CONNECTION_ACCEPTED); } diff --git a/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTPublishManager.java b/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTPublishManager.java index d12f30666f..e23385c781 100644 --- a/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTPublishManager.java +++ b/artemis-protocols/artemis-mqtt-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTPublishManager.java @@ -68,6 +68,7 @@ public class MQTTPublishManager { } synchronized void stop() throws Exception { + session.getServerSession().removeProducer(session.getServerSession().getName()); if (managementConsumer != null) { managementConsumer.removeItself(); managementConsumer.setStarted(false); diff --git a/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireConnection.java b/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireConnection.java index 06113b9736..95a6ef5616 100644 --- a/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireConnection.java +++ b/artemis-protocols/artemis-openwire-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/openwire/OpenWireConnection.java @@ -1609,4 +1609,13 @@ public class OpenWireConnection extends AbstractRemotingConnection implements Se //unsupported } + @Override + public String getProtocolName() { + return OpenWireProtocolManagerFactory.OPENWIRE_PROTOCOL_NAME; + } + + @Override + public String getClientID() { + return context.getClientId(); + } } diff --git a/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/StompConnection.java b/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/StompConnection.java index 3bf2b1e865..13b7b8693b 100644 --- a/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/StompConnection.java +++ b/artemis-protocols/artemis-stomp-protocol/src/main/java/org/apache/activemq/artemis/core/protocol/stomp/StompConnection.java @@ -421,10 +421,12 @@ public final class StompConnection implements RemotingConnection { return passcode; } + @Override public void setClientID(String clientID) { this.clientID = clientID; } + @Override public String getClientID() { return clientID; } @@ -786,4 +788,14 @@ public final class StompConnection implements RemotingConnection { public Subject getSubject() { return null; } + + /** + * Returns the name of the protocol for this Remoting Connection + * + * @return + */ + @Override + public String getProtocolName() { + return StompProtocolManagerFactory.STOMP_PROTOCOL_NAME; + } } diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/ActiveMQServerControlImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/ActiveMQServerControlImpl.java index 9419cbb9f5..a3773f8145 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/ActiveMQServerControlImpl.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/ActiveMQServerControlImpl.java @@ -56,6 +56,7 @@ import org.apache.activemq.artemis.api.core.management.AddressControl; import org.apache.activemq.artemis.api.core.management.BridgeControl; import org.apache.activemq.artemis.api.core.management.CoreNotificationType; import org.apache.activemq.artemis.api.core.management.DivertControl; +import org.apache.activemq.artemis.api.core.management.Parameter; import org.apache.activemq.artemis.api.core.management.QueueControl; import org.apache.activemq.artemis.core.client.impl.Topology; import org.apache.activemq.artemis.core.client.impl.TopologyMemberImpl; @@ -64,6 +65,12 @@ import org.apache.activemq.artemis.core.config.Configuration; import org.apache.activemq.artemis.core.config.ConnectorServiceConfiguration; import org.apache.activemq.artemis.core.config.DivertConfiguration; import org.apache.activemq.artemis.core.filter.Filter; +import org.apache.activemq.artemis.core.management.impl.view.AddressView; +import org.apache.activemq.artemis.core.management.impl.view.ConnectionView; +import org.apache.activemq.artemis.core.management.impl.view.ConsumerView; +import org.apache.activemq.artemis.core.management.impl.view.ProducerView; +import org.apache.activemq.artemis.core.management.impl.view.QueueView; +import org.apache.activemq.artemis.core.management.impl.view.SessionView; import org.apache.activemq.artemis.core.messagecounter.MessageCounterManager; import org.apache.activemq.artemis.core.messagecounter.impl.MessageCounterManagerImpl; import org.apache.activemq.artemis.core.persistence.StorageManager; @@ -86,6 +93,7 @@ import org.apache.activemq.artemis.core.server.DivertConfigurationRoutingType; import org.apache.activemq.artemis.core.server.JournalType; import org.apache.activemq.artemis.core.server.Queue; import org.apache.activemq.artemis.core.server.ServerConsumer; +import org.apache.activemq.artemis.core.server.ServerProducer; import org.apache.activemq.artemis.core.server.ServerSession; import org.apache.activemq.artemis.core.server.cluster.ClusterConnection; import org.apache.activemq.artemis.core.server.cluster.ClusterManager; @@ -1575,6 +1583,109 @@ public class ActiveMQServerControlImpl extends AbstractControl implements Active return producers.build().toString(); } + @Override + public String listConnections(String options, int page, int pageSize) throws Exception { + checkStarted(); + clearIO(); + try { + server.getPostOffice().getAddresses(); + ConnectionView view = new ConnectionView(server); + view.setCollection(server.getRemotingService().getConnections()); + view.setOptions(options); + return view.getResultsAsJson(page, pageSize); + } finally { + blockOnIO(); + } + } + + @Override + public String listSessions(String options, int page, int pageSize) throws Exception { + checkStarted(); + clearIO(); + try { + SessionView view = new SessionView(); + view.setCollection(server.getSessions()); + view.setOptions(options); + return view.getResultsAsJson(page, pageSize); + } finally { + blockOnIO(); + } + } + + @Override + public String listConsumers(String options, int page, int pageSize) throws Exception { + checkStarted(); + clearIO(); + try { + Set consumers = new HashSet(); + for (ServerSession session : server.getSessions()) { + consumers.addAll(session.getServerConsumers()); + } + ConsumerView view = new ConsumerView(server); + view.setCollection(consumers); + view.setOptions(options); + return view.getResultsAsJson(page, pageSize); + } finally { + blockOnIO(); + } + } + + @Override + public String listAddresses(String options, int page, int pageSize) throws Exception { + checkStarted(); + + clearIO(); + try { + final Set addresses = server.getPostOffice().getAddresses(); + AddressView view = new AddressView(server); + view.setCollection(addresses); + view.setOptions(options); + return view.getResultsAsJson(page, pageSize); + } finally { + blockOnIO(); + } + } + + @Override + public String listQueues(String options, int page, int pageSize) throws Exception { + checkStarted(); + + clearIO(); + try { + List queues = new ArrayList<>(); + Object[] qs = server.getManagementService().getResources(QueueControl.class); + for (int i = 0; i < qs.length; i++) { + queues.add((QueueControl) qs[i]); + } + QueueView view = new QueueView(server); + view.setCollection(queues); + view.setOptions(options); + return view.getResultsAsJson(page, pageSize); + } finally { + blockOnIO(); + } + } + + @Override + public String listProducers(@Parameter(name = "Options") String options, + @Parameter(name = "Page Number") int page, + @Parameter(name = "Page Size") int pageSize) throws Exception { + checkStarted(); + clearIO(); + try { + Set producers = new HashSet<>(); + for (ServerSession session : server.getSessions()) { + producers.addAll(session.getServerProducers().values()); + } + ProducerView view = new ProducerView(server); + view.setCollection(producers); + view.setOptions(options); + return view.getResultsAsJson(page, pageSize); + } finally { + blockOnIO(); + } + } + @Override public String listConnectionsAsJSON() throws Exception { checkStarted(); diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ActiveMQAbstractView.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ActiveMQAbstractView.java new file mode 100644 index 0000000000..4fb5afef5b --- /dev/null +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ActiveMQAbstractView.java @@ -0,0 +1,164 @@ +/* + * 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.activemq.artemis.core.management.impl.view; + +import javax.json.JsonArrayBuilder; +import javax.json.JsonObject; +import javax.json.JsonObjectBuilder; +import java.lang.reflect.Method; +import java.util.Collection; +import java.util.List; + +import com.google.common.base.Predicate; +import com.google.common.collect.Collections2; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Ordering; +import org.apache.activemq.artemis.api.core.JsonUtil; +import org.apache.activemq.artemis.core.management.impl.view.predicate.ActiveMQFilterPredicate; +import org.apache.activemq.artemis.utils.JsonLoader; + +public abstract class ActiveMQAbstractView { + + private static final String FILTER_FIELD = "field"; + + private static final String FILTER_OPERATION = "operation"; + + private static final String FILTER_VALUE = "value"; + + protected Collection collection; + + protected ActiveMQFilterPredicate predicate; + + protected String sortColumn; + + protected String sortOrder; + + protected String options; + + private Method getter; + + public ActiveMQAbstractView() { + this.sortColumn = getDefaultOrderColumn(); + this.sortOrder = "asc"; + } + + public void setCollection(Collection collection) { + this.collection = collection; + } + + public String getResultsAsJson(int page, int pageSize) { + JsonObjectBuilder obj = JsonLoader.createObjectBuilder(); + JsonArrayBuilder array = JsonLoader.createArrayBuilder(); + collection = Collections2.filter(collection, getPredicate()); + for (T element : getPagedResult(page, pageSize)) { + array.add(toJson(element)); + } + obj.add("data", array); + obj.add("count", collection.size()); + return obj.build().toString(); + } + + public List getPagedResult(int page, int pageSize) { + ImmutableList.Builder builder = ImmutableList.builder(); + int start = (page - 1) * pageSize; + int end = Math.min(page * pageSize, collection.size()); + int i = 0; + for (T e : getOrdering().sortedCopy(collection)) { + if (i >= start && i < end) { + builder.add(e); + } + i++; + } + return builder.build(); + } + + public Predicate getPredicate() { + return predicate; + } + + private Method getGetter() { + if (getter == null) { + getter = findGetterMethod(getClassT(), sortColumn); + } + return getter; + } + + public Ordering getOrdering() { + return new Ordering() { + + @Override + public int compare(T left, T right) { + Method getter = getGetter(); + try { + if (getter != null) { + Object leftValue = getter.invoke(left); + Object rightValue = getter.invoke(right); + if (leftValue instanceof Comparable && rightValue instanceof Comparable) { + if (sortOrder.equals("desc")) { + return ((Comparable) rightValue).compareTo(leftValue); + } else { + return ((Comparable) leftValue).compareTo(rightValue); + } + } + } + return 0; + } catch (Exception e) { + //LOG.info("Exception sorting destinations", e); + return 0; + } + } + }; + } + + public static Method findGetterMethod(Class clazz, String sortColumn) { + String name = "get" + Character.toUpperCase(sortColumn.charAt(0)) + sortColumn.substring(1); + Method[] methods = clazz.getMethods(); + for (Method method : methods) { + Class[] params = method.getParameterTypes(); + if (method.getName().equals(name) && params.length == 0) { + return method; + } + } + return null; + } + + public void setOptions(String options) { + JsonObject json = JsonUtil.readJsonObject(options); + if (predicate != null) { + predicate.setField(json.getString(FILTER_FIELD)); + predicate.setOperation(json.getString(FILTER_OPERATION)); + predicate.setValue(json.getString(FILTER_VALUE)); + } + } + + public abstract Class getClassT(); + + public abstract JsonObjectBuilder toJson(T obj); + + public abstract String getDefaultOrderColumn(); + + /** + * JsonObjectBuilder will throw an NPE if a null value is added. For this reason we check for null explicitly when + * adding objects. + * + * @param o + * @return + */ + protected String toString(Object o) { + return o == null ? "" : o.toString(); + } +} diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/AddressView.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/AddressView.java new file mode 100644 index 0000000000..fcc34648e4 --- /dev/null +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/AddressView.java @@ -0,0 +1,63 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.activemq.artemis.core.management.impl.view; + +import javax.json.JsonObjectBuilder; + +import org.apache.activemq.artemis.api.core.SimpleString; +import org.apache.activemq.artemis.core.management.impl.view.predicate.AddressFilterPredicate; +import org.apache.activemq.artemis.core.server.ActiveMQServer; +import org.apache.activemq.artemis.core.server.impl.AddressInfo; +import org.apache.activemq.artemis.utils.JsonLoader; + +public class AddressView extends ActiveMQAbstractView { + + private static final String defaultSortColumn = "creationTime"; + + private final ActiveMQServer server; + + public AddressView(ActiveMQServer server) { + super(); + this.server = server; + this.predicate = new AddressFilterPredicate(server); + } + + @Override + public Class getClassT() { + return AddressInfo.class; + } + + @Override + public JsonObjectBuilder toJson(SimpleString addressName) { + + AddressInfo address = server.getAddressInfo(addressName); + JsonObjectBuilder obj = JsonLoader.createObjectBuilder().add("id", toString(address.getId())).add("name", toString(address.getName())).add("routingTypes", toString(address.getRoutingTypes())); + + try { + obj.add("queueCount", toString(server.bindingQuery(address.getName()).getQueueNames().size())); + return obj; + } catch (Exception e) { + obj.add("queueCount", 0); + } + return obj; + } + + @Override + public String getDefaultOrderColumn() { + return defaultSortColumn; + } +} diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ConnectionView.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ConnectionView.java new file mode 100644 index 0000000000..32eedfff9c --- /dev/null +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ConnectionView.java @@ -0,0 +1,67 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.activemq.artemis.core.management.impl.view; + +import javax.json.JsonObjectBuilder; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.activemq.artemis.core.management.impl.view.predicate.ConnectionFilterPredicate; +import org.apache.activemq.artemis.core.server.ActiveMQServer; +import org.apache.activemq.artemis.core.server.ServerSession; +import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection; +import org.apache.activemq.artemis.utils.JsonLoader; +import org.apache.activemq.artemis.utils.StringUtil; + +public class ConnectionView extends ActiveMQAbstractView { + + private static final String defaultSortColumn = "creationTime"; + + private final ActiveMQServer server; + + public ConnectionView(ActiveMQServer server) { + super(); + this.server = server; + this.predicate = new ConnectionFilterPredicate(server); + } + + @Override + public Class getClassT() { + return RemotingConnection.class; + } + + @Override + public JsonObjectBuilder toJson(RemotingConnection connection) { + + List sessions = server.getSessions(connection.getID().toString()); + Set users = new HashSet<>(); + + for (ServerSession session : sessions) { + String username = session.getUsername() == null ? "" : session.getUsername(); + users.add(username); + } + + return JsonLoader.createObjectBuilder().add("connectionID", toString(connection.getID())).add("remoteAddress", toString(connection.getRemoteAddress())).add("users", StringUtil.joinStringList(users, ",")).add("creationTime", new Date(connection.getCreationTime()).toString()).add("implementation", toString(toString(connection.getClass().getSimpleName()))).add("protocol", toString(connection.getProtocolName())).add("clientID", toString(connection.getClientID())).add("localAddress", toString(connection.getTransportConnection().getLocalAddress())).add("sessionCount", server.getSessions(connection.getID().toString()).size()); + } + + @Override + public String getDefaultOrderColumn() { + return defaultSortColumn; + } +} diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ConsumerView.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ConsumerView.java new file mode 100644 index 0000000000..fcb7f5e32f --- /dev/null +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ConsumerView.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.activemq.artemis.core.management.impl.view; + +import javax.json.JsonObjectBuilder; +import java.util.Date; + +import org.apache.activemq.artemis.core.management.impl.view.predicate.ConsumerFilterPredicate; +import org.apache.activemq.artemis.core.server.ActiveMQServer; +import org.apache.activemq.artemis.core.server.ServerConsumer; +import org.apache.activemq.artemis.core.server.ServerSession; +import org.apache.activemq.artemis.utils.JsonLoader; + +public class ConsumerView extends ActiveMQAbstractView { + + private static final String defaultSortColumn = "creationTime"; + + private final ActiveMQServer server; + + public ConsumerView(ActiveMQServer server) { + super(); + this.server = server; + this.predicate = new ConsumerFilterPredicate(server); + } + + @Override + public Class getClassT() { + return ServerConsumer.class; + } + + @Override + public JsonObjectBuilder toJson(ServerConsumer consumer) { + ServerSession session = server.getSessionByID(consumer.getSessionID()); + JsonObjectBuilder obj = JsonLoader.createObjectBuilder().add("id", toString(consumer.sequentialID())).add("session", toString(session.getName())).add("clientID", toString(session.getRemotingConnection().getClientID())).add("user", toString(session.getUsername())).add("protocol", toString(session.getRemotingConnection().getProtocolName())).add("queue", toString(consumer.getQueue().getName())).add("queueType", toString(consumer.getQueue().getRoutingType()).toLowerCase()).add("address", toString(consumer.getQueue().getAddress().toString())).add("localAddress", toString(session.getRemotingConnection().getTransportConnection().getLocalAddress())).add("remoteAddress", toString(session.getRemotingConnection().getTransportConnection().getRemoteAddress())).add("creationTime", new Date(consumer.getCreationTime()).toString()); + return obj; + } + + @Override + public String getDefaultOrderColumn() { + return defaultSortColumn; + } +} diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ProducerView.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ProducerView.java new file mode 100644 index 0000000000..63c5e883c8 --- /dev/null +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/ProducerView.java @@ -0,0 +1,55 @@ +/* + * 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.activemq.artemis.core.management.impl.view; + +import javax.json.JsonObjectBuilder; + +import org.apache.activemq.artemis.core.management.impl.view.predicate.ProducerFilterPredicate; +import org.apache.activemq.artemis.core.server.ActiveMQServer; +import org.apache.activemq.artemis.core.server.ServerProducer; +import org.apache.activemq.artemis.core.server.ServerSession; +import org.apache.activemq.artemis.utils.JsonLoader; + +public class ProducerView extends ActiveMQAbstractView { + + private static final String defaultSortColumn = "creationTime"; + + private final ActiveMQServer server; + + public ProducerView(ActiveMQServer server) { + super(); + this.server = server; + this.predicate = new ProducerFilterPredicate(server); + } + + @Override + public Class getClassT() { + return ServerProducer.class; + } + + @Override + public JsonObjectBuilder toJson(ServerProducer producer) { + ServerSession session = server.getSessionByID(producer.getSessionID()); + JsonObjectBuilder obj = JsonLoader.createObjectBuilder().add("id", toString(producer.getID())).add("session", toString(session.getName())).add("clientID", toString(session.getRemotingConnection().getClientID())).add("user", toString(session.getUsername())).add("protocol", toString(session.getRemotingConnection().getProtocolName())).add("address", toString(producer.getAddress() != null ? producer.getAddress() : session.getDefaultAddress())).add("localAddress", toString(session.getRemotingConnection().getTransportConnection().getLocalAddress())).add("remoteAddress", toString(session.getRemotingConnection().getTransportConnection().getRemoteAddress())).add("creationTime", toString(producer.getCreationTime())); + return obj; + } + + @Override + public String getDefaultOrderColumn() { + return defaultSortColumn; + } +} diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/QueueView.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/QueueView.java new file mode 100644 index 0000000000..36686803de --- /dev/null +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/QueueView.java @@ -0,0 +1,56 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.activemq.artemis.core.management.impl.view; + +import javax.json.JsonObjectBuilder; + +import org.apache.activemq.artemis.api.core.SimpleString; +import org.apache.activemq.artemis.api.core.management.QueueControl; +import org.apache.activemq.artemis.core.management.impl.view.predicate.QueueFilterPredicate; +import org.apache.activemq.artemis.core.server.ActiveMQServer; +import org.apache.activemq.artemis.core.server.Queue; +import org.apache.activemq.artemis.utils.JsonLoader; + +public class QueueView extends ActiveMQAbstractView { + + private static final String defaultSortColumn = "name"; + + private ActiveMQServer server; + + public QueueView(ActiveMQServer server) { + super(); + this.predicate = new QueueFilterPredicate(server); + this.server = server; + } + + @Override + public Class getClassT() { + return QueueControl.class; + } + + @Override + public JsonObjectBuilder toJson(QueueControl queue) { + Queue q = server.locateQueue(new SimpleString(queue.getName())); + JsonObjectBuilder obj = JsonLoader.createObjectBuilder().add("id", toString(queue.getID())).add("name", toString(queue.getName())).add("address", toString(queue.getAddress())).add("filter", toString(queue.getFilter())).add("rate", toString(q.getRate())).add("durable", toString(queue.isDurable())).add("paused", toString(q.isPaused())).add("temporary", toString(queue.isTemporary())).add("purgeOnNoConsumers", toString(queue.isPurgeOnNoConsumers())).add("consumerCount", toString(queue.getConsumerCount())).add("maxConsumers", toString(queue.getMaxConsumers())).add("autoCreated", toString(q.isAutoCreated())).add("user", toString(q.getUser())).add("routingType", toString(queue.getRoutingType())).add("messagesAdded", toString(queue.getMessagesAdded())).add("messageCount", toString(queue.getMessageCount())).add("messagesAcked", toString(queue.getMessagesAcknowledged())).add("deliveringCount", toString(queue.getDeliveringCount())).add("messagesKilled", toString(queue.getMessagesKilled())).add("deliverDeliver", toString(q.isDirectDeliver())); + return obj; + } + + @Override + public String getDefaultOrderColumn() { + return defaultSortColumn; + } +} diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/SessionView.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/SessionView.java new file mode 100644 index 0000000000..30b5c69acd --- /dev/null +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/SessionView.java @@ -0,0 +1,50 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.activemq.artemis.core.management.impl.view; + +import javax.json.JsonObjectBuilder; +import java.util.Date; + +import org.apache.activemq.artemis.core.management.impl.view.predicate.SessionFilterPredicate; +import org.apache.activemq.artemis.core.server.ServerSession; +import org.apache.activemq.artemis.utils.JsonLoader; + +public class SessionView extends ActiveMQAbstractView { + + private static final String defaultSortColumn = "creationTime"; + + public SessionView() { + super(); + this.predicate = new SessionFilterPredicate(); + } + + @Override + public Class getClassT() { + return ServerSession.class; + } + + @Override + public JsonObjectBuilder toJson(ServerSession session) { + JsonObjectBuilder obj = JsonLoader.createObjectBuilder().add("id", toString(session.getName())).add("user", toString(session.getUsername())).add("creationTime", new Date(session.getCreationTime()).toString()).add("consumerCount", session.getServerConsumers().size()).add("producerCount", session.getServerProducers().size()).add("connectionID", session.getConnectionID().toString()); + return obj; + } + + @Override + public String getDefaultOrderColumn() { + return defaultSortColumn; + } +} diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/ActiveMQFilterPredicate.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/ActiveMQFilterPredicate.java new file mode 100644 index 0000000000..0195935e30 --- /dev/null +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/ActiveMQFilterPredicate.java @@ -0,0 +1,106 @@ +/* + * 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.activemq.artemis.core.management.impl.view.predicate; + +import java.util.Collection; + +import com.google.common.base.Predicate; + +public class ActiveMQFilterPredicate implements Predicate { + + enum Operation { + CONTAINS, EQUALS; + } + + protected String field; + + protected String value; + + protected Operation operation; + + public static boolean contains(String field, String value) { + return field.contains(value); + } + + public ActiveMQFilterPredicate() { + } + + @Override + public boolean apply(T input) { + return true; + } + + public String getField() { + return field; + } + + public void setField(String field) { + this.field = field; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + public Operation getOperation() { + return operation; + } + + public void setOperation(String operation) { + if (operation != null && !operation.equals("")) { + this.operation = Operation.valueOf(operation); + } + } + + public boolean matches(Object field) { + if (operation != null) { + switch (operation) { + case EQUALS: + return equals(field, value); + case CONTAINS: + return contains(field, value); + } + } + return true; + } + + public boolean matchAny(Collection objects) { + for (Object o : objects) { + if (matches(o)) + return true; + } + return false; + } + + private boolean equals(Object field, Object value) { + if (field == null) { + return (value.equals("") || value == null); + } + return field.toString().equals(value); + } + + private boolean contains(Object field, Object value) { + if (field == null) { + return (value.equals("") || value == null); + } + return field.toString().contains(value.toString()); + } +} diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/AddressFilterPredicate.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/AddressFilterPredicate.java new file mode 100644 index 0000000000..76e7c7124c --- /dev/null +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/AddressFilterPredicate.java @@ -0,0 +1,69 @@ +/* + * 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.activemq.artemis.core.management.impl.view.predicate; + +import org.apache.activemq.artemis.api.core.SimpleString; +import org.apache.activemq.artemis.core.server.ActiveMQServer; +import org.apache.activemq.artemis.core.server.impl.AddressInfo; + +public class AddressFilterPredicate extends ActiveMQFilterPredicate { + + enum Field { + ID, NAME, ROUTING_TYPES, PRODUCER_ID, QUEUE_COUNT + } + + private Field f; + + private final ActiveMQServer server; + + public AddressFilterPredicate(ActiveMQServer server) { + super(); + this.server = server; + } + + @Override + public boolean apply(SimpleString addressName) { + AddressInfo address = server.getAddressInfo(addressName); + if (f == null) + return true; + try { + switch (f) { + case ID: + return matches(address.getId()); + case NAME: + return matches(address.getName()); + case ROUTING_TYPES: + return matchAny(address.getRoutingTypes()); + case PRODUCER_ID: + return matches("TODO"); + case QUEUE_COUNT: + return matches(server.bindingQuery(address.getName()).getQueueNames().size()); + } + } catch (Exception e) { + return false; + } + + return true; + } + + @Override + public void setField(String field) { + if (field != null && !field.equals("")) { + this.f = Field.valueOf(field.toUpperCase()); + } + } +} diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/ConnectionFilterPredicate.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/ConnectionFilterPredicate.java new file mode 100644 index 0000000000..14996063e0 --- /dev/null +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/ConnectionFilterPredicate.java @@ -0,0 +1,79 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.activemq.artemis.core.management.impl.view.predicate; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import org.apache.activemq.artemis.core.server.ActiveMQServer; +import org.apache.activemq.artemis.core.server.ServerSession; +import org.apache.activemq.artemis.spi.core.protocol.RemotingConnection; + +public class ConnectionFilterPredicate extends ActiveMQFilterPredicate { + + enum Field { + CONNECTION_ID, CLIENT_ID, USERS, PROTOCOL, SESSION_COUNT, REMOTE_ADDRESS, LOCAL_ADDRESS, SESSION_ID + } + + private Field f; + + private ActiveMQServer server; + + public ConnectionFilterPredicate(ActiveMQServer server) { + this.server = server; + } + + @Override + public boolean apply(RemotingConnection connection) { + // Using switch over enum vs string comparison is better for perf. + if (f == null) + return true; + switch (f) { + case CONNECTION_ID: + return matches(connection.getID()); + case CLIENT_ID: + return matches(connection.getClientID()); + case USERS: + List sessions = server.getSessions(connection.getID().toString()); + Set users = new HashSet<>(); + for (ServerSession session : sessions) { + String username = session.getUsername() == null ? "" : session.getUsername(); + users.add(username); + } + return matchAny(users); + case PROTOCOL: + return matches(connection.getProtocolName()); + case SESSION_COUNT: + return matches(server.getSessions(connection.getID().toString()).size()); + case REMOTE_ADDRESS: + return matches(connection.getTransportConnection().getRemoteAddress()); + case LOCAL_ADDRESS: + return matches(connection.getTransportConnection().getLocalAddress()); + case SESSION_ID: + return matchAny(server.getSessions(connection.getID().toString())); + } + return true; + } + + @Override + public void setField(String field) { + if (field != null && !field.equals("")) { + this.f = Field.valueOf(field.toUpperCase()); + } + } +} diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/ConsumerFilterPredicate.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/ConsumerFilterPredicate.java new file mode 100644 index 0000000000..83ca2ec17f --- /dev/null +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/ConsumerFilterPredicate.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.activemq.artemis.core.management.impl.view.predicate; + +import org.apache.activemq.artemis.core.server.ActiveMQServer; +import org.apache.activemq.artemis.core.server.ServerConsumer; + +public class ConsumerFilterPredicate extends ActiveMQFilterPredicate { + + enum Field { + ID, SESSION_ID, QUEUE, ADDRESS, USER, PROTOCOL, CLIENT_ID, LOCAL_ADDRESS, REMOTE_ADDRESS + } + + private Field f; + + private final ActiveMQServer server; + + public ConsumerFilterPredicate(ActiveMQServer server) { + super(); + this.server = server; + } + + @Override + public boolean apply(ServerConsumer consumer) { + // Using switch over enum vs string comparison is better for perf. + if (f == null) + return true; + switch (f) { + case ID: + return matches(consumer.getID()); + case SESSION_ID: + return matches(consumer.getSessionID()); + case USER: + return matches(server.getSessionByID(consumer.getSessionID()).getUsername()); + case ADDRESS: + return matches(consumer.getQueue().getAddress()); + case QUEUE: + return matches(consumer.getQueue().getName()); + case PROTOCOL: + return matches(server.getSessionByID(consumer.getSessionID()).getRemotingConnection().getProtocolName()); + case CLIENT_ID: + return matches(server.getSessionByID(consumer.getSessionID()).getRemotingConnection().getClientID()); + case LOCAL_ADDRESS: + return matches(server.getSessionByID(consumer.getSessionID()).getRemotingConnection().getTransportConnection().getLocalAddress()); + case REMOTE_ADDRESS: + return matches(server.getSessionByID(consumer.getSessionID()).getRemotingConnection().getTransportConnection().getRemoteAddress()); + } + return true; + } + + @Override + public void setField(String field) { + if (field != null && !field.equals("")) { + this.f = Field.valueOf(field.toUpperCase()); + } + } +} diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/ProducerFilterPredicate.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/ProducerFilterPredicate.java new file mode 100644 index 0000000000..35abf11919 --- /dev/null +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/ProducerFilterPredicate.java @@ -0,0 +1,71 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.activemq.artemis.core.management.impl.view.predicate; + +import org.apache.activemq.artemis.core.server.ActiveMQServer; +import org.apache.activemq.artemis.core.server.ServerProducer; + +public class ProducerFilterPredicate extends ActiveMQFilterPredicate { + + enum Field { + ID, SESSION_ID, CONNECTION_ID, ADDRESS, USER, PROTOCOL, CLIENT_ID, LOCAL_ADDRESS, REMOTE_ADDRESS + } + + private Field f; + + private final ActiveMQServer server; + + public ProducerFilterPredicate(ActiveMQServer server) { + super(); + this.server = server; + } + + @Override + public boolean apply(ServerProducer producer) { + // Using switch over enum vs string comparison is better for perf. + if (f == null) + return true; + switch (f) { + case ID: + return matches(producer.getID()); + case CONNECTION_ID: + return matches(producer.getConnectionID()); + case SESSION_ID: + return matches(producer.getSessionID()); + case USER: + return matches(server.getSessionByID(producer.getSessionID()).getUsername()); + case ADDRESS: + return matches(producer.getAddress() != null ? producer.getAddress() : server.getSessionByID(producer.getSessionID()).getDefaultAddress()); + case PROTOCOL: + return matches(producer.getProtocol()); + case CLIENT_ID: + return matches(server.getSessionByID(producer.getSessionID()).getRemotingConnection().getClientID()); + case LOCAL_ADDRESS: + return matches(server.getSessionByID(producer.getSessionID()).getRemotingConnection().getTransportConnection().getLocalAddress()); + case REMOTE_ADDRESS: + return matches(server.getSessionByID(producer.getSessionID()).getRemotingConnection().getTransportConnection().getRemoteAddress()); + default: return true; + } + } + + @Override + public void setField(String field) { + if (field != null && !field.equals("")) { + this.f = Field.valueOf(field.toUpperCase()); + } + } +} diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/QueueFilterPredicate.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/QueueFilterPredicate.java new file mode 100644 index 0000000000..e1ddd2010b --- /dev/null +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/QueueFilterPredicate.java @@ -0,0 +1,107 @@ +/* + * 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.activemq.artemis.core.management.impl.view.predicate; + +import org.apache.activemq.artemis.api.core.SimpleString; +import org.apache.activemq.artemis.api.core.management.QueueControl; +import org.apache.activemq.artemis.core.server.ActiveMQServer; +import org.apache.activemq.artemis.core.server.Consumer; +import org.apache.activemq.artemis.core.server.Queue; + +public class QueueFilterPredicate extends ActiveMQFilterPredicate { + + enum Field { + ID, NAME, CONSUMER_ID, QUEUE, ADDRESS, MAX_CONSUMERS, FILTER, MESSAGE_COUNT, CONSUMER_COUNT, DELIVERING_COUNT, + MESSAGES_ADDED, MESSAGES_ACKED, RATE, ROUTING_TYPE, USER, AUTO_CREATED, DURABLE, PAUSED, TEMPORARY, + PURGE_ON_NO_CONSUMERS, MESSAGES_KILLED, DIRECT_DELIVER + } + + private Field f; + + private ActiveMQServer server; + + public QueueFilterPredicate(ActiveMQServer server) { + super(); + this.server = server; + } + + @Override + public boolean apply(QueueControl queue) { + // Using switch over enum vs string comparison is better for perf. + try { + if (f == null) + return true; + switch (f) { + case ID: + return matches(queue.getID()); + case NAME: + return matches(queue.getName()); + case CONSUMER_ID: + Queue q = server.locateQueue(new SimpleString(queue.getName())); + for (Consumer consumer : q.getConsumers()) { + if (value.equals(consumer.sequentialID())) + return true; + } + return false; + case MAX_CONSUMERS: + return matches(queue.getMaxConsumers()); + case ADDRESS: + return matches(queue.getAddress()); + case FILTER: + return matches(queue.getFilter()); + case MESSAGE_COUNT: + return matches(queue.getMessageCount()); + case CONSUMER_COUNT: + return matches(queue.getConsumerCount()); + case DELIVERING_COUNT: + return matches(queue.getDeliveringCount()); + case MESSAGES_ADDED: + return matches(queue.getMessagesAdded()); + case MESSAGES_ACKED: + return matches(queue.getMessagesAcknowledged()); + case RATE: + return matches(queue.getMessagesExpired()); + case ROUTING_TYPE: + return matches(queue.getRoutingType()); + case AUTO_CREATED: + return matches(server.locateQueue(new SimpleString(queue.getName())).isAutoCreated()); + case DURABLE: + return matches(queue.isDurable()); + case PAUSED: + return matches(queue.isPaused()); + case TEMPORARY: + return matches(queue.isTemporary()); + case PURGE_ON_NO_CONSUMERS: + return matches(queue.isPurgeOnNoConsumers()); + case MESSAGES_KILLED: + return matches(queue.getMessagesKilled()); + default: + return true; + } + } catch (Exception e) { + return true; + } + + } + + @Override + public void setField(String field) { + if (field != null && !field.equals("")) { + this.f = Field.valueOf(field.toUpperCase()); + } + } +} diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/SessionFilterPredicate.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/SessionFilterPredicate.java new file mode 100644 index 0000000000..481e986a08 --- /dev/null +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/management/impl/view/predicate/SessionFilterPredicate.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.activemq.artemis.core.management.impl.view.predicate; + +import org.apache.activemq.artemis.core.server.ServerSession; + +public class SessionFilterPredicate extends ActiveMQFilterPredicate { + + enum Field { + ID, CONNECTION_ID, CONSUMER_COUNT, PRODUCER_COUNT, USER, PROTOCOL, CLIENT_ID, LOCAL_ADDRESS, REMOTE_ADDRESS + } + + private Field f; + + public SessionFilterPredicate() { + super(); + } + + @Override + public boolean apply(ServerSession session) { + // Using switch over enum vs string comparison is better for perf. + if (f == null) + return true; + switch (f) { + case ID: + return matches(session.getName()); + case CONNECTION_ID: + return matches(session.getConnectionID()); + case CONSUMER_COUNT: + return matches(session.getServerConsumers().size()); + case PRODUCER_COUNT: + return matches(session.getServerProducers().size()); + case PROTOCOL: + return matches(session.getRemotingConnection().getProtocolName()); + case CLIENT_ID: + return matches(session.getRemotingConnection().getClientID()); + case LOCAL_ADDRESS: + return matches(session.getRemotingConnection().getTransportConnection().getLocalAddress()); + case REMOTE_ADDRESS: + return matches(session.getRemotingConnection().getTransportConnection().getRemoteAddress()); + default: return true; + } + } + + @Override + public void setField(String field) { + if (field != null && !field.equals("")) { + this.f = Field.valueOf(field.toUpperCase()); + } + } +} diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/ActiveMQPacketHandler.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/ActiveMQPacketHandler.java index cefd10cdc9..1b5a2a6b1f 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/ActiveMQPacketHandler.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/protocol/core/impl/ActiveMQPacketHandler.java @@ -44,7 +44,9 @@ import org.apache.activemq.artemis.core.server.ActiveMQMessageBundle; import org.apache.activemq.artemis.core.server.ActiveMQServer; import org.apache.activemq.artemis.core.server.ActiveMQServerLogger; import org.apache.activemq.artemis.api.core.RoutingType; +import org.apache.activemq.artemis.core.server.ServerProducer; import org.apache.activemq.artemis.core.server.ServerSession; +import org.apache.activemq.artemis.core.server.impl.ServerProducerImpl; import org.apache.activemq.artemis.core.version.Version; import org.jboss.logging.Logger; @@ -168,9 +170,9 @@ public class ActiveMQPacketHandler implements ChannelHandler { } CoreSessionCallback sessionCallback = new CoreSessionCallback(request.getName(), protocolManager, channel, connection); - ServerSession session = server.createSession(request.getName(), activeMQPrincipal == null ? request.getUsername() : activeMQPrincipal.getUserName(), activeMQPrincipal == null ? request.getPassword() : activeMQPrincipal.getPassword(), request.getMinLargeMessageSize(), connection, request.isAutoCommitSends(), request.isAutoCommitAcks(), request.isPreAcknowledge(), request.isXA(), request.getDefaultAddress(), sessionCallback, true, sessionOperationContext, routingTypeMap); - + ServerProducer serverProducer = new ServerProducerImpl(session.getName(), "CORE", request.getDefaultAddress()); + session.addProducer(serverProducer); ServerSessionPacketHandler handler = new ServerSessionPacketHandler(server, protocolManager, session, server.getStorageManager(), channel); channel.setHandler(handler); sessionCallback.setSessionHandler(handler); diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ServerProducer.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ServerProducer.java new file mode 100644 index 0000000000..ced8636423 --- /dev/null +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ServerProducer.java @@ -0,0 +1,35 @@ +/** + * 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.activemq.artemis.core.server; + +public interface ServerProducer { + String getAddress(); + + String getProtocol(); + + void setSessionID(String sessionID); + + void setConnectionID(String connectionID); + + String getSessionID(); + + String getConnectionID(); + + String getID(); + + long getCreationTime(); +} diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ServerSession.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ServerSession.java index 700b82757d..a014c12455 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ServerSession.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/ServerSession.java @@ -17,6 +17,7 @@ package org.apache.activemq.artemis.core.server; import java.util.List; +import java.util.Map; import java.util.Set; import javax.json.JsonArrayBuilder; @@ -292,4 +293,12 @@ public interface ServerSession extends SecurityAuth { */ Pair> getAddressAndRoutingTypes(SimpleString address, Set defaultRoutingTypes); + + void addProducer(ServerProducer serverProducer); + + void removeProducer(String ID); + + Map getServerProducers(); + + String getDefaultAddress(); } diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerProducerImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerProducerImpl.java new file mode 100644 index 0000000000..dd072b8fed --- /dev/null +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerProducerImpl.java @@ -0,0 +1,78 @@ +/** + * 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.activemq.artemis.core.server.impl; + +import org.apache.activemq.artemis.core.server.ServerProducer; + +public class ServerProducerImpl implements ServerProducer { + private final String ID; + private final String protocol; + private final long creationTime; + + + private final String address; + private String sessionID; + private String connectionID; + + public ServerProducerImpl(String ID, String protocol, String address) { + this.ID = ID; + this.protocol = protocol; + this.address = address; + this.creationTime = System.currentTimeMillis(); + } + + @Override + public String getAddress() { + return address; + } + + @Override + public String getProtocol() { + return protocol; + } + + @Override + public void setSessionID(String sessionID) { + this.sessionID = sessionID; + } + + @Override + public void setConnectionID(String connectionID) { + + this.connectionID = connectionID; + } + + @Override + public String getSessionID() { + return sessionID; + } + + @Override + public String getConnectionID() { + return connectionID; + } + + @Override + public String getID() { + return ID; + } + + @Override + public long getCreationTime() { + return creationTime; + } +} diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java index 72f215480d..9dc7c2e08b 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/impl/ServerSessionImpl.java @@ -74,6 +74,7 @@ import org.apache.activemq.artemis.core.server.Queue; import org.apache.activemq.artemis.core.server.QueueQueryResult; import org.apache.activemq.artemis.core.server.RoutingContext; import org.apache.activemq.artemis.core.server.ServerConsumer; +import org.apache.activemq.artemis.core.server.ServerProducer; import org.apache.activemq.artemis.core.server.ServerSession; import org.apache.activemq.artemis.core.server.TempQueueObserver; import org.apache.activemq.artemis.core.server.management.ManagementService; @@ -126,6 +127,8 @@ public class ServerSessionImpl implements ServerSession, FailureListener { protected final Map consumers = new ConcurrentHashMap<>(); + protected final Map producers = new ConcurrentHashMap<>(); + protected Transaction tx; protected boolean xa; @@ -383,6 +386,7 @@ public class ServerSessionImpl implements ServerSession, FailureListener { } consumers.clear(); + producers.clear(); if (closeables != null) { for (Closeable closeable : closeables) { @@ -1729,4 +1733,26 @@ public class ServerSessionImpl implements ServerSession, FailureListener { } return new Pair<>(address, defaultRoutingTypes); } + + @Override + public void addProducer(ServerProducer serverProducer) { + serverProducer.setSessionID(getName()); + serverProducer.setConnectionID(getConnectionID().toString()); + producers.put(serverProducer.getID(), serverProducer); + } + + @Override + public void removeProducer(String ID) { + producers.remove(ID); + } + + @Override + public Map getServerProducers() { + return Collections.unmodifiableMap(new HashMap(producers)); + } + + @Override + public String getDefaultAddress() { + return defaultAddress != null ? defaultAddress.toString() : null; + } } diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlUsingCoreTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlUsingCoreTest.java index ed704ef483..587cab4b15 100644 --- a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlUsingCoreTest.java +++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/management/ActiveMQServerControlUsingCoreTest.java @@ -891,6 +891,47 @@ public class ActiveMQServerControlUsingCoreTest extends ActiveMQServerControlTes public String listAddresses(@Parameter(name = "separator", desc = "Separator used on the string listing") String separator) throws Exception { return (String) proxy.invokeOperation("listAddresses", separator); } + + @Override + public String listConnections(String filter, int page, int pageSize) throws Exception { + return (String) proxy.invokeOperation("listAddresses", filter, page, pageSize); + } + + @Override + public String listSessions(@Parameter(name = "Filter String") String filter, + @Parameter(name = "Page Number") int page, + @Parameter(name = "Page Size") int pageSize) throws Exception { + return null; + } + + @Override + public String listConsumers(@Parameter(name = "Options") String options, + @Parameter(name = "Page Number") int page, + @Parameter(name = "Page Size") int pageSize) throws Exception { + return null; + } + + + @Override + public String listProducers(@Parameter(name = "Options") String options, + @Parameter(name = "Page Number") int page, + @Parameter(name = "Page Size") int pageSize) throws Exception { + return null; + } + + @Override + public String listAddresses(@Parameter(name = "Options") String options, + @Parameter(name = "Page Number") int page, + @Parameter(name = "Page Size") int pageSize) throws Exception { + return null; + } + + @Override + public String listQueues(@Parameter(name = "Options") String options, + @Parameter(name = "Page Number") int page, + @Parameter(name = "Page Size") int pageSize) throws Exception { + return null; + } }; } From 06ea18d55c579ab2b1c64e0dc819b3a14e4803d9 Mon Sep 17 00:00:00 2001 From: Martyn Taylor Date: Mon, 14 Aug 2017 16:40:24 +0100 Subject: [PATCH 2/2] ARTEMIS-1350 Expose Client Objects in Console --- .../main/webapp/plugin/html/addresses.html | 54 ++++ .../main/webapp/plugin/html/connections.html | 53 ++++ .../main/webapp/plugin/html/consumers.html | 54 ++++ .../main/webapp/plugin/html/producers.html | 54 ++++ .../src/main/webapp/plugin/html/queues.html | 54 ++++ .../src/main/webapp/plugin/html/sessions.html | 53 ++++ .../src/main/webapp/plugin/js/addresses.js | 196 ++++++++++++ .../main/webapp/plugin/js/artemisHelpers.js | 23 ++ .../main/webapp/plugin/js/artemisPlugin.js | 96 +++++- .../src/main/webapp/plugin/js/connections.js | 214 +++++++++++++ .../src/main/webapp/plugin/js/consumers.js | 239 ++++++++++++++ .../src/main/webapp/plugin/js/producers.js | 220 +++++++++++++ .../src/main/webapp/plugin/js/queues.js | 298 ++++++++++++++++++ .../src/main/webapp/plugin/js/sessions.js | 233 ++++++++++++++ 14 files changed, 1832 insertions(+), 9 deletions(-) create mode 100644 artemis-hawtio/artemis-plugin/src/main/webapp/plugin/html/addresses.html create mode 100644 artemis-hawtio/artemis-plugin/src/main/webapp/plugin/html/connections.html create mode 100644 artemis-hawtio/artemis-plugin/src/main/webapp/plugin/html/consumers.html create mode 100644 artemis-hawtio/artemis-plugin/src/main/webapp/plugin/html/producers.html create mode 100644 artemis-hawtio/artemis-plugin/src/main/webapp/plugin/html/queues.html create mode 100644 artemis-hawtio/artemis-plugin/src/main/webapp/plugin/html/sessions.html create mode 100644 artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/addresses.js create mode 100644 artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/connections.js create mode 100644 artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/consumers.js create mode 100644 artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/producers.js create mode 100644 artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/queues.js create mode 100644 artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/sessions.js diff --git a/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/html/addresses.html b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/html/addresses.html new file mode 100644 index 0000000000..f6ca987019 --- /dev/null +++ b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/html/addresses.html @@ -0,0 +1,54 @@ + +

+ + +
+
+
+
+  Filter +    + + + + +    + +
+
+
+
+ +
+
+
+ +
\ No newline at end of file diff --git a/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/html/connections.html b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/html/connections.html new file mode 100644 index 0000000000..c844ab86eb --- /dev/null +++ b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/html/connections.html @@ -0,0 +1,53 @@ + +
+ +
+
+
+
+  Filter +    + + + + +    + +
+
+
+
+ + +
+
+
+ +
\ No newline at end of file diff --git a/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/html/consumers.html b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/html/consumers.html new file mode 100644 index 0000000000..296c54dc7e --- /dev/null +++ b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/html/consumers.html @@ -0,0 +1,54 @@ + +
+ + +
+
+
+
+  Filter +    + + + + +    + +
+
+
+
+ +
+
+
+ +
\ No newline at end of file diff --git a/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/html/producers.html b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/html/producers.html new file mode 100644 index 0000000000..12bfe0c659 --- /dev/null +++ b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/html/producers.html @@ -0,0 +1,54 @@ + +
+ + +
+
+
+
+  Filter +    + + + + +    + +
+
+
+
+ +
+
+
+ +
\ No newline at end of file diff --git a/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/html/queues.html b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/html/queues.html new file mode 100644 index 0000000000..d5d03fe167 --- /dev/null +++ b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/html/queues.html @@ -0,0 +1,54 @@ + +
+ + +
+
+
+
+  Filter +    + + + + +    + +
+
+
+
+ +
+
+
+ +
\ No newline at end of file diff --git a/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/html/sessions.html b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/html/sessions.html new file mode 100644 index 0000000000..f81fd7ea9d --- /dev/null +++ b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/html/sessions.html @@ -0,0 +1,53 @@ + +
+ +
+
+
+
+  Filter +    + + + + +    + +
+
+
+
+ +
+
+
+ +
\ No newline at end of file diff --git a/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/addresses.js b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/addresses.js new file mode 100644 index 0000000000..9f9d87d734 --- /dev/null +++ b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/addresses.js @@ -0,0 +1,196 @@ +/* + * 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. + */ +/** + * @module ARTEMIS + */ +var ARTEMIS = (function(ARTEMIS) { + + ARTEMIS.AddressesController = function ($scope, $location, workspace, ARTEMISService, jolokia, localStorage, artemisAddress) { + + var artemisJmxDomain = localStorage['artemisJmxDomain'] || "org.apache.activemq.artemis"; + + /** + * Required For Each Object Type + */ + + var objectType = "address"; + var method = 'listAddresses(java.lang.String, int, int)'; + var attributes = [ + { + field: 'manage', + displayName: 'manage', + width: '*', + cellTemplate: '' + }, + { + field: 'id', + displayName: 'ID', + width: '*' + }, + { + field: 'name', + displayName: 'Name', + width: '*' + }, + { + field: 'routingTypes', + displayName: 'Routing Types', + width: '*' + }, + { + field: 'queueCount', + displayName: 'Queue Count', + width: '*' + } + ]; + $scope.filter = { + fieldOptions: [ + {id: 'ID', name: 'ID'}, + {id: 'NAME', name: 'Name'}, + {id: 'ROUTING_TYPES', name: 'Routing Types'}, + {id: 'QUEUE_COUNT', name: 'Queue Count'}, + ], + operationOptions: [ + {id: 'EQUALS', name: 'Equals'}, + {id: 'CONTAINS', name: 'Contains'} + ], + values: { + field: "", + operation: "", + value: "", + sortOrder: "asc", + sortBy: "ID" + } + }; + + /** + * Below here is utility. + * + * TODO Refactor into new separate files + */ + + + if (artemisAddress.address) { + $scope.filter.values.field = $scope.filter.fieldOptions[1].id; + $scope.filter.values.operation = $scope.filter.operationOptions[0].id; + $scope.filter.values.value = artemisAddress.address.address; + artemisAddress.address = null; + } + + $scope.navigateToAddressAtts = function (row) { + $location.path("jmx/attributes").search({"tab": "artemis", "nid": ARTEMIS.getAddressNid(row.entity, $location)}); + }; + $scope.navigateToAddressOps = function (row) { + $location.path("jmx/operations").search({"tab": "artemis", "nid": ARTEMIS.getAddressNid(row.entity, $location)}); + }; + $scope.workspace = workspace; + $scope.objects = []; + $scope.totalServerItems = 0; + $scope.pagingOptions = { + pageSizes: [50, 100, 200], + pageSize: 100, + currentPage: 1 + }; + $scope.sort = { + fields: ["ID"], + directions: ["asc"] + }; + var refreshed = false; + + $scope.gridOptions = { + selectedItems: [], + data: 'objects', + showFooter: true, + showFilter: true, + showColumnMenu: true, + enableCellSelection: false, + enableHighlighting: true, + enableColumnResize: true, + enableColumnReordering: true, + selectWithCheckboxOnly: false, + showSelectionCheckbox: false, + multiSelect: false, + displaySelectionCheckbox: false, + pagingOptions: $scope.pagingOptions, + enablePaging: true, + totalServerItems: 'totalServerItems', + maintainColumnRatios: false, + columnDefs: attributes, + enableFiltering: true, + useExternalFiltering: true, + sortInfo: $scope.sortOptions, + useExternalSorting: true, + }; + $scope.refresh = function () { + refreshed = true; + $scope.loadTable(); + }; + $scope.reset = function () { + $scope.filter.values.field = ""; + $scope.filter.values.operation = ""; + $scope.filter.values.value = ""; + $scope.loadTable(); + }; + $scope.loadTable = function () { + $scope.filter.values.sortColumn = $scope.sort.fields[0]; + $scope.filter.values.sortBy = $scope.sort.directions[0]; + var mbean = getBrokerMBean(jolokia); + if (mbean) { + var filter = JSON.stringify($scope.filter.values); + console.log("Filter string: " + filter); + jolokia.request({ type: 'exec', mbean: mbean, operation: method, arguments: [filter, $scope.pagingOptions.currentPage, $scope.pagingOptions.pageSize] }, onSuccess(populateTable, { error: onError })); + } + }; + function onError() { + Core.notification("error", "Could not retrieve " + objectType + " list from Artemis."); + } + function populateTable(response) { + var data = JSON.parse(response.value); + $scope.objects = []; + angular.forEach(data["data"], function (value, idx) { + $scope.objects.push(value); + }); + $scope.totalServerItems = data["count"]; + if (refreshed == true) { + $scope.gridOptions.pagingOptions.currentPage = 1; + refreshed = false; + } + Core.$apply($scope); + } + $scope.$watch('sortOptions', function (newVal, oldVal) { + if (newVal !== oldVal) { + $scope.loadTable(); + } + }, true); + $scope.$watch('pagingOptions', function (newVal, oldVal) { + if (parseInt(newVal.currentPage) && newVal !== oldVal && newVal.currentPage !== oldVal.currentPage) { + $scope.loadTable(); + } + }, true); + + function getBrokerMBean(jolokia) { + var mbean = null; + var selection = workspace.selection; + var folderNames = selection.folderNames; + mbean = "" + folderNames[0] + ":broker=" + folderNames[1]; + ARTEMIS.log.info("broker=" + mbean); + return mbean; + }; + $scope.refresh(); + }; + return ARTEMIS; +} (ARTEMIS || {})); diff --git a/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/artemisHelpers.js b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/artemisHelpers.js index 210c52a4be..354f0939db 100644 --- a/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/artemisHelpers.js +++ b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/artemisHelpers.js @@ -123,4 +123,27 @@ var ARTEMIS; }); } ARTEMIS.decorate = decorate; + + function getAddressNid(address, $location) { + var rootNID = getRootNid($location); + var targetNID = rootNID + "-addresses-\"" + address.name + "\""; + ARTEMIS.log.info("targetNID=" + targetNID); + return targetNID; + } + ARTEMIS.getAddressNid = getAddressNid; + + function getQueueNid(queue, $location) { + var rootNID = getRootNid($location); + var targetNID = rootNID + "-addresses-\"" + queue.address + "\"-queues-\"" + queue.routingType.toLowerCase() + "\"-\"" + queue.name + "\""; + return targetNID; + } + ARTEMIS.getQueueNid = getQueueNid; + + function getRootNid($location) { + var currentNid = $location.search()['nid']; + var firstQoute = currentNid.indexOf('"'); + var secondQuote = currentNid.indexOf('"', firstQoute + 1); + var rootNID = currentNid.substring(0, secondQuote + 1); + return rootNID; +} })(ARTEMIS || (ARTEMIS = {})); \ No newline at end of file diff --git a/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/artemisPlugin.js b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/artemisPlugin.js index 6f791698cc..a1c3d6a31b 100644 --- a/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/artemisPlugin.js +++ b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/artemisPlugin.js @@ -110,12 +110,48 @@ var ARTEMIS = (function(ARTEMIS) { }) .when('/artemis/sendMessage', { templateUrl: ARTEMIS.templatePath + 'sendMessage.html' - }); + }) + .when('/artemis/connections', { + templateUrl: ARTEMIS.templatePath + 'connections.html' + }) + .when('/artemis/sessions', { + templateUrl: ARTEMIS.templatePath + 'sessions.html' + }) + .when('/artemis/consumers', { + templateUrl: ARTEMIS.templatePath + 'consumers.html' + }) + .when('/artemis/producers', { + templateUrl: ARTEMIS.templatePath + 'producers.html' + }) + .when('/artemis/addresses', { + templateUrl: ARTEMIS.templatePath + 'addresses.html' + }) + .when('/artemis/queues', { + templateUrl: ARTEMIS.templatePath + 'queues.html' + }); }); ARTEMIS.module.factory('artemisMessage', function () { return { 'message': null }; - }); + }); + ARTEMIS.module.factory('artemisConnection', function () { + return { 'connection': null }; + }); + ARTEMIS.module.factory('artemisSession', function () { + return { 'session': null }; + }); + ARTEMIS.module.factory('artemisConsumer', function () { + return { 'consumer': null }; + }); + ARTEMIS.module.factory('artemisProducer', function () { + return { 'producer': null }; + }); + ARTEMIS.module.factory('artemisQueue', function () { + return { 'queue': null }; + }); + ARTEMIS.module.factory('artemisAddress', function () { + return { 'address': null }; + }); // one-time initialization happens in the run function // of our module @@ -213,12 +249,54 @@ var ARTEMIS = (function(ARTEMIS) { href: function () { return "#/artemis/sendMessage"; } }); - workspace.subLevelTabs.push({ - content: ' Diagram', - title: "View a diagram of the producers, destinations and consumers", - isValid: function (workspace) { return workspace.isTopTabActive("artemis") || workspace.selectionHasDomain(artemisJmxDomain); }, - href: function () { return "#/artemis/diagram"; } - }); + workspace.subLevelTabs.unshift({ + content: ' Diagram             |', + title: "View a diagram of the producers, destinations and consumers", + isValid: function (workspace) { return workspace.isTopTabActive("artemis") || workspace.selectionHasDomain(artemisJmxDomain); }, + href: function () { return "#/artemis/diagram"; } + }); + + workspace.subLevelTabs.unshift({ + content: ' Queues', + title: "Manage Queues", + isValid: function (workspace) { return workspace.isTopTabActive("artemis") || workspace.selectionHasDomain(artemisJmxDomain); }, + href: function () { return "#/artemis/queues"; } + }); + + workspace.subLevelTabs.unshift({ + content: ' Addresses', + title: "Manage Addresses", + isValid: function (workspace) { return workspace.isTopTabActive("artemis") || workspace.selectionHasDomain(artemisJmxDomain); }, + href: function () { return "#/artemis/addresses"; } + }); + + workspace.subLevelTabs.unshift({ + content: ' Producers', + title: "Manage Producers", + isValid: function (workspace) { return workspace.isTopTabActive("artemis") || workspace.selectionHasDomain(artemisJmxDomain); }, + href: function () { return "#/artemis/producers"; } + }); + + workspace.subLevelTabs.unshift({ + content: ' Consumers', + title: "Manage Consumers", + isValid: function (workspace) { return workspace.isTopTabActive("artemis") || workspace.selectionHasDomain(artemisJmxDomain); }, + href: function () { return "#/artemis/consumers"; } + }); + + workspace.subLevelTabs.unshift({ + content: ' Sessions', + title: "Manage Sessions", + isValid: function (workspace) { return workspace.isTopTabActive("artemis") || workspace.selectionHasDomain(artemisJmxDomain); }, + href: function () { return "#/artemis/sessions"; } + }); + + workspace.subLevelTabs.unshift({ + content: ' Connections', + title: "Manage Connections", + isValid: function (workspace) { return workspace.isTopTabActive("artemis") || workspace.selectionHasDomain(artemisJmxDomain); }, + href: function () { return "#/artemis/connections"; } + }); }); @@ -229,7 +307,7 @@ var ARTEMIS = (function(ARTEMIS) { function isAddressFolder(workspace, domain) { return workspace.selectionHasDomainAndLastFolderName(domain, 'addresses'); } - + function isAddress(workspace, domain) { return workspace.hasDomainAndProperties(domain, {'component': 'addresses'}) && !workspace.hasDomainAndProperties(domain, {'subcomponent': 'queues'}); } diff --git a/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/connections.js b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/connections.js new file mode 100644 index 0000000000..c362f361e5 --- /dev/null +++ b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/connections.js @@ -0,0 +1,214 @@ +/* + * 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. + */ +/** + * @module ARTEMIS + */ +var ARTEMIS = (function(ARTEMIS) { + + ARTEMIS.ConnectionsController = function ($scope, $location, workspace, ARTEMISService, jolokia, localStorage, artemisConnection, artemisSession) { + + var artemisJmxDomain = localStorage['artemisJmxDomain'] || "org.apache.activemq.artemis"; + + /** + * Required For Each Object Type + */ + + var objectType = "connection" + var method = 'listConnections(java.lang.String, int, int)'; + var attributes = [ + { + field: 'connectionID', + displayName: 'ID', + width: '*' + }, + { + field: 'clientID', + displayName: 'Client ID', + width: '*' + }, + { + field: 'users', + displayName: 'Users', + width: '*' + }, + { + field: 'protocol', + displayName: 'Protocol', + width: '*' + }, + { + field: 'sessionCount', + displayName: 'Session Count', + width: '*', + cellTemplate: '', + }, + { + field: 'remoteAddress', + displayName: 'Remote Address', + width: '*' + }, + { + field: 'localAddress', + displayName: 'Local Address', + width: '*' + }, + { + field: 'creationTime', + displayName: 'Creation Time', + width: '*' + } + ]; + $scope.filter = { + fieldOptions: [ + {id: 'CONNECTION_ID', name: 'Connection ID'}, + {id: 'CLIENT_ID', name: 'Client ID'}, + {id: 'USERS', name: 'Users'}, + {id: 'PROTOCOL', name: 'Protocol'}, + {id: 'SESSION_COUNT', name: 'Session Count'}, + {id: 'REMOTE_ADDRESS', name: 'Remote Address'}, + {id: 'LOCAL_ADDRESS', name: 'Local Address'}, + {id: 'SESSION_ID', name: 'Session ID'} + ], + operationOptions: [ + {id: 'EQUALS', name: 'Equals'}, + {id: 'CONTAINS', name: 'Contains'} + ], + values: { + field: "", + operation: "", + value: "", + sortOrder: "asc", + sortBy: "CONNECTION_ID" + } + }; + + // Configure Parent/Child click through relationships + if (artemisSession.session) { + $scope.filter.values.field = $scope.filter.fieldOptions[0].id; + $scope.filter.values.operation = $scope.filter.operationOptions[0].id; + $scope.filter.values.value = artemisSession.session.connectionID; + artemisSession.session = null; + } + + $scope.selectSessions = function (connection) { + artemisConnection.connection = connection.entity; + $location.path("artemis/sessions"); + }; + + /** + * Below here is utility. + * + * TODO Refactor into new separate files + */ + + $scope.workspace = workspace; + $scope.objects = []; + $scope.totalServerItems = 0; + $scope.pagingOptions = { + pageSizes: [50, 100, 200], + pageSize: 100, + currentPage: 1 + }; + $scope.sort = { + fields: ["ID"], + directions: ["asc"] + }; + var refreshed = false; + + $scope.gridOptions = { + selectedItems: [], + data: 'objects', + showFooter: true, + showFilter: true, + showColumnMenu: true, + enableCellSelection: false, + enableHighlighting: true, + enableColumnResize: true, + enableColumnReordering: true, + selectWithCheckboxOnly: false, + showSelectionCheckbox: false, + multiSelect: false, + displaySelectionCheckbox: false, + pagingOptions: $scope.pagingOptions, + enablePaging: true, + totalServerItems: 'totalServerItems', + maintainColumnRatios: false, + columnDefs: attributes, + enableFiltering: true, + useExternalFiltering: true, + sortInfo: $scope.sortOptions, + useExternalSorting: true, + }; + $scope.refresh = function () { + refreshed = true; + $scope.loadTable(); + }; + $scope.reset = function () { + $scope.filter.values.field = ""; + $scope.filter.values.operation = ""; + $scope.filter.values.value = ""; + $scope.loadTable(); + }; + $scope.loadTable = function () { + $scope.filter.values.sortColumn = $scope.sort.fields[0]; + $scope.filter.values.sortBy = $scope.sort.directions[0]; + var mbean = getBrokerMBean(jolokia); + if (mbean) { + var filter = JSON.stringify($scope.filter.values); + console.log("Filter string: " + filter); + jolokia.request({ type: 'exec', mbean: mbean, operation: method, arguments: [filter, $scope.pagingOptions.currentPage, $scope.pagingOptions.pageSize] }, onSuccess(populateTable, { error: onError })); + } + }; + function onError() { + Core.notification("error", "Could not retrieve " + objectType + " list from Artemis."); + } + function populateTable(response) { + var data = JSON.parse(response.value); + $scope.objects = []; + angular.forEach(data["data"], function (value, idx) { + $scope.objects.push(value); + }); + $scope.totalServerItems = data["count"]; + if (refreshed == true) { + $scope.gridOptions.pagingOptions.currentPage = 1; + refreshed = false; + } + Core.$apply($scope); + } + $scope.$watch('sortOptions', function (newVal, oldVal) { + if (newVal !== oldVal) { + $scope.loadTable(); + } + }, true); + $scope.$watch('pagingOptions', function (newVal, oldVal) { + if (parseInt(newVal.currentPage) && newVal !== oldVal && newVal.currentPage !== oldVal.currentPage) { + $scope.loadTable(); + } + }, true); + + function getBrokerMBean(jolokia) { + var mbean = null; + var selection = workspace.selection; + var folderNames = selection.folderNames; + mbean = "" + folderNames[0] + ":broker=" + folderNames[1]; + ARTEMIS.log.info("broker=" + mbean); + return mbean; + }; + $scope.refresh(); + }; + return ARTEMIS; +} (ARTEMIS || {})); diff --git a/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/consumers.js b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/consumers.js new file mode 100644 index 0000000000..8a22fb933e --- /dev/null +++ b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/consumers.js @@ -0,0 +1,239 @@ +/* + * 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. + */ +/** + * @module ARTEMIS + */ +var ARTEMIS = (function(ARTEMIS) { + + ARTEMIS.ConsumersController = function ($scope, $location, workspace, ARTEMISService, jolokia, localStorage, artemisConnection, artemisSession, artemisConsumer, artemisQueue, artemisAddress) { + + var artemisJmxDomain = localStorage['artemisJmxDomain'] || "org.apache.activemq.artemis"; + + /** + * Required For Each Object Type + */ + + var objectType = "consumer"; + var method = 'listConsumers(java.lang.String, int, int)'; + var attributes = [ + { + field: 'id', + displayName: 'ID', + width: '*' + }, + { + field: 'session', + displayName: 'Session', + width: '*', + cellTemplate: '' + }, + { + field: 'clientID', + displayName: 'Client ID', + width: '*' + }, + { + field: 'protocol', + displayName: 'Protocol', + width: '*' + }, + { + field: 'queue', + displayName: 'Queue', + width: '*', + cellTemplate: '' + }, + { + field: 'queueType', + displayName: 'Queue Type', + width: '*' + }, + { + field: 'address', + displayName: 'Address', + width: '*', + cellTemplate: '' + }, + { + field: 'remoteAddress', + displayName: 'Remote Address', + width: '*' + }, + { + field: 'localAddress', + displayName: 'Local Address', + width: '*' + }, + { + field: 'creationTime', + displayName: 'Creation Time', + width: '*' + } + ]; + $scope.filter = { + fieldOptions: [ + {id: 'ID', name: 'ID'}, + {id: 'SESSION_ID', name: 'Session ID'}, + {id: 'CLIENT_ID', name: 'Client ID'}, + {id: 'USER', name: 'User'}, + {id: 'ADDRESS', name: 'Address'}, + {id: 'QUEUE', name: 'Queue'}, + {id: 'PROTOCOL', name: 'Protocol'}, + {id: 'REMOTE_ADDRESS', name: 'Remote Address'}, + {id: 'LOCAL_ADDRESS', name: 'Local Address'} + ], + operationOptions: [ + {id: 'EQUALS', name: 'Equals'}, + {id: 'CONTAINS', name: 'Contains'} + ], + values: { + field: "", + operation: "", + value: "", + sortOrder: "asc", + sortBy: "ID" + } + }; + + $scope.selectSession = function (row) { + artemisConsumer.consumer = row.entity; + $location.path("artemis/sessions"); + }; + + $scope.selectQueue = function (row) { + artemisQueue.queue = row.entity; + $location.path("artemis/queues"); + }; + + $scope.selectAddress = function (row) { + artemisAddress.address = row.entity; + $location.path("artemis/addresses"); + }; + + // Configure Parent/Child click through relationships + if (artemisSession.session) { + $scope.filter.values.field = $scope.filter.fieldOptions[1].id; + $scope.filter.values.operation = $scope.filter.operationOptions[0].id; + $scope.filter.values.value = artemisSession.session.id; + artemisSession.session = null; + } + + artemisSession.session = null; + + /** + * Below here is utility. + * + * TODO Refactor into new separate files + */ + + $scope.workspace = workspace; + $scope.objects = []; + $scope.totalServerItems = 0; + $scope.pagingOptions = { + pageSizes: [50, 100, 200], + pageSize: 100, + currentPage: 1 + }; + $scope.sort = { + fields: ["ID"], + directions: ["asc"] + }; + var refreshed = false; + + $scope.gridOptions = { + selectedItems: [], + data: 'objects', + showFooter: true, + showFilter: true, + showColumnMenu: true, + enableCellSelection: false, + enableHighlighting: true, + enableColumnResize: true, + enableColumnReordering: true, + selectWithCheckboxOnly: false, + showSelectionCheckbox: false, + multiSelect: false, + displaySelectionCheckbox: false, + pagingOptions: $scope.pagingOptions, + enablePaging: true, + totalServerItems: 'totalServerItems', + maintainColumnRatios: false, + columnDefs: attributes, + enableFiltering: true, + useExternalFiltering: true, + sortInfo: $scope.sortOptions, + useExternalSorting: true, + }; + $scope.refresh = function () { + refreshed = true; + $scope.loadTable(); + }; + $scope.reset = function () { + $scope.filter.values.field = ""; + $scope.filter.values.operation = ""; + $scope.filter.values.value = ""; + $scope.loadTable(); + }; + $scope.loadTable = function () { + $scope.filter.values.sortColumn = $scope.sort.fields[0]; + $scope.filter.values.sortBy = $scope.sort.directions[0]; + var mbean = getBrokerMBean(jolokia); + if (mbean) { + var filter = JSON.stringify($scope.filter.values); + console.log("Filter string: " + filter); + jolokia.request({ type: 'exec', mbean: mbean, operation: method, arguments: [filter, $scope.pagingOptions.currentPage, $scope.pagingOptions.pageSize] }, onSuccess(populateTable, { error: onError })); + } + }; + function onError() { + Core.notification("error", "Could not retrieve " + objectType + " list from Artemis."); + } + function populateTable(response) { + var data = JSON.parse(response.value); + $scope.objects = []; + angular.forEach(data["data"], function (value, idx) { + $scope.objects.push(value); + }); + $scope.totalServerItems = data["count"]; + if (refreshed == true) { + $scope.gridOptions.pagingOptions.currentPage = 1; + refreshed = false; + } + Core.$apply($scope); + } + $scope.$watch('sortOptions', function (newVal, oldVal) { + if (newVal !== oldVal) { + $scope.loadTable(); + } + }, true); + $scope.$watch('pagingOptions', function (newVal, oldVal) { + if (parseInt(newVal.currentPage) && newVal !== oldVal && newVal.currentPage !== oldVal.currentPage) { + $scope.loadTable(); + } + }, true); + + function getBrokerMBean(jolokia) { + var mbean = null; + var selection = workspace.selection; + var folderNames = selection.folderNames; + mbean = "" + folderNames[0] + ":broker=" + folderNames[1]; + ARTEMIS.log.info("broker=" + mbean); + return mbean; + }; + $scope.refresh(); + }; + return ARTEMIS; +} (ARTEMIS || {})); diff --git a/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/producers.js b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/producers.js new file mode 100644 index 0000000000..c863268431 --- /dev/null +++ b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/producers.js @@ -0,0 +1,220 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/** + * @module ARTEMIS + */ +var ARTEMIS = (function(ARTEMIS) { + + ARTEMIS.ProducersController = function ($scope, $location, workspace, ARTEMISService, jolokia, localStorage, artemisAddress, artemisSession, artemisProducer) { + + var artemisJmxDomain = localStorage['artemisJmxDomain'] || "org.apache.activemq.artemis"; + + /** + * Required For Each Object Type + */ + + var objectType = "producer"; + var method = 'listProducers(java.lang.String, int, int)'; + var attributes = [ + { + field: 'id', + displayName: 'ID', + width: '*' + }, + { + field: 'session', + displayName: 'Session', + width: '*', + cellTemplate: '' + }, + { + field: 'clientID', + displayName: 'Client ID', + width: '*' + }, + { + field: 'protocol', + displayName: 'Protocol', + width: '*' + }, + { + field: 'user', + displayName: 'User', + width: '*' + }, + { + field: 'address', + displayName: 'Address', + width: '*', + cellTemplate: '' + }, + { + field: 'remoteAddress', + displayName: 'Remote Address', + width: '*' + }, + { + field: 'localAddress', + displayName: 'Local Address', + width: '*' + } + ]; + $scope.filter = { + fieldOptions: [ + {id: 'ID', name: 'ID'}, + {id: 'SESSION_ID', name: 'Session ID'}, + {id: 'CLIENT_ID', name: 'Client ID'}, + {id: 'USER', name: 'User'}, + {id: 'ADDRESS', name: 'Address'}, + {id: 'PROTOCOL', name: 'Protocol'}, + {id: 'REMOTE_ADDRESS', name: 'Remote Address'}, + {id: 'LOCAL_ADDRESS', name: 'Local Address'} + ], + operationOptions: [ + {id: 'EQUALS', name: 'Equals'}, + {id: 'CONTAINS', name: 'Contains'} + ], + values: { + field: "", + operation: "", + value: "", + sortOrder: "asc", + sortBy: "ID" + } + }; + + $scope.selectAddress = function (row) { + artemisAddress.address = row.entity; + $location.path("artemis/addresses"); + }; + + $scope.selectSession = function (row) { + artemisProducer.producer = row.entity; + $location.path("artemis/sessions"); + }; + + // Configure Parent/Child click through relationships + if (artemisSession.session) { + $scope.filter.values.field = $scope.filter.fieldOptions[1].id; + $scope.filter.values.operation = $scope.filter.operationOptions[0].id; + $scope.filter.values.value = artemisSession.session.id; + artemisSession.session = null; + } + + /** + * Below here is utility. + * + * TODO Refactor into new separate files + */ + + $scope.workspace = workspace; + $scope.objects = []; + $scope.totalServerItems = 0; + $scope.pagingOptions = { + pageSizes: [50, 100, 200], + pageSize: 100, + currentPage: 1 + }; + $scope.sort = { + fields: ["ID"], + directions: ["asc"] + }; + var refreshed = false; + + $scope.gridOptions = { + selectedItems: [], + data: 'objects', + showFooter: true, + showFilter: true, + showColumnMenu: true, + enableCellSelection: false, + enableHighlighting: true, + enableColumnResize: true, + enableColumnReordering: true, + selectWithCheckboxOnly: false, + showSelectionCheckbox: false, + multiSelect: false, + displaySelectionCheckbox: false, + pagingOptions: $scope.pagingOptions, + enablePaging: true, + totalServerItems: 'totalServerItems', + maintainColumnRatios: false, + columnDefs: attributes, + enableFiltering: true, + useExternalFiltering: true, + sortInfo: $scope.sortOptions, + useExternalSorting: true, + }; + $scope.refresh = function () { + refreshed = true; + $scope.loadTable(); + }; + $scope.reset = function () { + $scope.filter.values.field = ""; + $scope.filter.values.operation = ""; + $scope.filter.values.value = ""; + $scope.loadTable(); + }; + $scope.loadTable = function () { + $scope.filter.values.sortColumn = $scope.sort.fields[0]; + $scope.filter.values.sortBy = $scope.sort.directions[0]; + var mbean = getBrokerMBean(jolokia); + if (mbean) { + var filter = JSON.stringify($scope.filter.values); + console.log("Filter string: " + filter); + jolokia.request({ type: 'exec', mbean: mbean, operation: method, arguments: [filter, $scope.pagingOptions.currentPage, $scope.pagingOptions.pageSize] }, onSuccess(populateTable, { error: onError })); + } + }; + function onError() { + Core.notification("error", "Could not retrieve " + objectType + " list from Artemis."); + } + function populateTable(response) { + var data = JSON.parse(response.value); + $scope.objects = []; + angular.forEach(data["data"], function (value, idx) { + $scope.objects.push(value); + }); + $scope.totalServerItems = data["count"]; + if (refreshed == true) { + $scope.gridOptions.pagingOptions.currentPage = 1; + refreshed = false; + } + Core.$apply($scope); + } + $scope.$watch('sortOptions', function (newVal, oldVal) { + if (newVal !== oldVal) { + $scope.loadTable(); + } + }, true); + $scope.$watch('pagingOptions', function (newVal, oldVal) { + if (parseInt(newVal.currentPage) && newVal !== oldVal && newVal.currentPage !== oldVal.currentPage) { + $scope.loadTable(); + } + }, true); + + function getBrokerMBean(jolokia) { + var mbean = null; + var selection = workspace.selection; + var folderNames = selection.folderNames; + mbean = "" + folderNames[0] + ":broker=" + folderNames[1]; + ARTEMIS.log.info("broker=" + mbean); + return mbean; + }; + $scope.refresh(); + }; + return ARTEMIS; +} (ARTEMIS || {})); diff --git a/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/queues.js b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/queues.js new file mode 100644 index 0000000000..16300e6150 --- /dev/null +++ b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/queues.js @@ -0,0 +1,298 @@ +/* + * 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. + */ +/** + * @module ARTEMIS + */ +var ARTEMIS = (function(ARTEMIS) { + + ARTEMIS.QueuesController = function ($scope, $location, workspace, ARTEMISService, jolokia, localStorage, artemisConnection, artemisSession, artemisQueue) { + + var artemisJmxDomain = localStorage['artemisJmxDomain'] || "org.apache.activemq.artemis"; + + /** + * Required For Each Object Type + */ + + var objectType = "queue"; + var method = 'listQueues(java.lang.String, int, int)'; + var attributes = [ + { + field: 'manage', + displayName: 'manage', + width: '*', + cellTemplate: '' + }, + { + field: 'id', + displayName: 'ID', + width: '*' + }, + { + field: 'name', + displayName: 'Name', + width: '*' + }, + { + field: 'address', + displayName: 'Address', + width: '*' + }, + { + field: 'routingType', + displayName: 'Routing Type', + width: '*' + }, + { + field: 'filter', + displayName: 'Filter', + width: '*' + }, + { + field: 'durable', + displayName: 'Durable', + width: '*' + }, + { + field: 'maxConsumers', + displayName: 'Max Consumers', + width: '*' + }, + { + field: 'purgeOnNoConsumers', + displayName: 'Purge On No Consumers', + width: '*' + }, + { + field: 'consumerCount', + displayName: 'Consumer Count', + width: '*' + }, + { + field: 'rate', + displayName: 'Rate', + width: '*' + }, + { + field: 'messageCount', + displayName: 'Message Count', + width: '*' + }, + + // Hidden + { + field: 'paused', + displayName: 'Paused', + width: '*', + visible: false + }, + { + field: 'temporary', + displayName: 'Temporary', + width: '*', + visible: false + }, + { + field: 'autoCreated', + displayName: 'Auto Created', + width: '*', + visible: false + }, + { + field: 'user', + displayName: 'User', + width: '*', + visible: false + }, + { + field: 'messagesAdded', + displayName: 'Total Messages Added', + width: '*', + visible: false + }, + { + field: 'messagesAcked', + displayName: 'Total Messages Acked', + width: '*', + visible: false + }, + { + field: 'deliveringCount', + displayName: 'Deliveing Count', + width: '*', + visible: false + }, + { + field: 'messagesKilled', + displayName: 'Messages Killed', + width: '*', + visible: false + }, + { + field: 'directDeliver', + displayName: 'Deliveing Count', + width: '*', + visible: false + } + ]; + + $scope.filter = { + fieldOptions: [ + {id: 'ID', name: 'ID'}, + {id: 'NAME', name: 'Name'}, + {id: 'CONSUMER_ID', name: 'Consumer ID'}, + {id: 'ADDRESS', name: 'Address'}, + {id: 'FILTER', name: 'Filter'}, + {id: 'MAX_CONSUMERS', name: 'maxConsumers'}, + {id: 'ROUTING_TYPE', name: 'Routing Type'}, + {id: 'PURGE_ON_NO_CONSUMERS', name: 'Purge On No Consumers'}, + {id: 'USER', name: 'User'}, + {id: 'MESSAGE_COUNT', name: 'Message Count'}, + {id: 'DELIVERING_COUNT', name: 'Delivering Count'}, + {id: 'PAUSED', name: 'Paused'}, + {id: 'TEMPORARY', name: 'Temporary'}, + {id: 'AUTO_CREATED', name: 'Auto Created'}, + {id: 'RATE', name: 'Rate'}, + ], + operationOptions: [ + {id: 'EQUALS', name: 'Equals'}, + {id: 'CONTAINS', name: 'Contains'} + ], + values: { + field: "", + operation: "", + value: "", + sortOrder: "asc", + sortBy: "ID" + } + }; + + /** + * Below here is utility. + * + * TODO Refactor into new separate files + */ + if (artemisQueue.queue) { + $scope.filter.values.field = $scope.filter.fieldOptions[1].id; + $scope.filter.values.operation = $scope.filter.operationOptions[0].id; + $scope.filter.values.value = artemisQueue.queue.queue; + artemisQueue.queue = null; + } + + artemisSession.session = null; + $scope.navigateToQueueAtts = function (row) { + $location.path("jmx/attributes").search({"tab": "artemis", "nid": ARTEMIS.getQueueNid(row.entity, $location)}); + }; + $scope.navigateToQueueOps = function (row) { + $location.path("jmx/operations").search({"tab": "artemis", "nid": ARTEMIS.getQueueNid(row.entity, $location)}); + }; + $scope.workspace = workspace; + $scope.objects = []; + $scope.totalServerItems = 0; + $scope.pagingOptions = { + pageSizes: [50, 100, 200], + pageSize: 100, + currentPage: 1 + }; + $scope.sort = { + fields: ["ID"], + directions: ["asc"] + }; + var refreshed = false; + + $scope.gridOptions = { + selectedItems: [], + data: 'objects', + showFooter: true, + showFilter: true, + showColumnMenu: true, + enableCellSelection: false, + enableHighlighting: true, + enableColumnResize: true, + enableColumnReordering: true, + selectWithCheckboxOnly: false, + showSelectionCheckbox: false, + multiSelect: false, + displaySelectionCheckbox: false, + pagingOptions: $scope.pagingOptions, + enablePaging: true, + totalServerItems: 'totalServerItems', + maintainColumnRatios: false, + columnDefs: attributes, + enableFiltering: true, + useExternalFiltering: true, + sortInfo: $scope.sortOptions, + useExternalSorting: true, + }; + $scope.refresh = function () { + refreshed = true; + $scope.loadTable(); + }; + $scope.reset = function () { + $scope.filter.values.field = ""; + $scope.filter.values.operation = ""; + $scope.filter.values.value = ""; + $scope.loadTable(); + }; + $scope.loadTable = function () { + $scope.filter.values.sortColumn = $scope.sort.fields[0]; + $scope.filter.values.sortBy = $scope.sort.directions[0]; + var mbean = getBrokerMBean(jolokia); + if (mbean) { + var filter = JSON.stringify($scope.filter.values); + console.log("Filter string: " + filter); + jolokia.request({ type: 'exec', mbean: mbean, operation: method, arguments: [filter, $scope.pagingOptions.currentPage, $scope.pagingOptions.pageSize] }, onSuccess(populateTable, { error: onError })); + } + }; + function onError() { + Core.notification("error", "Could not retrieve " + objectType + " list from Artemis."); + } + function populateTable(response) { + var data = JSON.parse(response.value); + $scope.objects = []; + angular.forEach(data["data"], function (value, idx) { + $scope.objects.push(value); + }); + $scope.totalServerItems = data["count"]; + if (refreshed == true) { + $scope.gridOptions.pagingOptions.currentPage = 1; + refreshed = false; + } + Core.$apply($scope); + } + $scope.$watch('sortOptions', function (newVal, oldVal) { + if (newVal !== oldVal) { + $scope.loadTable(); + } + }, true); + $scope.$watch('pagingOptions', function (newVal, oldVal) { + if (parseInt(newVal.currentPage) && newVal !== oldVal && newVal.currentPage !== oldVal.currentPage) { + $scope.loadTable(); + } + }, true); + + function getBrokerMBean(jolokia) { + var mbean = null; + var selection = workspace.selection; + var folderNames = selection.folderNames; + mbean = "" + folderNames[0] + ":broker=" + folderNames[1]; + ARTEMIS.log.info("broker=" + mbean); + return mbean; + }; + $scope.refresh(); + }; + return ARTEMIS; +} (ARTEMIS || {})); diff --git a/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/sessions.js b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/sessions.js new file mode 100644 index 0000000000..bf63298b53 --- /dev/null +++ b/artemis-hawtio/artemis-plugin/src/main/webapp/plugin/js/sessions.js @@ -0,0 +1,233 @@ +/* + * 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. + */ +/** + * @module ARTEMIS + */ +var ARTEMIS = (function(ARTEMIS) { + + ARTEMIS.SessionsController = function ($scope, $location, workspace, ARTEMISService, jolokia, localStorage, artemisConnection, artemisSession, artemisConsumer, artemisProducer) { + + var artemisJmxDomain = localStorage['artemisJmxDomain'] || "org.apache.activemq.artemis"; + + /** + * Required For Each Object Type + */ + + var objectType = "sessions" + var method = 'listSessions(java.lang.String, int, int)'; + var attributes = [ + { + field: 'id', + displayName: 'ID', + width: '*' + }, + { + field: 'connectionID', + displayName: 'Connection', + width: '*', + cellTemplate: '' + }, + { + field: 'user', + displayName: 'User', + width: '*' + }, + { + field: 'consumerCount', + displayName: 'Consumer Count', + width: '*', + cellTemplate: '' + }, + { + field: 'producerCount', + displayName: 'Producer Count', + width: '*', + cellTemplate: '' + }, + { + field: 'creationTime', + displayName: 'Creation Time', + width: '*' + }, + ]; + $scope.filter = { + fieldOptions: [ + {id: 'ID', name: 'ID'}, + {id: 'CONNECTION_ID', name: 'Connection ID'}, + {id: 'CONSUMER_COUNT', name: 'Consumer Count'}, + {id: 'USER', name: 'User'}, + {id: 'PROTOCOL', name: 'Protocol'}, + {id: 'CLIENT_ID', name: 'Client ID'}, + {id: 'LOCAL_ADDRESS', name: 'Local Address'}, + {id: 'REMOTE_ADDRESS', name: 'Remote Address'}, + ], + operationOptions: [ + {id: 'EQUALS', name: 'Equals'}, + {id: 'CONTAINS', name: 'Contains'} + ], + values: { + field: "", + operation: "", + value: "", + sortOrder: "asc", + sortBy: "ID" + } + }; + // Configure Parent/Child click through relationships + $scope.selectConnection = function (row) { + artemisSession.session = row.entity; + $location.path("artemis/connections"); + }; + + $scope.selectProducers = function (row) { + artemisSession.session = row.entity; + $location.path("artemis/producers"); + }; + + $scope.selectConsumers = function (row) { + artemisSession.session = row.entity; + $location.path("artemis/consumers"); + }; + + if (artemisConnection.connection) { + ARTEMIS.log.info("navigating to connection = " + artemisConnection.connection.connectionID); + $scope.filter.values.field = $scope.filter.fieldOptions[1].id; + $scope.filter.values.operation = $scope.filter.operationOptions[0].id; + $scope.filter.values.value = artemisConnection.connection.connectionID; + } + + if (artemisConsumer.consumer) { + ARTEMIS.log.info("navigating to connection = " + artemisConsumer.consumer.ID); + $scope.filter.values.field = $scope.filter.fieldOptions[0].id; + $scope.filter.values.operation = $scope.filter.operationOptions[0].id; + $scope.filter.values.value = artemisConsumer.consumer.session; + } + + if (artemisProducer.producer) { + ARTEMIS.log.info("navigating to producer = " + artemisProducer.producer.ID); + $scope.filter.values.field = $scope.filter.fieldOptions[0].id; + $scope.filter.values.operation = $scope.filter.operationOptions[0].id; + $scope.filter.values.value = artemisProducer.producer.session; + } + //refresh after use + artemisSession.connection = null; + artemisConsumer.consumer = null; + artemisProducer.producer = null; + + /** + * Below here is utility. + * + * TODO Refactor into new separate files + */ + + $scope.workspace = workspace; + $scope.objects = []; + $scope.totalServerItems = 0; + $scope.pagingOptions = { + pageSizes: [50, 100, 200], + pageSize: 100, + currentPage: 1 + }; + $scope.sort = { + fields: ["ID"], + directions: ["asc"] + }; + var refreshed = false; + + $scope.gridOptions = { + selectedItems: [], + data: 'objects', + showFooter: true, + showFilter: true, + showColumnMenu: true, + enableCellSelection: false, + enableHighlighting: true, + enableColumnResize: true, + enableColumnReordering: true, + selectWithCheckboxOnly: false, + showSelectionCheckbox: false, + multiSelect: false, + displaySelectionCheckbox: false, + pagingOptions: $scope.pagingOptions, + enablePaging: true, + totalServerItems: 'totalServerItems', + maintainColumnRatios: false, + columnDefs: attributes, + enableFiltering: true, + useExternalFiltering: true, + sortInfo: $scope.sortOptions, + useExternalSorting: true, + }; + $scope.refresh = function () { + refreshed = true; + $scope.loadTable(); + }; + $scope.reset = function () { + $scope.filter.values.field = ""; + $scope.filter.values.operation = ""; + $scope.filter.values.value = ""; + $scope.loadTable(); + }; + $scope.loadTable = function () { + $scope.filter.values.sortColumn = $scope.sort.fields[0]; + $scope.filter.values.sortBy = $scope.sort.directions[0]; + var mbean = getBrokerMBean(jolokia); + if (mbean) { + var filter = JSON.stringify($scope.filter.values); + console.log("Filter string: " + filter); + jolokia.request({ type: 'exec', mbean: mbean, operation: method, arguments: [filter, $scope.pagingOptions.currentPage, $scope.pagingOptions.pageSize] }, onSuccess(populateTable, { error: onError })); + } + }; + function onError() { + Core.notification("error", "Could not retrieve " + objectType + " list from Artemis."); + } + function populateTable(response) { + var data = JSON.parse(response.value); + $scope.objects = []; + angular.forEach(data["data"], function (value, idx) { + $scope.objects.push(value); + }); + $scope.totalServerItems = data["count"]; + if (refreshed == true) { + $scope.gridOptions.pagingOptions.currentPage = 1; + refreshed = false; + } + Core.$apply($scope); + } + $scope.$watch('sortOptions', function (newVal, oldVal) { + if (newVal !== oldVal) { + $scope.loadTable(); + } + }, true); + $scope.$watch('pagingOptions', function (newVal, oldVal) { + if (parseInt(newVal.currentPage) && newVal !== oldVal && newVal.currentPage !== oldVal.currentPage) { + $scope.loadTable(); + } + }, true); + + function getBrokerMBean(jolokia) { + var mbean = null; + var selection = workspace.selection; + var folderNames = selection.folderNames; + mbean = "" + folderNames[0] + ":broker=" + folderNames[1]; + ARTEMIS.log.info("broker=" + mbean); + return mbean; + }; + $scope.refresh(); + }; + return ARTEMIS; +} (ARTEMIS || {}));