View Javadoc

1   //========================================================================
2   //Copyright 2005 Mort Bay Consulting Pty. Ltd.
3   //------------------------------------------------------------------------
4   //Licensed under the Apache License, Version 2.0 (the "License");
5   //you may not use this file except in compliance with the License.
6   //You may obtain a copy of the License at
7   //http://www.apache.org/licenses/LICENSE-2.0
8   //Unless required by applicable law or agreed to in writing, software
9   //distributed under the License is distributed on an "AS IS" BASIS,
10  //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11  //See the License for the specific language governing permissions and
12  //limitations under the License.
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             //no override mbean object name, so make a generic one
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                 //if no explicit domain, create one
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 }