View Javadoc

1   // ========================================================================
2   // Copyright (c) 2005-2009 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // All rights reserved. This program and the accompanying materials
5   // are made available under the terms of the Eclipse Public License v1.0
6   // and Apache License v2.0 which accompanies this distribution.
7   // The Eclipse Public License is available at 
8   // http://www.eclipse.org/legal/epl-v10.html
9   // The Apache License v2.0 is available at
10  // http://www.opensource.org/licenses/apache2.0.php
11  // You may elect to redistribute this code under either of these licenses. 
12  // ========================================================================
13  
14  package org.eclipse.jetty.jmx;
15  
16  import java.util.ArrayList;
17  import java.util.HashMap;
18  import java.util.Iterator;
19  import java.util.List;
20  import java.util.Map;
21  import java.util.WeakHashMap;
22  
23  import javax.management.MBeanServer;
24  import javax.management.ObjectInstance;
25  import javax.management.ObjectName;
26  
27  import org.eclipse.jetty.util.MultiMap;
28  import org.eclipse.jetty.util.TypeUtil;
29  import org.eclipse.jetty.util.component.AbstractLifeCycle;
30  import org.eclipse.jetty.util.component.Container;
31  import org.eclipse.jetty.util.component.Container.Relationship;
32  import org.eclipse.jetty.util.log.Log;
33  
34  public class MBeanContainer extends AbstractLifeCycle implements Container.Listener
35  {
36      private final MBeanServer _server;
37      private final WeakHashMap _beans = new WeakHashMap();
38      private final HashMap _unique = new HashMap();
39      private String _domain = null;
40      private MultiMap _relations = new MultiMap();
41      
42  
43      public synchronized ObjectName findMBean(Object object)
44      {
45          ObjectName bean = (ObjectName)_beans.get(object);
46          return bean==null?null:bean; 
47      }
48  
49      public synchronized Object findBean(ObjectName oname)
50      {
51          for (Iterator iter = _beans.entrySet().iterator(); iter.hasNext();)
52          {
53              Map.Entry entry = (Map.Entry) iter.next();
54              ObjectName bean = (ObjectName)entry.getValue();
55              if (bean.equals(oname))
56                  return entry.getKey();
57          }
58          return null;
59      }
60  
61      public MBeanContainer(MBeanServer server)
62      {
63          this._server = server;
64      }
65      
66      public MBeanServer getMBeanServer()
67      {
68          return _server;
69      }
70      
71      public void setDomain (String domain)
72      {
73          _domain =domain;
74      }
75      
76      public String getDomain()
77      {
78          return _domain;
79      }
80      
81      public void doStart()
82      {
83      }
84  
85      public synchronized void add(Relationship relationship)
86      {   
87          ObjectName parent=(ObjectName)_beans.get(relationship.getParent());
88          if (parent==null)
89          {
90              addBean(relationship.getParent());
91              parent=(ObjectName)_beans.get(relationship.getParent());
92          }
93          
94          ObjectName child=(ObjectName)_beans.get(relationship.getChild());
95          if (child==null)
96          {
97              addBean(relationship.getChild());
98              child=(ObjectName)_beans.get(relationship.getChild());
99          }
100         
101         if (parent!=null && child!=null)
102             _relations.add(parent,relationship);
103         
104         
105     }
106 
107     public synchronized void remove(Relationship relationship)
108     {
109         ObjectName parent=(ObjectName)_beans.get(relationship.getParent());
110         ObjectName child=(ObjectName)_beans.get(relationship.getChild());
111         if (parent!=null && child!=null)
112             _relations.removeValue(parent,relationship);
113     }
114 
115     public synchronized void removeBean(Object obj)
116     {
117         ObjectName bean=(ObjectName)_beans.remove(obj);
118 
119         if (bean!=null)
120         {
121             List r=_relations.getValues(bean);
122             if (r!=null && r.size()>0)
123             {
124                 Log.debug("Unregister {}", r);
125                 Iterator iter = new ArrayList(r).iterator();
126                 while (iter.hasNext())
127                 {
128                     Relationship rel = (Relationship)iter.next();
129                     rel.getContainer().update(rel.getParent(),rel.getChild(),null,rel.getRelationship(),true);
130                 }
131             }
132             
133             try
134             {
135                 _server.unregisterMBean(bean);
136                 Log.debug("Unregistered {}", bean);
137             }
138             catch (javax.management.InstanceNotFoundException e)
139             {
140                 Log.ignore(e);
141             }
142             catch (Exception e)
143             {
144                 Log.warn(e);
145             }
146         }
147     }
148     
149     public synchronized void addBean(Object obj)
150     {
151         try
152         {
153             if (obj == null || _beans.containsKey(obj))
154                 return;
155             
156             Object mbean = ObjectMBean.mbeanFor(obj);
157             if (mbean == null)
158                 return;
159 
160             ObjectName oname = null;
161             if (mbean instanceof ObjectMBean)
162             {
163                 ((ObjectMBean) mbean).setMBeanContainer(this);
164                 oname = ((ObjectMBean)mbean).getObjectName();
165             }
166             
167             //no override mbean object name, so make a generic one
168             if (oname == null)
169             {
170                 String type=obj.getClass().getName().toLowerCase();
171                 int dot = type.lastIndexOf('.');
172                 if (dot >= 0)
173                     type = type.substring(dot + 1);
174                 
175                 String name=null;
176                 if (mbean instanceof ObjectMBean)
177                 {
178                     name = ((ObjectMBean)mbean).getObjectNameBasis();
179                     if (name!=null)
180                     {
181                         name=name.replace('\\','/');
182                         if (name.endsWith("/"))
183                             name=name.substring(0,name.length()-1);
184 
185                         int slash=name.lastIndexOf('/',name.length()-1);
186                         if (slash>0)
187                             name=name.substring(slash+1);
188                         dot=name.lastIndexOf('.');
189                         if (dot>0)
190                             name=name.substring(0,dot);
191 
192                         name=name.replace(':','_').replace('*','_').replace('?','_').replace('=','_').replace(',','_').replace(' ','_');
193                     }
194                 }
195                 
196                 String basis=(name!=null&&name.length()>1)?("type="+type+",name="+name):("type="+type);
197                 
198                 Integer count = (Integer) _unique.get(basis);
199                 count = TypeUtil.newInteger(count == null ? 0 : (1 + count.intValue()));
200                 _unique.put(basis, count);
201 
202                 //if no explicit domain, create one
203                 String domain = _domain;
204                 if (domain==null)
205                     domain = obj.getClass().getPackage().getName();
206 
207                 oname = ObjectName.getInstance(domain+":"+basis+",id="+count);
208             }
209             
210             ObjectInstance oinstance = _server.registerMBean(mbean, oname);
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     public void doStop()
222     {
223         while (_beans.size()>0)
224             removeBean(_beans.keySet().iterator().next());
225     }
226     
227     private class ShutdownHook extends Thread
228     {
229         private final ObjectName mletName;
230         private final ObjectName adaptorName;
231         private final ObjectName processorName;
232 
233         public ShutdownHook(ObjectName mletName, ObjectName adaptorName, ObjectName processorName)
234         {
235             this.mletName = mletName;
236             this.adaptorName = adaptorName;
237             this.processorName = processorName;
238         }
239 
240         public void run()
241         {
242             halt();
243             unregister(processorName);
244             unregister(adaptorName);
245             unregister(mletName);
246         }
247 
248         private void halt()
249         {
250             try
251             {
252                 _server.invoke(adaptorName, "stop", null, null);
253             }
254             catch (Exception e)
255             {
256                 Log.warn(e);
257             }
258         }
259 
260         private void unregister(ObjectName objectName)
261         {
262             try
263             {
264                 _server.unregisterMBean(objectName);
265                 Log.debug("Unregistered " + objectName);
266             }
267             catch (Exception e)
268             {
269                 Log.warn(e);
270             }
271         }
272     }
273     
274 }