mirror of
https://github.com/apache/activemq.git
synced 2025-02-22 09:55:47 +00:00
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
(cherry picked from commit d2b0affedb38c5439bce2fb5a8e321bc5d0ec713)
This commit is contained in:
parent
509c781669
commit
70b2a43183
@ -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…
x
Reference in New Issue
Block a user