diff --git a/activemq-broker/src/main/java/org/apache/activemq/broker/jmx/AnnotatedMBean.java b/activemq-broker/src/main/java/org/apache/activemq/broker/jmx/AnnotatedMBean.java index c75d8a81bb..dc772c266b 100644 --- a/activemq-broker/src/main/java/org/apache/activemq/broker/jmx/AnnotatedMBean.java +++ b/activemq-broker/src/main/java/org/apache/activemq/broker/jmx/AnnotatedMBean.java @@ -68,6 +68,8 @@ public class AnnotatedMBean extends StandardMBean { } } + private final ObjectName objectName; + private static byte byteFromProperty(String s) { byte val = OFF; String config = System.getProperty(s, "").toLowerCase(Locale.ENGLISH); @@ -88,7 +90,7 @@ public class AnnotatedMBean extends StandardMBean { for (Class c : object.getClass().getInterfaces()) { if (mbeanName.equals(c.getName())) { - context.registerMBean(new AnnotatedMBean(object, c), objectName); + context.registerMBean(new AnnotatedMBean(object, c, objectName), objectName); return; } } @@ -97,13 +99,15 @@ public class AnnotatedMBean extends StandardMBean { } /** Instance where the MBean interface is implemented by another object. */ - public AnnotatedMBean(T impl, Class mbeanInterface) throws NotCompliantMBeanException { + public AnnotatedMBean(T impl, Class mbeanInterface, ObjectName objectName) throws NotCompliantMBeanException { super(impl, mbeanInterface); + this.objectName = objectName; } /** Instance where the MBean interface is implemented by this object. */ - protected AnnotatedMBean(Class mbeanInterface) throws NotCompliantMBeanException { + protected AnnotatedMBean(Class mbeanInterface, ObjectName objectName) throws NotCompliantMBeanException { super(mbeanInterface); + this.objectName = objectName; } /** {@inheritDoc} */ @@ -212,6 +216,7 @@ public class AnnotatedMBean extends StandardMBean { entry = new JMXAuditLogEntry(); entry.setUser(caller); entry.setTimestamp(System.currentTimeMillis()); + entry.setTarget(extractTargetTypeProperty(objectName)); entry.setOperation(this.getMBeanInfo().getClassName() + "." + s); try @@ -245,6 +250,21 @@ public class AnnotatedMBean extends StandardMBean { return result; } + // keep brokerName last b/c objectNames include the brokerName + final static String[] targetPropertiesCandidates = new String[] {"destinationName", "networkConnectorName", "connectorName", "connectionName", "brokerName"}; + private String extractTargetTypeProperty(ObjectName objectName) { + String result = null; + for (String attr: targetPropertiesCandidates) { + try { + result = objectName.getKeyProperty(attr); + if (result != null) { + break; + } + } catch (NullPointerException ok) {} + } + return result; + } + private Method getMBeanMethod(Class clazz, String methodName, String[] signature) throws ReflectiveOperationException { Class[] parameterTypes = new Class[signature.length]; for (int i = 0; i < signature.length; i++) { diff --git a/activemq-broker/src/main/java/org/apache/activemq/broker/jmx/AsyncAnnotatedMBean.java b/activemq-broker/src/main/java/org/apache/activemq/broker/jmx/AsyncAnnotatedMBean.java index 7460e16c10..7871a21b70 100644 --- a/activemq-broker/src/main/java/org/apache/activemq/broker/jmx/AsyncAnnotatedMBean.java +++ b/activemq-broker/src/main/java/org/apache/activemq/broker/jmx/AsyncAnnotatedMBean.java @@ -36,15 +36,15 @@ public class AsyncAnnotatedMBean extends AnnotatedMBean { private ExecutorService executor; private long timeout = 0; - public AsyncAnnotatedMBean(ExecutorService executor, long timeout, T impl, Class mbeanInterface) throws NotCompliantMBeanException { - super(impl, mbeanInterface); + public AsyncAnnotatedMBean(ExecutorService executor, long timeout, T impl, Class mbeanInterface, ObjectName objectName) throws NotCompliantMBeanException { + super(impl, mbeanInterface, objectName); this.executor = executor; this.timeout = timeout; } - protected AsyncAnnotatedMBean(Class mbeanInterface) throws NotCompliantMBeanException { - super(mbeanInterface); + protected AsyncAnnotatedMBean(Class mbeanInterface, ObjectName objectName) throws NotCompliantMBeanException { + super(mbeanInterface, objectName); } protected Object asyncInvole(String s, Object[] objects, String[] strings) throws MBeanException, ReflectionException { @@ -67,9 +67,9 @@ public class AsyncAnnotatedMBean extends AnnotatedMBean { for (Class c : object.getClass().getInterfaces()) { if (mbeanName.equals(c.getName())) { if (timeout == 0) { - context.registerMBean(new AnnotatedMBean(object, c), objectName); + context.registerMBean(new AnnotatedMBean(object, c, objectName), objectName); } else { - context.registerMBean(new AsyncAnnotatedMBean(executor, timeout, object, c), objectName); + context.registerMBean(new AsyncAnnotatedMBean(executor, timeout, object, c, objectName), objectName); } return; } diff --git a/activemq-broker/src/main/java/org/apache/activemq/broker/util/JMXAuditLogEntry.java b/activemq-broker/src/main/java/org/apache/activemq/broker/util/JMXAuditLogEntry.java index 7e0e0e3da5..3ced281505 100644 --- a/activemq-broker/src/main/java/org/apache/activemq/broker/util/JMXAuditLogEntry.java +++ b/activemq-broker/src/main/java/org/apache/activemq/broker/util/JMXAuditLogEntry.java @@ -21,14 +21,25 @@ import java.util.Arrays; public class JMXAuditLogEntry extends AuditLogEntry { public static final String[] VERBS = new String[] {" called ", " ended "}; private int state = 0; + protected String target; public void complete() { setTimestamp(System.currentTimeMillis()); state = 1; } + public String getTarget() { + return target; + } + + public void setTarget(String target) { + this.target = target; + } + @Override public String toString() { - return user.trim() + VERBS[state] + operation + Arrays.toString((Object[])parameters.get("arguments")) + " at " + getFormattedTime(); + return user.trim() + VERBS[state] + operation + Arrays.toString((Object[])parameters.get("arguments")) + + (target != null ? " on " + target : "") + + " at " + getFormattedTime(); } } diff --git a/activemq-unit-tests/src/test/java/org/apache/activemq/jmx/DLQRetryTest.java b/activemq-unit-tests/src/test/java/org/apache/activemq/jmx/DLQRetryTest.java index e2875fbb27..e4f3c1653f 100644 --- a/activemq-unit-tests/src/test/java/org/apache/activemq/jmx/DLQRetryTest.java +++ b/activemq-unit-tests/src/test/java/org/apache/activemq/jmx/DLQRetryTest.java @@ -151,6 +151,7 @@ public class DLQRetryTest extends EmbeddedBrokerTestSupport { } protected void setUp() throws Exception { + System.setProperty("org.apache.activemq.audit", "all"); bindAddress = "tcp://localhost:0"; useTopic = false; super.setUp(); diff --git a/activemq-unit-tests/src/test/java/org/apache/activemq/jmx/JmxAuditLogTest.java b/activemq-unit-tests/src/test/java/org/apache/activemq/jmx/JmxAuditLogTest.java index e6f1083013..5256b96a5a 100644 --- a/activemq-unit-tests/src/test/java/org/apache/activemq/jmx/JmxAuditLogTest.java +++ b/activemq-unit-tests/src/test/java/org/apache/activemq/jmx/JmxAuditLogTest.java @@ -30,6 +30,8 @@ import java.util.concurrent.atomic.AtomicInteger; import org.apache.activemq.TestSupport; import org.apache.activemq.broker.BrokerService; +import org.apache.activemq.broker.TransportConnector; +import org.apache.activemq.broker.jmx.BrokerMBeanSupport; import org.apache.activemq.broker.jmx.ManagementContext; import org.apache.activemq.command.ActiveMQDestination; import org.apache.activemq.command.ActiveMQQueue; @@ -62,10 +64,13 @@ public class JmxAuditLogTest extends TestSupport broker = new BrokerService(); broker.setUseJmx(true); + broker.setDeleteAllMessagesOnStartup(true); portToUse = findOpenPort(); broker.setManagementContext(createManagementContext("broker", portToUse)); broker.setPopulateUserNameInMBeans(true); broker.setDestinations(createDestinations()); + TransportConnector transportConnector = broker.addConnector("tcp://0.0.0.0:0"); + transportConnector.setName("TCP"); broker.start(); } @@ -154,4 +159,74 @@ public class JmxAuditLogTest extends TestSupport assertEquals("got two messages", 2, logCount.get()); } + + @Test + public void testNameTargetVisible() throws Exception + { + Logger log4jLogger = Logger.getLogger("org.apache.activemq.audit"); + log4jLogger.setLevel(Level.INFO); + final AtomicInteger logCount = new AtomicInteger(0); + final AtomicBoolean gotEnded = new AtomicBoolean(false); + final AtomicBoolean gotQueueName = new AtomicBoolean(false); + final AtomicBoolean gotBrokerName = new AtomicBoolean(false); + final AtomicBoolean gotConnectorName = new AtomicBoolean(false); + + final String queueName = queue.getQueueName(); + Appender appender = new DefaultTestAppender() + { + @Override + public void doAppend(LoggingEvent event) + { + if (event.getMessage() instanceof String) + { + String message = (String) event.getMessage(); + System.out.println(message); + if (message.contains(VERBS[0])) { + if (message.contains(queueName)) { + gotQueueName.set(true); + } + if (message.contains(broker.getBrokerName())) { + gotBrokerName.set(true); + } + + if (message.contains("TCP")) { + gotConnectorName.set(true); + } + } + + if (message.contains(VERBS[1])) { + gotEnded.set(true); + } + } + logCount.incrementAndGet(); + } + }; + log4jLogger.addAppender(appender); + + MBeanServerConnection conn = createJMXConnector(portToUse); + ObjectName queueObjName = new ObjectName(broker.getBrokerObjectName() + ",destinationType=Queue,destinationName=" + queueName); + + Object[] params = {}; + String[] signature = {}; + + conn.invoke(queueObjName, "purge", params, signature); + + assertTrue("got ended statement", gotEnded.get()); + assertEquals("got two messages", 2, logCount.get()); + assertTrue("got queueName in called statement", gotQueueName.get()); + + // call broker to verify brokerName + conn.invoke(broker.getBrokerObjectName(), "resetStatistics", params, signature); + assertEquals("got 4 messages", 4, logCount.get()); + assertTrue("got brokerName in called statement", gotBrokerName.get()); + + + ObjectName transportConnectorON = BrokerMBeanSupport.createConnectorName(broker.getBrokerObjectName(), "clientConnectors", "TCP"); + conn.invoke(transportConnectorON, "stop", params, signature); + assertEquals("got messages", 6, logCount.get()); + assertTrue("got connectorName in called statement", gotConnectorName.get()); + + log4jLogger.removeAppender(appender); + + } } diff --git a/activemq-unit-tests/src/test/java/org/apache/activemq/jmx/JmxCreateNCTest.java b/activemq-unit-tests/src/test/java/org/apache/activemq/jmx/JmxCreateNCTest.java index e96c5967ad..1d878b4f14 100644 --- a/activemq-unit-tests/src/test/java/org/apache/activemq/jmx/JmxCreateNCTest.java +++ b/activemq-unit-tests/src/test/java/org/apache/activemq/jmx/JmxCreateNCTest.java @@ -38,6 +38,9 @@ public class JmxCreateNCTest { @Test public void testBridgeRegistration() throws Exception { + + System.setProperty("org.apache.activemq.audit", "all"); + BrokerService broker = new BrokerService(); broker.setBrokerName(BROKER_NAME); broker.setUseJmx(true); // explicitly set this so no funny issues