1 package cz.cuni.amis.pogamut.base.agent.jmx;
2
3 import java.util.LinkedHashSet;
4 import java.util.Set;
5 import java.util.logging.Level;
6
7 import javax.management.InstanceAlreadyExistsException;
8 import javax.management.MBeanRegistrationException;
9 import javax.management.MBeanServer;
10 import javax.management.MalformedObjectNameException;
11 import javax.management.NotCompliantMBeanException;
12 import javax.management.ObjectName;
13
14 import com.google.inject.Inject;
15
16 import cz.cuni.amis.pogamut.base.agent.IAgent;
17 import cz.cuni.amis.pogamut.base.agent.exceptions.CantStartJMXException;
18 import cz.cuni.amis.pogamut.base.agent.exceptions.JMXAlreadyEnabledException;
19 import cz.cuni.amis.pogamut.base.agent.jmx.adapter.AgentMBeanAdapter;
20 import cz.cuni.amis.pogamut.base.utils.Pogamut;
21 import cz.cuni.amis.pogamut.base.utils.PogamutProperty;
22 import cz.cuni.amis.pogamut.base.utils.guice.AgentScoped;
23 import cz.cuni.amis.pogamut.base.utils.jmx.PogamutJMX;
24 import cz.cuni.amis.pogamut.base.utils.jmx.PogamutMBeanServer;
25 import cz.cuni.amis.pogamut.base.utils.logging.IAgentLogger;
26 import cz.cuni.amis.pogamut.base.utils.logging.LogCategory;
27 import cz.cuni.amis.utils.ExceptionToString;
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42 @AgentScoped
43 public class AgentJMXComponents<T extends IAgent> {
44
45 public static final String LOG_CATEGORY_NAME = "AgentJMXComponents";
46
47
48
49
50
51 public static final String JMX_SERVER_AGENT_NAME_DELIM = "|";
52
53
54
55
56 private PogamutMBeanServer mBeanServer = null;
57
58
59
60
61
62
63
64
65 private String jmxDomain = null;
66
67
68
69
70
71 private Set<IJMXEnabled> jmxComponents = new LinkedHashSet<IJMXEnabled>();
72
73
74
75
76 private ObjectName agentJMXName = null;
77
78 private IAgentLogger agentLogger;
79
80 private LogCategory log;
81
82
83
84
85 private T agent;
86
87 @Inject
88 public AgentJMXComponents(T agent) {
89 this.agent = agent;
90 this.agentLogger = agent.getLogger();
91 this.log = agentLogger.getCategory(LOG_CATEGORY_NAME);
92 }
93
94
95
96
97
98
99
100 public void addComponent(IJMXEnabled component) {
101 synchronized (jmxComponents) {
102 if (jmxComponents.contains(component)) {
103 return;
104 }
105 if (log.isLoggable(Level.FINER)) log.finer("Adding new JMX component " + component);
106 jmxComponents.add(component);
107 if (isJMXEnabled()) {
108 if (log.isLoggable(Level.FINE)) log.fine("Enabling JMX component " + component);
109 component.enableJMX(mBeanServer, agentJMXName);
110 }
111 if (log.isLoggable(Level.INFO)) log.info("New JMX component added: " + component);
112 }
113 }
114
115
116
117
118
119
120 public MBeanServer getMBeanServer() {
121 return mBeanServer;
122 }
123
124
125
126
127
128
129
130 public String getJMXDomain() {
131 return jmxDomain;
132 }
133
134
135
136
137
138
139 public boolean isJMXEnabled() {
140 return jmxDomain != null;
141 }
142
143
144
145
146
147
148 public ObjectName getAgentJMXName() {
149 return agentJMXName;
150 }
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165 public String enableJMX() throws JMXAlreadyEnabledException, CantStartJMXException {
166 synchronized (jmxComponents) {
167 if (!isJMXEnabled()) {
168 this.mBeanServer = new PogamutMBeanServer(Pogamut.getPlatform().getMBeanServer());
169 jmxDomain = PogamutJMX.getPogamutJMXDomain();
170 try {
171 agentJMXName = PogamutJMX.getAgentObjectName(agent.getComponentId());
172 } catch (Exception e) {
173 throw new CantStartJMXException("Can't create object name for the agent.", e, log, this);
174 }
175
176
177 try {
178
179 AgentMBeanAdapter agentMBean = createAgentMBean(agentJMXName, mBeanServer);
180 mBeanServer.registerMBean(agentMBean, agentJMXName);
181 } catch (Exception ex) {
182 throw new CantStartJMXException("Agent MBean cannot be registered.", ex, log, this);
183 }
184
185 if (log.isLoggable(Level.INFO)) log.info("Enabling JMX.");
186 int numOk = 0;
187 for (IJMXEnabled jmxComponent : jmxComponents) {
188 try {
189 if (log.isLoggable(Level.FINE)) log.fine("Starting JMX component: " + jmxComponent);
190 jmxComponent.enableJMX(mBeanServer, agentJMXName);
191 ++numOk;
192 } catch (JMXAlreadyEnabledException e) {
193 log.log(Level.SEVERE, ExceptionToString.process("IJMXEnabled[class="+ jmxComponent.getClass().getName()+ ",name="+ jmxComponent.toString()+ "]: states that it's been already enabled.", e));
194 } catch (CantStartJMXException e) {
195 if (log.isLoggable(Level.SEVERE)) log.severe(ExceptionToString.process("IJMXEnabled[class="+ jmxComponent.getClass().getName() + ",name="+ jmxComponent.toString()+ "]: can't start it's JMX.", e));
196 }
197 }
198 if (log.isLoggable(Level.INFO)) log.info(numOk + " JMX components enabled");
199 }
200 }
201 return Pogamut.getPlatform().getMBeanServerURL().toString() + AgentJMXComponents.JMX_SERVER_AGENT_NAME_DELIM + getAgentJMXName().toString();
202 }
203
204
205
206
207
208
209
210
211 protected AgentMBeanAdapter createAgentMBean(ObjectName objectName,
212 MBeanServer mbs) throws MalformedObjectNameException,
213 InstanceAlreadyExistsException, InstanceAlreadyExistsException,
214 MBeanRegistrationException, NotCompliantMBeanException {
215 return new AgentMBeanAdapter(agent, objectName, mbs);
216 }
217
218
219
220
221 public void unregisterJMX() {
222 if (isJMXEnabled()) {
223 if (log.isLoggable(Level.WARNING)) log.warning("Unregistering JMX components.");
224 mBeanServer.unregisterAll();
225 }
226 }
227
228
229
230
231 public void registerJMX() {
232 if (isJMXEnabled()) {
233 try {
234 if (log.isLoggable(Level.WARNING)) log.warning("Re-registering JMX components.");
235 mBeanServer.registerAll();
236 } catch (Exception e) {
237 throw new CantStartJMXException("JMX components can't be re-registered: " + e.getMessage(), e, this);
238 }
239 }
240 }
241
242 }