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.ioc.annotations.PostInjection; 018import org.apache.tapestry5.ioc.internal.util.CollectionFactory; 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 (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 @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}