1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.jmx;
20
21 import java.io.IOException;
22 import java.util.HashMap;
23 import java.util.Locale;
24 import java.util.Map;
25 import java.util.WeakHashMap;
26 import java.util.concurrent.ConcurrentHashMap;
27 import java.util.concurrent.ConcurrentMap;
28 import java.util.concurrent.atomic.AtomicInteger;
29
30 import javax.management.InstanceNotFoundException;
31 import javax.management.MBeanRegistrationException;
32 import javax.management.MBeanServer;
33 import javax.management.ObjectInstance;
34 import javax.management.ObjectName;
35
36 import org.eclipse.jetty.util.component.Container;
37 import org.eclipse.jetty.util.component.ContainerLifeCycle;
38 import org.eclipse.jetty.util.component.Dumpable;
39 import org.eclipse.jetty.util.log.Log;
40 import org.eclipse.jetty.util.log.Logger;
41
42
43
44
45 public class MBeanContainer implements Container.InheritedListener, Dumpable
46 {
47 private final static Logger LOG = Log.getLogger(MBeanContainer.class.getName());
48 private final static ConcurrentMap<String, AtomicInteger> __unique = new ConcurrentHashMap<String, AtomicInteger>();
49
50 public static void resetUnique()
51 {
52 __unique.clear();
53 }
54
55 private final MBeanServer _mbeanServer;
56 private final WeakHashMap<Object, ObjectName> _beans = new WeakHashMap<Object, ObjectName>();
57 private String _domain = null;
58
59
60
61
62
63
64
65 public synchronized ObjectName findMBean(Object object)
66 {
67 ObjectName bean = _beans.get(object);
68 return bean == null ? null : bean;
69 }
70
71
72
73
74
75
76
77 public synchronized Object findBean(ObjectName oname)
78 {
79 for (Map.Entry<Object, ObjectName> entry : _beans.entrySet())
80 {
81 ObjectName bean = entry.getValue();
82 if (bean.equals(oname))
83 return entry.getKey();
84 }
85 return null;
86 }
87
88
89
90
91
92
93 public MBeanContainer(MBeanServer server)
94 {
95 _mbeanServer = server;
96 }
97
98
99
100
101
102
103 public MBeanServer getMBeanServer()
104 {
105 return _mbeanServer;
106 }
107
108
109
110
111
112
113 public void setDomain(String domain)
114 {
115 _domain = domain;
116 }
117
118
119
120
121
122
123 public String getDomain()
124 {
125 return _domain;
126 }
127
128
129 @Override
130 public void beanAdded(Container parent, Object obj)
131 {
132 LOG.debug("beanAdded {}->{}",parent,obj);
133
134
135 ObjectName pname=null;
136 if (parent!=null)
137 {
138 pname=_beans.get(parent);
139 if (pname==null)
140 {
141
142 beanAdded(null,parent);
143 pname=_beans.get(parent);
144 }
145 }
146
147
148 if (obj == null || _beans.containsKey(obj))
149 return;
150
151 try
152 {
153
154 Object mbean = ObjectMBean.mbeanFor(obj);
155 if (mbean == null)
156 return;
157
158
159 ObjectName oname = null;
160 if (mbean instanceof ObjectMBean)
161 {
162 ((ObjectMBean)mbean).setMBeanContainer(this);
163 oname = ((ObjectMBean)mbean).getObjectName();
164 }
165
166
167 if (oname == null)
168 {
169
170 String domain = _domain;
171 if (domain == null)
172 domain = obj.getClass().getPackage().getName();
173
174
175 String type = obj.getClass().getName().toLowerCase(Locale.ENGLISH);
176 int dot = type.lastIndexOf('.');
177 if (dot >= 0)
178 type = type.substring(dot + 1);
179
180
181 StringBuffer buf = new StringBuffer();
182
183 String context = (mbean instanceof ObjectMBean)?makeName(((ObjectMBean)mbean).getObjectContextBasis()):null;
184 if (context==null && pname!=null)
185 context=pname.getKeyProperty("context");
186
187 if (context != null && context.length()>1)
188 buf.append("context=").append(context).append(",");
189
190 buf.append("type=").append(type);
191
192 String name = (mbean instanceof ObjectMBean)?makeName(((ObjectMBean)mbean).getObjectNameBasis()):context;
193 if (name != null && name.length()>1)
194 buf.append(",").append("name=").append(name);
195
196 String basis = buf.toString();
197
198 AtomicInteger count = __unique.get(basis);
199 if (count==null)
200 {
201 count=__unique.putIfAbsent(basis,new AtomicInteger());
202 if (count==null)
203 count=__unique.get(basis);
204 }
205
206 oname = ObjectName.getInstance(domain + ":" + basis + ",id=" + count.getAndIncrement());
207 }
208
209 ObjectInstance oinstance = _mbeanServer.registerMBean(mbean, oname);
210 LOG.debug("Registered {}", oinstance.getObjectName());
211 _beans.put(obj, oinstance.getObjectName());
212
213 }
214 catch (Exception e)
215 {
216 LOG.warn("bean: " + obj, e);
217 }
218 }
219
220 @Override
221 public void beanRemoved(Container parent, Object obj)
222 {
223 LOG.debug("beanRemoved {}",obj);
224 ObjectName bean = _beans.remove(obj);
225
226 if (bean != null)
227 {
228 try
229 {
230 _mbeanServer.unregisterMBean(bean);
231 LOG.debug("Unregistered {}", bean);
232 }
233 catch (javax.management.InstanceNotFoundException e)
234 {
235 LOG.ignore(e);
236 }
237 catch (Exception e)
238 {
239 LOG.warn(e);
240 }
241 }
242 }
243
244
245
246
247
248 public String makeName(String basis)
249 {
250 if (basis==null)
251 return basis;
252 return basis.replace(':', '_').replace('*', '_').replace('?', '_').replace('=', '_').replace(',', '_').replace(' ', '_');
253 }
254
255 @Override
256 public void dump(Appendable out, String indent) throws IOException
257 {
258 ContainerLifeCycle.dumpObject(out,this);
259 ContainerLifeCycle.dump(out, indent, _beans.entrySet());
260 }
261
262 @Override
263 public String dump()
264 {
265 return ContainerLifeCycle.dump(this);
266 }
267
268 public void destroy()
269 {
270 for (ObjectName oname : _beans.values())
271 if (oname!=null)
272 {
273 try
274 {
275 _mbeanServer.unregisterMBean(oname);
276 }
277 catch (MBeanRegistrationException | InstanceNotFoundException e)
278 {
279 LOG.warn(e);
280 }
281 }
282 }
283 }