001/*
002 * Licensed under the Apache License, Version 2.0 (the "License");
003 * you may not use this file except in compliance with the License.
004 * You may obtain a copy of the License at
005 *
006 * http://www.apache.org/licenses/LICENSE-2.0
007 *
008 * Unless required by applicable law or agreed to in writing, software
009 * distributed under the License is distributed on an "AS IS" BASIS,
010 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
011 * See the License for the specific language governing permissions and
012 * limitations under the License.
013 */
014package org.atteo.moonshine.logback;
015
016import javax.management.InstanceAlreadyExistsException;
017import javax.management.MBeanRegistrationException;
018import javax.management.MBeanServer;
019import javax.management.MalformedObjectNameException;
020import javax.management.NotCompliantMBeanException;
021import javax.management.ObjectName;
022import javax.xml.bind.annotation.XmlRootElement;
023
024import org.atteo.moonshine.TopLevelService;
025import org.slf4j.LoggerFactory;
026
027import com.google.inject.Inject;
028
029import ch.qos.logback.classic.LoggerContext;
030import ch.qos.logback.classic.jmx.JMXConfigurator;
031
032/**
033 * LogBack JMX support.
034 *
035 * <p>
036 * LogBack MBeans allow you to change logging levels in running application.
037 * </p>
038 */
039@XmlRootElement(name = "logback")
040public class LogBack extends TopLevelService {
041    @Inject
042    private MBeanServer mbeanServer;
043
044    @Override
045    public void start() {
046        configureJMX();
047    }
048
049    @Override
050    public void close() {
051        deconfigureJMX();
052    }
053
054    private JMXConfigurator jmxConfigurator;
055
056    private void configureJMX() throws RuntimeException {
057        LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
058        try {
059            ObjectName name = ObjectName.getInstance(JMXConfigurator.class.getPackage().getName()
060                    + ":type=" + JMXConfigurator.class.getSimpleName());
061            jmxConfigurator = new JMXConfigurator(context, mbeanServer, name);
062            if (!mbeanServer.isRegistered(name)) {
063                mbeanServer.registerMBean(jmxConfigurator, name);
064            }
065        } catch (MalformedObjectNameException | InstanceAlreadyExistsException | MBeanRegistrationException
066                | NotCompliantMBeanException e) {
067            throw new RuntimeException(e);
068        }
069    }
070
071    private void deconfigureJMX() {
072        // force JMXConfigurator to deregister itself from MBean server
073        jmxConfigurator.onStop(null);
074    }
075}