Skip to content

Method: {...}

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