1/*
2 * Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.jmx.mbeanserver;
27
28import com.sun.jmx.interceptor.DefaultMBeanServerInterceptor;
29import com.sun.jmx.interceptor.MBeanServerInterceptor;
30import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER;
31
32import java.io.ObjectInputStream;
33import java.security.AccessController;
34import java.security.Permission;
35import java.security.PrivilegedAction;
36import java.security.PrivilegedExceptionAction;
37import java.util.List;
38import java.util.Set;
39import java.lang.System.Logger.Level;
40
41import javax.management.Attribute;
42import javax.management.AttributeList;
43import javax.management.AttributeNotFoundException;
44import javax.management.InstanceAlreadyExistsException;
45import javax.management.InstanceNotFoundException;
46import javax.management.IntrospectionException;
47import javax.management.InvalidAttributeValueException;
48import javax.management.ListenerNotFoundException;
49import javax.management.MBeanException;
50import javax.management.MBeanInfo;
51import javax.management.MBeanPermission;
52import javax.management.MBeanRegistrationException;
53import javax.management.MBeanServer;
54import javax.management.MBeanServerDelegate;
55import javax.management.MBeanServerPermission;
56import javax.management.NotCompliantMBeanException;
57import javax.management.NotificationFilter;
58import javax.management.NotificationListener;
59import javax.management.ObjectInstance;
60import javax.management.ObjectName;
61import javax.management.OperationsException;
62import javax.management.QueryExp;
63import javax.management.ReflectionException;
64import javax.management.RuntimeOperationsException;
65import javax.management.loading.ClassLoaderRepository;
66
67/**
68 * This is the base class for MBean manipulation on the agent side. It
69 * contains the methods necessary for the creation, registration, and
70 * deletion of MBeans as well as the access methods for registered MBeans.
71 * This is the core component of the JMX infrastructure.
72 * <P>
73 * Every MBean which is added to the MBean server becomes manageable:
74 * its attributes and operations become remotely accessible through
75 * the connectors/adaptors connected to that MBean server.
76 * A Java object cannot be registered in the MBean server unless it is a
77 * JMX compliant MBean.
78 * <P>
79 * When an MBean is registered or unregistered in the MBean server an
80 * {@link javax.management.MBeanServerNotification MBeanServerNotification}
81 * Notification is emitted. To register an object as listener to
82 * MBeanServerNotifications you should call the MBean server method
83 * {@link #addNotificationListener addNotificationListener} with
84 * the <CODE>ObjectName</CODE> of the
85 * {@link javax.management.MBeanServerDelegate MBeanServerDelegate}.
86 * This <CODE>ObjectName</CODE> is:
87 * <BR>
88 * <CODE>JMImplementation:type=MBeanServerDelegate</CODE>.
89 *
90 * @since 1.5
91 */
92public final class JmxMBeanServer
93    implements SunJmxMBeanServer {
94
95    /** Control the default locking policy of the repository.
96     *  By default, we will be using a fair locking policy.
97     **/
98    public static final boolean DEFAULT_FAIR_LOCK_POLICY = true;
99
100    private final MBeanInstantiator instantiator;
101    private final SecureClassLoaderRepository secureClr;
102
103    /** true if interceptors are enabled **/
104    private final boolean interceptorsEnabled;
105
106    private final MBeanServer outerShell;
107
108    private volatile MBeanServer mbsInterceptor = null;
109
110    /** The MBeanServerDelegate object representing the MBean Server */
111    private final MBeanServerDelegate mBeanServerDelegateObject;
112
113    /**
114     * <b>Package:</b> Creates an MBeanServer with the
115     * specified default domain name, outer interface, and delegate.
116     * <p>The default domain name is used as the domain part in the ObjectName
117     * of MBeans if no domain is specified by the user.
118     * <ul><b>Note:</b>Using this constructor directly is strongly
119     *     discouraged. You should use
120     *     {@link javax.management.MBeanServerFactory#createMBeanServer(java.lang.String)}
121     *     or
122     *     {@link javax.management.MBeanServerFactory#newMBeanServer(java.lang.String)}
123     *     instead.
124     *     <p>
125     *     By default, interceptors are disabled. Use
126     *     {@link #JmxMBeanServer(java.lang.String,javax.management.MBeanServer,javax.management.MBeanServerDelegate,boolean)} to enable them.
127     * </ul>
128     * @param domain The default domain name used by this MBeanServer.
129     * @param outer A pointer to the MBeanServer object that must be
130     *        passed to the MBeans when invoking their
131     *        {@link javax.management.MBeanRegistration} interface.
132     * @param delegate A pointer to the MBeanServerDelegate associated
133     *        with the new MBeanServer. The new MBeanServer must register
134     *        this MBean in its MBean repository.
135     * @exception IllegalArgumentException if the instantiator is null.
136     */
137    JmxMBeanServer(String domain, MBeanServer outer,
138                   MBeanServerDelegate delegate) {
139        this(domain,outer,delegate,null,false);
140    }
141
142    /**
143     * <b>Package:</b> Creates an MBeanServer with the
144     * specified default domain name, outer interface, and delegate.
145     * <p>The default domain name is used as the domain part in the ObjectName
146     * of MBeans if no domain is specified by the user.
147     * <ul><b>Note:</b>Using this constructor directly is strongly
148     *     discouraged. You should use
149     *     {@link javax.management.MBeanServerFactory#createMBeanServer(java.lang.String)}
150     *     or
151     *     {@link javax.management.MBeanServerFactory#newMBeanServer(java.lang.String)}
152     *     instead.
153     * </ul>
154     * @param domain The default domain name used by this MBeanServer.
155     * @param outer A pointer to the MBeanServer object that must be
156     *        passed to the MBeans when invoking their
157     *        {@link javax.management.MBeanRegistration} interface.
158     * @param delegate A pointer to the MBeanServerDelegate associated
159     *        with the new MBeanServer. The new MBeanServer must register
160     *        this MBean in its MBean repository.
161     * @param interceptors If <code>true</code>,
162     *        {@link MBeanServerInterceptor} will be enabled (default is
163     *        <code>false</code>)
164     *        Note: this parameter is not taken into account by this
165     *        implementation - the default value <code>false</code> is
166     *        always used.
167     * @exception IllegalArgumentException if the instantiator is null.
168     */
169    JmxMBeanServer(String domain, MBeanServer outer,
170                   MBeanServerDelegate delegate, boolean interceptors) {
171        this(domain,outer,delegate,null,false);
172    }
173
174    /**
175     * <b>Package:</b> Creates an MBeanServer.
176     * @param domain The default domain name used by this MBeanServer.
177     * @param outer A pointer to the MBeanServer object that must be
178     *        passed to the MBeans when invoking their
179     *        {@link javax.management.MBeanRegistration} interface.
180     * @param delegate A pointer to the MBeanServerDelegate associated
181     *        with the new MBeanServer. The new MBeanServer must register
182     *        this MBean in its MBean repository.
183     * @param instantiator The MBeanInstantiator that will be used to
184     *        instantiate MBeans and take care of class loading issues.
185     * @param metadata The MetaData object that will be used by the
186     *        MBean server in order to invoke the MBean interface of
187     *        the registered MBeans.
188     * @param interceptors If <code>true</code>,
189     *        {@link MBeanServerInterceptor} will be enabled (default is
190     *        <code>false</code>).
191     */
192    JmxMBeanServer(String domain, MBeanServer outer,
193                   MBeanServerDelegate    delegate,
194                   MBeanInstantiator      instantiator,
195                   boolean                interceptors)  {
196                   this(domain,outer,delegate,instantiator,interceptors,true);
197    }
198
199    /**
200     * <b>Package:</b> Creates an MBeanServer.
201     * @param domain The default domain name used by this MBeanServer.
202     * @param outer A pointer to the MBeanServer object that must be
203     *        passed to the MBeans when invoking their
204     *        {@link javax.management.MBeanRegistration} interface.
205     * @param delegate A pointer to the MBeanServerDelegate associated
206     *        with the new MBeanServer. The new MBeanServer must register
207     *        this MBean in its MBean repository.
208     * @param instantiator The MBeanInstantiator that will be used to
209     *        instantiate MBeans and take care of class loading issues.
210     * @param metadata The MetaData object that will be used by the
211     *        MBean server in order to invoke the MBean interface of
212     *        the registered MBeans.
213     * @param interceptors If <code>true</code>,
214     *        {@link MBeanServerInterceptor} will be enabled (default is
215     *        <code>false</code>).
216     * @param fairLock If {@code true}, the MBean repository will use a {@link
217     *        java.util.concurrent.locks.ReentrantReadWriteLock#ReentrantReadWriteLock(boolean)
218     *        fair locking} policy.
219     */
220    JmxMBeanServer(String domain, MBeanServer outer,
221                   MBeanServerDelegate    delegate,
222                   MBeanInstantiator      instantiator,
223                   boolean                interceptors,
224                   boolean                fairLock)  {
225
226        if (instantiator == null) {
227            final ModifiableClassLoaderRepository
228                clr = new ClassLoaderRepositorySupport();
229            instantiator = new MBeanInstantiator(clr);
230        }
231
232        final MBeanInstantiator fInstantiator = instantiator;
233        this.secureClr = new
234            SecureClassLoaderRepository(AccessController.doPrivileged(new PrivilegedAction<ClassLoaderRepository>() {
235                @Override
236                public ClassLoaderRepository run() {
237                    return fInstantiator.getClassLoaderRepository();
238                }
239            })
240        );
241        if (delegate == null)
242            delegate = new MBeanServerDelegateImpl();
243        if (outer == null)
244            outer = this;
245
246        this.instantiator = instantiator;
247        this.mBeanServerDelegateObject = delegate;
248        this.outerShell   = outer;
249
250        final Repository repository = new Repository(domain);
251        this.mbsInterceptor =
252            new DefaultMBeanServerInterceptor(outer, delegate, instantiator,
253                                              repository);
254        this.interceptorsEnabled = interceptors;
255        initialize();
256    }
257
258    /**
259     * Tell whether {@link MBeanServerInterceptor}s are enabled on this
260     * object.
261     * @return <code>true</code> if {@link MBeanServerInterceptor}s are
262     *         enabled.
263     * @see #newMBeanServer(java.lang.String,javax.management.MBeanServer,javax.management.MBeanServerDelegate,boolean)
264     **/
265    public boolean interceptorsEnabled() {
266        return interceptorsEnabled;
267    }
268
269    /**
270     * Return the MBeanInstantiator associated to this MBeanServer.
271     * @exception UnsupportedOperationException if
272     *            {@link MBeanServerInterceptor}s
273     *            are not enabled on this object.
274     * @see #interceptorsEnabled
275     **/
276    public MBeanInstantiator getMBeanInstantiator() {
277        if (interceptorsEnabled) return instantiator;
278        else throw new UnsupportedOperationException(
279                       "MBeanServerInterceptors are disabled.");
280    }
281
282    /**
283     * Instantiates and registers an MBean in the MBean server.
284     * The MBean server will use its
285     * {@link javax.management.loading.ClassLoaderRepository Default Loader Repository}
286     * to load the class of the MBean.
287     * An object name is associated to the MBean.
288     * If the object name given is null, the MBean can automatically
289     * provide its own name by implementing the
290     * {@link javax.management.MBeanRegistration MBeanRegistration} interface.
291     * The call returns an <CODE>ObjectInstance</CODE> object representing
292     * the newly created MBean.
293     *
294     * @param className The class name of the MBean to be instantiated.
295     * @param name The object name of the MBean. May be null.
296     *
297     * @return  An <CODE>ObjectInstance</CODE>, containing the
298     *     <CODE>ObjectName</CODE> and the Java class name of the newly
299     *     instantiated MBean.
300     *
301     * @exception ReflectionException Wraps an
302     *     <CODE>{@link java.lang.ClassNotFoundException}</CODE> or an
303     *     <CODE>{@link java.lang.Exception}</CODE> that occurred
304     *     when trying to invoke the MBean's constructor.
305     * @exception InstanceAlreadyExistsException The MBean is already
306     *     under the control of the MBean server.
307     * @exception MBeanRegistrationException The <CODE>preRegister()</CODE>
308     *     (<CODE>MBeanRegistration</CODE> interface) method of the MBean
309     *     has thrown an exception. The MBean will not be registered.
310     * @exception MBeanException The constructor of the MBean has thrown
311     *     an exception.
312     * @exception NotCompliantMBeanException This class is not a JMX
313     *     compliant MBean.
314     * @exception RuntimeOperationsException Wraps an
315     *     <CODE>{@link java.lang.IllegalArgumentException}</CODE>:
316     *     The className passed in parameter is null, the
317     *     <CODE>ObjectName</CODE> passed in parameter contains a pattern
318     *     or no <CODE>ObjectName</CODE> is specified for the MBean.
319     *
320     */
321    public ObjectInstance createMBean(String className, ObjectName name)
322        throws ReflectionException, InstanceAlreadyExistsException,
323               MBeanRegistrationException, MBeanException,
324               NotCompliantMBeanException {
325
326        return mbsInterceptor.createMBean(className,
327                                          cloneObjectName(name),
328                                          (Object[]) null,
329                                          (String[]) null);
330    }
331
332    /**
333     * Instantiates and registers an MBean in the MBean server.
334     * The class loader to be used is identified by its object  name.
335     * An object name is associated to the MBean.
336     * If the object name  of the loader is null, the ClassLoader that
337     * loaded the MBean server will be used.
338     * If the MBean's object name given is null, the MBean can
339     * automatically provide its own name by implementing the
340     * {@link javax.management.MBeanRegistration MBeanRegistration} interface.
341     * The call returns an <CODE>ObjectInstance</CODE> object representing
342     * the newly created MBean.
343     *
344     * @param className The class name of the MBean to be instantiated.
345     * @param name The object name of the MBean. May be null.
346     * @param loaderName The object name of the class loader to be used.
347     *
348     * @return  An <CODE>ObjectInstance</CODE>, containing the
349     *     <CODE>ObjectName</CODE> and the Java class name
350     *     of the newly instantiated MBean.
351     *
352     * @exception ReflectionException  Wraps an
353     *     <CODE>{@link java.lang.ClassNotFoundException}</CODE> or an
354     *     <CODE>{@link java.lang.Exception}</CODE> that occurred when trying
355     *     to invoke the MBean's constructor.
356     * @exception InstanceAlreadyExistsException The MBean is already
357     *     under the control of the MBean server.
358     * @exception MBeanRegistrationException The <CODE>preRegister()</CODE>
359     *     (<CODE>MBeanRegistration</CODE>  interface) method of the MBean
360     *     has thrown an exception. The MBean will not be registered.
361     * @exception MBeanException The constructor of the MBean has thrown
362     *     an exception
363     * @exception NotCompliantMBeanException This class is not a JMX
364     *     compliant MBean.
365     * @exception InstanceNotFoundException The specified class loader
366     *     is not registered in the MBean server.
367     * @exception RuntimeOperationsException Wraps an
368     *     <CODE>{@link java.lang.IllegalArgumentException}</CODE>: The
369     *     className passed in parameter is null, the <CODE>ObjectName</CODE>
370     *     passed in parameter contains a pattern or no
371     *     <CODE>ObjectName</CODE> is specified for the MBean.
372     */
373    public ObjectInstance createMBean(String className, ObjectName name,
374                                      ObjectName loaderName)
375        throws ReflectionException, InstanceAlreadyExistsException,
376               MBeanRegistrationException, MBeanException,
377               NotCompliantMBeanException, InstanceNotFoundException {
378
379        return mbsInterceptor.createMBean(className,
380                                          cloneObjectName(name),
381                                          loaderName,
382                                          (Object[]) null,
383                                          (String[]) null);
384    }
385
386    /**
387     * Instantiates and registers an MBean in the MBean server.
388     * The MBean server will use its
389     * {@link javax.management.loading.ClassLoaderRepository Default Loader Repository}
390     * to load the class of the MBean.
391     * An object name is associated to the MBean.
392     * If the object name given is null, the MBean can automatically
393     * provide its own name by implementing the
394     * {@link javax.management.MBeanRegistration MBeanRegistration} interface.
395     * The call returns an <CODE>ObjectInstance</CODE> object representing
396     * the newly created MBean.
397     *
398     * @param className The class name of the MBean to be instantiated.
399     * @param name The object name of the MBean. May be null.
400     * @param params An array containing the parameters of the constructor
401     *     to be invoked.
402     * @param signature An array containing the signature of the
403     *     constructor to be invoked.
404     *
405     * @return  An <CODE>ObjectInstance</CODE>, containing the
406     *     <CODE>ObjectName</CODE> and the Java class name
407     *     of the newly instantiated MBean.
408     *
409     * @exception ReflectionException Wraps a
410     *     <CODE>{@link java.lang.ClassNotFoundException}</CODE> or an
411     *     <CODE>{@link java.lang.Exception}</CODE> that occurred
412     *     when trying to invoke the MBean's constructor.
413     * @exception InstanceAlreadyExistsException The MBean is already
414     *     under the control of the MBean server.
415     * @exception MBeanRegistrationException The <CODE>preRegister()</CODE>
416     *     (<CODE>MBeanRegistration</CODE>  interface) method of the MBean
417     *     has thrown an exception. The MBean will not be registered.
418     * @exception MBeanException The constructor of the MBean has
419     *     thrown an exception.
420     * @exception RuntimeOperationsException Wraps an
421     *     <CODE>{@link java.lang.IllegalArgumentException}</CODE>: The
422     *     className passed in parameter is null, the <CODE>ObjectName</CODE>
423     *     passed in parameter contains a pattern or no
424     *     <CODE>ObjectName</CODE> is specified for the MBean.
425     *
426     */
427    public ObjectInstance createMBean(String className, ObjectName name,
428                                      Object params[], String signature[])
429        throws ReflectionException, InstanceAlreadyExistsException,
430               MBeanRegistrationException, MBeanException,
431               NotCompliantMBeanException  {
432
433        return mbsInterceptor.createMBean(className, cloneObjectName(name),
434                                          params, signature);
435    }
436
437   /**
438     * Instantiates and registers an MBean in the MBean server.
439     * The class loader to be used is identified by its object name.
440     * An object name is associated to the MBean. If the object name
441     * of the loader is not specified, the ClassLoader that loaded the
442     * MBean server will be used.
443     * If  the MBean object name given is null, the MBean can automatically
444     * provide its own name by implementing the
445     * {@link javax.management.MBeanRegistration MBeanRegistration} interface.
446     * The call returns an <CODE>ObjectInstance</CODE> object representing
447     * the newly created MBean.
448     *
449     * @param className The class name of the MBean to be instantiated.
450     * @param name The object name of the MBean. May be null.
451     * @param params An array containing the parameters of the constructor
452     *      to be invoked.
453     * @param signature An array containing the signature of the
454     *     constructor to be invoked.
455     * @param loaderName The object name of the class loader to be used.
456     *
457     * @return  An <CODE>ObjectInstance</CODE>, containing the
458     *     <CODE>ObjectName</CODE> and the Java class name of the newly
459     *     instantiated MBean.
460     *
461     * @exception ReflectionException Wraps a
462     *     <CODE>{@link java.lang.ClassNotFoundException}</CODE> or an
463     *     <CODE>{@link java.lang.Exception}</CODE>
464     *     that occurred when trying to invoke the MBean's constructor.
465     * @exception InstanceAlreadyExistsException The MBean is already
466     *     under the control of the MBean server.
467     * @exception MBeanRegistrationException The <CODE>preRegister()</CODE>
468     *     (<CODE>MBeanRegistration</CODE>  interface) method of the MBean
469     *     has thrown an exception. The MBean will not be registered.
470     * @exception MBeanException The constructor of the MBean has
471     *      thrown an exception
472     * @exception InstanceNotFoundException The specified class loader is
473     *      not registered in the MBean server.
474     * @exception RuntimeOperationsException Wraps an
475     *     <CODE>{@link java.lang.IllegalArgumentException}</CODE>: The
476     *     className passed in parameter is null, the <CODE>ObjectName</CODE>
477     *     passed in parameter contains a pattern or no
478     *     <CODE>ObjectName</CODE> is specified for the MBean.
479     *
480     */
481    public ObjectInstance createMBean(String className, ObjectName name,
482                                      ObjectName loaderName, Object params[],
483                                      String signature[])
484        throws ReflectionException, InstanceAlreadyExistsException,
485               MBeanRegistrationException, MBeanException,
486               NotCompliantMBeanException, InstanceNotFoundException {
487
488        return mbsInterceptor.createMBean(className, cloneObjectName(name),
489                                          loaderName, params, signature);
490    }
491
492    /**
493     * Registers a pre-existing object as an MBean with the MBean server.
494     * If the object name given is null, the MBean may automatically
495     * provide its own name by implementing the
496     * {@link javax.management.MBeanRegistration MBeanRegistration}  interface.
497     * The call returns an <CODE>ObjectInstance</CODE> object representing
498     * the registered MBean.
499     *
500     * @param object The  MBean to be registered as an MBean.
501     * @param name The object name of the MBean. May be null.
502     *
503     * @return The <CODE>ObjectInstance</CODE> for the MBean that has been
504     *      registered.
505     *
506     * @exception InstanceAlreadyExistsException The MBean is already
507     *      under the control of the MBean server.
508     * @exception MBeanRegistrationException The <CODE>preRegister()</CODE>
509     *      (<CODE>MBeanRegistration</CODE>  interface) method of the MBean
510     *      has thrown an exception. The MBean will not be registered.
511     * @exception NotCompliantMBeanException This object is not a JMX
512     *      compliant MBean
513     * @exception RuntimeOperationsException Wraps an
514     *      <CODE>{@link java.lang.IllegalArgumentException}</CODE>: The
515     *      object passed in parameter is null or no object name is specified.
516     *
517     */
518    public ObjectInstance registerMBean(Object object, ObjectName name)
519        throws InstanceAlreadyExistsException, MBeanRegistrationException,
520               NotCompliantMBeanException  {
521
522        return mbsInterceptor.registerMBean(object, cloneObjectName(name));
523    }
524
525    /**
526     * De-registers an MBean from the MBean server. The MBean is identified by
527     * its object name. Once the method has been invoked, the MBean may
528     * no longer be accessed by its object name.
529     *
530     * @param name The object name of the MBean to be de-registered.
531     *
532     * @exception InstanceNotFoundException The MBean specified is not
533     *     registered in the MBean server.
534     * @exception MBeanRegistrationException The <code>preDeregister()</code>
535     *     (<CODE>MBeanRegistration</CODE>  interface) method of the MBean
536     *     has thrown an exception.
537     * @exception RuntimeOperationsException Wraps an
538     *     <CODE>{@link java.lang.IllegalArgumentException}</CODE>: The
539     *     object name in parameter is null or the MBean you are when
540     *     trying to de-register is the
541     *     {@link javax.management.MBeanServerDelegate MBeanServerDelegate}
542     *     MBean.
543     **/
544    public void unregisterMBean(ObjectName name)
545        throws InstanceNotFoundException, MBeanRegistrationException  {
546        mbsInterceptor.unregisterMBean(cloneObjectName(name));
547    }
548
549    /**
550     * Gets the <CODE>ObjectInstance</CODE> for a given MBean registered
551     * with the MBean server.
552     *
553     * @param name The object name of the MBean.
554     *
555     * @return The <CODE>ObjectInstance</CODE> associated to the MBean
556     *       specified by <VAR>name</VAR>.
557     *
558     * @exception InstanceNotFoundException The MBean specified is not
559     *       registered in the MBean server.
560     */
561    public ObjectInstance getObjectInstance(ObjectName name)
562        throws InstanceNotFoundException {
563
564        return mbsInterceptor.getObjectInstance(cloneObjectName(name));
565    }
566
567    /**
568     * Gets MBeans controlled by the MBean server. This method allows any
569     * of the following to be obtained: All MBeans, a set of MBeans specified
570     * by pattern matching on the <CODE>ObjectName</CODE> and/or a Query
571     * expression, a specific MBean. When the object name is null or no
572     * domain and key properties are specified, all objects are to be
573     * selected (and filtered if a query is specified). It returns the
574     * set of <CODE>ObjectInstance</CODE> objects (containing the
575     * <CODE>ObjectName</CODE> and the Java Class name) for
576     * the selected MBeans.
577     *
578     * @param name The object name pattern identifying the MBeans to
579     *      be retrieved. If null or no domain and key properties
580     *      are specified, all the MBeans registered will be retrieved.
581     * @param query The query expression to be applied for selecting
582     *      MBeans. If null no query expression will be applied for
583     *      selecting MBeans.
584     *
585     * @return  A set containing the <CODE>ObjectInstance</CODE> objects
586     *      for the selected MBeans.
587     *      If no MBean satisfies the query an empty list is returned.
588     *
589     */
590    public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) {
591
592        return mbsInterceptor.queryMBeans(cloneObjectName(name), query);
593    }
594
595    /**
596     * Gets the names of MBeans controlled by the MBean server. This method
597     * enables any of the following to be obtained: The names of all MBeans,
598     * the names of a set of MBeans specified by pattern matching on the
599     * <CODE>ObjectName</CODE> and/or a Query expression, a specific
600     * MBean name (equivalent to testing whether an MBean is registered).
601     * When the object name is null or no domain and key properties are
602     * specified, all objects are selected (and filtered if a query is
603     * specified). It returns the set of ObjectNames for the MBeans
604     * selected.
605     *
606     * @param name The object name pattern identifying the MBeans to be
607     *     retrieved. If null or no domain and key properties are
608     *     specified, all the MBeans registered will be retrieved.
609     * @param query The query expression to be applied for selecting
610     *     MBeans. If null no query expression will be applied for
611     *     selecting MBeans.
612     *
613     * @return  A set containing the ObjectNames for the MBeans selected.
614     *     If no MBean satisfies the query, an empty list is returned.
615     *
616     */
617    public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
618
619        return mbsInterceptor.queryNames(cloneObjectName(name), query);
620    }
621
622    /**
623     * Checks whether an MBean, identified by its object name, is already
624     * registered with the MBean server.
625     *
626     * @param name The object name of the MBean to be checked.
627     *
628     * @return  True if the MBean is already registered in the MBean server,
629     *     false otherwise.
630     *
631     * @exception RuntimeOperationsException Wraps an
632     *     <CODE>{@link java.lang.IllegalArgumentException}</CODE>: The object
633     *      name in parameter is null.
634     *
635     */
636    public boolean isRegistered(ObjectName name)  {
637
638        return mbsInterceptor.isRegistered(name);
639    }
640
641    /**
642     * Returns the number of MBeans registered in the MBean server.
643     */
644    public Integer getMBeanCount()  {
645
646        return mbsInterceptor.getMBeanCount();
647    }
648
649    /**
650     * Gets the value of a specific attribute of a named MBean. The MBean
651     * is identified by its object name.
652     *
653     * @param name The object name of the MBean from which the attribute
654     *     is to be retrieved.
655     * @param attribute A String specifying the name of the attribute to be
656     *     retrieved.
657     *
658     * @return  The value of the retrieved attribute.
659     *
660     * @exception AttributeNotFoundException The attribute specified
661     *     is not accessible in the MBean.
662     * @exception MBeanException  Wraps an exception thrown by the
663     *     MBean's getter.
664     * @exception InstanceNotFoundException The MBean specified is not
665     *     registered in the MBean server.
666     * @exception ReflectionException  Wraps an
667     *     <CODE>{@link java.lang.Exception}</CODE> thrown when trying to
668     *     invoke the setter.
669     * @exception RuntimeOperationsException Wraps an
670     *     <CODE>{@link java.lang.IllegalArgumentException}</CODE>:
671     *     The object name in parameter is null or the attribute in
672     *     parameter is null.
673     */
674    public Object getAttribute(ObjectName name, String attribute)
675        throws MBeanException, AttributeNotFoundException,
676               InstanceNotFoundException, ReflectionException {
677
678        return mbsInterceptor.getAttribute(cloneObjectName(name), attribute);
679    }
680
681
682    /**
683     * Enables the values of several attributes of a named MBean. The MBean
684     * is identified by its object name.
685     *
686     * @param name The object name of the MBean from which the attributes are
687     *     retrieved.
688     * @param attributes A list of the attributes to be retrieved.
689     *
690     * @return The list of the retrieved attributes.
691     *
692     * @exception InstanceNotFoundException The MBean specified is not
693     *     registered in the MBean server.
694     * @exception ReflectionException An exception occurred when trying
695     *     to invoke the getAttributes method of a Dynamic MBean.
696     * @exception RuntimeOperationsException Wrap an
697     *     <CODE>{@link java.lang.IllegalArgumentException}</CODE>: The
698     *     object name in parameter is null or attributes in parameter
699     *     is null.
700     *
701     */
702    public AttributeList getAttributes(ObjectName name, String[] attributes)
703        throws InstanceNotFoundException, ReflectionException  {
704
705        return mbsInterceptor.getAttributes(cloneObjectName(name), attributes);
706
707    }
708
709    /**
710     * Sets the value of a specific attribute of a named MBean. The MBean
711     * is identified by its object name.
712     *
713     * @param name The name of the MBean within which the attribute is
714     *     to be set.
715     * @param attribute The identification of the attribute to be set
716     *     and the value it is to be set to.
717     *
718     * @exception InstanceNotFoundException The MBean specified is
719     *     not registered in the MBean server.
720     * @exception AttributeNotFoundException The attribute specified is
721     *     not accessible in the MBean.
722     * @exception InvalidAttributeValueException The value specified for
723     *     the attribute is not valid.
724     * @exception MBeanException Wraps an exception thrown by the
725     *     MBean's setter.
726     * @exception ReflectionException  Wraps an
727     *     <CODE>{@link java.lang.Exception}</CODE> thrown when trying
728     *     to invoke the setter.
729     * @exception RuntimeOperationsException Wraps an
730     *     <CODE>{@link java.lang.IllegalArgumentException}</CODE>: The
731     *     object name in parameter is null or the attribute in parameter
732     *     is null.
733     */
734    public void setAttribute(ObjectName name, Attribute attribute)
735        throws InstanceNotFoundException, AttributeNotFoundException,
736               InvalidAttributeValueException, MBeanException,
737               ReflectionException  {
738
739        mbsInterceptor.setAttribute(cloneObjectName(name),
740                                    cloneAttribute(attribute));
741    }
742
743    /**
744     * Sets the values of several attributes of a named MBean. The MBean is
745     * identified by its object name.
746     *
747     * @param name The object name of the MBean within which the
748     *     attributes are to  be set.
749     * @param attributes A list of attributes: The identification of the
750     *     attributes to be set and  the values they are to be set to.
751     *
752     * @return  The list of attributes that were set, with their new values.
753     *
754     * @exception InstanceNotFoundException The MBean specified is not
755     *      registered in the MBean server.
756     * @exception ReflectionException An exception occurred when trying
757     *      to invoke the getAttributes method of a Dynamic MBean.
758     * @exception RuntimeOperationsException Wraps an
759     *      <CODE>{@link java.lang.IllegalArgumentException}</CODE>:
760     *     The object name in parameter is null or  attributes in
761     *     parameter is null.
762     *
763     */
764    public AttributeList setAttributes(ObjectName name,
765                                       AttributeList attributes)
766        throws InstanceNotFoundException, ReflectionException  {
767
768        return mbsInterceptor.setAttributes(cloneObjectName(name),
769                                            cloneAttributeList(attributes));
770    }
771
772    /**
773     * Invokes an operation on an MBean.
774     *
775     * @param name The object name of the MBean on which the method is to be
776     *     invoked.
777     * @param operationName The name of the operation to be invoked.
778     * @param params An array containing the parameters to be set when
779     *     the operation is invoked
780     * @param signature An array containing the signature of the operation.
781     *     The class objects will be loaded using the same class loader as
782     *     the one used for loading the MBean on which the operation was
783     *     invoked.
784     *
785     * @return  The object returned by the operation, which represents the
786     *      result ofinvoking the operation on the  MBean specified.
787     *
788     * @exception InstanceNotFoundException The MBean specified is not
789     *       registered in the MBean server.
790     * @exception MBeanException  Wraps an exception thrown by the MBean's
791     *       invoked method.
792     * @exception ReflectionException  Wraps an
793     *       <CODE>{@link java.lang.Exception}</CODE> thrown while trying
794     *        to invoke the method.
795     *
796     */
797    public Object invoke(ObjectName name, String operationName,
798                         Object params[], String signature[])
799        throws InstanceNotFoundException, MBeanException,
800               ReflectionException {
801        return mbsInterceptor.invoke(cloneObjectName(name), operationName,
802                                     params, signature);
803    }
804
805    /**
806     * Returns the default domain used for naming the MBean.
807     * The default domain name is used as the domain part in the ObjectName
808     * of MBeans if no domain is specified by the user.
809     */
810    public String getDefaultDomain()  {
811        return mbsInterceptor.getDefaultDomain();
812    }
813
814    // From MBeanServer
815    public String[] getDomains() {
816        return mbsInterceptor.getDomains();
817    }
818
819    /**
820     * Adds a listener to a registered MBean.
821     *
822     * @param name The name of the MBean on which the listener should be added.
823     * @param listener The listener object which will handle the
824     *        notifications emitted by the registered MBean.
825     * @param filter The filter object. If filter is null, no filtering
826     *        will be performed before handling notifications.
827     * @param handback The context to be sent to the listener when a
828     *        notification is emitted.
829     *
830     * @exception InstanceNotFoundException The MBean name provided does
831     *       not match any of the registered MBeans.
832     */
833    public void addNotificationListener(ObjectName name,
834                                        NotificationListener listener,
835                                        NotificationFilter filter,
836                                        Object handback)
837        throws InstanceNotFoundException {
838
839        mbsInterceptor.addNotificationListener(cloneObjectName(name), listener,
840                                               filter, handback);
841    }
842
843    /**
844     * Adds a listener to a registered MBean.
845     *
846     * @param name The name of the MBean on which the listener should be added.
847     * @param listener The object name of the listener which will handle the
848     *        notifications emitted by the registered MBean.
849     * @param filter The filter object. If filter is null, no filtering will
850     *        be performed before handling notifications.
851     * @param handback The context to be sent to the listener when a
852     *        notification is emitted.
853     *
854     * @exception InstanceNotFoundException The MBean name of the
855     *       notification listener or of the notification broadcaster
856     *       does not match any of the registered MBeans.
857     */
858    public void addNotificationListener(ObjectName name, ObjectName listener,
859                                   NotificationFilter filter, Object handback)
860        throws InstanceNotFoundException {
861
862        mbsInterceptor.addNotificationListener(cloneObjectName(name), listener,
863                                               filter, handback);
864    }
865
866    public void removeNotificationListener(ObjectName name,
867                                           NotificationListener listener)
868            throws InstanceNotFoundException, ListenerNotFoundException {
869
870        mbsInterceptor.removeNotificationListener(cloneObjectName(name),
871                                                  listener);
872    }
873
874    public void removeNotificationListener(ObjectName name,
875                                           NotificationListener listener,
876                                           NotificationFilter filter,
877                                           Object handback)
878            throws InstanceNotFoundException, ListenerNotFoundException {
879
880        mbsInterceptor.removeNotificationListener(cloneObjectName(name),
881                                                  listener, filter, handback);
882    }
883
884    public void removeNotificationListener(ObjectName name,
885                                           ObjectName listener)
886        throws InstanceNotFoundException, ListenerNotFoundException {
887
888        mbsInterceptor.removeNotificationListener(cloneObjectName(name),
889                                                  listener);
890    }
891
892    public void removeNotificationListener(ObjectName name,
893                                           ObjectName listener,
894                                           NotificationFilter filter,
895                                           Object handback)
896            throws InstanceNotFoundException, ListenerNotFoundException {
897
898        mbsInterceptor.removeNotificationListener(cloneObjectName(name),
899                                                  listener, filter, handback);
900    }
901
902    /**
903     * This method discovers the attributes and operations that an MBean exposes
904     * for management.
905     *
906     * @param name The name of the MBean to analyze
907     *
908     * @return  An instance of <CODE>MBeanInfo</CODE> allowing the retrieval of
909     * all attributes and operations of this MBean.
910     *
911     * @exception IntrospectionException An exception occurs during
912     * introspection.
913     * @exception InstanceNotFoundException The MBean specified is not found.
914     * @exception ReflectionException An exception occurred when trying to
915     * invoke the getMBeanInfo of a Dynamic MBean.
916     */
917    public MBeanInfo getMBeanInfo(ObjectName name) throws
918    InstanceNotFoundException, IntrospectionException, ReflectionException {
919
920        return mbsInterceptor.getMBeanInfo(cloneObjectName(name));
921    }
922
923    /**
924     * Instantiates an object using the list of all class loaders registered
925     * in the MBean server (using its
926     * {@link javax.management.loading.ClassLoaderRepository Default Loader Repository}).
927     * The object's class should have a public constructor.
928     * It returns a reference to the newly created object.
929     * The newly created object is not registered in the MBean server.
930     *
931     * @param className The class name of the object to be instantiated.
932     *
933     * @return The newly instantiated object.
934     *
935     * @exception ReflectionException Wraps the
936     *     <CODE>{@link java.lang.ClassNotFoundException}</CODE> or the
937     *     <CODE>{@link java.lang.Exception}</CODE> that
938     *     occurred when trying to invoke the object's constructor.
939     * @exception MBeanException The constructor of the object has thrown
940     *     an exception.
941     * @exception RuntimeOperationsException Wraps an
942     *     <CODE>{@link java.lang.IllegalArgumentException}</CODE>:
943     *     The className passed in parameter is null.
944     *
945     */
946    public Object instantiate(String className)
947        throws ReflectionException, MBeanException {
948
949        /* Permission check */
950        checkMBeanPermission(className, null, null, "instantiate");
951
952        return instantiator.instantiate(className);
953    }
954
955    /**
956     * Instantiates an object using the class Loader specified by its
957     * <CODE>ObjectName</CODE>.
958     * If the loader name is null, the ClassLoader that loaded the
959     * MBean Server will be used.
960     * The object's class should have a public constructor.
961     * It returns a reference to the newly created object.
962     * The newly created object is not registered in the MBean server.
963     *
964     * @param className The class name of the MBean to be instantiated.
965     * @param loaderName The object name of the class loader to be used.
966     *
967     * @return The newly instantiated object.
968     *
969     * @exception ReflectionException Wraps the
970     *     <CODE>{@link java.lang.ClassNotFoundException}</CODE> or the
971     *     <CODE>{@link java.lang.Exception}</CODE> that
972     *     occurred when trying to invoke the object's constructor.
973     * @exception MBeanException The constructor of the object has thrown
974     *     an exception.
975     * @exception InstanceNotFoundException The specified class loader
976     *     is not registered in the MBaenServer.
977     * @exception RuntimeOperationsException Wraps an
978     *     <CODE>{@link java.lang.IllegalArgumentException}</CODE>: The
979     *     className passed in parameter is null.
980     *
981     */
982    public Object instantiate(String className, ObjectName loaderName)
983        throws ReflectionException, MBeanException,
984               InstanceNotFoundException {
985
986        /* Permission check */
987        checkMBeanPermission(className, null, null, "instantiate");
988
989        ClassLoader myLoader = outerShell.getClass().getClassLoader();
990        return instantiator.instantiate(className, loaderName, myLoader);
991    }
992
993    /**
994     * Instantiates an object using the list of all class loaders registered
995     * in the MBean server (using its
996     * {@link javax.management.loading.ClassLoaderRepository Default Loader Repository}).
997     * The object's class should have a public constructor.
998     * The call returns a reference to the newly created object.
999     * The newly created object is not registered in the MBean server.
1000     *
1001     * @param className The class name of the object to be instantiated.
1002     * @param params An array containing the parameters of the constructor
1003     *     to be invoked.
1004     * @param signature An array containing the signature of the
1005     *     constructor to be invoked.
1006     *
1007     * @return The newly instantiated object.
1008     *
1009     * @exception ReflectionException Wraps the
1010     *     <CODE>{@link java.lang.ClassNotFoundException}</CODE> or the
1011     *     <CODE>{@link java.lang.Exception}</CODE> that
1012     *     occurred when trying to invoke the object's constructor.
1013     * @exception MBeanException The constructor of the object has thrown
1014     *     an exception.
1015     * @exception RuntimeOperationsException Wraps an
1016     *     <CODE>{@link java.lang.IllegalArgumentException}</CODE>:
1017     *     The className passed in parameter is null.
1018     *
1019     */
1020    public Object instantiate(String className, Object params[],
1021                              String signature[])
1022        throws ReflectionException, MBeanException {
1023
1024        /* Permission check */
1025        checkMBeanPermission(className, null, null, "instantiate");
1026
1027        ClassLoader myLoader = outerShell.getClass().getClassLoader();
1028        return instantiator.instantiate(className, params, signature,
1029                                        myLoader);
1030    }
1031
1032    /**
1033     * Instantiates an object. The class loader to be used is identified
1034     * by its object name. If the object name of the loader is null,
1035     * the ClassLoader that loaded the MBean server will be used.
1036     * The object's class should have a public constructor.
1037     * The call returns a reference to the newly created object.
1038     * The newly created object is not registered in the MBean server.
1039     *
1040     * @param className The class name of the object to be instantiated.
1041     * @param params An array containing the parameters of the constructor
1042     *     to be invoked.
1043     * @param signature An array containing the signature of the constructor
1044     *     to be invoked.
1045     * @param loaderName The object name of the class loader to be used.
1046     *
1047     * @return The newly instantiated object.
1048     *
1049     * @exception ReflectionException Wraps the
1050     *    <CODE>{@link java.lang.ClassNotFoundException}</CODE> or the
1051     *    <CODE>{@link java.lang.Exception}</CODE> that
1052     *    occurred when trying to invoke the object's constructor.
1053     * @exception MBeanException The constructor of the object has thrown
1054     *    an exception.
1055     * @exception InstanceNotFoundException The specified class loader
1056     *    is not registered in the MBean server.
1057     * @exception RuntimeOperationsException Wraps an
1058     *    <CODE>{@link java.lang.IllegalArgumentException}</CODE>:
1059     *    The className passed in parameter is null.
1060     *
1061     */
1062    public Object instantiate(String className, ObjectName loaderName,
1063                              Object params[], String signature[])
1064        throws ReflectionException, MBeanException,
1065               InstanceNotFoundException {
1066
1067        /* Permission check */
1068        checkMBeanPermission(className, null, null, "instantiate");
1069
1070        ClassLoader myLoader = outerShell.getClass().getClassLoader();
1071        return instantiator.instantiate(className,loaderName,params,signature,
1072                                        myLoader);
1073    }
1074
1075    /**
1076     * Returns true if the MBean specified is an instance of the specified
1077     * class, false otherwise.
1078     *
1079     * @param name The <CODE>ObjectName</CODE> of the MBean.
1080     * @param className The name of the class.
1081     *
1082     * @return true if the MBean specified is an instance of the specified
1083     *     class, false otherwise.
1084     *
1085     * @exception InstanceNotFoundException The MBean specified is not
1086     *     registered in the MBean server.
1087     */
1088    public boolean isInstanceOf(ObjectName name, String className)
1089        throws InstanceNotFoundException {
1090
1091        return mbsInterceptor.isInstanceOf(cloneObjectName(name), className);
1092    }
1093
1094    /**
1095     * De-serializes a byte array in the context of the class loader
1096     * of an MBean.
1097     *
1098     * @param name The name of the MBean whose class loader should
1099     *     be used for the de-serialization.
1100     * @param data The byte array to be de-sererialized.
1101     *
1102     * @return  The de-serialized object stream.
1103     *
1104     * @exception InstanceNotFoundException The MBean specified is not
1105     *     found.
1106     * @exception OperationsException Any of the usual Input/Output
1107     *     related exceptions.
1108     *
1109     */
1110    @Deprecated
1111    public ObjectInputStream deserialize(ObjectName name, byte[] data)
1112        throws InstanceNotFoundException, OperationsException {
1113
1114        /* Permission check */
1115        // This call requires MBeanPermission 'getClassLoaderFor'
1116        final ClassLoader loader = getClassLoaderFor(name);
1117
1118        return instantiator.deserialize(loader, data);
1119    }
1120
1121    /**
1122     * De-serializes a byte array in the context of a given MBean class loader.
1123     * The class loader is the one that loaded the class with name "className".
1124     *
1125     * @param className The name of the class whose class loader should be
1126     *      used for the de-serialization.
1127     * @param data The byte array to be de-sererialized.
1128     *
1129     * @return  The de-serialized object stream.
1130     *
1131     * @exception OperationsException Any of the usual Input/Output
1132     *      related exceptions.
1133     * @exception ReflectionException The specified class could not be
1134     *      loaded by the default loader repository
1135     *
1136     */
1137    @Deprecated
1138    public ObjectInputStream deserialize(String className, byte[] data)
1139        throws OperationsException, ReflectionException {
1140
1141        if (className == null) {
1142            throw new  RuntimeOperationsException(
1143                                        new IllegalArgumentException(),
1144                                        "Null className passed in parameter");
1145        }
1146
1147        /* Permission check */
1148        // This call requires MBeanPermission 'getClassLoaderRepository'
1149        final ClassLoaderRepository clr = getClassLoaderRepository();
1150
1151        Class<?> theClass;
1152        try {
1153            if (clr == null) throw new ClassNotFoundException(className);
1154            theClass = clr.loadClass(className);
1155        } catch (ClassNotFoundException e) {
1156            throw new ReflectionException(e,
1157                                          "The given class could not be " +
1158                                          "loaded by the default loader " +
1159                                          "repository");
1160        }
1161
1162        return instantiator.deserialize(theClass.getClassLoader(), data);
1163    }
1164
1165    /**
1166     * De-serializes a byte array in the context of a given MBean class loader.
1167     * The class loader is the one that loaded the class with name "className".
1168     * The name of the class loader to be used for loading the specified
1169     * class is specified.
1170     * If null, the MBean Server's class loader will be used.
1171     *
1172     * @param className The name of the class whose class loader should be
1173     *     used for the de-serialization.
1174     * @param data The byte array to be de-sererialized.
1175     * @param loaderName The name of the class loader to be used for
1176     *     loading the specified class.
1177     *     If null, the MBean Server's class loader will be used.
1178     *
1179     * @return  The de-serialized object stream.
1180     *
1181     * @exception InstanceNotFoundException The specified class loader
1182     *     MBean is not found.
1183     * @exception OperationsException Any of the usual Input/Output
1184     *     related exceptions.
1185     * @exception ReflectionException The specified class could not
1186     *     be loaded by the specified class loader.
1187     *
1188     */
1189    @Deprecated
1190    public ObjectInputStream deserialize(String className,
1191                                         ObjectName loaderName,
1192                                         byte[] data) throws
1193        InstanceNotFoundException, OperationsException, ReflectionException {
1194
1195        // Clone ObjectName
1196        //
1197        loaderName = cloneObjectName(loaderName);
1198
1199        /* Permission check */
1200        // Make this call just to force the 'getClassLoader'
1201        // permission check
1202        try {
1203            getClassLoader(loaderName);
1204        } catch (SecurityException e) {
1205            throw e;
1206        } catch (Exception e) {
1207        }
1208
1209        ClassLoader myLoader = outerShell.getClass().getClassLoader();
1210        return instantiator.deserialize(className, loaderName, data, myLoader);
1211    }
1212
1213    /**
1214     * Initializes this MBeanServer, registering the MBeanServerDelegate.
1215     * <p>This method must be called once, before using the MBeanServer.
1216     **/
1217    private void initialize() {
1218        if (instantiator == null) throw new
1219            IllegalStateException("instantiator must not be null.");
1220
1221        // Registers the MBeanServer identification MBean
1222        try {
1223            AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
1224                public Object run() throws Exception {
1225                    mbsInterceptor.registerMBean(
1226                            mBeanServerDelegateObject,
1227                            MBeanServerDelegate.DELEGATE_NAME);
1228                    return null;
1229                }
1230            });
1231        } catch (SecurityException e) {
1232            if (MBEANSERVER_LOGGER.isLoggable(Level.DEBUG)) {
1233                MBEANSERVER_LOGGER.log(Level.DEBUG,
1234                        "Unexpected security exception occurred", e);
1235            }
1236            throw e;
1237        } catch (Exception e) {
1238            if (MBEANSERVER_LOGGER.isLoggable(Level.DEBUG)) {
1239                MBEANSERVER_LOGGER.log(Level.DEBUG,
1240                        "Unexpected exception occurred", e);
1241            }
1242            throw new
1243                IllegalStateException("Can't register delegate.",e);
1244        }
1245
1246
1247        /* Add my class loader to the repository
1248           This can be null if my class loader is the bootstrap
1249           class loader.  The ClassLoaderRepository knows how
1250           to handle that case.  */
1251        ClassLoader myLoader = outerShell.getClass().getClassLoader();
1252        final ModifiableClassLoaderRepository loaders = AccessController.doPrivileged(new PrivilegedAction<ModifiableClassLoaderRepository>() {
1253
1254            @Override
1255            public ModifiableClassLoaderRepository run() {
1256                return instantiator.getClassLoaderRepository();
1257            }
1258        });
1259
1260        if (loaders != null) {
1261            loaders.addClassLoader(myLoader);
1262
1263            /* Add the system class loader, so that if the MBean server is
1264               loaded by the bootstrap class loader we can still load
1265               MBeans from the classpath using
1266               createMBean(className, objectName).
1267
1268               If this class (JmxMBeanServer) was not loaded by the
1269               system class loader or a parent of it, then the caller
1270               must have RuntimePermission("getClassLoader") for the
1271               getSystemClassLoader() call to succeed.  If the caller
1272               does not have that permission, any call to
1273               Class.getClassLoader() will fail.  Since there are lots
1274               of those in JMX, we better throw the exception now.
1275
1276               This permission question is irrelevant when JMX is part
1277               of J2SE (as of 1.5). */
1278            ClassLoader systemLoader = ClassLoader.getSystemClassLoader();
1279            if (systemLoader != myLoader)
1280                loaders.addClassLoader(systemLoader);
1281        }
1282    }
1283
1284    /**
1285     * Return the MBeanServerInterceptor.
1286     * @exception UnsupportedOperationException if
1287     *            {@link MBeanServerInterceptor}s
1288     *            are not enabled on this object.
1289     * @see #interceptorsEnabled
1290     **/
1291    public synchronized MBeanServer getMBeanServerInterceptor() {
1292        if (interceptorsEnabled) return mbsInterceptor;
1293        else throw new UnsupportedOperationException(
1294                       "MBeanServerInterceptors are disabled.");
1295    }
1296
1297    /**
1298     * Set the MBeanServerInterceptor.
1299     * @exception UnsupportedOperationException if
1300     *            {@link MBeanServerInterceptor}s
1301     *            are not enabled on this object.
1302     * @see #interceptorsEnabled
1303     **/
1304    public synchronized void
1305        setMBeanServerInterceptor(MBeanServer interceptor) {
1306        if (!interceptorsEnabled) throw new UnsupportedOperationException(
1307                       "MBeanServerInterceptors are disabled.");
1308        if (interceptor == null) throw new
1309            IllegalArgumentException("MBeanServerInterceptor is null");
1310        mbsInterceptor = interceptor;
1311    }
1312
1313    /**
1314     * <p>Return the {@link java.lang.ClassLoader} that was used for
1315     * loading the class of the named MBean.
1316     * @param mbeanName The ObjectName of the MBean.
1317     * @return The ClassLoader used for that MBean.
1318     * @exception InstanceNotFoundException if the named MBean is not found.
1319     */
1320    public ClassLoader getClassLoaderFor(ObjectName mbeanName)
1321        throws InstanceNotFoundException {
1322        return mbsInterceptor.getClassLoaderFor(cloneObjectName(mbeanName));
1323    }
1324
1325    /**
1326     * <p>Return the named {@link java.lang.ClassLoader}.
1327     * @param loaderName The ObjectName of the ClassLoader.
1328     * @return The named ClassLoader.
1329     * @exception InstanceNotFoundException if the named ClassLoader
1330     * is not found.
1331     */
1332    public ClassLoader getClassLoader(ObjectName loaderName)
1333        throws InstanceNotFoundException {
1334        return mbsInterceptor.getClassLoader(cloneObjectName(loaderName));
1335    }
1336
1337    /**
1338     * <p>Return the ClassLoaderRepository for that MBeanServer.
1339     * @return The ClassLoaderRepository for that MBeanServer.
1340     **/
1341    public ClassLoaderRepository getClassLoaderRepository() {
1342        /* Permission check */
1343        checkMBeanPermission(null, null, null, "getClassLoaderRepository");
1344        return secureClr;
1345    }
1346
1347    public MBeanServerDelegate getMBeanServerDelegate() {
1348        if (!interceptorsEnabled) throw new UnsupportedOperationException(
1349                       "MBeanServerInterceptors are disabled.");
1350        return mBeanServerDelegateObject;
1351    }
1352
1353    // These methods are called by the JMX MBeanServerBuilder.
1354
1355    /**
1356     * This method creates a new MBeanServerDelegate for a new MBeanServer.
1357     * When creating a new MBeanServer the
1358     * {@link javax.management.MBeanServerBuilder} first calls this method
1359     * in order to create a new MBeanServerDelegate.
1360     * <br>Then it calls
1361     * <code>newMBeanServer(defaultDomain,outer,delegate,interceptors)</code>
1362     * passing the <var>delegate</var> that should be used by the MBeanServer
1363     * implementation.
1364     * <p>Note that the passed <var>delegate</var> might not be directly the
1365     * MBeanServerDelegate that was returned by this method. It could
1366     * be, for instance, a new object wrapping the previously
1367     * returned object.
1368     *
1369     * @return A new {@link javax.management.MBeanServerDelegate}.
1370     **/
1371    public static MBeanServerDelegate newMBeanServerDelegate() {
1372        return new MBeanServerDelegateImpl();
1373    }
1374
1375    /**
1376     * This method creates a new MBeanServer implementation object.
1377     * When creating a new MBeanServer the
1378     * {@link javax.management.MBeanServerBuilder} first calls
1379     * <code>newMBeanServerDelegate()</code> in order to obtain a new
1380     * {@link javax.management.MBeanServerDelegate} for the new
1381     * MBeanServer. Then it calls
1382     * <code>newMBeanServer(defaultDomain,outer,delegate)</code>
1383     * passing the <var>delegate</var> that should be used by the
1384     * MBeanServer  implementation.
1385     * <p>Note that the passed <var>delegate</var> might not be directly the
1386     * MBeanServerDelegate that was returned by this implementation. It could
1387     * be, for instance, a new object wrapping the previously
1388     * returned delegate.
1389     * <p>The <var>outer</var> parameter is a pointer to the MBeanServer that
1390     * should be passed to the {@link javax.management.MBeanRegistration}
1391     * interface when registering MBeans inside the MBeanServer.
1392     * If <var>outer</var> is <code>null</code>, then the MBeanServer
1393     * implementation is free to use its own <code>this</code> pointer when
1394     * invoking the {@link javax.management.MBeanRegistration} interface.
1395     * <p>This makes it possible for a MBeanServer implementation to wrap
1396     * another MBeanServer implementation, in order to implement, e.g,
1397     * security checks, or to prevent access to the actual MBeanServer
1398     * implementation by returning a pointer to a wrapping object.
1399     *
1400     * @param defaultDomain Default domain of the new MBeanServer.
1401     * @param outer A pointer to the MBeanServer object that must be
1402     *        passed to the MBeans when invoking their
1403     *        {@link javax.management.MBeanRegistration} interface.
1404     * @param delegate A pointer to the MBeanServerDelegate associated
1405     *        with the new MBeanServer. The new MBeanServer must register
1406     *        this MBean in its MBean repository.
1407     * @param interceptors If <code>true</code>,
1408     *        {@link MBeanServerInterceptor}s will be enabled (default is
1409     *        <code>false</code>).
1410     *        Note: this parameter is not taken into account by this
1411     *        implementation - the default value <code>false</code> is
1412     *        always used.
1413     * @return A new private implementation of an MBeanServer.
1414     * @see #interceptorsEnabled
1415     * @see javax.management.MBeanServerBuilder
1416     * @see com.sun.jmx.mbeanserver.JmxMBeanServerBuilder
1417     **/
1418    public static MBeanServer newMBeanServer(String defaultDomain,
1419                                             MBeanServer outer,
1420                                             MBeanServerDelegate delegate,
1421                                             boolean interceptors) {
1422        // Determine whether to use fair locking for the repository.
1423        // Default is true.
1424        final boolean fairLock = DEFAULT_FAIR_LOCK_POLICY;
1425
1426        checkNewMBeanServerPermission();
1427
1428        // This constructor happens to disregard the value of the interceptors
1429        // flag - that is, it always uses the default value - false.
1430        // This is admitedly a bug, but we chose not to fix it for now
1431        // since we would rather not have anybody depending on the Sun private
1432        // interceptor APIs - which is most probably going to be removed and
1433        // replaced by a public (javax) feature in the future.
1434        //
1435        return new JmxMBeanServer(defaultDomain,outer,delegate,null,
1436                                  interceptors,fairLock);
1437    }
1438
1439    // JMX OBJECT CLONING
1440    //-------------------
1441
1442    /**
1443     * Clone object name.
1444     */
1445    private ObjectName cloneObjectName(ObjectName name) {
1446        if (name != null) {
1447            return ObjectName.getInstance(name);
1448        }
1449        return name;
1450    }
1451
1452    /**
1453     * Clone attribute.
1454     */
1455    private Attribute cloneAttribute(Attribute attribute) {
1456        if (attribute != null) {
1457            if (!attribute.getClass().equals(Attribute.class)) {
1458                return new Attribute(attribute.getName(), attribute.getValue());
1459            }
1460        }
1461        return attribute;
1462    }
1463
1464    /**
1465     * Clone attribute list.
1466     */
1467    private AttributeList cloneAttributeList(AttributeList list) {
1468        if (list != null) {
1469            List<Attribute> alist = list.asList();
1470            if (!list.getClass().equals(AttributeList.class)) {
1471                // Create new attribute list
1472                //
1473                AttributeList newList = new AttributeList(alist.size());
1474
1475                // Iterate through list and replace non JMX attributes
1476                //
1477                for (Attribute attribute : alist)
1478                    newList.add(cloneAttribute(attribute));
1479                return newList;
1480            } else {
1481                // Iterate through list and replace non JMX attributes
1482                //
1483                for (int i = 0; i < alist.size(); i++) {
1484                    Attribute attribute = alist.get(i);
1485                    if (!attribute.getClass().equals(Attribute.class)) {
1486                        list.set(i, cloneAttribute(attribute));
1487                    }
1488                }
1489                return list;
1490            }
1491        }
1492        return list;
1493    }
1494
1495    // SECURITY CHECKS
1496    //----------------
1497
1498    private static void checkMBeanPermission(String classname,
1499                                             String member,
1500                                             ObjectName objectName,
1501                                             String actions)
1502        throws SecurityException {
1503        SecurityManager sm = System.getSecurityManager();
1504        if (sm != null) {
1505            Permission perm = new MBeanPermission(classname,
1506                                                  member,
1507                                                  objectName,
1508                                                  actions);
1509            sm.checkPermission(perm);
1510        }
1511    }
1512
1513    private static void checkNewMBeanServerPermission() {
1514        SecurityManager sm = System.getSecurityManager();
1515        if (sm != null) {
1516            Permission perm = new MBeanServerPermission("newMBeanServer");
1517            sm.checkPermission(perm);
1518        }
1519    }
1520}
1521