mirror of https://github.com/apache/activemq.git
AMQ-7094 - track the objectName with an annotated mbean such that the jmx audit log event can extract that target of an mbean operation, fix and test
This commit is contained in:
parent
85859fd8dc
commit
d2b0affedb
|
@ -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 <T> AnnotatedMBean(T impl, Class<T> mbeanInterface) throws NotCompliantMBeanException {
|
||||
public <T> AnnotatedMBean(T impl, Class<T> 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++) {
|
||||
|
|
|
@ -36,15 +36,15 @@ public class AsyncAnnotatedMBean extends AnnotatedMBean {
|
|||
private ExecutorService executor;
|
||||
private long timeout = 0;
|
||||
|
||||
public <T> AsyncAnnotatedMBean(ExecutorService executor, long timeout, T impl, Class<T> mbeanInterface) throws NotCompliantMBeanException {
|
||||
super(impl, mbeanInterface);
|
||||
public <T> AsyncAnnotatedMBean(ExecutorService executor, long timeout, T impl, Class<T> 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;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue