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