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 }