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