From 25f1fe8460242530b7d2deb7ae9a48a85a90662b Mon Sep 17 00:00:00 2001 From: Timothy Bish Date: Thu, 5 Jun 2014 14:39:56 -0400 Subject: [PATCH] https://issues.apache.org/jira/browse/AMQ-5213 Adds a Log4JConfigViewMBean for use in configuring runtime logger levels. --- .../apache/activemq/broker/BrokerService.java | 7 + .../broker/jmx/BrokerMBeanSupport.java | 8 + .../activemq/broker/jmx/BrokerView.java | 34 +-- .../activemq/broker/jmx/Log4JConfigView.java | 286 ++++++++++++++++++ .../broker/jmx/Log4JConfigViewMBean.java | 92 ++++++ .../activemq/broker/jmx/Log4JConfigTest.java | 200 ++++++++++++ 6 files changed, 594 insertions(+), 33 deletions(-) create mode 100644 activemq-broker/src/main/java/org/apache/activemq/broker/jmx/Log4JConfigView.java create mode 100644 activemq-broker/src/main/java/org/apache/activemq/broker/jmx/Log4JConfigViewMBean.java create mode 100644 activemq-unit-tests/src/test/java/org/apache/activemq/broker/jmx/Log4JConfigTest.java diff --git a/activemq-broker/src/main/java/org/apache/activemq/broker/BrokerService.java b/activemq-broker/src/main/java/org/apache/activemq/broker/BrokerService.java index 3c542ceeef..6ecd427644 100644 --- a/activemq-broker/src/main/java/org/apache/activemq/broker/BrokerService.java +++ b/activemq-broker/src/main/java/org/apache/activemq/broker/BrokerService.java @@ -68,6 +68,7 @@ import org.apache.activemq.broker.jmx.HealthViewMBean; import org.apache.activemq.broker.jmx.JmsConnectorView; import org.apache.activemq.broker.jmx.JobSchedulerView; import org.apache.activemq.broker.jmx.JobSchedulerViewMBean; +import org.apache.activemq.broker.jmx.Log4JConfigView; import org.apache.activemq.broker.jmx.ManagedRegionBroker; import org.apache.activemq.broker.jmx.ManagementContext; import org.apache.activemq.broker.jmx.NetworkConnectorView; @@ -690,6 +691,12 @@ public class BrokerService implements Service { setIoExceptionHandler(new DefaultIOExceptionHandler()); } + if (isUseJmx() && Log4JConfigView.isLog4JAvailable()) { + ObjectName objectName = BrokerMBeanSupport.createLog4JConfigViewName(getBrokerObjectName().toString()); + Log4JConfigView log4jConfigView = new Log4JConfigView(); + AnnotatedMBean.registerMBean(getManagementContext(), log4jConfigView, objectName); + } + startAllConnectors(); LOG.info("Apache ActiveMQ {} ({}, {}) started", new Object[]{ getBrokerVersion(), getBrokerName(), brokerId}); diff --git a/activemq-broker/src/main/java/org/apache/activemq/broker/jmx/BrokerMBeanSupport.java b/activemq-broker/src/main/java/org/apache/activemq/broker/jmx/BrokerMBeanSupport.java index 87605bc823..97a4f986df 100644 --- a/activemq-broker/src/main/java/org/apache/activemq/broker/jmx/BrokerMBeanSupport.java +++ b/activemq-broker/src/main/java/org/apache/activemq/broker/jmx/BrokerMBeanSupport.java @@ -118,6 +118,14 @@ public class BrokerMBeanSupport { return new ObjectName(objectNameStr); } + public static ObjectName createLog4JConfigViewName(String brokerObjectName) throws MalformedObjectNameException { + String objectNameStr = brokerObjectName; + + objectNameStr += "," + "Service=Log4JConfiguration"; + + return new ObjectName(objectNameStr); + } + public static ObjectName createPersistenceAdapterName(String brokerObjectName, String name) throws MalformedObjectNameException { String objectNameStr = brokerObjectName; diff --git a/activemq-broker/src/main/java/org/apache/activemq/broker/jmx/BrokerView.java b/activemq-broker/src/main/java/org/apache/activemq/broker/jmx/BrokerView.java index 852120fc38..3f34768614 100755 --- a/activemq-broker/src/main/java/org/apache/activemq/broker/jmx/BrokerView.java +++ b/activemq-broker/src/main/java/org/apache/activemq/broker/jmx/BrokerView.java @@ -18,11 +18,7 @@ package org.apache.activemq.broker.jmx; import java.io.File; import java.io.IOException; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.MalformedURLException; import java.net.URI; -import java.net.URL; import java.util.HashMap; import java.util.Map; import java.util.NoSuchElementException; @@ -450,35 +446,7 @@ public class BrokerView implements BrokerViewMBean { @Override public void reloadLog4jProperties() throws Throwable { - - // Avoid a direct dependency on log4j.. use reflection. - try { - ClassLoader cl = getClass().getClassLoader(); - Class logManagerClass = cl.loadClass("org.apache.log4j.LogManager"); - - Method resetConfiguration = logManagerClass.getMethod("resetConfiguration", new Class[]{}); - resetConfiguration.invoke(null, new Object[]{}); - - String configurationOptionStr = System.getProperty("log4j.configuration"); - URL log4jprops = null; - if (configurationOptionStr != null) { - try { - log4jprops = new URL(configurationOptionStr); - } catch (MalformedURLException ex) { - log4jprops = cl.getResource("log4j.properties"); - } - } else { - log4jprops = cl.getResource("log4j.properties"); - } - - if (log4jprops != null) { - Class propertyConfiguratorClass = cl.loadClass("org.apache.log4j.PropertyConfigurator"); - Method configure = propertyConfiguratorClass.getMethod("configure", new Class[]{URL.class}); - configure.invoke(null, new Object[]{log4jprops}); - } - } catch (InvocationTargetException e) { - throw e.getTargetException(); - } + Log4JConfigView.doReloadLog4jProperties(); } @Override diff --git a/activemq-broker/src/main/java/org/apache/activemq/broker/jmx/Log4JConfigView.java b/activemq-broker/src/main/java/org/apache/activemq/broker/jmx/Log4JConfigView.java new file mode 100644 index 0000000000..b58d72ec25 --- /dev/null +++ b/activemq-broker/src/main/java/org/apache/activemq/broker/jmx/Log4JConfigView.java @@ -0,0 +1,286 @@ +/** + * 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.broker.jmx; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; +import java.util.Locale; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Log4JConfigView implements Log4JConfigViewMBean { + + private static final Logger LOG = LoggerFactory.getLogger(Log4JConfigView.class); + + @Override + public String getRootLogLevel() throws Exception { + ClassLoader cl = getClassLoader(); + + if (!isLog4JAvailable(cl)) { + return null; + } + + Class loggerClass = getLoggerClass(cl); + if (loggerClass == null) { + return null; + } + + Method getRootLogger = loggerClass.getMethod("getRootLogger", new Class[]{}); + Method getLevel = loggerClass.getMethod("getLevel", new Class[]{}); + Object rootLogger = getRootLogger.invoke(null, (Object[])null); + + return getLevel.invoke(rootLogger, (Object[])null).toString(); + } + + @Override + public void setRootLogLevel(String level) throws Exception { + ClassLoader cl = getClassLoader(); + + if (!isLog4JAvailable(cl)) { + return; + } + + Class loggerClass = getLoggerClass(cl); + Class levelClass = getLevelClass(cl); + if (levelClass == null || loggerClass == null) { + return; + } + + String targetLevel = level.toUpperCase(Locale.US); + Method getRootLogger = loggerClass.getMethod("getRootLogger", new Class[]{}); + Method setLevel = loggerClass.getMethod("setLevel", levelClass); + Object rootLogger = getRootLogger.invoke(null, (Object[])null); + Method toLevel = levelClass.getMethod("toLevel", String.class); + Object newLevel = toLevel.invoke(null, targetLevel); + + // Check that the level conversion worked and that we got a level + // that matches what was asked for. A bad level name will result + // in the lowest level value and we don't want to change unless we + // matched what the user asked for. + if (newLevel != null && newLevel.toString().equals(targetLevel)) { + LOG.debug("Set level {} for root logger.", level); + setLevel.invoke(rootLogger, newLevel); + } + } + + @Override + public List getLoggers() throws Exception { + + ClassLoader cl = getClassLoader(); + + if (!isLog4JAvailable(cl)) { + return Collections.emptyList(); + } + + Class logManagerClass = getLogManagerClass(cl); + Class loggerClass = getLoggerClass(cl); + if (logManagerClass == null || loggerClass == null) { + return Collections.emptyList(); + } + + Method getCurrentLoggers = logManagerClass.getMethod("getCurrentLoggers", new Class[]{}); + Method getName = loggerClass.getMethod("getName", new Class[]{}); + + List list = new ArrayList(); + Enumeration loggers = (Enumeration)getCurrentLoggers.invoke(null, (Object[])null); + + while (loggers.hasMoreElements()) { + Object logger = loggers.nextElement(); + if (logger != null) { + list.add((String) getName.invoke(logger, (Object[])null)); + } + } + + LOG.debug("Found {} loggers", list.size()); + + return list; + } + + @Override + public String getLogLevel(String loggerName) throws Exception { + + ClassLoader cl = getClassLoader(); + + if (!isLog4JAvailable(cl)) { + return null; + } + + Class loggerClass = getLoggerClass(cl); + if (loggerClass == null) { + return null; + } + + Method getLogger = loggerClass.getMethod("getLogger", String.class); + String logLevel = null; + + if (loggerName != null && !loggerName.isEmpty()) { + Object logger = getLogger.invoke(null, loggerName); + if (logger != null) { + LOG.debug("Found level {} for logger: {}", logLevel, loggerName); + Method getLevel = loggerClass.getMethod("getLevel", new Class[]{}); + Object level = getLevel.invoke(logger, (Object[])null); + if (level != null) { + logLevel = level.toString(); + } else { + Method getRootLogger = loggerClass.getMethod("getRootLogger", new Class[]{}); + Object rootLogger = getRootLogger.invoke(null, (Object[])null); + logLevel = getLevel.invoke(rootLogger, (Object[])null).toString(); + } + } + } else { + throw new IllegalArgumentException("Logger names cannot be null or empty strings"); + } + + return logLevel; + } + + @Override + public void setLogLevel(String loggerName, String level) throws Exception { + + if (loggerName == null || loggerName.isEmpty()) { + throw new IllegalArgumentException("Logger names cannot be null or empty strings"); + } + + if (level == null || level.isEmpty()) { + throw new IllegalArgumentException("Level name cannot be null or empty strings"); + } + + ClassLoader cl = getClassLoader(); + + if (!isLog4JAvailable(cl)) { + return; + } + + Class loggerClass = getLoggerClass(cl); + Class levelClass = getLevelClass(cl); + if (loggerClass == null || levelClass == null) { + return; + } + + String targetLevel = level.toUpperCase(Locale.US); + Method getLogger = loggerClass.getMethod("getLogger", String.class); + Method setLevel = loggerClass.getMethod("setLevel", levelClass); + Method toLevel = levelClass.getMethod("toLevel", String.class); + + Object logger = getLogger.invoke(null, loggerName); + if (logger != null) { + Object newLevel = toLevel.invoke(null, targetLevel); + + // Check that the level conversion worked and that we got a level + // that matches what was asked for. A bad level name will result + // in the lowest level value and we don't want to change unless we + // matched what the user asked for. + if (newLevel != null && newLevel.toString().equals(targetLevel)) { + LOG.debug("Set level {} for logger: {}", level, loggerName); + setLevel.invoke(logger, newLevel); + } + } + } + + @Override + public void reloadLog4jProperties() throws Throwable { + doReloadLog4jProperties(); + } + + //---------- Static Helper Methods ---------------------------------------// + + public static void doReloadLog4jProperties() throws Throwable { + try { + ClassLoader cl = Log4JConfigView.class.getClassLoader(); + Class logManagerClass = getLogManagerClass(cl); + if (logManagerClass == null) { + LOG.debug("Could not locate log4j classes on classpath."); + return; + } + + Method resetConfiguration = logManagerClass.getMethod("resetConfiguration", new Class[]{}); + resetConfiguration.invoke(null, new Object[]{}); + + String configurationOptionStr = System.getProperty("log4j.configuration"); + URL log4jprops = null; + if (configurationOptionStr != null) { + try { + log4jprops = new URL(configurationOptionStr); + } catch (MalformedURLException ex) { + log4jprops = cl.getResource("log4j.properties"); + } + } else { + log4jprops = cl.getResource("log4j.properties"); + } + + if (log4jprops != null) { + Class propertyConfiguratorClass = cl.loadClass("org.apache.log4j.PropertyConfigurator"); + Method configure = propertyConfiguratorClass.getMethod("configure", new Class[]{URL.class}); + configure.invoke(null, new Object[]{log4jprops}); + } + } catch (InvocationTargetException e) { + throw e.getTargetException(); + } + } + + public static boolean isLog4JAvailable() { + return isLog4JAvailable(getClassLoader()); + } + + private static ClassLoader getClassLoader() { + return Log4JConfigView.class.getClassLoader(); + } + + private static boolean isLog4JAvailable(ClassLoader cl) { + if (getLogManagerClass(cl) != null) { + return true; + } + + LOG.debug("Could not locate log4j classes on classpath."); + + return false; + } + + private static Class getLogManagerClass(ClassLoader cl) { + Class logManagerClass = null; + try { + logManagerClass = cl.loadClass("org.apache.log4j.LogManager"); + } catch (ClassNotFoundException e) { + } + return logManagerClass; + } + + private static Class getLoggerClass(ClassLoader cl) { + Class loggerClass = null; + try { + loggerClass = cl.loadClass("org.apache.log4j.Logger"); + } catch (ClassNotFoundException e) { + } + return loggerClass; + } + + private static Class getLevelClass(ClassLoader cl) { + Class levelClass = null; + try { + levelClass = cl.loadClass("org.apache.log4j.Level"); + } catch (ClassNotFoundException e) { + } + return levelClass; + } +} diff --git a/activemq-broker/src/main/java/org/apache/activemq/broker/jmx/Log4JConfigViewMBean.java b/activemq-broker/src/main/java/org/apache/activemq/broker/jmx/Log4JConfigViewMBean.java new file mode 100644 index 0000000000..2e67446c43 --- /dev/null +++ b/activemq-broker/src/main/java/org/apache/activemq/broker/jmx/Log4JConfigViewMBean.java @@ -0,0 +1,92 @@ +/** + * 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.broker.jmx; + +import java.util.List; + +/** + * Log4J Configuration Management MBean used to alter the runtime log levels + * or force a reload of the Log4J configuration file. + */ +public interface Log4JConfigViewMBean { + + /** + * Get the log level for the root logger + * + * @returns the current log level of the root logger. + * + * @throws Exception if an error occurs while getting the root level. + */ + @MBeanInfo("Returns the current logging level of the root logger.") + String getRootLogLevel() throws Exception; + + /** + * Get the log level for the root logger + * + * @param level + * the new level to assign to the root logger. + * + * @throws Exception if an error occurs while setting the root level. + */ + @MBeanInfo("Sets the current logging level of the root logger.") + void setRootLogLevel(String level) throws Exception; + + /** + * list of all the logger names and their levels + * + * @returns a List of all known loggers names. + * + * @throws Exception if an error occurs while getting the loggers. + */ + @MBeanInfo("List of all loggers that are available for configuration.") + List getLoggers() throws Exception; + + /** + * Get the log level for a given logger + * + * @param loggerName + * the name of the logger whose level should be queried. + * + * @returns the current log level of the given logger. + * + * @throws Exception if an error occurs while getting the log level. + */ + @MBeanInfo("Returns the current logging level of a named logger.") + String getLogLevel(String loggerName) throws Exception; + + /** + * Set the log level for a given logger + * + * @param loggerName + * the name of the logger whose level is to be adjusted. + * @param level + * the new level to assign the given logger. + * + * @throws Exception if an error occurs while setting the log level. + */ + @MBeanInfo("Sets the logging level for the named logger.") + void setLogLevel(String loggerName, String level) throws Exception; + + /** + * Reloads log4j.properties from the classpath. + * + * @throws Exception if an error occurs trying to reload the config file. + */ + @MBeanInfo(value="Reloads log4j.properties from the classpath.") + public void reloadLog4jProperties() throws Throwable; + +} diff --git a/activemq-unit-tests/src/test/java/org/apache/activemq/broker/jmx/Log4JConfigTest.java b/activemq-unit-tests/src/test/java/org/apache/activemq/broker/jmx/Log4JConfigTest.java new file mode 100644 index 0000000000..2c2b3735cd --- /dev/null +++ b/activemq-unit-tests/src/test/java/org/apache/activemq/broker/jmx/Log4JConfigTest.java @@ -0,0 +1,200 @@ +/** + * 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.broker.jmx; + +import java.util.List; + +import javax.jms.ConnectionFactory; +import javax.management.MBeanServer; +import javax.management.MBeanServerInvocationHandler; +import javax.management.MalformedObjectNameException; +import javax.management.ObjectName; + +import org.apache.activemq.ActiveMQConnectionFactory; +import org.apache.activemq.EmbeddedBrokerTestSupport; +import org.apache.activemq.broker.BrokerService; +import org.apache.log4j.Level; +import org.apache.log4j.Logger; +import org.junit.Test; +import org.slf4j.LoggerFactory; + +public class Log4JConfigTest extends EmbeddedBrokerTestSupport { + + private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(Log4JConfigTest.class); + + private static final String BROKER_LOGGER = "org.apache.activemq.broker.BrokerService"; + + protected MBeanServer mbeanServer; + protected String domain = "org.apache.activemq"; + + @Override + protected void setUp() throws Exception { + bindAddress = "tcp://localhost:0"; + useTopic = false; + super.setUp(); + mbeanServer = broker.getManagementContext().getMBeanServer(); + } + + @Override + protected void tearDown() throws Exception { + super.tearDown(); + } + + @Override + protected ConnectionFactory createConnectionFactory() throws Exception { + return new ActiveMQConnectionFactory(broker.getTransportConnectors().get(0).getPublishableConnectString()); + } + + @Override + protected BrokerService createBroker() throws Exception { + BrokerService answer = new BrokerService(); + answer.setPersistent(true); + answer.setDeleteAllMessagesOnStartup(true); + answer.setUseJmx(true); + answer.setSchedulerSupport(true); + answer.addConnector(bindAddress); + return answer; + } + + @Test + public void testLog4JConfigViewExists() throws Exception { + String brokerObjectName = broker.getBrokerObjectName().toString(); + String log4jConfigViewName = BrokerMBeanSupport.createLog4JConfigViewName(brokerObjectName).toString(); + assertRegisteredObjectName(log4jConfigViewName); + } + + @Test + public void testLog4JConfigViewGetLoggers() throws Throwable { + String brokerObjectName = broker.getBrokerObjectName().toString(); + ObjectName log4jConfigViewName = BrokerMBeanSupport.createLog4JConfigViewName(brokerObjectName); + Log4JConfigViewMBean log4jConfigView = MBeanServerInvocationHandler.newProxyInstance( + mbeanServer, log4jConfigViewName, Log4JConfigViewMBean.class, true); + + List loggers = log4jConfigView.getLoggers(); + assertNotNull(loggers); + assertFalse(loggers.isEmpty()); + } + + @Test + public void testLog4JConfigViewGetLevel() throws Throwable { + String brokerObjectName = broker.getBrokerObjectName().toString(); + ObjectName log4jConfigViewName = BrokerMBeanSupport.createLog4JConfigViewName(brokerObjectName); + Log4JConfigViewMBean log4jConfigView = MBeanServerInvocationHandler.newProxyInstance( + mbeanServer, log4jConfigViewName, Log4JConfigViewMBean.class, true); + + String level = log4jConfigView.getLogLevel(BROKER_LOGGER); + assertNotNull(level); + assertFalse(level.isEmpty()); + } + + @Test + public void testLog4JConfigViewGetLevelUnknownLoggerName() throws Throwable { + String brokerObjectName = broker.getBrokerObjectName().toString(); + ObjectName log4jConfigViewName = BrokerMBeanSupport.createLog4JConfigViewName(brokerObjectName); + Log4JConfigViewMBean log4jConfigView = MBeanServerInvocationHandler.newProxyInstance( + mbeanServer, log4jConfigViewName, Log4JConfigViewMBean.class, true); + + // Non-existent loggers will return a name equal to the root level. + String level = log4jConfigView.getLogLevel("not.a.logger"); + assertNotNull(level); + assertFalse(level.isEmpty()); + assertEquals(Logger.getRootLogger().getLevel().toString(), level); + } + + @Test + public void testLog4JConfigViewSetLevel() throws Throwable { + String brokerObjectName = broker.getBrokerObjectName().toString(); + ObjectName log4jConfigViewName = BrokerMBeanSupport.createLog4JConfigViewName(brokerObjectName); + Log4JConfigViewMBean log4jConfigView = MBeanServerInvocationHandler.newProxyInstance( + mbeanServer, log4jConfigViewName, Log4JConfigViewMBean.class, true); + + String level = log4jConfigView.getLogLevel(BROKER_LOGGER); + assertNotNull(level); + assertFalse(level.isEmpty()); + + log4jConfigView.setLogLevel(BROKER_LOGGER, "WARN"); + level = log4jConfigView.getLogLevel(BROKER_LOGGER); + assertNotNull(level); + assertEquals("WARN", level); + + log4jConfigView.setLogLevel(BROKER_LOGGER, "INFO"); + level = log4jConfigView.getLogLevel(BROKER_LOGGER); + assertNotNull(level); + assertEquals("INFO", level); + } + + @Test + public void testLog4JConfigViewSetLevelNoChangeIfLevelIsBad() throws Throwable { + String brokerObjectName = broker.getBrokerObjectName().toString(); + ObjectName log4jConfigViewName = BrokerMBeanSupport.createLog4JConfigViewName(brokerObjectName); + Log4JConfigViewMBean log4jConfigView = MBeanServerInvocationHandler.newProxyInstance( + mbeanServer, log4jConfigViewName, Log4JConfigViewMBean.class, true); + + log4jConfigView.setLogLevel(BROKER_LOGGER, "INFO"); + String level = log4jConfigView.getLogLevel(BROKER_LOGGER); + assertNotNull(level); + assertEquals("INFO", level); + + log4jConfigView.setLogLevel(BROKER_LOGGER, "BAD"); + level = log4jConfigView.getLogLevel(BROKER_LOGGER); + assertNotNull(level); + assertEquals("INFO", level); + } + + @Test + public void testLog4JConfigViewGetRootLogLevel() throws Throwable { + String brokerObjectName = broker.getBrokerObjectName().toString(); + ObjectName log4jConfigViewName = BrokerMBeanSupport.createLog4JConfigViewName(brokerObjectName); + Log4JConfigViewMBean log4jConfigView = MBeanServerInvocationHandler.newProxyInstance( + mbeanServer, log4jConfigViewName, Log4JConfigViewMBean.class, true); + + String level = log4jConfigView.getRootLogLevel(); + assertNotNull(level); + assertFalse(level.isEmpty()); + + String currentRootLevel = Logger.getRootLogger().getLevel().toString(); + assertEquals(currentRootLevel, level); + } + + @Test + public void testLog4JConfigViewSetRootLevel() throws Throwable { + String brokerObjectName = broker.getBrokerObjectName().toString(); + ObjectName log4jConfigViewName = BrokerMBeanSupport.createLog4JConfigViewName(brokerObjectName); + Log4JConfigViewMBean log4jConfigView = MBeanServerInvocationHandler.newProxyInstance( + mbeanServer, log4jConfigViewName, Log4JConfigViewMBean.class, true); + + String currentRootLevel = Logger.getRootLogger().getLevel().toString(); + log4jConfigView.setRootLogLevel("WARN"); + currentRootLevel = Logger.getRootLogger().getLevel().toString(); + assertEquals("WARN", currentRootLevel); + log4jConfigView.setRootLogLevel("INFO"); + currentRootLevel = Logger.getRootLogger().getLevel().toString(); + assertEquals("INFO", currentRootLevel); + + Level level; + } + + protected ObjectName assertRegisteredObjectName(String name) throws MalformedObjectNameException, NullPointerException { + ObjectName objectName = new ObjectName(name); + if (mbeanServer.isRegistered(objectName)) { + LOG.info("Bean Registered: " + objectName); + } else { + fail("Could not find MBean!: " + objectName); + } + return objectName; + } +}