// Copyright 2010, 2011 The Apache Software Foundation // // Licensed 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.tapestry5.internal.jmx; import org.apache.tapestry5.ioc.annotations.PostInjection; import org.apache.tapestry5.ioc.internal.util.CollectionFactory; import org.apache.tapestry5.ioc.internal.util.OneShotLock; import org.apache.tapestry5.ioc.services.RegistryShutdownHub; import org.apache.tapestry5.jmx.MBeanSupport; import org.slf4j.Logger; import javax.management.MBeanServer; import javax.management.MBeanServerFactory; import javax.management.ObjectName; import java.lang.management.ManagementFactory; import java.util.List; import java.util.Set; import static java.lang.String.format; public class MBeanSupportImpl implements MBeanSupport { private final Logger logger; private final MBeanServer server; private final OneShotLock lock = new OneShotLock(); private final Set<ObjectName> registeredBeans = CollectionFactory.newSet(); public MBeanSupportImpl(Logger logger) { this.logger = logger; // TODO: Agent Id should be configurable final List<MBeanServer> servers = MBeanServerFactory.findMBeanServer(null); MBeanServer server = null; if (servers != null && 0 < servers.size()) { server = servers.get(0); } if (server == null) { server = ManagementFactory.getPlatformMBeanServer(); } this.server = server; } @PostInjection public void listenForShutdown(RegistryShutdownHub hub) { hub.addRegistryShutdownListener(new Runnable() { @Override public void run() { registryDidShutdown(); } }); } @Override public void register(Object bean, String name) { register(bean, toObjectName(name)); } private static ObjectName toObjectName(String name) { try { return new ObjectName(name); } catch (Exception ex) { throw new RuntimeException(ex); } } @Override public void register(final Object object, final ObjectName objectName) { lock.check(); if (this.server.isRegistered(objectName)) return; try { this.server.registerMBean(object, objectName); this.registeredBeans.add(objectName); this.logger.info(format("Registered MBean '%s' with server", objectName)); } catch (final Exception e) { this.logger.error(format("Failed to register MBean '%s' with server", objectName), e); } } @Override public void unregister(final ObjectName objectName) { lock.check(); doUnregister(objectName); } private void doUnregister(final ObjectName objectName) { if (this.server.isRegistered(objectName)) { try { this.server.unregisterMBean(objectName); this.logger.info(format("Unregistered MBean '%s' from server", objectName)); if (registeredBeans.contains(objectName)) registeredBeans.remove(objectName); } catch (final Exception e) { this.logger.error(String.format("Failed to unregister MBean '%s' from server", objectName), e); } } } private void registryDidShutdown() { lock.lock(); // store into new data structure so we can remove them from registered beans ObjectName[] objects = registeredBeans.toArray(new ObjectName[registeredBeans.size()]); for (final ObjectName name : objects) { doUnregister(name); } this.registeredBeans.clear(); } }