1/*
2 * Copyright (c) 2000, 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
28
29import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER;
30import java.io.ByteArrayInputStream;
31import java.io.IOException;
32import java.io.ObjectInputStream;
33import java.lang.reflect.Constructor;
34import java.lang.reflect.InvocationTargetException;
35import java.lang.reflect.Modifier;
36import java.security.AccessControlContext;
37import java.security.AccessController;
38import java.security.Permission;
39import java.security.Permissions;
40import java.security.PrivilegedAction;
41import java.security.ProtectionDomain;
42import java.util.Map;
43import java.lang.System.Logger.Level;
44
45import javax.management.InstanceNotFoundException;
46import javax.management.MBeanException;
47import javax.management.MBeanPermission;
48import javax.management.NotCompliantMBeanException;
49import javax.management.ObjectName;
50import javax.management.OperationsException;
51import javax.management.ReflectionException;
52import javax.management.RuntimeErrorException;
53import javax.management.RuntimeMBeanException;
54import javax.management.RuntimeOperationsException;
55import sun.reflect.misc.ConstructorUtil;
56import sun.reflect.misc.ReflectUtil;
57
58/**
59 * Implements the MBeanInstantiator interface. Provides methods for
60 * instantiating objects, finding the class given its name and using
61 * different class loaders, deserializing objects in the context of a
62 * given class loader.
63 *
64 * @since 1.5
65 */
66public class MBeanInstantiator {
67    private final ModifiableClassLoaderRepository clr;
68    //    private MetaData meta = null;
69
70    MBeanInstantiator(ModifiableClassLoaderRepository clr) {
71        this.clr = clr;
72    }
73
74
75    /**
76     * This methods tests if the MBean class makes it possible to
77     * instantiate an MBean of this class in the MBeanServer.
78     * e.g. it must have a public constructor, be a concrete class...
79     */
80    public void testCreation(Class<?> c) throws NotCompliantMBeanException {
81        Introspector.testCreation(c);
82    }
83
84    /**
85     * Loads the class with the specified name using this object's
86     * Default Loader Repository.
87     **/
88    public Class<?> findClassWithDefaultLoaderRepository(String className)
89        throws ReflectionException {
90
91        Class<?> theClass;
92        if (className == null) {
93            throw new RuntimeOperationsException(new
94                IllegalArgumentException("The class name cannot be null"),
95                             "Exception occurred during object instantiation");
96        }
97
98        ReflectUtil.checkPackageAccess(className);
99        try {
100            if (clr == null) throw new ClassNotFoundException(className);
101            theClass = clr.loadClass(className);
102        }
103        catch (ClassNotFoundException ee) {
104            throw new ReflectionException(ee,
105       "The MBean class could not be loaded by the default loader repository");
106        }
107
108        return theClass;
109    }
110
111
112    /**
113     * Gets the class for the specified class name using the MBean
114     * Interceptor's classloader
115     */
116    public Class<?> findClass(String className, ClassLoader loader)
117        throws ReflectionException {
118
119        return loadClass(className,loader);
120    }
121
122    /**
123     * Gets the class for the specified class name using the specified
124     * class loader
125     */
126    public Class<?> findClass(String className, ObjectName aLoader)
127        throws ReflectionException, InstanceNotFoundException  {
128
129        if (aLoader == null)
130            throw new RuntimeOperationsException(new
131                IllegalArgumentException(), "Null loader passed in parameter");
132
133        // Retrieve the class loader from the repository
134        ClassLoader loader = null;
135        synchronized (this) {
136            loader = getClassLoader(aLoader);
137        }
138        if (loader == null) {
139            throw new InstanceNotFoundException("The loader named " +
140                       aLoader + " is not registered in the MBeanServer");
141        }
142        return findClass(className,loader);
143    }
144
145
146    /**
147     * Return an array of Class corresponding to the given signature, using
148     * the specified class loader.
149     */
150    public Class<?>[] findSignatureClasses(String signature[],
151                                           ClassLoader loader)
152        throws ReflectionException {
153
154        if (signature == null) return null;
155        final ClassLoader aLoader = loader;
156        final int length= signature.length;
157        final Class<?> tab[]=new Class<?>[length];
158
159        if (length == 0) return tab;
160        try {
161            for (int i= 0; i < length; i++) {
162                // Start handling primitive types (int. boolean and so
163                // forth)
164                //
165
166                final Class<?> primCla = primitiveClasses.get(signature[i]);
167                if (primCla != null) {
168                    tab[i] = primCla;
169                    continue;
170                }
171
172                ReflectUtil.checkPackageAccess(signature[i]);
173                // Ok we do not have a primitive type ! We need to build
174                // the signature of the method
175                //
176                if (aLoader != null) {
177                    // We need to load the class through the class
178                    // loader of the target object.
179                    //
180                    tab[i] = Class.forName(signature[i], false, aLoader);
181                } else {
182                    // Load through the default class loader
183                    //
184                    tab[i] = findClass(signature[i],
185                                       this.getClass().getClassLoader());
186                }
187            }
188        } catch (ClassNotFoundException e) {
189            if (MBEANSERVER_LOGGER.isLoggable(Level.DEBUG)) {
190                MBEANSERVER_LOGGER.log(Level.DEBUG,
191                        "The parameter class could not be found", e);
192            }
193            throw new ReflectionException(e,
194                      "The parameter class could not be found");
195        } catch (RuntimeException e) {
196            if (MBEANSERVER_LOGGER.isLoggable(Level.DEBUG)) {
197                MBEANSERVER_LOGGER.log(Level.DEBUG,
198                        "Unexpected exception", e);
199            }
200            throw e;
201        }
202        return tab;
203    }
204
205
206    /**
207     * Instantiates an object given its class, using its empty constructor.
208     * The call returns a reference to the newly created object.
209     */
210    public Object instantiate(Class<?> theClass)
211        throws ReflectionException, MBeanException {
212
213        checkMBeanPermission(theClass, null, null, "instantiate");
214
215        Object moi;
216
217        // ------------------------------
218        // ------------------------------
219        Constructor<?> cons = findConstructor(theClass, null);
220        if (cons == null) {
221            throw new ReflectionException(new
222                NoSuchMethodException("No such constructor"));
223        }
224        // Instantiate the new object
225        try {
226            ReflectUtil.checkPackageAccess(theClass);
227            ensureClassAccess(theClass);
228            moi= cons.newInstance();
229        } catch (InvocationTargetException e) {
230            // Wrap the exception.
231            Throwable t = e.getTargetException();
232            if (t instanceof RuntimeException) {
233                throw new RuntimeMBeanException((RuntimeException)t,
234                   "RuntimeException thrown in the MBean's empty constructor");
235            } else if (t instanceof Error) {
236                throw new RuntimeErrorException((Error) t,
237                   "Error thrown in the MBean's empty constructor");
238            } else {
239                throw new MBeanException((Exception) t,
240                   "Exception thrown in the MBean's empty constructor");
241            }
242        } catch (NoSuchMethodError error) {
243            throw new ReflectionException(new
244                NoSuchMethodException("No constructor"),
245                                          "No such constructor");
246        } catch (InstantiationException e) {
247            throw new ReflectionException(e,
248            "Exception thrown trying to invoke the MBean's empty constructor");
249        } catch (IllegalAccessException e) {
250            throw new ReflectionException(e,
251            "Exception thrown trying to invoke the MBean's empty constructor");
252        } catch (IllegalArgumentException e) {
253            throw new ReflectionException(e,
254            "Exception thrown trying to invoke the MBean's empty constructor");
255        }
256        return moi;
257
258    }
259
260
261
262   /**
263     * Instantiates an object given its class, the parameters and
264     * signature of its constructor The call returns a reference to
265     * the newly created object.
266     */
267    public Object instantiate(Class<?> theClass, Object params[],
268                              String signature[], ClassLoader loader)
269        throws ReflectionException, MBeanException {
270
271        checkMBeanPermission(theClass, null, null, "instantiate");
272
273        // Instantiate the new object
274        // ------------------------------
275        // ------------------------------
276        final Class<?>[] tab;
277        Object moi;
278        try {
279            // Build the signature of the method
280            //
281            ClassLoader aLoader= theClass.getClassLoader();
282            // Build the signature of the method
283            //
284            tab =
285                ((signature == null)?null:
286                 findSignatureClasses(signature,aLoader));
287        }
288        // Exception IllegalArgumentException raised in Jdk1.1.8
289        catch (IllegalArgumentException e) {
290            throw new ReflectionException(e,
291                    "The constructor parameter classes could not be loaded");
292        }
293
294        // Query the metadata service to get the right constructor
295        Constructor<?> cons = findConstructor(theClass, tab);
296
297        if (cons == null) {
298            throw new ReflectionException(new
299                NoSuchMethodException("No such constructor"));
300        }
301        try {
302            ReflectUtil.checkPackageAccess(theClass);
303            ensureClassAccess(theClass);
304            moi = cons.newInstance(params);
305        }
306        catch (NoSuchMethodError error) {
307            throw new ReflectionException(new
308                NoSuchMethodException("No such constructor found"),
309                                          "No such constructor" );
310        }
311        catch (InstantiationException e) {
312            throw new ReflectionException(e,
313                "Exception thrown trying to invoke the MBean's constructor");
314        }
315        catch (IllegalAccessException e) {
316            throw new ReflectionException(e,
317                "Exception thrown trying to invoke the MBean's constructor");
318        }
319        catch (InvocationTargetException e) {
320            // Wrap the exception.
321            Throwable th = e.getTargetException();
322            if (th instanceof RuntimeException) {
323                throw new RuntimeMBeanException((RuntimeException)th,
324                      "RuntimeException thrown in the MBean's constructor");
325            } else if (th instanceof Error) {
326                throw new RuntimeErrorException((Error) th,
327                      "Error thrown in the MBean's constructor");
328            } else {
329                throw new MBeanException((Exception) th,
330                      "Exception thrown in the MBean's constructor");
331            }
332        }
333        return moi;
334    }
335
336    /**
337     * De-serializes a byte array in the context of a classloader.
338     *
339     * @param loader the classloader to use for de-serialization
340     * @param data The byte array to be de-sererialized.
341     *
342     * @return  The de-serialized object stream.
343     *
344     * @exception OperationsException Any of the usual Input/Output related
345     * exceptions.
346     */
347    public ObjectInputStream deserialize(ClassLoader loader, byte[] data)
348        throws OperationsException {
349
350        // Check parameter validity
351        if (data == null) {
352            throw new  RuntimeOperationsException(new
353                IllegalArgumentException(), "Null data passed in parameter");
354        }
355        if (data.length == 0) {
356            throw new  RuntimeOperationsException(new
357                IllegalArgumentException(), "Empty data passed in parameter");
358        }
359
360        // Object deserialization
361        ByteArrayInputStream bIn;
362        ObjectInputStream    objIn;
363
364        bIn   = new ByteArrayInputStream(data);
365        try {
366            objIn = new ObjectInputStreamWithLoader(bIn,loader);
367        } catch (IOException e) {
368            throw new OperationsException(
369                     "An IOException occurred trying to de-serialize the data");
370        }
371
372        return objIn;
373    }
374
375    /**
376     * De-serializes a byte array in the context of a given MBean class loader.
377     * <P>The class loader is the one that loaded the class with name
378     * "className".
379     * <P>The name of the class loader to be used for loading the specified
380     * class is specified. If null, a default one has to be provided (for a
381     * MBean Server, its own class loader will be used).
382     *
383     * @param className The name of the class whose class loader should
384     *  be used for the de-serialization.
385     * @param data The byte array to be de-sererialized.
386     * @param loaderName The name of the class loader to be used for loading
387     * the specified class. If null, a default one has to be provided (for a
388     * MBean Server, its own class loader will be used).
389     *
390     * @return  The de-serialized object stream.
391     *
392     * @exception InstanceNotFoundException The specified class loader MBean is
393     * not found.
394     * @exception OperationsException Any of the usual Input/Output related
395     * exceptions.
396     * @exception ReflectionException The specified class could not be loaded
397     * by the specified class loader.
398     */
399    public ObjectInputStream deserialize(String className,
400                                         ObjectName loaderName,
401                                         byte[] data,
402                                         ClassLoader loader)
403        throws InstanceNotFoundException,
404               OperationsException,
405               ReflectionException  {
406
407        // Check parameter validity
408        if (data == null) {
409            throw new  RuntimeOperationsException(new
410                IllegalArgumentException(), "Null data passed in parameter");
411        }
412        if (data.length == 0) {
413            throw new  RuntimeOperationsException(new
414                IllegalArgumentException(), "Empty data passed in parameter");
415        }
416        if (className == null) {
417            throw new  RuntimeOperationsException(new
418             IllegalArgumentException(), "Null className passed in parameter");
419        }
420
421        ReflectUtil.checkPackageAccess(className);
422        Class<?> theClass;
423        if (loaderName == null) {
424            // Load the class using the agent class loader
425            theClass = findClass(className, loader);
426
427        } else {
428            // Get the class loader MBean
429            try {
430                ClassLoader instance = null;
431
432                instance = getClassLoader(loaderName);
433                if (instance == null)
434                    throw new ClassNotFoundException(className);
435                theClass = Class.forName(className, false, instance);
436            }
437            catch (ClassNotFoundException e) {
438                throw new ReflectionException(e,
439                               "The MBean class could not be loaded by the " +
440                               loaderName.toString() + " class loader");
441            }
442        }
443
444        // Object deserialization
445        ByteArrayInputStream bIn;
446        ObjectInputStream    objIn;
447
448        bIn   = new ByteArrayInputStream(data);
449        try {
450            objIn = new ObjectInputStreamWithLoader(bIn,
451                                           theClass.getClassLoader());
452        } catch (IOException e) {
453            throw new OperationsException(
454                    "An IOException occurred trying to de-serialize the data");
455        }
456
457        return objIn;
458    }
459
460
461    /**
462     * Instantiates an object using the list of all class loaders registered
463     * in the MBean Interceptor
464     * (using its {@link javax.management.loading.ClassLoaderRepository}).
465     * <P>The object's class should have a public constructor.
466     * <P>It returns a reference to the newly created object.
467     * <P>The newly created object is not registered in the MBean Interceptor.
468     *
469     * @param className The class name of the object to be instantiated.
470     *
471     * @return The newly instantiated object.
472     *
473     * @exception ReflectionException Wraps a
474     * <CODE>java.lang.ClassNotFoundException</CODE> or the
475     * <CODE>java.lang.Exception</CODE> that occurred when trying to invoke the
476     * object's constructor.
477     * @exception MBeanException The constructor of the object has thrown an
478     * exception
479     * @exception RuntimeOperationsException Wraps a
480     * <CODE>java.lang.IllegalArgumentException</CODE>: the className passed in
481     * parameter is null.
482     */
483    public Object instantiate(String className)
484        throws ReflectionException,
485        MBeanException {
486
487        return instantiate(className, (Object[]) null, (String[]) null, null);
488    }
489
490
491
492    /**
493     * Instantiates an object using the class Loader specified by its
494     * <CODE>ObjectName</CODE>.
495     * <P>If the loader name is null, a default one has to be provided (for a
496     * MBean Server, the ClassLoader that loaded it will be used).
497     * <P>The object's class should have a public constructor.
498     * <P>It returns a reference to the newly created object.
499     * <P>The newly created object is not registered in the MBean Interceptor.
500     *
501     * @param className The class name of the MBean to be instantiated.
502     * @param loaderName The object name of the class loader to be used.
503     *
504     * @return The newly instantiated object.
505     *
506     * @exception ReflectionException Wraps a
507     * <CODE>java.lang.ClassNotFoundException</CODE> or the
508     * <CODE>java.lang.Exception</CODE> that occurred when trying to invoke the
509     * object's constructor.
510     * @exception MBeanException The constructor of the object has thrown an
511     * exception.
512     * @exception InstanceNotFoundException The specified class loader is not
513     * registered in the MBeanServerInterceptor.
514     * @exception RuntimeOperationsException Wraps a
515     * <CODE>java.lang.IllegalArgumentException</CODE>: the className passed in
516     * parameter is null.
517     */
518    public Object instantiate(String className, ObjectName loaderName,
519                              ClassLoader loader)
520        throws ReflectionException, MBeanException,
521               InstanceNotFoundException {
522
523        return instantiate(className, loaderName, (Object[]) null,
524                           (String[]) null, loader);
525    }
526
527
528    /**
529     * Instantiates an object using the list of all class loaders registered
530     * in the MBean server
531     * (using its {@link javax.management.loading.ClassLoaderRepository}).
532     * <P>The object's class should have a public constructor.
533     * <P>The call returns a reference to the newly created object.
534     * <P>The newly created object is not registered in the MBean Interceptor.
535     *
536     * @param className The class name of the object to be instantiated.
537     * @param params An array containing the parameters of the constructor to
538     * be invoked.
539     * @param signature An array containing the signature of the constructor to
540     * be invoked.
541     *
542     * @return The newly instantiated object.
543     *
544     * @exception ReflectionException Wraps a
545     * <CODE>java.lang.ClassNotFoundException</CODE> or the
546     * <CODE>java.lang.Exception</CODE> that occurred when trying to invoke the
547     * object's constructor.
548     * @exception MBeanException The constructor of the object has thrown an
549     * exception
550     * @exception RuntimeOperationsException Wraps a
551     * <CODE>java.lang.IllegalArgumentException</CODE>: the className passed in
552     * parameter is null.
553     */
554    public Object instantiate(String className,
555                              Object params[],
556                              String signature[],
557                              ClassLoader loader)
558        throws ReflectionException,
559        MBeanException {
560
561        Class<?> theClass = findClassWithDefaultLoaderRepository(className);
562        return instantiate(theClass, params, signature, loader);
563    }
564
565
566
567    /**
568     * Instantiates an object. The class loader to be used is identified by its
569     * object name.
570     * <P>If the object name of the loader is null, a default has to be
571     * provided (for example, for a MBean Server, the ClassLoader that loaded
572     * it will be used).
573     * <P>The object's class should have a public constructor.
574     * <P>The call returns a reference to the newly created object.
575     * <P>The newly created object is not registered in the MBean server.
576     *
577     * @param className The class name of the object to be instantiated.
578     * @param params An array containing the parameters of the constructor to
579     * be invoked.
580     * @param signature An array containing the signature of the constructor to
581     * be invoked.
582     * @param loaderName The object name of the class loader to be used.
583     *
584     * @return The newly instantiated object.
585     *
586     * @exception ReflectionException Wraps a
587     * <CODE>java.lang.ClassNotFoundException</CODE> or the
588     * <CODE>java.lang.Exception</CODE> that occurred when trying to invoke the
589     * object's constructor.
590     * @exception MBeanException The constructor of the object has thrown an
591     * exception
592     * @exception InstanceNotFoundException The specified class loader is not
593     * registered in the MBean Interceptor.
594     * @exception RuntimeOperationsException Wraps a
595     * <CODE>java.lang.IllegalArgumentException</CODE>: the className passed in
596     * parameter is null.
597     */
598    public Object instantiate(String className,
599                              ObjectName loaderName,
600                              Object params[],
601                              String signature[],
602                              ClassLoader loader)
603        throws ReflectionException,
604               MBeanException,
605        InstanceNotFoundException {
606
607        // ------------------------------
608        // ------------------------------
609        Class<?> theClass;
610
611        if (loaderName == null) {
612            theClass = findClass(className, loader);
613        } else {
614            theClass = findClass(className, loaderName);
615        }
616        return instantiate(theClass, params, signature, loader);
617    }
618
619
620    /**
621     * Return the Default Loader Repository used by this instantiator object.
622     **/
623    public ModifiableClassLoaderRepository getClassLoaderRepository() {
624        checkMBeanPermission((String)null, null, null, "getClassLoaderRepository");
625        return clr;
626    }
627
628    /**
629     * Load a class with the specified loader, or with this object
630     * class loader if the specified loader is null.
631     **/
632    static Class<?> loadClass(String className, ClassLoader loader)
633        throws ReflectionException {
634        Class<?> theClass;
635        if (className == null) {
636            throw new RuntimeOperationsException(new
637                IllegalArgumentException("The class name cannot be null"),
638                              "Exception occurred during object instantiation");
639        }
640        ReflectUtil.checkPackageAccess(className);
641        try {
642            if (loader == null)
643                loader = MBeanInstantiator.class.getClassLoader();
644            if (loader != null) {
645                theClass = Class.forName(className, false, loader);
646            } else {
647                theClass = Class.forName(className);
648            }
649        } catch (ClassNotFoundException e) {
650            throw new ReflectionException(e,
651            "The MBean class could not be loaded");
652        }
653        return theClass;
654    }
655
656
657
658    /**
659     * Load the classes specified in the signature with the given loader,
660     * or with this object class loader.
661     **/
662    static Class<?>[] loadSignatureClasses(String signature[],
663                                           ClassLoader loader)
664        throws  ReflectionException {
665
666        if (signature == null) return null;
667        final ClassLoader aLoader =
668           (loader==null?MBeanInstantiator.class.getClassLoader():loader);
669        final int length= signature.length;
670        final Class<?> tab[]=new Class<?>[length];
671
672        if (length == 0) return tab;
673        try {
674            for (int i= 0; i < length; i++) {
675                // Start handling primitive types (int. boolean and so
676                // forth)
677                //
678
679                final Class<?> primCla = primitiveClasses.get(signature[i]);
680                if (primCla != null) {
681                    tab[i] = primCla;
682                    continue;
683                }
684
685                // Ok we do not have a primitive type ! We need to build
686                // the signature of the method
687                //
688                // We need to load the class through the class
689                // loader of the target object.
690                //
691                ReflectUtil.checkPackageAccess(signature[i]);
692                tab[i] = Class.forName(signature[i], false, aLoader);
693            }
694        } catch (ClassNotFoundException e) {
695            if (MBEANSERVER_LOGGER.isLoggable(Level.DEBUG)) {
696                MBEANSERVER_LOGGER.log(Level.DEBUG,
697                        "The parameter class could not be found", e);
698            }
699            throw new ReflectionException(e,
700                      "The parameter class could not be found");
701        } catch (RuntimeException e) {
702            if (MBEANSERVER_LOGGER.isLoggable(Level.DEBUG)) {
703                MBEANSERVER_LOGGER.log(Level.DEBUG,
704                        "Unexpected exception", e);
705            }
706            throw e;
707        }
708        return tab;
709    }
710
711    private Constructor<?> findConstructor(Class<?> c, Class<?>[] params) {
712        try {
713            return ConstructorUtil.getConstructor(c, params);
714        } catch (Exception e) {
715            return null;
716        }
717    }
718
719
720    private static final Map<String, Class<?>> primitiveClasses = Util.newMap();
721    static {
722        for (Class<?> c : new Class<?>[] {byte.class, short.class, int.class,
723                                          long.class, float.class, double.class,
724                                          char.class, boolean.class})
725            primitiveClasses.put(c.getName(), c);
726    }
727
728    private static void checkMBeanPermission(Class<?> clazz,
729                                             String member,
730                                             ObjectName objectName,
731                                             String actions) {
732        if (clazz != null) {
733            checkMBeanPermission(clazz.getName(), member, objectName, actions);
734        }
735    }
736
737    private static void checkMBeanPermission(String classname,
738                                             String member,
739                                             ObjectName objectName,
740                                             String actions)
741        throws SecurityException {
742        SecurityManager sm = System.getSecurityManager();
743        if (sm != null) {
744            Permission perm = new MBeanPermission(classname,
745                                                  member,
746                                                  objectName,
747                                                  actions);
748            sm.checkPermission(perm);
749        }
750    }
751
752    private static void ensureClassAccess(Class<?> clazz)
753            throws IllegalAccessException
754    {
755        int mod = clazz.getModifiers();
756        if (!Modifier.isPublic(mod)) {
757            throw new IllegalAccessException("Class is not public and can't be instantiated");
758        }
759    }
760
761    private ClassLoader getClassLoader(final ObjectName name) {
762        if(clr == null){
763            return null;
764        }
765        // Restrict to getClassLoader permission only
766        Permissions permissions = new Permissions();
767        permissions.add(new MBeanPermission("*", null, name, "getClassLoader"));
768        ProtectionDomain protectionDomain = new ProtectionDomain(null, permissions);
769        ProtectionDomain[] domains = {protectionDomain};
770        AccessControlContext ctx = new AccessControlContext(domains);
771        ClassLoader loader = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
772            public ClassLoader run() {
773                return clr.getClassLoader(name);
774            }
775        }, ctx);
776        return loader;
777    }
778}
779