    001// Copyright 2010, 2011 The Apache Software Foundation
    002//
    003// Licensed under the Apache License, Version 2.0 (the "License");
    004// you may not use this file except in compliance with the License.
    005// You may obtain a copy of the License at
    006//
    007// http://www.apache.org/licenses/LICENSE-2.0
    008//
    009// Unless required by applicable law or agreed to in writing, software
    010// distributed under the License is distributed on an "AS IS" BASIS,
    011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    012// See the License for the specific language governing permissions and
    013// limitations under the License.
    014
    015package org.apache.tapestry5.internal.jmx;
    016
    017import org.apache.tapestry5.commons.util.CollectionFactory;
    018import org.apache.tapestry5.ioc.annotations.PostInjection;
    019import org.apache.tapestry5.ioc.internal.util.OneShotLock;
    020import org.apache.tapestry5.ioc.services.RegistryShutdownHub;
    021import org.apache.tapestry5.jmx.MBeanSupport;
    022import org.slf4j.Logger;
    023
    024import javax.management.MBeanServer;
    025import javax.management.MBeanServerFactory;
    026import javax.management.ObjectName;
    027import java.lang.management.ManagementFactory;
    028import java.util.List;
    029import java.util.Set;
    030
    031import static java.lang.String.format;
    032
    033public class MBeanSupportImpl implements MBeanSupport
    034{
    035    private final Logger logger;
    036
    037    private final MBeanServer server;
    038
    039    private final OneShotLock lock = new OneShotLock();
    040
    041    private final Set<ObjectName> registeredBeans = CollectionFactory.newSet();
    042
    043    public MBeanSupportImpl(Logger logger)
    044    {
    045        this.logger = logger;
    046
    047        // TODO: Agent Id should be configurable
    048        final List<MBeanServer> servers = MBeanServerFactory.findMBeanServer(null);
    049
    050        MBeanServer server = null;
    051
    052        if (servers != null && 0 < servers.size())
    053        {
    054            server = servers.get(0);
    055        }
    056
    057        if (server == null)
    058        {
    059            server = ManagementFactory.getPlatformMBeanServer();
    060        }
    061
    062        this.server = server;
    063    }
    064
    065    @PostInjection
    066    public void listenForShutdown(RegistryShutdownHub hub)
    067    {
    068        hub.addRegistryShutdownListener(new Runnable()
    069        {
    070            @Override
    071            public void run()
    072            {
    073                registryDidShutdown();
    074            }
    075        });
    076    }
    077
    078    @Override
    079    public void register(Object bean, String name)
    080    {
    081        register(bean, toObjectName(name));
    082    }
    083
    084    private static ObjectName toObjectName(String name)
    085    {
    086        try
    087        {
    088            return new ObjectName(name);
    089        } catch (Exception ex)
    090        {
    091            throw new RuntimeException(ex);
    092        }
    093    }
    094
    095    @Override
    096    public void register(final Object object, final ObjectName objectName)
    097    {
    098        lock.check();
    099
    100        if (this.server.isRegistered(objectName))
    101            return;
    102
    103        try
    104        {
    105            this.server.registerMBean(object, objectName);
    106
    107            this.registeredBeans.add(objectName);
    108
    109            this.logger.info(format("Registered MBean '%s' with server", objectName));
    110        } catch (final Exception e)
    111        {
    112            this.logger.error(format("Failed to register MBean '%s' with server", objectName), e);
    113        }
    114    }
    115
    116    @Override
    117    public void unregister(final ObjectName objectName)
    118    {
    119        lock.check();
    120
    121        doUnregister(objectName);
    122    }
    123
    124    private void doUnregister(final ObjectName objectName)
    125    {
    126        if (this.server.isRegistered(objectName))
    127        {
    128            try
    129            {
    130                this.server.unregisterMBean(objectName);
    131
    132                this.logger.info(format("Unregistered MBean '%s' from server", objectName));
    133
    134                if (registeredBeans.contains(objectName))
    135                    registeredBeans.remove(objectName);
    136            } catch (final Exception e)
    137            {
    138                this.logger.error(String.format("Failed to unregister MBean '%s' from server", objectName), e);
    139            }
    140        }
    141    }
    142
    143    private void registryDidShutdown()
    144    {
    145        lock.lock();
    146        // store into new data structure so we can remove them from registered beans
    147        ObjectName[] objects = registeredBeans.toArray(new ObjectName[registeredBeans.size()]);
    148        for (final ObjectName name : objects)
    149        {
    150            doUnregister(name);
    151        }
    152
    153        this.registeredBeans.clear();
    154
    155    }
    156}