1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.jmx;
15
16 import java.io.IOException;
17 import java.util.ArrayList;
18 import java.util.HashMap;
19 import java.util.HashSet;
20 import java.util.Iterator;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.Set;
24 import java.util.WeakHashMap;
25 import javax.management.MBeanServer;
26 import javax.management.ObjectInstance;
27 import javax.management.ObjectName;
28
29 import org.eclipse.jetty.util.MultiMap;
30 import org.eclipse.jetty.util.component.AbstractLifeCycle;
31 import org.eclipse.jetty.util.component.AggregateLifeCycle;
32 import org.eclipse.jetty.util.component.Container;
33 import org.eclipse.jetty.util.component.Container.Relationship;
34 import org.eclipse.jetty.util.component.Dumpable;
35 import org.eclipse.jetty.util.log.Log;
36 import org.eclipse.jetty.util.log.Logger;
37 import org.eclipse.jetty.util.thread.ShutdownThread;
38
39
40
41
42 public class MBeanContainer extends AbstractLifeCycle implements Container.Listener, Dumpable
43 {
44 private final static Logger LOG = Log.getLogger(MBeanContainer.class.getName());
45
46 private final MBeanServer _server;
47 private final WeakHashMap<Object, ObjectName> _beans = new WeakHashMap<Object, ObjectName>();
48 private final HashMap<String, Integer> _unique = new HashMap<String, Integer>();
49 private final WeakHashMap<ObjectName,List<Container.Relationship>> _relations = new WeakHashMap<ObjectName,List<Container.Relationship>>();
50 private String _domain = null;
51
52
53
54
55
56
57
58 public synchronized ObjectName findMBean(Object object)
59 {
60 ObjectName bean = _beans.get(object);
61 return bean == null ? null : bean;
62 }
63
64
65
66
67
68
69
70 public synchronized Object findBean(ObjectName oname)
71 {
72 for (Map.Entry<Object, ObjectName> entry : _beans.entrySet())
73 {
74 ObjectName bean = entry.getValue();
75 if (bean.equals(oname))
76 return entry.getKey();
77 }
78 return null;
79 }
80
81
82
83
84
85
86 public MBeanContainer(MBeanServer server)
87 {
88 _server = server;
89
90 try
91 {
92 start();
93 }
94 catch (Exception e)
95 {
96 LOG.ignore(e);
97 }
98 }
99
100
101
102
103
104
105 public MBeanServer getMBeanServer()
106 {
107 return _server;
108 }
109
110
111
112
113
114
115 public void setDomain(String domain)
116 {
117 _domain = domain;
118 }
119
120
121
122
123
124
125 public String getDomain()
126 {
127 return _domain;
128 }
129
130
131
132
133
134
135 public synchronized void add(Relationship relationship)
136 {
137 LOG.debug("add {}",relationship);
138 ObjectName parent = _beans.get(relationship.getParent());
139 if (parent == null)
140 {
141 addBean(relationship.getParent());
142 parent = _beans.get(relationship.getParent());
143 }
144
145 ObjectName child = _beans.get(relationship.getChild());
146 if (child == null)
147 {
148 addBean(relationship.getChild());
149 child = _beans.get(relationship.getChild());
150 }
151
152 if (parent != null && child != null)
153 {
154 List<Container.Relationship> rels = _relations.get(parent);
155 if (rels==null)
156 {
157 rels=new ArrayList<Container.Relationship>();
158 _relations.put(parent,rels);
159 }
160 rels.add(relationship);
161 }
162 }
163
164
165
166
167
168
169 public synchronized void remove(Relationship relationship)
170 {
171 LOG.debug("remove {}",relationship);
172 ObjectName parent = _beans.get(relationship.getParent());
173 ObjectName child = _beans.get(relationship.getChild());
174
175 if (parent != null && child != null)
176 {
177 List<Container.Relationship> rels = _relations.get(parent);
178 if (rels!=null)
179 {
180 for (Iterator<Container.Relationship> i=rels.iterator();i.hasNext();)
181 {
182 Container.Relationship r = i.next();
183 if (relationship.equals(r) || r.getChild()==null)
184 i.remove();
185 }
186 }
187 }
188 }
189
190
191
192
193
194
195 public synchronized void removeBean(Object obj)
196 {
197 LOG.debug("removeBean {}",obj);
198 ObjectName bean = _beans.remove(obj);
199
200 if (bean != null)
201 {
202 List<Container.Relationship> beanRelations= _relations.remove(bean);
203 if (beanRelations != null)
204 {
205 LOG.debug("Unregister {}", beanRelations);
206 List<?> removeList = new ArrayList<Object>(beanRelations);
207 for (Object r : removeList)
208 {
209 Container.Relationship relation = (Relationship)r;
210 relation.getContainer().update(relation.getParent(), relation.getChild(), null, relation.getRelationship(), true);
211 }
212 }
213
214 try
215 {
216 _server.unregisterMBean(bean);
217 LOG.debug("Unregistered {}", bean);
218 }
219 catch (javax.management.InstanceNotFoundException e)
220 {
221 LOG.ignore(e);
222 }
223 catch (Exception e)
224 {
225 LOG.warn(e);
226 }
227 }
228 }
229
230
231
232
233
234
235 public synchronized void addBean(Object obj)
236 {
237 LOG.debug("addBean {}",obj);
238 try
239 {
240 if (obj == null || _beans.containsKey(obj))
241 return;
242
243 Object mbean = ObjectMBean.mbeanFor(obj);
244 if (mbean == null)
245 return;
246
247 ObjectName oname = null;
248 if (mbean instanceof ObjectMBean)
249 {
250 ((ObjectMBean)mbean).setMBeanContainer(this);
251 oname = ((ObjectMBean)mbean).getObjectName();
252 }
253
254
255 if (oname == null)
256 {
257 String type = obj.getClass().getName().toLowerCase();
258 int dot = type.lastIndexOf('.');
259 if (dot >= 0)
260 type = type.substring(dot + 1);
261
262 String context = null;
263 if (mbean instanceof ObjectMBean)
264 {
265 context = makeName(((ObjectMBean)mbean).getObjectContextBasis());
266 }
267
268 String name = null;
269 if (mbean instanceof ObjectMBean)
270 {
271 name = makeName(((ObjectMBean)mbean).getObjectNameBasis());
272 }
273
274 StringBuffer buf = new StringBuffer();
275 buf.append("type=").append(type);
276 if (context != null && context.length()>1)
277 {
278 buf.append(buf.length()>0 ? ",":"");
279 buf.append("context=").append(context);
280 }
281 if (name != null && name.length()>1)
282 {
283 buf.append(buf.length()>0 ? ",":"");
284 buf.append("name=").append(name);
285 }
286
287 String basis = buf.toString();
288 Integer count = _unique.get(basis);
289 count = count == null ? 0 : 1 + count;
290 _unique.put(basis, count);
291
292
293 String domain = _domain;
294 if (domain == null)
295 domain = obj.getClass().getPackage().getName();
296
297 oname = ObjectName.getInstance(domain + ":" + basis + ",id=" + count);
298 }
299
300 ObjectInstance oinstance = _server.registerMBean(mbean, oname);
301 LOG.debug("Registered {}", oinstance.getObjectName());
302 _beans.put(obj, oinstance.getObjectName());
303
304 }
305 catch (Exception e)
306 {
307 LOG.warn("bean: " + obj, e);
308 }
309 }
310
311
312
313
314
315 public String makeName(String basis)
316 {
317 if (basis==null)
318 return basis;
319 return basis.replace(':', '_').replace('*', '_').replace('?', '_').replace('=', '_').replace(',', '_').replace(' ', '_');
320 }
321
322
323
324
325
326
327 public void doStart()
328 {
329 ShutdownThread.register(this);
330 }
331
332
333
334
335
336
337 public void doStop()
338 {
339 Set<Object> removeSet = new HashSet<Object>(_beans.keySet());
340 for (Object removeObj : removeSet)
341 {
342 removeBean(removeObj);
343 }
344 }
345
346 public void dump(Appendable out, String indent) throws IOException
347 {
348 out.append(toString()).append("\n");
349 AggregateLifeCycle.dump(out, indent, _beans.entrySet());
350 }
351
352 public String dump()
353 {
354 return AggregateLifeCycle.dump(this);
355 }
356 }