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.Locale;
23 import java.util.Map;
24 import java.util.WeakHashMap;
25 import java.util.concurrent.ConcurrentHashMap;
26 import java.util.concurrent.ConcurrentMap;
27 import java.util.concurrent.atomic.AtomicInteger;
28
29 import javax.management.InstanceNotFoundException;
30 import javax.management.MBeanRegistrationException;
31 import javax.management.MBeanServer;
32 import javax.management.ObjectInstance;
33 import javax.management.ObjectName;
34
35 import org.eclipse.jetty.util.component.Container;
36 import org.eclipse.jetty.util.component.ContainerLifeCycle;
37 import org.eclipse.jetty.util.component.Dumpable;
38 import org.eclipse.jetty.util.log.Log;
39 import org.eclipse.jetty.util.log.Logger;
40
41
42
43
44 public class MBeanContainer implements Container.InheritedListener, Dumpable
45 {
46 private final static Logger LOG = Log.getLogger(MBeanContainer.class.getName());
47 private final static ConcurrentMap<String, AtomicInteger> __unique = new ConcurrentHashMap<String, AtomicInteger>();
48
49 public static void resetUnique()
50 {
51 __unique.clear();
52 }
53
54 private final MBeanServer _mbeanServer;
55 private final WeakHashMap<Object, ObjectName> _beans = new WeakHashMap<Object, ObjectName>();
56 private String _domain = null;
57
58
59
60
61
62
63
64 public synchronized ObjectName findMBean(Object object)
65 {
66 ObjectName bean = _beans.get(object);
67 return bean == null ? null : bean;
68 }
69
70
71
72
73
74
75
76 public synchronized Object findBean(ObjectName oname)
77 {
78 for (Map.Entry<Object, ObjectName> entry : _beans.entrySet())
79 {
80 ObjectName bean = entry.getValue();
81 if (bean.equals(oname))
82 return entry.getKey();
83 }
84 return null;
85 }
86
87
88
89
90
91
92 public MBeanContainer(MBeanServer server)
93 {
94 _mbeanServer = server;
95 }
96
97
98
99
100
101
102 public MBeanServer getMBeanServer()
103 {
104 return _mbeanServer;
105 }
106
107
108
109
110
111
112 public void setDomain(String domain)
113 {
114 _domain = domain;
115 }
116
117
118
119
120
121
122 public String getDomain()
123 {
124 return _domain;
125 }
126
127
128 @Override
129 public void beanAdded(Container parent, Object obj)
130 {
131 if (LOG.isDebugEnabled())
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 if (LOG.isDebugEnabled())
211 LOG.debug("Registered {}", oinstance.getObjectName());
212 _beans.put(obj, oinstance.getObjectName());
213
214 }
215 catch (Exception e)
216 {
217 LOG.warn("bean: " + obj, e);
218 }
219 }
220
221 @Override
222 public void beanRemoved(Container parent, Object obj)
223 {
224 if (LOG.isDebugEnabled())
225 LOG.debug("beanRemoved {}",obj);
226 ObjectName bean = _beans.remove(obj);
227
228 if (bean != null)
229 {
230 try
231 {
232 _mbeanServer.unregisterMBean(bean);
233 if (LOG.isDebugEnabled())
234 LOG.debug("Unregistered {}", bean);
235 }
236 catch (javax.management.InstanceNotFoundException e)
237 {
238 LOG.ignore(e);
239 }
240 catch (Exception e)
241 {
242 LOG.warn(e);
243 }
244 }
245 }
246
247
248
249
250
251 public String makeName(String basis)
252 {
253 if (basis==null)
254 return basis;
255 return basis.replace(':', '_').replace('*', '_').replace('?', '_').replace('=', '_').replace(',', '_').replace(' ', '_');
256 }
257
258 @Override
259 public void dump(Appendable out, String indent) throws IOException
260 {
261 ContainerLifeCycle.dumpObject(out,this);
262 ContainerLifeCycle.dump(out, indent, _beans.entrySet());
263 }
264
265 @Override
266 public String dump()
267 {
268 return ContainerLifeCycle.dump(this);
269 }
270
271 public void destroy()
272 {
273 for (ObjectName oname : _beans.values())
274 if (oname!=null)
275 {
276 try
277 {
278 _mbeanServer.unregisterMBean(oname);
279 }
280 catch (MBeanRegistrationException | InstanceNotFoundException e)
281 {
282 LOG.warn(e);
283 }
284 }
285 }
286 }