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 }