    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
    015    package org.apache.tapestry5.internal.jmx;
    016
    017    import org.apache.tapestry5.ioc.annotations.PostInjection;
    018    import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
    019    import org.apache.tapestry5.ioc.internal.util.OneShotLock;
    020    import org.apache.tapestry5.ioc.services.RegistryShutdownHub;
    021    import org.apache.tapestry5.jmx.MBeanSupport;
    022    import org.slf4j.Logger;
    023
    024    import javax.management.MBeanServer;
    025    import javax.management.MBeanServerFactory;
    026    import javax.management.ObjectName;
    027    import java.lang.management.ManagementFactory;
    028    import java.util.List;
    029    import java.util.Set;
    030
    031    import static java.lang.String.format;
    032
    033    public 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 (this.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                public void run()
    071                {
    072                    registryDidShutdown();
    073                }
    074            });
    075        }
    076
    077        public void register(Object bean, String name)
    078        {
    079            register(bean, toObjectName(name));
    080        }
    081
    082        private static ObjectName toObjectName(String name)
    083        {
    084            try
    085            {
    086                return new ObjectName(name);
    087            } catch (Exception ex)
    088            {
    089                throw new RuntimeException(ex);
    090            }
    091        }
    092
    093        public void register(final Object object, final ObjectName objectName)
    094        {
    095            lock.check();
    096
    097            if (this.server.isRegistered(objectName))
    098                return;
    099
    100            try
    101            {
    102                this.server.registerMBean(object, objectName);
    103
    104                this.registeredBeans.add(objectName);
    105
    106                this.logger.info(format("Registered MBean '%s' with server", objectName));
    107            } catch (final Exception e)
    108            {
    109                this.logger.error(format("Failed to register MBean '%s' with server", objectName), e);
    110            }
    111        }
    112
    113        public void unregister(final ObjectName objectName)
    114        {
    115            lock.check();
    116
    117            doUnregister(objectName);
    118        }
    119
    120        private void doUnregister(final ObjectName objectName)
    121        {
    122            if (this.server.isRegistered(objectName))
    123            {
    124                try
    125                {
    126                    this.server.unregisterMBean(objectName);
    127
    128                    this.logger.info(format("Unregistered MBean '%s' from server", objectName));
    129
    130                    if (registeredBeans.contains(objectName))
    131                        registeredBeans.remove(objectName);
    132                } catch (final Exception e)
    133                {
    134                    this.logger.error(String.format("Failed to unregister MBean '%s' from server", objectName), e);
    135                }
    136            }
    137        }
    138
    139        private void registryDidShutdown()
    140        {
    141            lock.lock();
    142            // store into new data structure so we can remove them from registered beans
    143            ObjectName[] objects = registeredBeans.toArray(new ObjectName[registeredBeans.size()]);
    144            for (final ObjectName name : objects)
    145            {
    146                doUnregister(name);
    147            }
    148
    149            this.registeredBeans.clear();
    150
    151        }
    152    }