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