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 LOG.debug("beanAdded {}->{}",parent,obj);
132
133
134 ObjectName pname=null;
135 if (parent!=null)
136 {
137 pname=_beans.get(parent);
138 if (pname==null)
139 {
140
141 beanAdded(null,parent);
142 pname=_beans.get(parent);
143 }
144 }
145
146
147 if (obj == null || _beans.containsKey(obj))
148 return;
149
150 try
151 {
152
153 Object mbean = ObjectMBean.mbeanFor(obj);
154 if (mbean == null)
155 return;
156
157
158 ObjectName oname = null;
159 if (mbean instanceof ObjectMBean)
160 {
161 ((ObjectMBean)mbean).setMBeanContainer(this);
162 oname = ((ObjectMBean)mbean).getObjectName();
163 }
164
165
166 if (oname == null)
167 {
168
169 String domain = _domain;
170 if (domain == null)
171 domain = obj.getClass().getPackage().getName();
172
173
174 String type = obj.getClass().getName().toLowerCase(Locale.ENGLISH);
175 int dot = type.lastIndexOf('.');
176 if (dot >= 0)
177 type = type.substring(dot + 1);
178
179
180 StringBuffer buf = new StringBuffer();
181
182 String context = (mbean instanceof ObjectMBean)?makeName(((ObjectMBean)mbean).getObjectContextBasis()):null;
183 if (context==null && pname!=null)
184 context=pname.getKeyProperty("context");
185
186 if (context != null && context.length()>1)
187 buf.append("context=").append(context).append(",");
188
189 buf.append("type=").append(type);
190
191 String name = (mbean instanceof ObjectMBean)?makeName(((ObjectMBean)mbean).getObjectNameBasis()):context;
192 if (name != null && name.length()>1)
193 buf.append(",").append("name=").append(name);
194
195 String basis = buf.toString();
196
197 AtomicInteger count = __unique.get(basis);
198 if (count==null)
199 {
200 count=__unique.putIfAbsent(basis,new AtomicInteger());
201 if (count==null)
202 count=__unique.get(basis);
203 }
204
205 oname = ObjectName.getInstance(domain + ":" + basis + ",id=" + count.getAndIncrement());
206 }
207
208 ObjectInstance oinstance = _mbeanServer.registerMBean(mbean, oname);
209 LOG.debug("Registered {}", oinstance.getObjectName());
210 _beans.put(obj, oinstance.getObjectName());
211
212 }
213 catch (Exception e)
214 {
215 LOG.warn("bean: " + obj, e);
216 }
217 }
218
219 @Override
220 public void beanRemoved(Container parent, Object obj)
221 {
222 LOG.debug("beanRemoved {}",obj);
223 ObjectName bean = _beans.remove(obj);
224
225 if (bean != null)
226 {
227 try
228 {
229 _mbeanServer.unregisterMBean(bean);
230 LOG.debug("Unregistered {}", bean);
231 }
232 catch (javax.management.InstanceNotFoundException e)
233 {
234 LOG.ignore(e);
235 }
236 catch (Exception e)
237 {
238 LOG.warn(e);
239 }
240 }
241 }
242
243
244
245
246
247 public String makeName(String basis)
248 {
249 if (basis==null)
250 return basis;
251 return basis.replace(':', '_').replace('*', '_').replace('?', '_').replace('=', '_').replace(',', '_').replace(' ', '_');
252 }
253
254 @Override
255 public void dump(Appendable out, String indent) throws IOException
256 {
257 ContainerLifeCycle.dumpObject(out,this);
258 ContainerLifeCycle.dump(out, indent, _beans.entrySet());
259 }
260
261 @Override
262 public String dump()
263 {
264 return ContainerLifeCycle.dump(this);
265 }
266
267 public void destroy()
268 {
269 for (ObjectName oname : _beans.values())
270 if (oname!=null)
271 {
272 try
273 {
274 _mbeanServer.unregisterMBean(oname);
275 }
276 catch (MBeanRegistrationException | InstanceNotFoundException e)
277 {
278 LOG.warn(e);
279 }
280 }
281 }
282 }