jdk/src/share/classes/com/sun/jmx/mbeanserver/MBeanInjector.java
author emcmanus
Tue, 09 Dec 2008 12:01:07 +0100
changeset 1697 98a530cd0594
parent 1247 b4c26443dee5
permissions -rw-r--r--
6774918: @NotificationInfo is ineffective on MBeans that cannot send notifications Reviewed-by: jfdenise
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
833
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
     1
/*
1247
b4c26443dee5 6754988: Update copyright year
xdono
parents: 1004
diff changeset
     2
 * Copyright 2007-2008 Sun Microsystems, Inc.  All Rights Reserved.
833
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
     4
 *
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Sun designates this
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
     9
 * by Sun in the LICENSE file that accompanied this code.
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    10
 *
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    15
 * accompanied this code).
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    16
 *
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    20
 *
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    21
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    22
 * CA 95054 USA or visit www.sun.com if you need additional information or
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    23
 * have any questions.
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    24
 */
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    25
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    26
package com.sun.jmx.mbeanserver;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    27
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    28
import java.lang.ref.WeakReference;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    29
import java.security.PrivilegedAction;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    30
import java.util.Map;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    31
import java.util.WeakHashMap;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    32
import javax.annotation.Resource;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    33
import javax.management.MBeanServer;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    34
import javax.management.NotCompliantMBeanException;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    35
import javax.management.ObjectName;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    36
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    37
import static com.sun.jmx.mbeanserver.Util.newMap;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    38
import java.lang.reflect.AccessibleObject;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    39
import java.lang.reflect.Field;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    40
import java.lang.reflect.InvocationTargetException;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    41
import java.lang.reflect.Method;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    42
import java.lang.reflect.Modifier;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    43
import java.security.AccessController;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    44
import java.util.ArrayList;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    45
import java.util.Collections;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    46
import java.util.List;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    47
import javax.management.SendNotification;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    48
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    49
public class MBeanInjector {
1697
98a530cd0594 6774918: @NotificationInfo is ineffective on MBeans that cannot send notifications
emcmanus
parents: 1247
diff changeset
    50
    // There are no instances of this class
98a530cd0594 6774918: @NotificationInfo is ineffective on MBeans that cannot send notifications
emcmanus
parents: 1247
diff changeset
    51
    private MBeanInjector() {
98a530cd0594 6774918: @NotificationInfo is ineffective on MBeans that cannot send notifications
emcmanus
parents: 1247
diff changeset
    52
    }
98a530cd0594 6774918: @NotificationInfo is ineffective on MBeans that cannot send notifications
emcmanus
parents: 1247
diff changeset
    53
833
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    54
    private static Class<?>[] injectedClasses = {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    55
        MBeanServer.class, ObjectName.class, SendNotification.class,
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    56
    };
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    57
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    58
    public static void inject(Object mbean, MBeanServer mbs, ObjectName name)
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    59
    throws Exception {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    60
        ClassInjector injector = injectorForClass(mbean.getClass());
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    61
        injector.inject(mbean, MBeanServer.class, mbs);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    62
        injector.inject(mbean, ObjectName.class, name);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    63
    }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    64
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    65
    public static boolean injectsSendNotification(Object mbean)
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    66
    throws NotCompliantMBeanException {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    67
        ClassInjector injector = injectorForClass(mbean.getClass());
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    68
        return injector.injects(SendNotification.class);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    69
    }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    70
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    71
    public static void injectSendNotification(Object mbean, SendNotification sn)
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    72
    throws Exception {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    73
        ClassInjector injector = injectorForClass(mbean.getClass());
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    74
        injector.inject(mbean, SendNotification.class, sn);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    75
    }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    76
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    77
    public static void validate(Class<?> c) throws NotCompliantMBeanException {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    78
        injectorForClass(c);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    79
    }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    80
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    81
    private static class ClassInjector {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    82
        private Map<Class<?>, List<Field>> fields;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    83
        private Map<Class<?>, List<Method>> methods;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    84
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    85
        ClassInjector(Class<?> c) throws NotCompliantMBeanException {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    86
            fields = newMap();
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    87
            methods = newMap();
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    88
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    89
            Class<?> sup = c.getSuperclass();
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    90
            ClassInjector supInjector;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    91
            if (sup == null) {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    92
                supInjector = null;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    93
            } else {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    94
                supInjector = injectorForClass(sup);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    95
                fields.putAll(supInjector.fields);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    96
                methods.putAll(supInjector.methods);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    97
            }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    98
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
    99
            addMembers(c);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   100
            eliminateOverriddenMethods();
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   101
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   102
            // If we haven't added any new fields or methods to what we
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   103
            // inherited, then we can share the parent's maps.
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   104
            if (supInjector != null) {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   105
                if (fields.equals(supInjector.fields))
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   106
                    fields = supInjector.fields;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   107
                if (methods.equals(supInjector.methods))
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   108
                    methods = supInjector.methods;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   109
            }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   110
        }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   111
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   112
        boolean injects(Class<?> c) {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   113
            return (fields.get(c) != null || methods.get(c) != null);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   114
        }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   115
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   116
        <T> void inject(Object instance, Class<T> type, T resource)
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   117
        throws Exception {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   118
            List<Field> fs = fields.get(type);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   119
            if (fs != null) {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   120
                for (Field f : fs)
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   121
                    f.set(instance, resource);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   122
            }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   123
            List<Method> ms = methods.get(type);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   124
            if (ms != null) {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   125
                for (Method m : ms) {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   126
                    try {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   127
                        m.invoke(instance, resource);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   128
                    } catch (InvocationTargetException e) {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   129
                        Throwable cause = e.getCause();
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   130
                        if (cause instanceof Error)
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   131
                            throw (Error) cause;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   132
                        else
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   133
                            throw (Exception) cause;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   134
                    }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   135
                }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   136
            }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   137
        }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   138
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   139
        private void eliminateOverriddenMethods() {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   140
            /* Covariant overriding is unlikely, but it is possible that the
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   141
             * parent has a @Resource method that we override with another
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   142
             * @Resource method.  We don't want to invoke both methods,
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   143
             * because polymorphism means we would actually invoke the same
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   144
             * method twice.
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   145
             */
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   146
            for (Map.Entry<Class<?>, List<Method>> entry : methods.entrySet()) {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   147
                List<Method> list = entry.getValue();
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   148
                list = MBeanAnalyzer.eliminateCovariantMethods(list);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   149
                entry.setValue(list);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   150
            }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   151
        }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   152
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   153
        /*
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   154
         * Find Fields or Methods within the given Class that we can inject
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   155
         * resource references into.  Suppose we want to know if a Field can get
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   156
         * a reference to an ObjectName.  We'll accept fields like this:
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   157
         *
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   158
         * @Resource
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   159
         * private transient ObjectName name;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   160
         *
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   161
         * or like this:
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   162
         *
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   163
         * @Resource(type = ObjectName.class)
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   164
         * private transient Object name;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   165
         *
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   166
         * but not like this:
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   167
         *
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   168
         * @Resource
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   169
         * private transient Object name;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   170
         *
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   171
         * (Plain @Resource is equivalent to @Resource(type = Object.class).)
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   172
         *
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   173
         * We don't want to inject into everything that might possibly accept
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   174
         * an ObjectName reference, because examples like the last one above
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   175
         * could also accept an MBeanServer reference or any other sort of
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   176
         * reference.
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   177
         *
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   178
         * So we accept a Field if it has a @Resource annotation and either
1004
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents: 833
diff changeset
   179
         * (a) its type is exactly ObjectName and its @Resource type is
833
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   180
         * compatible with ObjectName (e.g. it is Object); or
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   181
         * (b) its type is compatible with ObjectName and its @Resource type
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   182
         * is exactly ObjectName.  Fields that meet these criteria will not
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   183
         * meet the same criteria with respect to other types such as MBeanServer.
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   184
         *
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   185
         * The same logic applies mutatis mutandis to Methods such as this:
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   186
         *
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   187
         * @Resource
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   188
         * private void setObjectName1(ObjectName name)
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   189
         * @Resource(type = Object.class)
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   190
         * private void setObjectName2(Object name)
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   191
         */
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   192
        private void addMembers(final Class<?> c)
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   193
        throws NotCompliantMBeanException {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   194
            AccessibleObject[][] memberArrays =
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   195
                AccessController.doPrivileged(
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   196
                    new PrivilegedAction<AccessibleObject[][]>() {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   197
                        public AccessibleObject[][] run() {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   198
                            return new AccessibleObject[][] {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   199
                                c.getDeclaredFields(), c.getDeclaredMethods()
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   200
                            };
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   201
                        }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   202
                    });
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   203
            for (AccessibleObject[] members : memberArrays) {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   204
                for (final AccessibleObject member : members) {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   205
                    Resource res = member.getAnnotation(Resource.class);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   206
                    if (res == null)
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   207
                        continue;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   208
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   209
                    final Field field;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   210
                    final Method method;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   211
                    final Class<?> memberType;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   212
                    final int modifiers;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   213
                    if (member instanceof Field) {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   214
                        field = (Field) member;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   215
                        memberType = field.getType();
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   216
                        modifiers = field.getModifiers();
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   217
                        method = null;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   218
                    } else {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   219
                        field = null;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   220
                        method = (Method) member;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   221
                        Class<?>[] paramTypes = method.getParameterTypes();
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   222
                        if (paramTypes.length != 1) {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   223
                            throw new NotCompliantMBeanException(
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   224
                                    "@Resource method must have exactly 1 " +
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   225
                                    "parameter: " + method);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   226
                        }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   227
                        if (method.getReturnType() != void.class) {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   228
                            throw new NotCompliantMBeanException(
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   229
                                    "@Resource method must return void: " +
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   230
                                    method);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   231
                        }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   232
                        memberType = paramTypes[0];
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   233
                        modifiers = method.getModifiers();
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   234
                    }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   235
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   236
                    if (Modifier.isStatic(modifiers)) {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   237
                        throw new NotCompliantMBeanException(
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   238
                                "@Resource method or field cannot be static: " +
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   239
                                member);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   240
                    }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   241
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   242
                    for (Class<?> injectedClass : injectedClasses) {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   243
                        Class<?>[] types = {memberType, res.type()};
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   244
                        boolean accept = false;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   245
                        for (int i = 0; i < 2; i++) {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   246
                            if (types[i] == injectedClass &&
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   247
                                    types[1 - i].isAssignableFrom(injectedClass)) {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   248
                                accept = true;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   249
                                break;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   250
                            }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   251
                        }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   252
                        if (accept) {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   253
                            AccessController.doPrivileged(new PrivilegedAction<Void>() {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   254
                                public Void run() {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   255
                                    member.setAccessible(true);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   256
                                    return null;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   257
                                }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   258
                            });
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   259
                            addToMap(fields, injectedClass, field);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   260
                            addToMap(methods, injectedClass, method);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   261
                        }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   262
                    }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   263
                }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   264
            }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   265
        }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   266
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   267
        private static <K, V> void addToMap(Map<K, List<V>> map, K key, V value) {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   268
            if (value == null)
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   269
                return;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   270
            List<V> list = map.get(key);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   271
            if (list == null)
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   272
                list = Collections.singletonList(value);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   273
            else {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   274
                if (list.size() == 1)
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   275
                    list = new ArrayList<V>(list);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   276
                list.add(value);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   277
            }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   278
            map.put(key, list);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   279
        }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   280
    }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   281
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   282
    private static synchronized ClassInjector injectorForClass(Class<?> c)
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   283
    throws NotCompliantMBeanException {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   284
        WeakReference<ClassInjector> wr = injectorMap.get(c);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   285
        ClassInjector ci = (wr == null) ? null : wr.get();
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   286
        if (ci == null) {
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   287
            ci = new ClassInjector(c);
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   288
            injectorMap.put(c, new WeakReference<ClassInjector>(ci));
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   289
        }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   290
        return ci;
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   291
    }
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   292
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   293
    private static Map<Class<?>, WeakReference<ClassInjector>> injectorMap =
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   294
            new WeakHashMap<Class<?>, WeakReference<ClassInjector>>();
bfa2bef7517c 6323980: Annotations to simplify MBean development
emcmanus
parents:
diff changeset
   295
}