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