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 }