Skip to contentPackage: MBeansManager$1
MBeansManager$1
Coverage
1: /*
2: * *************************************************************************************************************************************************************
3: *
4: * TheseFoolishThings: Miscellaneous utilities
5: * http://tidalwave.it/projects/thesefoolishthings
6: *
7: * Copyright (C) 2009 - 2024 by Tidalwave s.a.s. (http://tidalwave.it)
8: *
9: * *************************************************************************************************************************************************************
10: *
11: * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
12: * You may obtain a copy of the License at
13: *
14: * http://www.apache.org/licenses/LICENSE-2.0
15: *
16: * 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
17: * CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
18: *
19: * *************************************************************************************************************************************************************
20: *
21: * git clone https://bitbucket.org/tidalwave/thesefoolishthings-src
22: * git clone https://github.com/tidalwave-it/thesefoolishthings-src
23: *
24: * *************************************************************************************************************************************************************
25: */
26: package it.tidalwave.actor.impl;
27:
28: import java.lang.management.ManagementFactory;
29: import java.lang.reflect.Modifier;
30: import javax.annotation.Nonnegative;
31: import javax.annotation.Nonnull;
32: import java.util.HashMap;
33: import java.util.Map;
34: import it.tidalwave.actor.spi.ActorActivatorStats;
35: import javax.management.InstanceAlreadyExistsException;
36: import javax.management.InstanceNotFoundException;
37: import javax.management.MBeanRegistrationException;
38: import javax.management.MalformedObjectNameException;
39: import javax.management.NotCompliantMBeanException;
40: import javax.management.ObjectName;
41: import lombok.Getter;
42: import lombok.extern.slf4j.Slf4j;
43: import static it.tidalwave.messagebus.spi.ReflectionUtils.*;
44:
45: /***************************************************************************************************************************************************************
46: *
47: * @author Fabrizio Giudici
48: *
49: **************************************************************************************************************************************************************/
50: @Slf4j
51: public class MBeansManager
52: {
53: @Nonnull
54: private final Object actorObject;
55:
56: @Nonnull @Getter
57: private final ActorActivatorStats stats;
58:
59: private ObjectName statsName;
60:
61: private final Map<ObjectName, Object> mbeansMapByName = new HashMap<>();
62:
63: /***********************************************************************************************************************************************************
64: *
65: **********************************************************************************************************************************************************/
66: public MBeansManager (@Nonnull final Object actorObject, @Nonnegative final int poolSize)
67: {
68: this.actorObject = actorObject;
69: stats = new ActorActivatorStats(poolSize);
70: }
71:
72: /***********************************************************************************************************************************************************
73: *
74: **********************************************************************************************************************************************************/
75: public void register()
76: {
77: forEachMethodInTopDownHierarchy(actorObject, new MethodProcessorSupport()
78: {
79: @Override @Nonnull
80: public FilterResult filter (@Nonnull final Class<?> clazz)
81: {
82: mbeansMapByName.putAll(getMBeans(actorObject, clazz));
83: return FilterResult.IGNORE;
84: }
85: });
86:
87: final var mBeanServer = ManagementFactory.getPlatformMBeanServer();
88:
89: try
90: {
91: final var name = String.format("%s:type=%s", actorObject.getClass().getPackage().getName(),
92: actorObject.getClass().getSimpleName());
93: statsName = new ObjectName(name);
94: mBeanServer.registerMBean(stats, statsName);
95: }
96: catch (InstanceAlreadyExistsException | MalformedObjectNameException | NotCompliantMBeanException | MBeanRegistrationException e)
97: {
98: log.error("Cannot register master MBean for actor " + actorObject, e);
99: }
100:
101: for (final var entry : mbeansMapByName.entrySet())
102: {
103: try
104: {
105: log.info(">>>> registering MBean {}", entry);
106: mBeanServer.registerMBean(entry.getValue(), entry.getKey());
107: }
108: catch (InstanceAlreadyExistsException | NotCompliantMBeanException | MBeanRegistrationException e)
109: {
110: log.error("Cannot register MBean: " + entry, e);
111: }
112: }
113: }
114:
115: /***********************************************************************************************************************************************************
116: * Unregisters the MBeans.
117: **********************************************************************************************************************************************************/
118: public void unregister()
119: {
120: final var mBeanServer = ManagementFactory.getPlatformMBeanServer();
121:
122: try
123: {
124: mBeanServer.unregisterMBean(statsName);
125: }
126: catch (InstanceNotFoundException | MBeanRegistrationException e)
127: {
128: log.error("Cannot register master MBean for actor " + actorObject, e);
129: }
130:
131: for (final var entry : mbeansMapByName.entrySet())
132: {
133: try
134: {
135: log.info(">>>> unregistering MBean {}", entry);
136: mBeanServer.unregisterMBean(entry.getKey());
137: }
138: catch (InstanceNotFoundException | MBeanRegistrationException e)
139: {
140: log.error("Cannot unregister MBean: " + entry, e);
141: }
142: }
143: }
144:
145: /***********************************************************************************************************************************************************
146: *
147: **********************************************************************************************************************************************************/
148: @Nonnull
149: private static Map<ObjectName, Object> getMBeans (@Nonnull final Object actorObject, @Nonnull final Class<?> clazz)
150: {
151: final Map<ObjectName, Object> result = new HashMap<>();
152:
153: for (final var field : clazz.getDeclaredFields())
154: {
155: if (!field.isSynthetic() && ((field.getModifiers() & Modifier.STATIC) == 0))
156: {
157: try
158: {
159: field.setAccessible(true);
160: final var value = field.get(actorObject);
161:
162: if (value != null)
163: {
164: final var interfaces = value.getClass().getInterfaces();
165: //
166: // TODO: it checks only first interface - what about an annotation?
167: //
168: if ((interfaces.length > 0) && interfaces[0].getName().endsWith("MBean"))
169: {
170: final var name = String.format("%s:type=%s", clazz.getPackage().getName(),
171: value.getClass().getSimpleName());
172: result.put(new ObjectName(name), value);
173: }
174: }
175: }
176: catch (IllegalArgumentException | MalformedObjectNameException | IllegalAccessException e)
177: {
178: log.error("Cannot handle object: {}", field);
179: }
180: }
181: }
182:
183: return result;
184: }
185: }