Source for gnu.javax.management.Server

   1: /* Server.java -- A GNU Classpath management server.
   2:    Copyright (C) 2006 Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: package gnu.javax.management;
  39: 
  40: import java.io.ByteArrayInputStream;
  41: import java.io.InputStream;
  42: import java.io.IOException;
  43: import java.io.ObjectInputStream;
  44: import java.io.ObjectStreamClass;
  45: import java.io.StreamCorruptedException;
  46: 
  47: import java.lang.reflect.Constructor;
  48: import java.lang.reflect.InvocationTargetException;
  49: import java.lang.reflect.Method;
  50: 
  51: import java.util.HashMap;
  52: import java.util.HashSet;
  53: import java.util.Iterator;
  54: import java.util.Map;
  55: import java.util.Set;
  56: import java.util.concurrent.atomic.AtomicLong;
  57: 
  58: import javax.management.Attribute;
  59: import javax.management.AttributeList;
  60: import javax.management.AttributeNotFoundException;
  61: import javax.management.BadAttributeValueExpException;
  62: import javax.management.BadBinaryOpValueExpException;
  63: import javax.management.BadStringOperationException;
  64: import javax.management.DynamicMBean;
  65: import javax.management.InstanceAlreadyExistsException;
  66: import javax.management.InstanceNotFoundException;
  67: import javax.management.IntrospectionException;
  68: import javax.management.InvalidApplicationException;
  69: import javax.management.InvalidAttributeValueException;
  70: import javax.management.ListenerNotFoundException;
  71: import javax.management.MalformedObjectNameException;
  72: import javax.management.MBeanException;
  73: import javax.management.MBeanInfo;
  74: import javax.management.MBeanPermission;
  75: import javax.management.MBeanRegistration;
  76: import javax.management.MBeanRegistrationException;
  77: import javax.management.MBeanServer;
  78: import javax.management.MBeanServerDelegate;
  79: import javax.management.MBeanServerNotification;
  80: import javax.management.MBeanTrustPermission;
  81: import javax.management.NotCompliantMBeanException;
  82: import javax.management.Notification;
  83: import javax.management.NotificationBroadcaster;
  84: import javax.management.NotificationEmitter;
  85: import javax.management.NotificationFilter;
  86: import javax.management.NotificationListener;
  87: import javax.management.ObjectInstance;
  88: import javax.management.ObjectName;
  89: import javax.management.OperationsException;
  90: import javax.management.QueryExp;
  91: import javax.management.ReflectionException;
  92: import javax.management.RuntimeOperationsException;
  93: import javax.management.StandardMBean;
  94: 
  95: import javax.management.loading.ClassLoaderRepository;
  96: 
  97: /**
  98:  * This class provides an {@link javax.management.MBeanServer}
  99:  * implementation for GNU Classpath.
 100:  *
 101:  * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
 102:  * @since 1.5
 103:  */
 104: public class Server
 105:   implements MBeanServer
 106: {
 107: 
 108:   /**
 109:    * The name of the delegate bean.
 110:    */
 111:   private static final ObjectName DELEGATE_NAME;
 112: 
 113:   /**
 114:    * The registered beans, represented as a map of
 115:    * {@link javax.management.ObjectName}s to
 116:    * {@link java.lang.Object}s.
 117:    */
 118:   private final Map beans = new HashMap();
 119: 
 120:   /**
 121:    * The default domain.
 122:    */
 123:   private String defaultDomain;
 124: 
 125:   /**
 126:    * The outer server.
 127:    */
 128:   private MBeanServer outer;
 129: 
 130:   /**
 131:    * The class loader repository.
 132:    */
 133:   private ClassLoaderRepository repository;
 134: 
 135:   /**
 136:    * The map of listener delegates to the true
 137:    * listener.
 138:    */
 139:   private Map listeners;
 140: 
 141:   /**
 142:    * An MBean that emits notifications when an MBean is registered and
 143:    * unregistered with this server.
 144:    *
 145:    */
 146:   private final MBeanServerDelegate delegate;
 147: 
 148:   static private final AtomicLong sequenceNumber = new AtomicLong(1);
 149: 
 150:   /**
 151:    * Initialise the delegate name.
 152:    */
 153:   static
 154:   {
 155:     try
 156:       {
 157:     DELEGATE_NAME = 
 158:       new ObjectName("JMImplementation:type=MBeanServerDelegate");
 159:       }
 160:     catch (MalformedObjectNameException e)
 161:       {
 162:     throw (Error) 
 163:       (new InternalError("Failed to construct " +
 164:                  "the delegate's object name.").initCause(e));
 165:       }
 166:   }
 167: 
 168:   /**
 169:    * Constructs a new management server using the specified
 170:    * default domain, delegate bean and outer server.
 171:    *
 172:    * @param domain the default domain to use for beans constructed
 173:    *               with no specified domain.
 174:    * @param outer an {@link javax.management.MBeanServer} to pass
 175:    *              to beans implementing the {@link MBeanRegistration}
 176:    *              interface, or <code>null</code> if <code>this</code>
 177:    *              should be passed.
 178:    * @param delegate the delegate bean for this server.
 179:    */
 180:   public Server(String defaultDomain, MBeanServer outer,
 181:         MBeanServerDelegate delegate)
 182:   {
 183:     this.defaultDomain = defaultDomain;
 184:     this.outer = outer;
 185:     this.delegate = delegate;
 186:     try
 187:       {
 188:     registerMBean(delegate, DELEGATE_NAME);
 189:       }
 190:     catch (InstanceAlreadyExistsException e)
 191:       {
 192:     throw (Error) 
 193:       (new InternalError("The delegate bean is " +
 194:                  "already registered.").initCause(e));
 195:       }
 196:     catch (MBeanRegistrationException e)
 197:       {
 198:     throw (Error) 
 199:       (new InternalError("The delegate bean's preRegister " +
 200:                  "methods threw an exception.").initCause(e));
 201:       }
 202:     catch (NotCompliantMBeanException e)
 203:       {
 204:     throw (Error) 
 205:       (new InternalError("The delegate bean is " +
 206:                  "not compliant.").initCause(e));
 207:       }
 208:   }
 209: 
 210:   /**
 211:    * Checks for the necessary security privileges to perform an
 212:    * operation.
 213:    *
 214:    * @param name the name of the bean being accessed.
 215:    * @param member the name of the operation or attribute being
 216:    *               accessed, or <code>null</code> if one is not
 217:    *               involved.
 218:    * @param action the action being performed.
 219:    * @throws SecurityException if the action is denied.
 220:    */
 221:   private void checkSecurity(ObjectName name, String member,
 222:                  String action)
 223:   {
 224:     SecurityManager sm = System.getSecurityManager();
 225:     if (sm != null)
 226:       try
 227:     {
 228:       MBeanInfo info = null;
 229:       if (name != null)
 230:         {
 231:           Object bean = getBean(name);
 232:           Method method = bean.getClass().getMethod("getMBeanInfo", null);
 233:           info = (MBeanInfo) method.invoke(bean, null);
 234:         }
 235:       sm.checkPermission(new MBeanPermission((info == null) ? 
 236:                          null : info.getClassName(),
 237:                          member, name, action));
 238:     }
 239:       catch (InstanceNotFoundException e)
 240:     {
 241:       throw (Error) 
 242:         (new InternalError("Failed to get bean.").initCause(e));
 243:     }
 244:       catch (NoSuchMethodException e)
 245:     {
 246:       throw (Error) 
 247:         (new InternalError("Failed to get bean info.").initCause(e));
 248:     }
 249:       catch (IllegalAccessException e)
 250:     {
 251:       throw (Error) 
 252:         (new InternalError("Failed to get bean info.").initCause(e));
 253:     }
 254:       catch (IllegalArgumentException e)
 255:     {
 256:       throw (Error) 
 257:         (new InternalError("Failed to get bean info.").initCause(e));
 258:     }
 259:       catch (InvocationTargetException e)
 260:     {
 261:       throw (Error) 
 262:         (new InternalError("Failed to get bean info.").initCause(e));
 263:     }
 264:   }
 265: 
 266:   /**
 267:    * Retrieves the specified bean.
 268:    *
 269:    * @param name the name of the bean.
 270:    * @return the bean.
 271:    * @throws InstanceNotFoundException if the name of the management bean
 272:    *                                   could not be resolved.
 273:    */
 274:   private Object getBean(ObjectName name)
 275:     throws InstanceNotFoundException
 276:   {
 277:     ServerInfo bean = (ServerInfo) beans.get(name);
 278:     if (bean == null)
 279:       throw new InstanceNotFoundException("The bean, " + name +
 280:                       ", was not found.");
 281:     return bean.getObject();
 282:   }
 283: 
 284:   /**
 285:    * Registers the supplied listener with the specified management
 286:    * bean.  Notifications emitted by the management bean are forwarded
 287:    * to the listener via the server, which will convert an MBean
 288:    * references in the source to a portable {@link ObjectName}
 289:    * instance.  The notification is otherwise unchanged.
 290:    *
 291:    * @param name the name of the management bean with which the listener
 292:    *             should be registered.
 293:    * @param listener the listener which will handle notifications from
 294:    *                 the bean.
 295:    * @param filter the filter to apply to incoming notifications, or
 296:    *               <code>null</code> if no filtering should be applied.
 297:    * @param passback an object to be passed to the listener when a
 298:    *                 notification is emitted.
 299:    * @throws InstanceNotFoundException if the name of the management bean
 300:    *                                   could not be resolved.
 301:    * @throws SecurityException if a security manager exists and the
 302:    *                           caller's permissions don't imply {@link
 303:    *                           MBeanPermission(String,String,ObjectName,String)
 304:    *                           <code>MBeanPermission(className, null, name,
 305:    *                           "addNotificationListener")</code>}.
 306:    * @see #removeNotificationListener(ObjectName, NotificationListener)
 307:    * @see #removeNotificationListener(ObjectName, NotificationListener,
 308:    *                                  NotificationFilter, Object)
 309:    * @see NotificationBroadcaster#addNotificationListener(NotificationListener,
 310:    *                                                      NotificationFilter,
 311:    *                                                      Object)
 312:    */
 313:   public void addNotificationListener(ObjectName name, NotificationListener listener,
 314:                       NotificationFilter filter, Object passback)
 315:     throws InstanceNotFoundException
 316:   {
 317:     Object bean = getBean(name);
 318:     checkSecurity(name, null, "addNotificationListener");
 319:     if (bean instanceof NotificationBroadcaster)
 320:       {
 321:     NotificationBroadcaster bbean = (NotificationBroadcaster) bean;
 322:     if (listeners == null)
 323:       listeners = new HashMap();
 324:     NotificationListener indirection = new ServerNotificationListener(bean, name,
 325:                                       listener);
 326:     bbean.addNotificationListener(indirection, filter, passback);
 327:     listeners.put(listener, indirection);
 328:       }
 329:   }
 330: 
 331:   /**
 332:    * <p>
 333:    * Registers the supplied listener with the specified management
 334:    * bean.  Notifications emitted by the management bean are forwarded
 335:    * to the listener via the server, which will convert any MBean
 336:    * references in the source to portable {@link ObjectName}
 337:    * instances.  The notification is otherwise unchanged.  
 338:    * </p>
 339:    * <p>
 340:    * The listener that receives notifications will be the one that is
 341:    * registered with the given name at the time this method is called.
 342:    * Even if it later unregisters and ceases to use that name, it will
 343:    * still receive notifications.
 344:    * </p>
 345:    *
 346:    * @param name the name of the management bean with which the listener
 347:    *             should be registered.
 348:    * @param listener the name of the listener which will handle
 349:    *                 notifications from the bean.
 350:    * @param filter the filter to apply to incoming notifications, or
 351:    *               <code>null</code> if no filtering should be applied.
 352:    * @param passback an object to be passed to the listener when a
 353:    *                 notification is emitted.
 354:    * @throws InstanceNotFoundException if the name of the management bean
 355:    *                                   could not be resolved.
 356:    * @throws RuntimeOperationsException if the bean associated with the given
 357:    *                                    object name is not a
 358:    *                                    {@link NotificationListener}.  This
 359:    *                                    exception wraps an
 360:    *                                    {@link IllegalArgumentException}.
 361:    * @throws SecurityException if a security manager exists and the
 362:    *                           caller's permissions don't imply {@link
 363:    *                           MBeanPermission(String,String,ObjectName,String)
 364:    *                           <code>MBeanPermission(className, null, name,
 365:    *                           "addNotificationListener")</code>}.
 366:    * @see #removeNotificationListener(ObjectName, NotificationListener)
 367:    * @see #removeNotificationListener(ObjectName, NotificationListener,
 368:    *                                  NotificationFilter, Object)
 369:    * @see NotificationBroadcaster#addNotificationListener(NotificationListener,
 370:    *                                                      NotificationFilter,
 371:    *                                                      Object)
 372:    */
 373:   public void addNotificationListener(ObjectName name, ObjectName listener,
 374:                       NotificationFilter filter, Object passback)
 375:     throws InstanceNotFoundException
 376:   {
 377:     Object lbean = getBean(listener);
 378:     if (!(lbean instanceof NotificationListener))
 379:       {
 380:     RuntimeException e =
 381:       new IllegalArgumentException("The supplied listener name does not " +
 382:                        "correspond to a notification listener.");
 383:     throw new RuntimeOperationsException(e);
 384:       }
 385:     addNotificationListener(name, ((NotificationListener) lbean), filter, passback);
 386:   }
 387: 
 388:   /**
 389:    * <p>
 390:    * Instantiates a new instance of the specified management bean
 391:    * using the default constructor and registers it with the server
 392:    * under the supplied name.  The class is loaded using the
 393:    * {@link javax.management.loading.ClassLoaderRepository default
 394:    * loader repository} of the server. 
 395:    * </p>
 396:    * <p>
 397:    * If the name supplied is <code>null</code>, then the bean is
 398:    * expected to implement the {@link MBeanRegistration} interface.
 399:    * The {@link MBeanRegistration#preRegister preRegister} method
 400:    * of this interface will be used to obtain the name in this case.
 401:    * </p>
 402:    * <p>
 403:    * This method is equivalent to calling {@link 
 404:    * #createMBean(String, ObjectName, Object[], String[])
 405:    * <code>createMBean(className, name, (Object[]) null,
 406:    * (String[]) null)</code>} with <code>null</code> parameters
 407:    * and signature.
 408:    * </p>
 409:    *
 410:    * @param className the class of the management bean, of which
 411:    *                  an instance should be created.
 412:    * @param name the name to register the new bean with.
 413:    * @return an {@link ObjectInstance} containing the {@link ObjectName}
 414:    *         and Java class name of the created instance.
 415:    * @throws ReflectionException if an exception occurs in creating
 416:    *                             an instance of the bean.
 417:    * @throws InstanceAlreadyExistsException if a matching instance
 418:    *                                        already exists.
 419:    * @throws MBeanRegistrationException if an exception occurs in
 420:    *                                    calling the preRegister
 421:    *                                    method.
 422:    * @throws MBeanException if the bean's constructor throws an exception.
 423:    * @throws NotCompliantMBeanException if the created bean is not
 424:    *                                    compliant with the JMX specification.
 425:    * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
 426:    *                                    is thrown by the server due to a
 427:    *                                    <code>null</code> class name or object
 428:    *                                    name or if the object name is a pattern.
 429:    * @throws SecurityException if a security manager exists and the
 430:    *                           caller's permissions don't imply the
 431:    *                           use of the <code>instantiate</code>
 432:    *                           and <code>registerMBean</code> methods.
 433:    * @see #createMBean(String, ObjectName, Object[], String[])
 434:    */
 435:   public ObjectInstance createMBean(String className, ObjectName name)
 436:     throws ReflectionException, InstanceAlreadyExistsException,
 437:        MBeanRegistrationException, MBeanException,
 438:        NotCompliantMBeanException
 439:   {
 440:     return createMBean(className, name, (Object[]) null, (String[]) null);
 441:   }
 442:   
 443:   /**
 444:    * <p>
 445:    * Instantiates a new instance of the specified management bean
 446:    * using the given constructor and registers it with the server
 447:    * under the supplied name.  The class is loaded using the
 448:    * {@link javax.management.loading.ClassLoaderRepository default
 449:    * loader repository} of the server. 
 450:    * </p>
 451:    * <p>
 452:    * If the name supplied is <code>null</code>, then the bean is
 453:    * expected to implement the {@link MBeanRegistration} interface.
 454:    * The {@link MBeanRegistration#preRegister preRegister} method
 455:    * of this interface will be used to obtain the name in this case.
 456:    * </p>
 457:    * 
 458:    * @param className the class of the management bean, of which
 459:    *                  an instance should be created.
 460:    * @param name the name to register the new bean with.
 461:    * @param params the parameters for the bean's constructor.
 462:    * @param sig the signature of the constructor to use.
 463:    * @return an {@link ObjectInstance} containing the {@link ObjectName}
 464:    *         and Java class name of the created instance.
 465:    * @throws ReflectionException if an exception occurs in creating
 466:    *                             an instance of the bean.
 467:    * @throws InstanceAlreadyExistsException if a matching instance
 468:    *                                        already exists.
 469:    * @throws MBeanRegistrationException if an exception occurs in
 470:    *                                    calling the preRegister
 471:    *                                    method.
 472:    * @throws MBeanException if the bean's constructor throws an exception.
 473:    * @throws NotCompliantMBeanException if the created bean is not
 474:    *                                    compliant with the JMX specification.
 475:    * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
 476:    *                                    is thrown by the server due to a
 477:    *                                    <code>null</code> class name or object
 478:    *                                    name or if the object name is a pattern.
 479:    * @throws SecurityException if a security manager exists and the
 480:    *                           caller's permissions don't imply the
 481:    *                           use of the <code>instantiate</code>
 482:    *                           and <code>registerMBean</code> methods.
 483:    */
 484:   public ObjectInstance createMBean(String className, ObjectName name,
 485:                     Object[] params, String[] sig)
 486:     throws ReflectionException, InstanceAlreadyExistsException,
 487:        MBeanRegistrationException, MBeanException,
 488:        NotCompliantMBeanException
 489:   {
 490:     return registerMBean(instantiate(className, params, sig), name);
 491:   } 
 492: 
 493:   /**
 494:    * <p>
 495:    * Instantiates a new instance of the specified management bean
 496:    * using the default constructor and registers it with the server
 497:    * under the supplied name.  The class is loaded using the
 498:    * given class loader.  If this argument is <code>null</code>,
 499:    * then the same class loader as was used to load the server
 500:    * is used.
 501:    * </p>
 502:    * <p>
 503:    * If the name supplied is <code>null</code>, then the bean is
 504:    * expected to implement the {@link MBeanRegistration} interface.
 505:    * The {@link MBeanRegistration#preRegister preRegister} method
 506:    * of this interface will be used to obtain the name in this case.
 507:    * </p>
 508:    * <p>
 509:    * This method is equivalent to calling {@link 
 510:    * #createMBean(String, ObjectName, ObjectName, Object[], String)
 511:    * <code>createMBean(className, name, loaderName, (Object[]) null,
 512:    * (String) null)</code>} with <code>null</code> parameters
 513:    * and signature.
 514:    * </p>
 515:    *
 516:    * @param className the class of the management bean, of which
 517:    *                  an instance should be created.
 518:    * @param name the name to register the new bean with.
 519:    * @param loaderName the name of the class loader.
 520:    * @return an {@link ObjectInstance} containing the {@link ObjectName}
 521:    *         and Java class name of the created instance.
 522:    * @throws ReflectionException if an exception occurs in creating
 523:    *                             an instance of the bean.
 524:    * @throws InstanceAlreadyExistsException if a matching instance
 525:    *                                        already exists.
 526:    * @throws MBeanRegistrationException if an exception occurs in
 527:    *                                    calling the preRegister
 528:    *                                    method.
 529:    * @throws MBeanException if the bean's constructor throws an exception.
 530:    * @throws NotCompliantMBeanException if the created bean is not
 531:    *                                    compliant with the JMX specification.
 532:    * @throws InstanceNotFoundException if the specified class loader is not
 533:    *                                   registered with the server.
 534:    * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
 535:    *                                    is thrown by the server due to a
 536:    *                                    <code>null</code> class name or object
 537:    *                                    name or if the object name is a pattern.
 538:    * @throws SecurityException if a security manager exists and the
 539:    *                           caller's permissions don't imply the
 540:    *                           use of the <code>instantiate</code>
 541:    *                           and <code>registerMBean</code> methods.
 542:    * @see #createMBean(String, ObjectName, ObjectName, Object[], String[])
 543:    */
 544:   public ObjectInstance createMBean(String className, ObjectName name, 
 545:                     ObjectName loaderName)
 546:     throws ReflectionException, InstanceAlreadyExistsException,
 547:        MBeanRegistrationException, MBeanException,
 548:        NotCompliantMBeanException, InstanceNotFoundException
 549:   {
 550:     return createMBean(className, name, loaderName, (Object[]) null,
 551:                (String[]) null);
 552:   }
 553: 
 554:   /**
 555:    * <p>
 556:    * Instantiates a new instance of the specified management bean
 557:    * using the given constructor and registers it with the server
 558:    * under the supplied name.  The class is loaded using the
 559:    * given class loader.  If this argument is <code>null</code>,
 560:    * then the same class loader as was used to load the server
 561:    * is used. 
 562:    * </p>
 563:    * <p>
 564:    * If the name supplied is <code>null</code>, then the bean is
 565:    * expected to implement the {@link MBeanRegistration} interface.
 566:    * The {@link MBeanRegistration#preRegister preRegister} method
 567:    * of this interface will be used to obtain the name in this case.
 568:    * </p>
 569:    * 
 570:    * @param className the class of the management bean, of which
 571:    *                  an instance should be created.
 572:    * @param name the name to register the new bean with.
 573:    * @param loaderName the name of the class loader.
 574:    * @param params the parameters for the bean's constructor.
 575:    * @param sig the signature of the constructor to use.
 576:    * @return an {@link ObjectInstance} containing the {@link ObjectName}
 577:    *         and Java class name of the created instance.
 578:    * @throws ReflectionException if an exception occurs in creating
 579:    *                             an instance of the bean.
 580:    * @throws InstanceAlreadyExistsException if a matching instance
 581:    *                                        already exists.
 582:    * @throws MBeanRegistrationException if an exception occurs in
 583:    *                                    calling the preRegister
 584:    *                                    method.
 585:    * @throws MBeanException if the bean's constructor throws an exception.
 586:    * @throws NotCompliantMBeanException if the created bean is not
 587:    *                                    compliant with the JMX specification.
 588:    * @throws InstanceNotFoundException if the specified class loader is not
 589:    *                                   registered with the server.
 590:    * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
 591:    *                                    is thrown by the server due to a
 592:    *                                    <code>null</code> class name or object
 593:    *                                    name or if the object name is a pattern.
 594:    * @throws SecurityException if a security manager exists and the
 595:    *                           caller's permissions don't imply the
 596:    *                           use of the <code>instantiate</code>
 597:    *                           and <code>registerMBean</code> methods.
 598:    */
 599:   public ObjectInstance createMBean(String className, ObjectName name,
 600:                     ObjectName loaderName, Object[] params,
 601:                     String[] sig)
 602:     throws ReflectionException, InstanceAlreadyExistsException,
 603:        MBeanRegistrationException, MBeanException,
 604:        NotCompliantMBeanException, InstanceNotFoundException
 605:   {
 606:     return registerMBean(instantiate(className, loaderName, params, sig),
 607:              name);
 608:   }
 609: 
 610:   /**
 611:    * Deserializes a byte array using the class loader of the specified
 612:    * management bean as its context.
 613:    *
 614:    * @param name the name of the bean whose class loader should be used.
 615:    * @param data the byte array to be deserialized.
 616:    * @return the deserialized object stream.
 617:    * @deprecated {@link #getClassLoaderFor(ObjectName)} should be used
 618:    *             to obtain the class loader of the bean, which can then
 619:    *             be used to perform deserialization in the user's code.
 620:    * @throws InstanceNotFoundException if the specified bean is not
 621:    *                                   registered with the server.
 622:    * @throws OperationsException if any I/O error is thrown by the
 623:    *                             deserialization process.
 624:    * @throws SecurityException if a security manager exists and the
 625:    *                           caller's permissions don't imply {@link
 626:    *                           MBeanPermission(String,String,ObjectName,String)
 627:    *                           <code>MBeanPermission(className, null, name,
 628:    *                           "getClassLoaderFor")</code>
 629:    */
 630:   public ObjectInputStream deserialize(ObjectName name, byte[] data)
 631:     throws InstanceNotFoundException, OperationsException
 632:   {
 633:     try
 634:       {
 635:     return new ServerInputStream(new ByteArrayInputStream(data),
 636:                      getClassLoaderFor(name));
 637:       }
 638:     catch (IOException e)
 639:       {
 640:     throw new OperationsException("An I/O error occurred: " + e);
 641:       }
 642:   }
 643: 
 644:   /**
 645:    * Deserializes a byte array using the same class loader for its context
 646:    * as was used to load the given class.  This class loader is obtained by
 647:    * loading the specified class using the {@link
 648:    * javax.management.loading.ClassLoaderRepository Class Loader Repository}
 649:    * and then using the class loader of the resulting {@link Class} instance.
 650:    *
 651:    * @param name the name of the class which should be loaded to obtain the
 652:    *             class loader.
 653:    * @param data the byte array to be deserialized.
 654:    * @return the deserialized object stream.
 655:    * @deprecated {@link #getClassLoaderRepository} should be used
 656:    *             to obtain the class loading repository, which can then
 657:    *             be used to obtain the {@link Class} instance and deserialize
 658:    *             the array using its class loader.
 659:    * @throws OperationsException if any I/O error is thrown by the
 660:    *                             deserialization process.
 661:    * @throws ReflectionException if an error occurs in obtaining the
 662:    *                             {@link Class} instance.
 663:    * @throws SecurityException if a security manager exists and the
 664:    *                           caller's permissions don't imply {@link
 665:    *                           MBeanPermission(String,String,ObjectName,String)
 666:    *                           <code>MBeanPermission(null, null, null,
 667:    *                           "getClassLoaderRepository")</code>
 668:    */
 669:   public ObjectInputStream deserialize(String name, byte[] data)
 670:     throws OperationsException, ReflectionException
 671:   {
 672:     try
 673:       {
 674:     Class c = getClassLoaderRepository().loadClass(name);
 675:     return new ServerInputStream(new ByteArrayInputStream(data),
 676:                        c.getClassLoader());
 677:       }
 678:     catch (IOException e)
 679:       {
 680:     throw new OperationsException("An I/O error occurred: " + e);
 681:       }
 682:     catch (ClassNotFoundException e)
 683:       {
 684:     throw new ReflectionException(e, "The class could not be found.");
 685:       }
 686:   }
 687: 
 688:   /**
 689:    * Deserializes a byte array using the same class loader for its context
 690:    * as was used to load the given class.  The name of the class loader to
 691:    * be used is supplied, and may be <code>null</code> if the server's
 692:    * class loader should be used instead.
 693:    *
 694:    * @param name the name of the class which should be loaded to obtain the
 695:    *             class loader.
 696:    * @param loader the name of the class loader to use, or <code>null</code>
 697:    *               if the class loader of the server should be used.
 698:    * @param data the byte array to be deserialized.
 699:    * @return the deserialized object stream.
 700:    * @deprecated {@link #getClassLoader(ObjectName} can be used to obtain
 701:    *              the named class loader and deserialize the array.
 702:    * @throws InstanceNotFoundException if the specified class loader is not
 703:    *                                   registered with the server.
 704:    * @throws OperationsException if any I/O error is thrown by the
 705:    *                             deserialization process.
 706:    * @throws ReflectionException if an error occurs in obtaining the
 707:    *                             {@link Class} instance.
 708:    * @throws SecurityException if a security manager exists and the
 709:    *                           caller's permissions don't imply {@link
 710:    *                           MBeanPermission(String,String,ObjectName,String)
 711:    *                           <code>MBeanPermission(className, null, loader,
 712:    *                           "getClassLoader")</code>
 713:    */
 714:   public ObjectInputStream deserialize(String name, ObjectName loader, byte[] data)
 715:     throws InstanceNotFoundException, ReflectionException,
 716:        OperationsException
 717:   {
 718:     try
 719:       {
 720:     Class c = getClassLoader(loader).loadClass(name);
 721:     return new ServerInputStream(new ByteArrayInputStream(data),
 722:                        c.getClassLoader());
 723:       }
 724:     catch (IOException e)
 725:       {
 726:     throw new OperationsException("An I/O error occurred: " + e);
 727:       }
 728:     catch (ClassNotFoundException e)
 729:       {
 730:     throw new ReflectionException(e, "The class could not be found.");
 731:       }
 732:   }
 733: 
 734:   /**
 735:    * Returns the value of the supplied attribute from the specified
 736:    * management bean.
 737:    *
 738:    * @param bean the bean to retrieve the value from.
 739:    * @param name the name of the attribute to retrieve.
 740:    * @return the value of the attribute.
 741:    * @throws AttributeNotFoundException if the attribute could not be
 742:    *                                    accessed from the bean.
 743:    * @throws MBeanException if the management bean's accessor throws
 744:    *                        an exception.
 745:    * @throws InstanceNotFoundException if the bean can not be found.
 746:    * @throws ReflectionException if an exception was thrown in trying
 747:    *                             to invoke the bean's accessor.
 748:    * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
 749:    *                                    is thrown by the server due to a
 750:    *                                    <code>null</code> bean or attribute
 751:    *                                    name.
 752:    * @throws SecurityException if a security manager exists and the
 753:    *                           caller's permissions don't imply {@link
 754:    *                           MBeanPermission(String,String,ObjectName,String)
 755:    *                           <code>MBeanPermission(className, name, bean,
 756:    *                           "getAttribute")</code>}.
 757:    * @see DynamicMBean#getAttribute(String)
 758:    */
 759:   public Object getAttribute(ObjectName bean, String name)
 760:     throws MBeanException, AttributeNotFoundException,
 761:        InstanceNotFoundException, ReflectionException
 762:   {
 763:     if (bean == null || name == null)
 764:       {
 765:     RuntimeException e =
 766:       new IllegalArgumentException("One of the supplied arguments was null.");
 767:     throw new RuntimeOperationsException(e);
 768:       }
 769:     Object abean = getBean(bean);
 770:     checkSecurity(bean, name, "getAttribute");
 771:     if (abean instanceof DynamicMBean)
 772:       return ((DynamicMBean) abean).getAttribute(name);
 773:     else
 774:       try
 775:     {
 776:       return new StandardMBean(abean, null).getAttribute(name);
 777:     }
 778:       catch (NotCompliantMBeanException e)
 779:     {
 780:       throw (Error) 
 781:         (new InternalError("Failed to create dynamic bean.").initCause(e));
 782:     }
 783:   }
 784: 
 785: 
 786:   /**
 787:    * Returns the values of the named attributes from the specified
 788:    * management bean.
 789:    *
 790:    * @param bean the bean to retrieve the value from.
 791:    * @param names the names of the attributes to retrieve.
 792:    * @return the values of the attributes.
 793:    * @throws InstanceNotFoundException if the bean can not be found.
 794:    * @throws ReflectionException if an exception was thrown in trying
 795:    *                             to invoke the bean's accessor.
 796:    * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
 797:    *                                    is thrown by the server due to a
 798:    *                                    <code>null</code> bean or attribute
 799:    *                                    name.
 800:    * @throws SecurityException if a security manager exists and the
 801:    *                           caller's permissions don't imply {@link
 802:    *                           MBeanPermission(String,String,ObjectName,String)
 803:    *                           <code>MBeanPermission(className, null, bean,
 804:    *                           "getAttribute")</code>}.  Additionally,
 805:    *                           for an attribute name, <code>n</code>, the
 806:    *                           caller's permission must imply {@link
 807:    *                           MBeanPermission(String,String,ObjectName,String)
 808:    *                           <code>MBeanPermission(className, n, bean,
 809:    *                           "getAttribute")</code>} or that attribute will
 810:    *                           not be included.
 811:    *                           
 812:    * @see DynamicMBean#getAttributes(String[])
 813:    */
 814:   public AttributeList getAttributes(ObjectName bean, String[] names)
 815:     throws InstanceNotFoundException, ReflectionException
 816:   {
 817:     if (bean == null || names == null)
 818:       {
 819:     RuntimeException e =
 820:       new IllegalArgumentException("One of the supplied arguments was null.");
 821:     throw new RuntimeOperationsException(e);
 822:       }
 823:     Object abean = getBean(bean);
 824:     checkSecurity(bean, null, "getAttribute");
 825:     AttributeList list = new AttributeList(names.length);
 826:     for (int a = 0; a < names.length; ++a)
 827:       {
 828:     if (names[a] == null)
 829:       {
 830:         RuntimeException e =
 831:           new IllegalArgumentException("Argument " + a + " was null.");
 832:         throw new RuntimeOperationsException(e);
 833:       }
 834:     checkSecurity(bean, names[a], "getAttribute");
 835:     try
 836:       {
 837:         Object value;
 838:         if (abean instanceof DynamicMBean)
 839:           value = ((DynamicMBean) abean).getAttribute(names[a]);
 840:         else
 841:           try
 842:         {
 843:           value = new StandardMBean(abean, null).getAttribute(names[a]);
 844:         }
 845:           catch (NotCompliantMBeanException e)
 846:         {
 847:           throw (Error) 
 848:             (new InternalError("Failed to create dynamic bean.").initCause(e));
 849:         }
 850:         list.add(new Attribute(names[a], value));
 851:       }
 852:     catch (AttributeNotFoundException e)
 853:       {
 854:         /* Ignored */
 855:       }
 856:     catch (MBeanException e)
 857:       {
 858:         /* Ignored */
 859:       }
 860:       }
 861:     return list;
 862:   }
 863: 
 864: 
 865:   /**
 866:    * Returns the specified class loader.  If the specified value is
 867:    * <code>null</code>, then the class loader of the server will be
 868:    * returned.  If <code>l</code> is the requested class loader,
 869:    * and <code>r</code> is the actual class loader returned, then
 870:    * either <code>l</code> and <code>r</code> will be identical,
 871:    * or they will at least return the same class from
 872:    * {@link ClassLoader#loadClass(String)} for any given string.
 873:    * They may not be identical due to one or the other
 874:    * being wrapped in another class loader (e.g. for security).
 875:    *
 876:    * @param name the name of the class loader to return.
 877:    * @return the class loader.
 878:    * @throws InstanceNotFoundException if the class loader can not
 879:    *                                   be found.
 880:    * @throws SecurityException if a security manager exists and the
 881:    *                           caller's permissions don't imply {@link
 882:    *                           MBeanPermission(String,String,ObjectName,String)
 883:    *                           <code>MBeanPermission(className, null, name,
 884:    *                           "getClassLoader")</code>
 885:    */
 886:   public ClassLoader getClassLoader(ObjectName name)
 887:     throws InstanceNotFoundException
 888:   {
 889:     if (name == null)
 890:       {
 891:     checkSecurity(null, null, "getClassLoader");
 892:     return getClass().getClassLoader();
 893:       }
 894:     Object bean = getBean(name);
 895:     checkSecurity(name, null, "getClassLoader");
 896:     return (ClassLoader) bean;
 897:   }
 898:  
 899:   /**
 900:    * Returns the class loader of the specified management bean.  If
 901:    * <code>l</code> is the requested class loader, and <code>r</code>
 902:    * is the actual class loader returned, then either <code>l</code>
 903:    * and <code>r</code> will be identical, or they will at least
 904:    * return the same class from {@link ClassLoader#loadClass(String)}
 905:    * for any given string.  They may not be identical due to one or
 906:    * the other being wrapped in another class loader (e.g. for
 907:    * security).
 908:    *
 909:    * @param name the name of the bean whose class loader should be
 910:    *             returned.
 911:    * @return the class loader.
 912:    * @throws InstanceNotFoundException if the bean is not registered
 913:    *                                   with the server.
 914:    * @throws SecurityException if a security manager exists and the
 915:    *                           caller's permissions don't imply {@link
 916:    *                           MBeanPermission(String,String,ObjectName,String)
 917:    *                           <code>MBeanPermission(className, null, name,
 918:    *                           "getClassLoaderFor")</code>
 919:    */
 920:   public ClassLoader getClassLoaderFor(ObjectName name)
 921:     throws InstanceNotFoundException
 922:   {
 923:     Object bean = getBean(name);
 924:     checkSecurity(name, null, "getClassLoaderFor");
 925:     return bean.getClass().getClassLoader();
 926:   }    
 927: 
 928:   /**
 929:    * Returns the class loader repository used by this server.
 930:    *
 931:    * @return the class loader repository.
 932:    * @throws SecurityException if a security manager exists and the
 933:    *                           caller's permissions don't imply {@link
 934:    *                           MBeanPermission(String,String,ObjectName,String)
 935:    *                           <code>MBeanPermission(null, null, null,
 936:    *                           "getClassLoaderRepository")</code>
 937:    */
 938:   public ClassLoaderRepository getClassLoaderRepository()
 939:   {
 940:     return repository;
 941:   }
 942: 
 943:   /**
 944:    * Returns the default domain this server applies to beans that have
 945:    * no specified domain.
 946:    *
 947:    * @return the default domain.
 948:    */
 949:   public String getDefaultDomain()
 950:   {
 951:     return defaultDomain;
 952:   }
 953: 
 954: 
 955:   /**
 956:    * Returns an array containing all the domains used by beans registered
 957:    * with this server.  The ordering of the array is undefined.
 958:    *
 959:    * @return the list of domains.
 960:    * @throws SecurityException if a security manager exists and the
 961:    *                           caller's permissions don't imply {@link
 962:    *                           MBeanPermission(String,String,ObjectName,String)
 963:    *                           <code>MBeanPermission(null, null, name,
 964:    *                           "getDomains")</code>}.  Additionally,
 965:    *                           for an domain, <code>d</code>, the
 966:    *                           caller's permission must imply {@link
 967:    *                           MBeanPermission(String,String,ObjectName,String)
 968:    *                           <code>MBeanPermission(null, null,
 969:    *                           new ObjectName("d:x=x"), "getDomains")</code>}
 970:    *                           or that domain will not be included.  Note
 971:    *                           that "x=x" is an arbitrary key-value pair
 972:    *                           provided to satisfy the constructor.
 973:    * @see ObjectName#getDomain()
 974:    */
 975:   public String[] getDomains()
 976:   {
 977:     checkSecurity(null, null, "getDomains");
 978:     Set domains = new HashSet();
 979:     Iterator iterator = beans.keySet().iterator();
 980:     while (iterator.hasNext())
 981:       {
 982:     String d  = ((ObjectName) iterator.next()).getDomain();
 983:     try
 984:       {
 985:         checkSecurity(new ObjectName(d + ":x=x"), null, "getDomains");
 986:         domains.add(d);
 987:       }
 988:     catch (MalformedObjectNameException e)
 989:       {
 990:         /* Ignored */
 991:       }
 992:       }
 993:     return (String[]) domains.toArray(new String[domains.size()]);
 994:   }
 995: 
 996:   /**
 997:    * Returns the number of management beans registered with this server.
 998:    * This may be less than the real number if the caller's access is
 999:    * restricted.
1000:    *
1001:    * @return the number of registered beans.
1002:    */
1003:   public Integer getMBeanCount()
1004:   {
1005:     return Integer.valueOf(beans.size());
1006:   }
1007: 
1008:   /**
1009:    * Returns information on the given management bean.
1010:    *
1011:    * @param name the name of the management bean.
1012:    * @return an instance of {@link MBeanInfo} for the bean.
1013:    * @throws IntrospectionException if an exception occurs in examining
1014:    *                                the bean.
1015:    * @throws InstanceNotFoundException if the bean can not be found.
1016:    * @throws ReflectionException if an exception occurs when trying
1017:    *                             to invoke {@link DynamicMBean#getMBeanInfo()}
1018:    *                             on the bean.
1019:    * @throws SecurityException if a security manager exists and the
1020:    *                           caller's permissions don't imply {@link
1021:    *                           MBeanPermission(String,String,ObjectName,String)
1022:    *                           <code>MBeanPermission(className, null, name,
1023:    *                           "getMBeanInfo")</code>}.
1024:    * @see DynamicMBean#getMBeanInfo()
1025:    */
1026:   public MBeanInfo getMBeanInfo(ObjectName name)
1027:     throws InstanceNotFoundException, IntrospectionException,
1028:        ReflectionException
1029:   {
1030:     Object bean = getBean(name);
1031:     checkSecurity(name, null, "getMBeanInfo");
1032:     try
1033:       {
1034:     Method method = bean.getClass().getMethod("getMBeanInfo", null);
1035:     return (MBeanInfo) method.invoke(bean, null);
1036:       }
1037:     catch (NoSuchMethodException e)
1038:       {
1039:     throw new IntrospectionException("The getMBeanInfo method " + 
1040:                      "could not be found.");
1041:       }
1042:     catch (IllegalAccessException e)
1043:       {
1044:     throw new ReflectionException(e, "Failed to call getMBeanInfo");
1045:       }
1046:     catch (IllegalArgumentException e)
1047:       {
1048:     throw new ReflectionException(e, "Failed to call getMBeanInfo");
1049:       }
1050:     catch (InvocationTargetException e)
1051:       {
1052:     throw new ReflectionException(e, "The method threw an exception");
1053:       }
1054:   }
1055: 
1056:   /**
1057:    * Returns the {@link ObjectInstance} created for the specified
1058:    * management bean on registration.
1059:    *
1060:    * @param name the name of the bean.
1061:    * @return the corresponding {@link ObjectInstance} instance.
1062:    * @throws InstanceNotFoundException if the bean can not be found.
1063:    * @throws SecurityException if a security manager exists and the
1064:    *                           caller's permissions don't imply {@link
1065:    *                           MBeanPermission(String,String,ObjectName,String)
1066:    *                           <code>MBeanPermission(className, null, name,
1067:    *                           "getObjectInstance")</code>
1068:    * @see #createMBean(String, ObjectName)
1069:    */
1070:   public ObjectInstance getObjectInstance(ObjectName name)
1071:     throws InstanceNotFoundException
1072:   {
1073:     ServerInfo bean = (ServerInfo) beans.get(name);
1074:     if (bean == null)
1075:       throw new InstanceNotFoundException("The bean, " + name +
1076:                       ", was not found.");
1077:     return bean.getInstance();
1078:   }
1079: 
1080:   /**
1081:    * <p>
1082:    * Creates an instance of the specified class using the list of
1083:    * class loaders from the {@link
1084:    * javax.management.loading.ClassLoaderRepository Class Loader
1085:    * Repository}.  The class should have a public constructor
1086:    * with no arguments.  A reference to the new instance is returned,
1087:    * but the instance is not yet registered with the server.
1088:    * </p>
1089:    * <p>
1090:    * This method is equivalent to calling {@link 
1091:    * #instantiate(String, Object[], String[])
1092:    * <code>instantiate(name, (Object[]) null, (String[]) null)</code>}
1093:    * with <code>null</code> parameters and signature.
1094:    * </p>
1095:    *
1096:    * @param name the name of the class of bean to be instantiated.
1097:    * @return an instance of the given class.
1098:    * @throws ReflectionException if an exception is thrown during
1099:    *                             loading the class or calling the
1100:    *                             constructor.
1101:    * @throws MBeanException if the constructor throws an exception.
1102:    * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
1103:    *                                    is thrown by the server due to a
1104:    *                                    <code>null</code> name.
1105:    * @throws SecurityException if a security manager exists and the
1106:    *                           caller's permissions don't imply {@link
1107:    *                           MBeanPermission(String,String,ObjectName,String)
1108:    *                           <code>MBeanPermission(className, null, null,
1109:    *                           "instantiate")</code>}.
1110:    * @see #instantiate(String, Object[], String[])
1111:    */
1112:   public Object instantiate(String name)
1113:     throws ReflectionException, MBeanException
1114:   {
1115:     return instantiate(name, (Object[]) null, (String[]) null);
1116:   }
1117: 
1118:   /**
1119:    * Creates an instance of the specified class using the list of
1120:    * class loaders from the {@link
1121:    * javax.management.loading.ClassLoaderRepository Class Loader
1122:    * Repository}.  The class should have a public constructor
1123:    * matching the supplied signature.  A reference to the new
1124:    * instance is returned, but the instance is not yet
1125:    * registered with the server.
1126:    *
1127:    * @param name the name of the class of bean to be instantiated.
1128:    * @param params the parameters for the constructor.
1129:    * @param sig the signature of the constructor.
1130:    * @return an instance of the given class.
1131:    * @throws ReflectionException if an exception is thrown during
1132:    *                             loading the class or calling the
1133:    *                             constructor.
1134:    * @throws MBeanException if the constructor throws an exception.
1135:    * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
1136:    *                                    is thrown by the server due to a
1137:    *                                    <code>null</code> name.
1138:    * @throws SecurityException if a security manager exists and the
1139:    *                           caller's permissions don't imply {@link
1140:    *                           MBeanPermission(String,String,ObjectName,String)
1141:    *                           <code>MBeanPermission(className, null, null,
1142:    *                           "instantiate")</code>}.
1143:    */
1144:   public Object instantiate(String name, Object[] params, String[] sig)
1145:     throws ReflectionException, MBeanException
1146:   {
1147:     checkSecurity(null, null, "instantiate");
1148:     if (name == null)
1149:       {
1150:     RuntimeException e = 
1151:       new IllegalArgumentException("The name was null.");
1152:     throw new RuntimeOperationsException(e);
1153:       }
1154:     Class[] sigTypes = new Class[sig.length];
1155:     for (int a = 0; a < sigTypes.length; ++a)
1156:       {
1157:     try 
1158:       {
1159:         sigTypes[a] = repository.loadClass(sig[a]);
1160:       }
1161:     catch (ClassNotFoundException e)
1162:       {
1163:         throw new ReflectionException(e, "The class, " + sigTypes[a] + 
1164:                       ", in the method signature " +
1165:                       "could not be loaded.");
1166:       }
1167:       }
1168:     try
1169:       {
1170:     Constructor cons =
1171:       repository.loadClass(name).getConstructor(sigTypes);
1172:     return cons.newInstance(params);
1173:       }
1174:     catch (ClassNotFoundException e)
1175:       {
1176:     throw new ReflectionException(e, "The class, " + name + 
1177:                       ", of the constructor " +
1178:                       "could not be loaded.");
1179:       }
1180:     catch (NoSuchMethodException e)
1181:       {
1182:     throw new ReflectionException(e, "The method, " + name +
1183:                       ", could not be found.");
1184:       }
1185:     catch (IllegalAccessException e)
1186:       {
1187:     throw new ReflectionException(e, "Failed to instantiate the object");
1188:       }
1189:     catch (InstantiationException e)
1190:       {
1191:     throw new ReflectionException(e, "Failed to instantiate the object");
1192:       }
1193:     catch (InvocationTargetException e)
1194:       {
1195:     throw new MBeanException((Exception) e.getCause(), "The constructor "
1196:                  + name + " threw an exception");
1197:       }
1198:   }
1199: 
1200:   /**
1201:    * <p>
1202:    * Creates an instance of the specified class using the supplied
1203:    * class loader.  If the class loader given is <code>null</code>,
1204:    * then the class loader of the server will be used.  The class
1205:    * should have a public constructor with no arguments.  A reference
1206:    * to the new instance is returned, but the instance is not yet
1207:    * registered with the server.
1208:    * </p>
1209:    * <p>
1210:    * This method is equivalent to calling {@link 
1211:    * #instantiate(String, ObjectName, Object[], String[])
1212:    * <code>instantiate(name, loaderName, (Object[]) null,
1213:    * (String[]) null)</code>} with <code>null</code> parameters
1214:    * and signature.
1215:    * </p>
1216:    *
1217:    * @param name the name of the class of bean to be instantiated.
1218:    * @param loaderName the name of the class loader to use.
1219:    * @return an instance of the given class.
1220:    * @throws InstanceNotFoundException if the class loader is not
1221:    *                                   registered with the server.
1222:    * @throws ReflectionException if an exception is thrown during
1223:    *                             loading the class or calling the
1224:    *                             constructor.
1225:    * @throws MBeanException if the constructor throws an exception.
1226:    * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
1227:    *                                    is thrown by the server due to a
1228:    *                                    <code>null</code> name.
1229:    * @throws SecurityException if a security manager exists and the
1230:    *                           caller's permissions don't imply {@link
1231:    *                           MBeanPermission(String,String,ObjectName,String)
1232:    *                           <code>MBeanPermission(className, null, null,
1233:    *                           "instantiate")</code>}.
1234:    * @see #instantiate(String, Object[], String[])
1235:    */
1236:   public Object instantiate(String name, ObjectName loaderName)
1237:     throws InstanceNotFoundException, ReflectionException,
1238:        MBeanException
1239:   {
1240:     return instantiate(name, loaderName);
1241:   }
1242: 
1243:   /**
1244:    * Creates an instance of the specified class using the supplied
1245:    * class loader.  If the class loader given is <code>null</code>,
1246:    * then the class loader of the server will be used.  The class
1247:    * should have a public constructor matching the supplied
1248:    * signature.  A reference to the new instance is returned,
1249:    * but the instance is not yet registered with the server.
1250:    *
1251:    * @param name the name of the class of bean to be instantiated.
1252:    * @param loaderName the name of the class loader to use.
1253:    * @param params the parameters for the constructor.
1254:    * @param sig the signature of the constructor.
1255:    * @return an instance of the given class.
1256:    * @throws InstanceNotFoundException if the class loader is not
1257:    *                                   registered with the server.
1258:    * @throws ReflectionException if an exception is thrown during
1259:    *                             loading the class or calling the
1260:    *                             constructor.
1261:    * @throws MBeanException if the constructor throws an exception.
1262:    * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
1263:    *                                    is thrown by the server due to a
1264:    *                                    <code>null</code> name.
1265:    * @throws SecurityException if a security manager exists and the
1266:    *                           caller's permissions don't imply {@link
1267:    *                           MBeanPermission(String,String,ObjectName,String)
1268:    *                           <code>MBeanPermission(className, null, null,
1269:    *                           "instantiate")</code>}.
1270:    */
1271:   public Object instantiate(String name, ObjectName loaderName,
1272:                 Object[] params, String[] sig)
1273:     throws InstanceNotFoundException, ReflectionException,
1274:        MBeanException
1275:   {
1276:     checkSecurity(null, null, "instantiate");
1277:     if (name == null)
1278:       {
1279:     RuntimeException e = 
1280:       new IllegalArgumentException("The name was null.");
1281:     throw new RuntimeOperationsException(e);
1282:       }
1283:     ClassLoader loader = getClassLoader(loaderName);
1284:     Class[] sigTypes = new Class[sig.length];
1285:     for (int a = 0; a < sig.length; ++a)
1286:       {
1287:     try 
1288:       {
1289:         sigTypes[a] = Class.forName(sig[a], true, loader);
1290:       }
1291:     catch (ClassNotFoundException e)
1292:       {
1293:         throw new ReflectionException(e, "The class, " + sig[a] + 
1294:                       ", in the method signature " +
1295:                       "could not be loaded.");
1296:       }
1297:       }
1298:     try
1299:       {
1300:     Constructor cons =
1301:       Class.forName(name, true, loader).getConstructor(sigTypes);
1302:     return cons.newInstance(params);
1303:       }
1304:     catch (ClassNotFoundException e)
1305:       {
1306:     throw new ReflectionException(e, "The class, " + name + 
1307:                       ", of the constructor " +
1308:                       "could not be loaded.");
1309:       }
1310:     catch (NoSuchMethodException e)
1311:       {
1312:     throw new ReflectionException(e, "The method, " + name +
1313:                       ", could not be found.");
1314:       }
1315:     catch (IllegalAccessException e)
1316:       {
1317:     throw new ReflectionException(e, "Failed to instantiate the object");
1318:       }
1319:     catch (InstantiationException e)
1320:       {
1321:     throw new ReflectionException(e, "Failed to instantiate the object");
1322:       }
1323:     catch (InvocationTargetException e)
1324:       {
1325:     throw new MBeanException((Exception) e.getCause(), "The constructor "
1326:                  + name + " threw an exception");
1327:       }
1328:   }
1329: 
1330:   /**
1331:    * Invokes the supplied operation on the specified management
1332:    * bean.  The class objects specified in the signature are loaded
1333:    * using the same class loader as was used for the management bean.
1334:    *
1335:    * @param bean the management bean whose operation should be invoked.
1336:    * @param name the name of the operation to invoke.
1337:    * @param params the parameters of the operation.
1338:    * @param sig the signature of the operation.
1339:    * @return the return value of the method.
1340:    * @throws InstanceNotFoundException if the bean can not be found.
1341:    * @throws MBeanException if the method invoked throws an exception.
1342:    * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
1343:    *                                    is thrown by the server due to a
1344:    *                                    <code>null</code> name.
1345:    * @throws ReflectionException if an exception is thrown in invoking the
1346:    *                             method.
1347:    * @throws SecurityException if a security manager exists and the
1348:    *                           caller's permissions don't imply {@link
1349:    *                           MBeanPermission(String,String,ObjectName,String)
1350:    *                           <code>MBeanPermission(className, name, bean,
1351:    *                           "invoke")</code>}.
1352:    * @see DynamicMBean#invoke(String, Object[], String[])
1353:    */
1354:   public Object invoke(ObjectName bean, String name, Object[] params, String[] sig)
1355:     throws InstanceNotFoundException, MBeanException,
1356:        ReflectionException
1357:   {
1358:     if (bean == null)
1359:       {
1360:     RuntimeException e =
1361:       new IllegalArgumentException("The bean was null.");
1362:     throw new RuntimeOperationsException(e);
1363:       }
1364:     Object abean = getBean(bean);
1365:     checkSecurity(bean, name, "invoke");
1366:     if (abean instanceof DynamicMBean)
1367:       return ((DynamicMBean) abean).invoke(name, params, sig);
1368:     else
1369:       try
1370:     {
1371:       return new StandardMBean(abean, null).invoke(name, params, sig);
1372:     }
1373:       catch (NotCompliantMBeanException e)
1374:     {
1375:       throw (Error) 
1376:         (new InternalError("Failed to create dynamic bean.").initCause(e));
1377:     }
1378:   }
1379: 
1380:   /**
1381:    * <p>
1382:    * Returns true if the specified management bean is an instance
1383:    * of the supplied class.
1384:    * </p>
1385:    * <p>
1386:    * A bean, B, is an instance of a class, C, if either of the following
1387:    * conditions holds:
1388:    * </p>
1389:    * <ul>
1390:    * <li>The class name in B's {@link MBeanInfo} is equal to the supplied
1391:    * name.</li>
1392:    * <li>Both the class of B and C were loaded by the same class loader,
1393:    * and B is assignable to C.</li>
1394:    * </ul>
1395:    * 
1396:    * @param name the name of the management bean.
1397:    * @param className the name of the class to test if <code>name</code> is
1398:    *                  an instance of.
1399:    * @return true if either B is directly an instance of the named class,
1400:    *         or B is assignable to the class, given that both it and B's
1401:    *         current class were loaded using the same class loader.
1402:    * @throws InstanceNotFoundException if the bean can not be found.
1403:    * @throws SecurityException if a security manager exists and the
1404:    *                           caller's permissions don't imply {@link
1405:    *                           MBeanPermission(String,String,ObjectName,String)
1406:    *                           <code>MBeanPermission(className, null, name,
1407:    *                           "isInstanceOf")</code>
1408:    */
1409:   public boolean isInstanceOf(ObjectName name, String className)
1410:     throws InstanceNotFoundException
1411:   {
1412:     Object bean = getBean(name);
1413:     checkSecurity(name, null, "isInstanceOf");
1414:     MBeanInfo info;
1415:     if (bean instanceof DynamicMBean)
1416:       info = ((DynamicMBean) bean).getMBeanInfo();
1417:     else
1418:       try
1419:     {
1420:       info = new StandardMBean(bean, null).getMBeanInfo();
1421:     }
1422:       catch (NotCompliantMBeanException e)
1423:     {
1424:       throw (Error) 
1425:         (new InternalError("Failed to create dynamic bean.").initCause(e));
1426:     }
1427:     if (info.getClassName().equals(className))
1428:       return true;
1429:     Class bclass = bean.getClass();
1430:     try
1431:       {
1432:     Class oclass = Class.forName(className);
1433:     return (bclass.getClassLoader().equals(oclass.getClassLoader()) &&
1434:         oclass.isAssignableFrom(bclass));  
1435:       }
1436:     catch (ClassNotFoundException e)
1437:       {
1438:     return false;
1439:       }
1440:   }
1441: 
1442:   /**
1443:    * Returns true if the specified management bean is registered with
1444:    * the server.
1445:    *
1446:    * @param name the name of the management bean.
1447:    * @return true if the bean is registered.
1448:    * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
1449:    *                                    is thrown by the server due to a
1450:    *                                    <code>null</code> bean name.
1451:    */
1452:   public boolean isRegistered(ObjectName name)
1453:   {
1454:     if (name == null)
1455:       {
1456:     RuntimeException e =
1457:       new IllegalArgumentException("The name was null.");
1458:     throw new RuntimeOperationsException(e);
1459:       }
1460:     return beans.containsKey(name);
1461:   }
1462: 
1463:   /**
1464:    * <p>
1465:    * Returns a set of {@link ObjectInstance}s matching the specified
1466:    * criteria.  The full set of beans registered with the server
1467:    * are passed through two filters:
1468:    * </p>
1469:    * <ol>
1470:    * <li>Pattern matching is performed using the supplied
1471:    * {@link ObjectName}.</li>
1472:    * <li>The supplied query expression is applied.</li>
1473:    * </ol>
1474:    * <p>
1475:    * If both the object name and the query expression are <code>null</code>,
1476:    * or the object name has no domain and no key properties,
1477:    * no filtering will be performed and all beans are returned. 
1478:    * </p>
1479:    *
1480:    * @param name an {@link ObjectName} to use as a filter.
1481:    * @param query a query expression to apply to each of the beans that match
1482:    *              the given object name.
1483:    * @return a set of {@link ObjectInstance}s matching the filtered beans.
1484:    * @throws SecurityException if a security manager exists and the
1485:    *                           caller's permissions don't imply {@link
1486:    *                           MBeanPermission(String,String,ObjectName,String)
1487:    *                           <code>MBeanPermission(null, null, name,
1488:    *                           "queryMBeans")</code>}.  Additionally,
1489:    *                           for an bean, <code>b</code>, the
1490:    *                           caller's permission must imply {@link
1491:    *                           MBeanPermission(String,String,ObjectName,String)
1492:    *                           <code>MBeanPermission(className, b, name,
1493:    *                           "queryMBeans")</code>} or that bean will
1494:    *                           not be included.  Such an exception may also
1495:    *                           arise from the execution of the query, in which
1496:    *                           case that particular bean will again be excluded.
1497:    */
1498:   public Set queryMBeans(ObjectName name, QueryExp query)
1499:   {
1500:     checkSecurity(name, null, "queryMBeans");
1501:     Set results = new HashSet();
1502:     Iterator iterator = beans.entrySet().iterator();
1503:     while (iterator.hasNext())
1504:       {
1505:     Map.Entry entry = (Map.Entry) iterator.next();
1506:     ObjectName nextName = (ObjectName) entry.getKey();
1507:     checkSecurity(name, nextName.toString(), "queryMBeans");
1508:     try
1509:       {
1510:         if ((name == null || name.apply(nextName)) &&
1511:         (query == null || query.apply(nextName)))
1512:           results.add(((ServerInfo) entry.getValue()).getInstance());
1513:       }
1514:     catch (BadStringOperationException e)
1515:       {
1516:         /* Ignored -- assume false result */
1517:       }
1518:     catch (BadBinaryOpValueExpException e)
1519:       {
1520:         /* Ignored -- assume false result */
1521:       }
1522:     catch (BadAttributeValueExpException e)
1523:       {
1524:         /* Ignored -- assume false result */
1525:       }
1526:     catch (InvalidApplicationException e)
1527:       {
1528:         /* Ignored -- assume false result */
1529:       }
1530:       }
1531:     return results;
1532:   }
1533:  
1534:   /**
1535:    * <p>
1536:    * Returns a set of {@link ObjectName}s matching the specified
1537:    * criteria.  The full set of beans registered with the server
1538:    * are passed through two filters:
1539:    * </p>
1540:    * <ol>
1541:    * <li>Pattern matching is performed using the supplied
1542:    * {@link ObjectName}.</li>
1543:    * <li>The supplied query expression is applied.</li>
1544:    * </ol>
1545:    * <p>
1546:    * If both the object name and the query expression are <code>null</code>,
1547:    * or the object name has no domain and no key properties,
1548:    * no filtering will be performed and all beans are returned. 
1549:    * </p>
1550:    *
1551:    * @param name an {@link ObjectName} to use as a filter.
1552:    * @param query a query expression to apply to each of the beans that match
1553:    *              the given object name.
1554:    * @return a set of {@link ObjectName}s matching the filtered beans.
1555:    * @throws SecurityException if a security manager exists and the
1556:    *                           caller's permissions don't imply {@link
1557:    *                           MBeanPermission(String,String,ObjectName,String)
1558:    *                           <code>MBeanPermission(null, null, name,
1559:    *                           "queryNames")</code>}.  Additionally,
1560:    *                           for an name, <code>n</code>, the
1561:    *                           caller's permission must imply {@link
1562:    *                           MBeanPermission(String,String,ObjectName,String)
1563:    *                           <code>MBeanPermission(className, n, name,
1564:    *                           "queryNames")</code>} or that name will
1565:    *                           not be included.  Such an exception may also
1566:    *                           arise from the execution of the query, in which
1567:    *                           case that particular bean will again be excluded.
1568:    *                           Note that these permissions are implied if the
1569:    *                           <code>queryMBeans</code> permissions are available.
1570:    */
1571:   public Set queryNames(ObjectName name, QueryExp query)
1572:   {
1573:     checkSecurity(name, null, "queryNames");
1574:     Set results = new HashSet();
1575:     Iterator iterator = beans.entrySet().iterator();
1576:     while (iterator.hasNext())
1577:       {
1578:     Map.Entry entry = (Map.Entry) iterator.next();
1579:     ObjectName nextName = (ObjectName) entry.getKey();
1580:     checkSecurity(name, nextName.toString(), "queryNames");
1581:     try
1582:       {
1583:         if ((name == null || name.apply(nextName)) &&
1584:         (query == null || query.apply(nextName)))
1585:           results.add(nextName);
1586:       }
1587:     catch (BadStringOperationException e)
1588:       {
1589:         /* Ignored -- assume false result */
1590:       }
1591:     catch (BadBinaryOpValueExpException e)
1592:       {
1593:         /* Ignored -- assume false result */
1594:       }
1595:     catch (BadAttributeValueExpException e)
1596:       {
1597:         /* Ignored -- assume false result */
1598:       }
1599:     catch (InvalidApplicationException e)
1600:       {
1601:         /* Ignored -- assume false result */
1602:       }
1603:       }
1604:     return results;
1605:   }
1606: 
1607:   /**
1608:    * Registers the supplied instance with the server, using the specified
1609:    * {@link ObjectName}.  If the name given is <code>null</code>, then
1610:    * the bean supplied is expected to implement the {@link MBeanRegistration}
1611:    * interface and provide the name via the 
1612:    * {@link MBeanRegistration#preRegister preRegister} method
1613:    * of this interface.
1614:    *
1615:    * @param obj the object to register with the server.
1616:    * @param name the name under which to register the object,
1617:    *             or <code>null</code> if the {@link MBeanRegistration}
1618:    *             interface should be used.
1619:    * @return an {@link ObjectInstance} containing the supplied
1620:    *         {@link ObjectName} along with the name of the bean's class.
1621:    * @throws InstanceAlreadyExistsException if a matching instance
1622:    *                                        already exists.
1623:    * @throws MBeanRegistrationException if an exception occurs in
1624:    *                                    calling the preRegister
1625:    *                                    method.
1626:    * @throws NotCompliantMBeanException if the created bean is not
1627:    *                                    compliant with the JMX specification.
1628:    * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
1629:    *                                    is thrown by the server due to a
1630:    *                                    <code>null</code> object.
1631:    * @throws SecurityException if a security manager exists and the
1632:    *                           caller's permissions don't imply {@link
1633:    *                           MBeanPermission(String,String,ObjectName,String)
1634:    *                           <code>MBeanPermission(className, null, name,
1635:    *                           "registerMBean")</code>}.  <code>className</code>
1636:    *                           here corresponds to the result of
1637:    *                           {@link MBeanInfo#getClassName()} for objects of
1638:    *                           this class.  If this check succeeds, a check
1639:    *                           is also made on its
1640:    *                           {@link java.security.ProtectionDomain} to ensure
1641:    *                           it implies {@link MBeanTrustPermission(String)
1642:    *                           <code>MBeanTrustPermission("register")</code>}.
1643:    *                           The use of the {@link MBeanRegistration} interface
1644:    *                           results in another {@link MBeanPermission} check
1645:    *                           being made on the returned {@link ObjectName}.
1646:    */
1647:   public ObjectInstance registerMBean(Object obj, ObjectName name)
1648:     throws InstanceAlreadyExistsException, MBeanRegistrationException,
1649:        NotCompliantMBeanException
1650:   {  
1651:     SecurityManager sm = System.getSecurityManager();
1652:     Class cl = obj.getClass();
1653:     String className = cl.getName();
1654:     if (sm != null)
1655:       {
1656:     sm.checkPermission(new MBeanPermission(className, null, name,
1657:                            "registerMBean"));
1658:     if (!(cl.getProtectionDomain().implies(new MBeanTrustPermission("register"))))
1659:       throw new SecurityException("The protection domain of the object's class" +
1660:                       "does not imply the trust permission," +
1661:                       "register");
1662:       }
1663:     if (obj == null)
1664:       {
1665:     RuntimeException e =
1666:       new IllegalArgumentException("The object was null.");
1667:     throw new RuntimeOperationsException(e);
1668:       }
1669:     MBeanRegistration register = null;
1670:     if (obj instanceof MBeanRegistration)
1671:       register = (MBeanRegistration) obj;
1672:     if (name == null && register == null)
1673:       {
1674:     RuntimeException e =
1675:       new IllegalArgumentException("The name was null and " +
1676:                        "the bean does not implement " +
1677:                        "MBeanRegistration.");
1678:     throw new RuntimeOperationsException(e);
1679:       }
1680:     if (register != null)
1681:       {
1682:     try
1683:       {
1684:         name = register.preRegister(this, name);
1685:         if (name == null)
1686:           {
1687:         RuntimeException e =
1688:           new NullPointerException("The name returned by " +
1689:                        "MBeanRegistration.preRegister() " +
1690:                        "was null");
1691:         throw e;
1692:           }
1693:         if (sm != null)
1694:           sm.checkPermission(new MBeanPermission(className, null, name,
1695:                              "registerMBean"));
1696:       }
1697:     catch (SecurityException e)
1698:       {
1699:         register.postRegister(Boolean.FALSE);
1700:         throw e;
1701:       }
1702:     catch (Exception e)
1703:       {
1704:         register.postRegister(Boolean.FALSE);
1705:         throw new MBeanRegistrationException(e, "Pre-registration failed.");
1706:       }
1707:       }
1708:     if (beans.containsKey(name))
1709:       {
1710:     if (register != null)
1711:       register.postRegister(Boolean.FALSE);
1712:     throw new InstanceAlreadyExistsException(name + "is already registered.");
1713:       }
1714:     ObjectInstance obji = new ObjectInstance(name, className);
1715:     beans.put(name, new ServerInfo(obji, obj));
1716:     if (register != null)
1717:       register.postRegister(Boolean.TRUE);
1718:     notify(name, MBeanServerNotification.REGISTRATION_NOTIFICATION);
1719:     return obji;
1720:   }
1721: 
1722:   /**
1723:    * Removes the specified listener from the list of recipients
1724:    * of notifications from the supplied bean.  This includes all
1725:    * combinations of filters and passback objects registered for
1726:    * this listener.  For more specific removal of listeners, see
1727:    * {@link #removeNotificationListener(ObjectName,
1728:    * NotificationListener,NotificationFilter,Object)}
1729:    *
1730:    * @param name the name of the management bean from which the
1731:    *             listener should be removed.
1732:    * @param listener the listener to remove.
1733:    * @throws InstanceNotFoundException if the bean can not be found.
1734:    * @throws ListenerNotFoundException if the specified listener
1735:    *                                   is not registered with the bean.
1736:    * @throws SecurityException if a security manager exists and the
1737:    *                           caller's permissions don't imply {@link
1738:    *                           MBeanPermission(String,String,ObjectName,String)
1739:    *                           <code>MBeanPermission(className, null, name,
1740:    *                           "removeNotificationListener")</code>}.
1741:    * @see #addNotificationListener(NotificationListener, NotificationFilter,
1742:    *                               java.lang.Object)
1743:    * @see NotificationBroadcaster#removeNotificationListener(NotificationListener)
1744:    */
1745:   public void removeNotificationListener(ObjectName name,
1746:                      NotificationListener listener)
1747:     throws InstanceNotFoundException, ListenerNotFoundException
1748:   {
1749:     Object bean = getBean(name);
1750:     checkSecurity(name, null, "removeNotificationListener");
1751:     if (bean instanceof NotificationBroadcaster)
1752:       {
1753:     NotificationBroadcaster bbean = (NotificationBroadcaster) bean;
1754:     NotificationListener indirection = (NotificationListener)
1755:       listeners.get(listener);
1756:     if (indirection == null)
1757:       bbean.removeNotificationListener(listener);
1758:     else
1759:       {
1760:         bbean.removeNotificationListener(indirection);
1761:         listeners.remove(listener);
1762:       }
1763:       }
1764:   }
1765: 
1766:   /**
1767:    * Removes the specified listener from the list of recipients
1768:    * of notifications from the supplied bean.  Only the first instance with
1769:    * the supplied filter and passback object is removed.
1770:    * <code>null</code> is used as a valid value for these parameters,
1771:    * rather than as a way to remove all registration instances for
1772:    * the specified listener; for this behaviour instead, see
1773:    * {@link #removeNotificationListener(ObjectName, NotificationListener)}.
1774:    *
1775:    * @param name the name of the management bean from which the
1776:    *             listener should be removed.
1777:    * @param listener the listener to remove.
1778:    * @param filter the filter of the listener to remove.
1779:    * @param passback the passback object of the listener to remove.
1780:    * @throws InstanceNotFoundException if the bean can not be found.
1781:    * @throws ListenerNotFoundException if the specified listener
1782:    *                                   is not registered with the bean.
1783:    * @throws SecurityException if a security manager exists and the
1784:    *                           caller's permissions don't imply {@link
1785:    *                           MBeanPermission(String,String,ObjectName,String)
1786:    *                           <code>MBeanPermission(className, null, name,
1787:    *                           "removeNotificationListener")</code>}.
1788:    * @see #addNotificationListener(ObjectName, NotificationListener,
1789:    *                               NotificationFilter, Object)
1790:    * @see NotificationEmitter#removeNotificationListener(NotificationListener,
1791:    *                                                     NotificationFilter,
1792:    *                                                     Object)
1793:    */
1794:   public void removeNotificationListener(ObjectName name,
1795:                      NotificationListener listener,
1796:                      NotificationFilter filter,
1797:                      Object passback)
1798:     throws InstanceNotFoundException, ListenerNotFoundException
1799:   {
1800:     Object bean = getBean(name);
1801:     checkSecurity(name, null, "removeNotificationListener");
1802:     if (bean instanceof NotificationEmitter)
1803:       {
1804:     NotificationEmitter bbean = (NotificationEmitter) bean;
1805:     NotificationListener indirection = (NotificationListener)
1806:       listeners.get(listener);
1807:     if (indirection == null)
1808:       bbean.removeNotificationListener(listener, filter, passback);
1809:     else
1810:       {
1811:         bbean.removeNotificationListener(indirection, filter, passback);
1812:         listeners.remove(listener);
1813:       }
1814:       }
1815:   }
1816: 
1817:   /**
1818:    * Removes the specified listener from the list of recipients
1819:    * of notifications from the supplied bean.  This includes all
1820:    * combinations of filters and passback objects registered for
1821:    * this listener.  For more specific removal of listeners, see
1822:    * {@link #removeNotificationListener(ObjectName,
1823:    * ObjectName,NotificationFilter,Object)}
1824:    *
1825:    * @param name the name of the management bean from which the
1826:    *             listener should be removed.
1827:    * @param listener the name of the listener to remove.
1828:    * @throws InstanceNotFoundException if a name doesn't match a registered
1829:    *                                   bean.
1830:    * @throws ListenerNotFoundException if the specified listener
1831:    *                                   is not registered with the bean.
1832:    * @throws SecurityException if a security manager exists and the
1833:    *                           caller's permissions don't imply {@link
1834:    *                           MBeanPermission(String,String,ObjectName,String)
1835:    *                           <code>MBeanPermission(className, null, name,
1836:    *                           "removeNotificationListener")</code>}.
1837:    * @see #addNotificationListener(NotificationListener, NotificationFilter,
1838:    *                               java.lang.Object)
1839:    * @see NotificationBroadcaster#removeNotificationListener(NotificationListener)
1840:    */
1841:   public void removeNotificationListener(ObjectName name, ObjectName listener)
1842:     throws InstanceNotFoundException, ListenerNotFoundException
1843:   {
1844:     Object lbean = getBean(listener);
1845:     if (!(lbean instanceof NotificationListener))
1846:       {
1847:     RuntimeException e =
1848:       new IllegalArgumentException("The supplied listener name does not " +
1849:                        "correspond to a notification listener.");
1850:     throw new RuntimeOperationsException(e);
1851:       }
1852:     removeNotificationListener(name, ((NotificationListener) lbean));
1853:   }
1854: 
1855:   /**
1856:    * Removes the specified listener from the list of recipients
1857:    * of notifications from the supplied bean.  Only the first instance with
1858:    * the supplied filter and passback object is removed.
1859:    * <code>null</code> is used as a valid value for these parameters,
1860:    * rather than as a way to remove all registration instances for
1861:    * the specified listener; for this behaviour instead, see
1862:    * {@link #removeNotificationListener(ObjectName, ObjectName)}.
1863:    *
1864:    * @param name the name of the management bean from which the
1865:    *             listener should be removed.
1866:    * @param listener the name of the listener to remove.
1867:    * @param filter the filter of the listener to remove.
1868:    * @param passback the passback object of the listener to remove.
1869:    * @throws InstanceNotFoundException if a name doesn't match a registered
1870:    *                                   bean.
1871:    * @throws ListenerNotFoundException if the specified listener
1872:    *                                   is not registered with the bean.
1873:    * @throws SecurityException if a security manager exists and the
1874:    *                           caller's permissions don't imply {@link
1875:    *                           MBeanPermission(String,String,ObjectName,String)
1876:    *                           <code>MBeanPermission(className, null, name,
1877:    *                           "removeNotificationListener")</code>}.
1878:    * @see #addNotificationListener(ObjectName, NotificationListener,
1879:    *                               NotificationFilter, Object)
1880:    * @see NotificationEmitter#removeNotificationListener(NotificationListener,
1881:    *                                                     NotificationFilter,
1882:    *                                                     Object)
1883:    */
1884:   public void removeNotificationListener(ObjectName name,
1885:                   ObjectName listener,
1886:                   NotificationFilter filter,
1887:                   Object passback)
1888:     throws InstanceNotFoundException, ListenerNotFoundException
1889:   {
1890:     Object lbean = getBean(listener);
1891:     if (!(lbean instanceof NotificationListener))
1892:       {
1893:     RuntimeException e =
1894:       new IllegalArgumentException("The supplied listener name does not " +
1895:                        "correspond to a notification listener.");
1896:     throw new RuntimeOperationsException(e);
1897:       }
1898:     removeNotificationListener(name, ((NotificationListener) lbean), filter,
1899:                    passback);
1900:   }
1901: 
1902:   /**
1903:    * Sets the value of the specified attribute of the supplied
1904:    * management bean.  
1905:    *
1906:    * @param name the name of the management bean.
1907:    * @param attribute the attribute to set.
1908:    * @throws InstanceNotFoundException if the bean can not be found.
1909:    * @throws AttributeNotFoundException if the attribute does not
1910:    *                                    correspond to an attribute
1911:    *                                    of the bean.
1912:    * @throws InvalidAttributeValueException if the value is invalid
1913:    *                                        for this particular
1914:    *                                        attribute of the bean.
1915:    * @throws MBeanException if setting the attribute causes
1916:    *                        the bean to throw an exception (which
1917:    *                        becomes the cause of this exception).
1918:    * @throws ReflectionException if an exception occurred in trying
1919:    *                             to use the reflection interface
1920:    *                             to lookup the attribute.  The
1921:    *                             thrown exception is the cause of
1922:    *                             this exception.
1923:    * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
1924:    *                                    is thrown by the server due to a
1925:    *                                    <code>null</code> bean or attribute
1926:    *                                    name.
1927:    * @throws SecurityException if a security manager exists and the
1928:    *                           caller's permissions don't imply {@link
1929:    *                           MBeanPermission(String,String,ObjectName,String)
1930:    *                           <code>MBeanPermission(className, name, bean,
1931:    *                           "setAttribute")</code>}.
1932:    * @see #getAttribute(ObjectName, String)
1933:    * @see DynamicMBean#setAttribute(Attribute)
1934:    */
1935:   public void setAttribute(ObjectName name, Attribute attribute)
1936:     throws InstanceNotFoundException, AttributeNotFoundException,
1937:        InvalidAttributeValueException, MBeanException,
1938:        ReflectionException
1939:   {
1940:     if (attribute == null || name == null)
1941:       {
1942:     RuntimeException e =
1943:       new IllegalArgumentException("One of the supplied arguments was null.");
1944:     throw new RuntimeOperationsException(e);
1945:       }
1946:     Object bean = getBean(name);
1947:     checkSecurity(name, attribute.getName(), "setAttribute");
1948:     if (bean instanceof DynamicMBean)
1949:       ((DynamicMBean) bean).setAttribute(attribute);
1950:     else
1951:       try
1952:     {
1953:       new StandardMBean(bean, null).setAttribute(attribute);
1954:     }
1955:       catch (NotCompliantMBeanException e)
1956:     {
1957:       throw (Error) 
1958:         (new InternalError("Failed to create dynamic bean.").initCause(e));
1959:     }
1960:   }
1961: 
1962:   /**
1963:    * Sets the value of each of the specified attributes
1964:    * of the supplied management bean to that specified by
1965:    * the {@link Attribute} object.  The returned list contains
1966:    * the attributes that were set and their new values.
1967:    *
1968:    * @param name the name of the management bean.
1969:    * @param attributes the attributes to set.
1970:    * @return a list of the changed attributes.
1971:    * @throws InstanceNotFoundException if the bean can not be found.
1972:    * @throws ReflectionException if an exception occurred in trying
1973:    *                             to use the reflection interface
1974:    *                             to lookup the attribute.  The
1975:    *                             thrown exception is the cause of
1976:    *                             this exception.
1977:    * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
1978:    *                                    is thrown by the server due to a
1979:    *                                    <code>null</code> bean or attribute
1980:    *                                    list.
1981:    * @throws SecurityException if a security manager exists and the
1982:    *                           caller's permissions don't imply {@link
1983:    *                           MBeanPermission(String,String,ObjectName,String)
1984:    *                           <code>MBeanPermission(className, null, bean,
1985:    *                           "setAttribute")</code>}.  Additionally,
1986:    *                           for an attribute name, <code>n</code>, the
1987:    *                           caller's permission must imply {@link
1988:    *                           MBeanPermission(String,String,ObjectName,String)
1989:    *                           <code>MBeanPermission(className, n, bean,
1990:    *                           "setAttribute")</code>} or that attribute will
1991:    *                           not be included.
1992:    * @see #getAttributes(ObjectName, String[])
1993:    * @see DynamicMBean#setAttributes(AttributeList)
1994:    */
1995:   public AttributeList setAttributes(ObjectName name, AttributeList attributes)
1996:     throws InstanceNotFoundException, ReflectionException
1997:   {
1998:     if (name == null || attributes == null)
1999:       {
2000:     RuntimeException e =
2001:       new IllegalArgumentException("One of the supplied arguments was null.");
2002:     throw new RuntimeOperationsException(e);
2003:       }
2004:     Object abean = getBean(name);
2005:     checkSecurity(name, null, "setAttribute");
2006:     AttributeList list = new AttributeList(attributes.size());
2007:     Iterator it = attributes.iterator();
2008:     while (it.hasNext())
2009:       {
2010:     try
2011:       {
2012:         Attribute attrib = (Attribute) it.next();
2013:         if (attrib == null)
2014:           {
2015:         RuntimeException e =
2016:           new IllegalArgumentException("An attribute was null.");
2017:         throw new RuntimeOperationsException(e);
2018:           }
2019:         checkSecurity(name, attrib.getName(), "setAttribute");
2020:         if (abean instanceof DynamicMBean)
2021:           ((DynamicMBean) abean).setAttribute(attrib);
2022:         else
2023:           try
2024:         {
2025:           new StandardMBean(abean, null).setAttribute(attrib);
2026:         }
2027:           catch (NotCompliantMBeanException e)
2028:         {
2029:           throw (Error) 
2030:             (new InternalError("Failed to create dynamic bean.").initCause(e));
2031:         }
2032:         list.add(attrib);
2033:       }
2034:     catch (AttributeNotFoundException e)
2035:       {
2036:         /* Ignored */
2037:       }
2038:     catch (InvalidAttributeValueException e)
2039:       {
2040:         /* Ignored */
2041:       }
2042:     catch (MBeanException e)
2043:       {
2044:         /* Ignored */
2045:       }
2046:       }
2047:     return list;
2048:   }
2049: 
2050:   /**
2051:    * Unregisters the specified management bean.  Following this operation,
2052:    * the bean instance is no longer accessible from the server via this
2053:    * name.  Prior to unregistering the bean, the
2054:    * {@link MBeanRegistration#preDeregister()} method will be called if
2055:    * the bean implements the {@link MBeanRegistration} interface.
2056:    *
2057:    * @param name the name of the management bean.
2058:    * @throws InstanceNotFoundException if the bean can not be found.
2059:    * @throws MBeanRegistrationException if an exception occurs in
2060:    *                                    calling the preDeregister
2061:    *                                    method.
2062:    * @throws RuntimeOperationsException if an {@link IllegalArgumentException}
2063:    *                                    is thrown by the server due to a
2064:    *                                    <code>null</code> bean name or a
2065:    *                                    request being made to unregister the
2066:    *                                    {@link MBeanServerDelegate} bean.
2067:    * @throws SecurityException if a security manager exists and the
2068:    *                           caller's permissions don't imply {@link
2069:    *                           MBeanPermission(String,String,ObjectName,String)
2070:    *                           <code>MBeanPermission(className, null, name,
2071:    *                           "unregisterMBean")</code>}.
2072:    */ 
2073:   public void unregisterMBean(ObjectName name)
2074:     throws InstanceNotFoundException, MBeanRegistrationException
2075:   {
2076:     if (name == null)
2077:       {
2078:     RuntimeException e =
2079:       new IllegalArgumentException("The name was null.");
2080:     throw new RuntimeOperationsException(e);
2081:       }
2082:     if (name.equals(DELEGATE_NAME))
2083:       {
2084:     RuntimeException e =
2085:       new IllegalArgumentException("The delegate can not be unregistered.");
2086:     throw new RuntimeOperationsException(e);
2087:       }    
2088:     Object bean = getBean(name);    
2089:     checkSecurity(name, null, "unregisterMBean");
2090:     MBeanRegistration register = null;
2091:     if (bean instanceof MBeanRegistration)
2092:       {
2093:     register = (MBeanRegistration) bean;
2094:     try
2095:       {
2096:         register.preDeregister();
2097:       }
2098:     catch (Exception e)
2099:       {
2100:         throw new MBeanRegistrationException(e, "Pre-deregistration failed.");
2101:       }
2102:       }
2103:     beans.remove(name);
2104:     notify(name, MBeanServerNotification.UNREGISTRATION_NOTIFICATION);
2105:     if (register != null)
2106:       register.postDeregister();
2107:   }
2108: 
2109:    private void notify(ObjectName name, String type)
2110:    {
2111:       delegate.sendNotification
2112:     (new MBeanServerNotification
2113:      (type, DELEGATE_NAME, sequenceNumber.getAndIncrement(), name));
2114:    }
2115: 
2116:   /**
2117:    * Input stream which deserializes using the given classloader.
2118:    */
2119:   private class ServerInputStream
2120:     extends ObjectInputStream
2121:   {
2122: 
2123:     private ClassLoader cl;
2124: 
2125:     public ServerInputStream(InputStream is, ClassLoader cl)
2126:       throws IOException, StreamCorruptedException
2127:     {
2128:       super(is);
2129:       this.cl = cl;
2130:     }
2131: 
2132:     protected Class resolveClass(ObjectStreamClass osc)
2133:       throws ClassNotFoundException, IOException
2134:     {
2135:       try
2136:     {
2137:       return Class.forName(osc.getName(), true, cl);
2138:     }
2139:       catch (ClassNotFoundException e)
2140:     {
2141:       return super.resolveClass(osc);
2142:     }
2143:     }
2144: 
2145:   }
2146: 
2147:   /**
2148:    * Holder for information on registered beans.
2149:    */
2150:   private class ServerInfo
2151:   {  
2152:     private ObjectInstance instance;
2153: 
2154:     private Object object;
2155: 
2156:     public ServerInfo(ObjectInstance instance, Object object)
2157:     {
2158:       this.instance = instance;
2159:       this.object = object;
2160:     }
2161: 
2162:     public Object getObject()
2163:     {
2164:       return object;
2165:     }
2166: 
2167:     public ObjectInstance getInstance()
2168:     {
2169:       return instance;
2170:     }
2171:   }
2172: 
2173:   /**
2174:    * Notification listener which removes direct references
2175:    * to beans.
2176:    */
2177:   private class ServerNotificationListener
2178:     implements NotificationListener
2179:   {
2180: 
2181:     /**
2182:      * The bean from which notifications are emitted.
2183:      */
2184:     Object bean;
2185: 
2186:     /**
2187:      * The {@link ObjectName} of the emitting bean.
2188:      */
2189:     ObjectName name;
2190: 
2191:     /**
2192:      * The real {@link NotificationListener}.
2193:      */
2194:     NotificationListener listener;
2195: 
2196:     /**
2197:      * Constructs a new {@link ServerNotificationListener} replacing
2198:      * occurrences of <code>bean</code> with its name.
2199:      *
2200:      * @param bean the bean emitting notifications.
2201:      * @param name the object name of the emitting bean.
2202:      * @param listener the listener events eventually reach.
2203:      */
2204:     public ServerNotificationListener(Object bean, ObjectName name,
2205:                       NotificationListener listener)
2206:     {
2207:       this.bean = bean;
2208:       this.name = name;
2209:       this.listener = listener;
2210:     }
2211: 
2212:     /**
2213:      * Replace a direct reference to <code>bean</code> with its
2214:      * object reference, if necessary, before calling the listener.
2215:      *
2216:      * @param notif the notification being emitted.
2217:      * @param handback an object that will be returned to the notification
2218:      *                 listener when an event occurs.
2219:      */
2220:     public void handleNotification(Notification notif, Object handback)
2221:     {
2222:       if (notif.getSource() == bean)
2223:     notif.setSource(name);
2224:       listener.handleNotification(notif, handback);
2225:     }
2226: 
2227:   }
2228: 
2229: }