jdk/src/share/classes/com/sun/jmx/remote/util/EventClientConnection.java
author dfuchs
Thu, 04 Sep 2008 14:46:36 +0200
changeset 1156 bbc2d15aaf7a
parent 1004 5ba8217eb504
child 1247 b4c26443dee5
permissions -rw-r--r--
5072476: RFE: support cascaded (federated) MBean Servers 6299231: Add support for named MBean Servers Summary: New javax.management.namespace package. Reviewed-by: emcmanus
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
1004
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
     1
/*
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
     2
 * Copyright 2007 Sun Microsystems, Inc.  All Rights Reserved.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
     3
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
     4
 *
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
     5
 * This code is free software; you can redistribute it and/or modify it
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
     6
 * under the terms of the GNU General Public License version 2 only, as
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
     7
 * published by the Free Software Foundation.  Sun designates this
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
     8
 * particular file as subject to the "Classpath" exception as provided
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
     9
 * by Sun in the LICENSE file that accompanied this code.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    10
 *
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    11
 * This code is distributed in the hope that it will be useful, but WITHOUT
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    12
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    13
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    14
 * version 2 for more details (a copy is included in the LICENSE file that
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    15
 * accompanied this code).
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    16
 *
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    17
 * You should have received a copy of the GNU General Public License version
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    18
 * 2 along with this work; if not, write to the Free Software Foundation,
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    19
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    20
 *
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    21
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    22
 * CA 95054 USA or visit www.sun.com if you need additional information or
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    23
 * have any questions.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    24
 */
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    25
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    26
package com.sun.jmx.remote.util;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    27
1156
bbc2d15aaf7a 5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents: 1004
diff changeset
    28
import com.sun.jmx.defaults.JmxProperties;
1004
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    29
import com.sun.jmx.event.EventClientFactory;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    30
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    31
import java.lang.reflect.InvocationHandler;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    32
import java.lang.reflect.InvocationTargetException;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    33
import java.lang.reflect.Method;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    34
import java.lang.reflect.Proxy;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    35
import java.util.Arrays;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    36
import java.util.concurrent.Callable;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    37
import java.util.concurrent.TimeUnit;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    38
import java.util.concurrent.locks.Lock;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    39
import java.util.concurrent.locks.ReentrantLock;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    40
import java.util.logging.Level;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    41
import java.util.logging.Logger;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    42
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    43
import javax.management.MBeanServerConnection;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    44
import javax.management.NotificationFilter;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    45
import javax.management.NotificationListener;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    46
import javax.management.ObjectName;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    47
import javax.management.event.EventClient;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    48
import javax.management.event.EventClientDelegate;
1156
bbc2d15aaf7a 5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents: 1004
diff changeset
    49
import javax.management.namespace.JMXNamespaces;
1004
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    50
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    51
/**
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    52
 * Class EventClientConnection - a {@link Proxy} that wraps an
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    53
 * {@link MBeanServerConnection} and an {@link EventClient}.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    54
 * All methods are routed to the underlying {@code MBeanServerConnection},
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    55
 * except add/remove notification listeners which are routed to the
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    56
 * {@code EventClient}.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    57
 * The caller only sees an {@code MBeanServerConnection} which uses an
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    58
 * {@code EventClient} behind the scenes.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    59
 *
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    60
 * @author Sun Microsystems, Inc.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    61
 */
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    62
public class EventClientConnection implements InvocationHandler,
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    63
        EventClientFactory {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    64
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    65
    /**
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    66
     * A logger for this class.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    67
     **/
1156
bbc2d15aaf7a 5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents: 1004
diff changeset
    68
    private static final Logger LOG = JmxProperties.NOTIFICATION_LOGGER;
1004
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    69
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    70
    private static final int NAMESPACE_SEPARATOR_LENGTH =
1156
bbc2d15aaf7a 5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents: 1004
diff changeset
    71
            JMXNamespaces.NAMESPACE_SEPARATOR.length();
1004
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    72
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    73
    /**
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    74
     * Creates a new {@code EventClientConnection}.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    75
     * @param  connection The underlying MBeanServerConnection.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    76
     */
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    77
    public EventClientConnection(MBeanServerConnection connection) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    78
        this(connection,null);
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    79
    }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    80
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    81
    /**
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    82
     * Creates a new {@code EventClientConnection}.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    83
     * @param connection The underlying MBeanServerConnection.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    84
     * @param eventClientFactory a factory object that will be invoked
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    85
     *        to create an {@link EventClient} when needed.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    86
     *        The {@code EventClient} is created lazily, when it is needed
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    87
     *        for the first time. If null, a default factory will be used
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    88
     *        (see {@link #createEventClient}).
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    89
     */
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    90
    public EventClientConnection(MBeanServerConnection connection,
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    91
                                 Callable<EventClient> eventClientFactory) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    92
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    93
        if (connection == null) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    94
            throw new IllegalArgumentException("Null connection");
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    95
        }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    96
        this.connection = connection;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    97
        if (eventClientFactory == null) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    98
            eventClientFactory = new Callable<EventClient>() {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
    99
                public final EventClient call() throws Exception {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   100
                    return createEventClient(EventClientConnection.this.connection);
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   101
                }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   102
            };
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   103
        }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   104
        this.eventClientFactory = eventClientFactory;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   105
        this.lock = new ReentrantLock();
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   106
     }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   107
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   108
    /**
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   109
     * <p>The MBean server connection through which the methods of
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   110
     * a proxy using this handler are forwarded.</p>
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   111
     *
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   112
     * @return the MBean server connection.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   113
     *
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   114
     * @since 1.6
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   115
     */
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   116
    public MBeanServerConnection getMBeanServerConnection() {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   117
        return connection;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   118
    }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   119
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   120
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   121
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   122
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   123
    /**
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   124
     * Creates a new EventClientConnection proxy instance.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   125
     *
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   126
     * @param <T> The underlying {@code MBeanServerConnection} - which should
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   127
     *        not be using the Event Service itself.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   128
     * @param interfaceClass {@code MBeanServerConnection.class}, or a subclass.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   129
     * @param eventClientFactory a factory used to create the EventClient.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   130
     *        If null, a default factory is used (see {@link
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   131
     *        #createEventClient}).
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   132
     * @return the new proxy instance, which will route add/remove notification
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   133
     *         listener calls through an {@code EventClient}.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   134
     *
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   135
     */
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   136
    private static <T extends MBeanServerConnection> T
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   137
            newProxyInstance(T connection,
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   138
            Class<T> interfaceClass, Callable<EventClient> eventClientFactory) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   139
        final InvocationHandler handler =
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   140
                new EventClientConnection(connection,eventClientFactory);
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   141
        final Class[] interfaces =
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   142
                new Class[] {interfaceClass, EventClientFactory.class};
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   143
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   144
        Object proxy =
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   145
                Proxy.newProxyInstance(interfaceClass.getClassLoader(),
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   146
                interfaces,
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   147
                handler);
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   148
        return interfaceClass.cast(proxy);
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   149
    }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   150
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   151
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   152
    public Object invoke(Object proxy, Method method, Object[] args)
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   153
            throws Throwable {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   154
        final String methodName = method.getName();
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   155
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   156
        // add/remove notification listener are routed to the EventClient
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   157
        if (methodName.equals("addNotificationListener")
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   158
            || methodName.equals("removeNotificationListener")) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   159
            final Class[] sig = method.getParameterTypes();
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   160
            if (sig.length>1 &&
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   161
                    NotificationListener.class.isAssignableFrom(sig[1])) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   162
                return invokeBroadcasterMethod(proxy,method,args);
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   163
            }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   164
        }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   165
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   166
        // subscribe/unsubscribe are also routed to the EventClient.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   167
        final Class clazz = method.getDeclaringClass();
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   168
        if (clazz.equals(EventClientFactory.class)) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   169
            return invokeEventClientSubscriberMethod(proxy,method,args);
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   170
        }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   171
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   172
        // local or not: equals, toString, hashCode
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   173
        if (shouldDoLocally(proxy, method))
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   174
            return doLocally(proxy, method, args);
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   175
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   176
        return call(connection,method,args);
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   177
    }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   178
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   179
    // The purpose of this method is to unwrap InvocationTargetException,
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   180
    // in order to avoid throwing UndeclaredThrowableException for
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   181
    // declared exceptions.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   182
    //
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   183
    // When calling method.invoke(), any exception thrown by the invoked
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   184
    // method will be wrapped in InvocationTargetException. If we don't
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   185
    // unwrap this exception, the proxy will always throw
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   186
    // UndeclaredThrowableException, even for runtime exceptions.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   187
    //
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   188
    private Object call(final Object obj, final Method m,
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   189
            final Object[] args)
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   190
        throws Throwable {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   191
        try {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   192
            return m.invoke(obj,args);
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   193
        } catch (InvocationTargetException x) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   194
            final Throwable xx = x.getTargetException();
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   195
            if (xx == null) throw x;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   196
            else throw xx;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   197
        }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   198
    }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   199
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   200
    /**
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   201
     * Route add/remove notification listener to the event client.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   202
     **/
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   203
    private Object invokeBroadcasterMethod(Object proxy, Method method,
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   204
                                           Object[] args) throws Exception {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   205
        final String methodName = method.getName();
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   206
        final int nargs = (args == null) ? 0 : args.length;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   207
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   208
        if (nargs < 1) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   209
           final String msg =
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   210
                    "Bad arg count: " + nargs;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   211
           throw new IllegalArgumentException(msg);
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   212
        }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   213
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   214
        final ObjectName mbean = (ObjectName) args[0];
1156
bbc2d15aaf7a 5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents: 1004
diff changeset
   215
        final EventClient evtClient = getEventClient();
1004
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   216
1156
bbc2d15aaf7a 5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents: 1004
diff changeset
   217
        // Fails if evtClient is null AND the MBean we try to listen to is
1004
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   218
        // in a subnamespace. We fail here because we know this will not
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   219
        // work.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   220
        //
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   221
        // Note that if the wrapped MBeanServerConnection points to a an
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   222
        // earlier agent (JDK 1.6 or earlier), then the EventClient will
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   223
        // be null (we can't use the event service with earlier JDKs).
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   224
        //
1156
bbc2d15aaf7a 5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents: 1004
diff changeset
   225
        // In principle a null evtClient indicates that the remote VM is of
1004
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   226
        // an earlier version, in which case it shouldn't contain any namespace.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   227
        //
1156
bbc2d15aaf7a 5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents: 1004
diff changeset
   228
        // So having a null evtClient AND an MBean contained in a namespace is
1004
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   229
        // clearly an error case.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   230
        //
1156
bbc2d15aaf7a 5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents: 1004
diff changeset
   231
        if (evtClient == null) {
1004
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   232
            final String domain = mbean.getDomain();
1156
bbc2d15aaf7a 5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents: 1004
diff changeset
   233
            final int index = domain.indexOf(JMXNamespaces.NAMESPACE_SEPARATOR);
1004
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   234
            if (index > -1 && index <
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   235
                    (domain.length()-NAMESPACE_SEPARATOR_LENGTH)) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   236
                throw new UnsupportedOperationException(method.getName()+
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   237
                        " on namespace "+domain.substring(0,index+
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   238
                        NAMESPACE_SEPARATOR_LENGTH));
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   239
            }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   240
        }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   241
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   242
        if (methodName.equals("addNotificationListener")) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   243
            /* The various throws of IllegalArgumentException here
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   244
               should not happen, since we know what the methods in
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   245
               NotificationBroadcaster and NotificationEmitter
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   246
               are.  */
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   247
            if (nargs != 4) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   248
                final String msg =
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   249
                    "Bad arg count to addNotificationListener: " + nargs;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   250
                throw new IllegalArgumentException(msg);
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   251
            }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   252
            /* Other inconsistencies will produce ClassCastException
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   253
               below.  */
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   254
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   255
            final NotificationListener listener = (NotificationListener) args[1];
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   256
            final NotificationFilter filter = (NotificationFilter) args[2];
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   257
            final Object handback = args[3];
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   258
1156
bbc2d15aaf7a 5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents: 1004
diff changeset
   259
            if (evtClient != null) {
1004
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   260
                // general case
1156
bbc2d15aaf7a 5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents: 1004
diff changeset
   261
                evtClient.addNotificationListener(mbean,listener,filter,handback);
1004
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   262
            } else {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   263
                // deprecated case. Only works for mbean in local namespace.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   264
                connection.addNotificationListener(mbean,listener,filter,
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   265
                                                   handback);
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   266
            }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   267
            return null;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   268
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   269
        } else if (methodName.equals("removeNotificationListener")) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   270
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   271
            /* NullPointerException if method with no args, but that
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   272
               shouldn't happen because removeNL does have args.  */
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   273
            NotificationListener listener = (NotificationListener) args[1];
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   274
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   275
            switch (nargs) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   276
            case 2:
1156
bbc2d15aaf7a 5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents: 1004
diff changeset
   277
                if (evtClient != null) {
1004
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   278
                    // general case
1156
bbc2d15aaf7a 5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents: 1004
diff changeset
   279
                    evtClient.removeNotificationListener(mbean,listener);
1004
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   280
                } else {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   281
                    // deprecated case. Only works for mbean in local namespace.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   282
                    connection.removeNotificationListener(mbean, listener);
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   283
                }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   284
                return null;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   285
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   286
            case 4:
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   287
                NotificationFilter filter = (NotificationFilter) args[2];
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   288
                Object handback = args[3];
1156
bbc2d15aaf7a 5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents: 1004
diff changeset
   289
                if (evtClient != null) {
bbc2d15aaf7a 5072476: RFE: support cascaded (federated) MBean Servers
dfuchs
parents: 1004
diff changeset
   290
                    evtClient.removeNotificationListener(mbean,
1004
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   291
                                                      listener,
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   292
                                                      filter,
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   293
                                                      handback);
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   294
                } else {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   295
                    connection.removeNotificationListener(mbean,
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   296
                                                      listener,
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   297
                                                      filter,
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   298
                                                      handback);
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   299
                }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   300
                return null;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   301
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   302
            default:
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   303
                final String msg =
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   304
                    "Bad arg count to removeNotificationListener: " + nargs;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   305
                throw new IllegalArgumentException(msg);
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   306
            }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   307
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   308
        } else {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   309
            throw new IllegalArgumentException("Bad method name: " +
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   310
                                               methodName);
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   311
        }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   312
    }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   313
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   314
    private boolean shouldDoLocally(Object proxy, Method method) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   315
        final String methodName = method.getName();
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   316
        if ((methodName.equals("hashCode") || methodName.equals("toString"))
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   317
            && method.getParameterTypes().length == 0
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   318
                && isLocal(proxy, method))
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   319
            return true;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   320
        if (methodName.equals("equals")
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   321
            && Arrays.equals(method.getParameterTypes(),
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   322
                new Class[] {Object.class})
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   323
                && isLocal(proxy, method))
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   324
            return true;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   325
        return false;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   326
    }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   327
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   328
    private Object doLocally(Object proxy, Method method, Object[] args) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   329
        final String methodName = method.getName();
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   330
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   331
        if (methodName.equals("equals")) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   332
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   333
            if (this == args[0]) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   334
                return true;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   335
            }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   336
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   337
            if (!(args[0] instanceof Proxy)) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   338
                return false;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   339
            }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   340
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   341
            final InvocationHandler ihandler =
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   342
                Proxy.getInvocationHandler(args[0]);
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   343
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   344
            if (ihandler == null ||
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   345
                !(ihandler instanceof EventClientConnection)) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   346
                return false;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   347
            }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   348
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   349
            final EventClientConnection handler =
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   350
                (EventClientConnection)ihandler;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   351
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   352
            return connection.equals(handler.connection) &&
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   353
                proxy.getClass().equals(args[0].getClass());
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   354
        } else if (methodName.equals("hashCode")) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   355
            return connection.hashCode();
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   356
        }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   357
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   358
        throw new RuntimeException("Unexpected method name: " + methodName);
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   359
    }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   360
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   361
    private static boolean isLocal(Object proxy, Method method) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   362
        final Class<?>[] interfaces = proxy.getClass().getInterfaces();
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   363
        if(interfaces == null) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   364
            return true;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   365
        }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   366
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   367
        final String methodName = method.getName();
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   368
        final Class<?>[] params = method.getParameterTypes();
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   369
        for (Class<?> intf : interfaces) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   370
            try {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   371
                intf.getMethod(methodName, params);
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   372
                return false; // found method in one of our interfaces
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   373
            } catch (NoSuchMethodException nsme) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   374
                // OK.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   375
            }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   376
        }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   377
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   378
        return true;  // did not find in any interface
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   379
    }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   380
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   381
    /**
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   382
     * Return the EventClient used by this object. Can be null if the
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   383
     * remote VM is of an earlier JDK version which doesn't have the
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   384
     * event service.<br>
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   385
     * This method will invoke the event client factory the first time
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   386
     * it is called.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   387
     **/
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   388
    public final EventClient getEventClient()  {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   389
        if (initialized) return client;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   390
        try {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   391
            if (!lock.tryLock(TRYLOCK_TIMEOUT,TimeUnit.SECONDS))
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   392
                throw new IllegalStateException("can't acquire lock");
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   393
            try {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   394
                client = eventClientFactory.call();
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   395
                initialized = true;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   396
            } finally {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   397
                lock.unlock();
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   398
            }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   399
        } catch (RuntimeException x) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   400
            throw x;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   401
        } catch (Exception x) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   402
            throw new IllegalStateException("Can't create EventClient: "+x,x);
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   403
        }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   404
        return client;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   405
    }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   406
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   407
    /**
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   408
     * Returns an event client for the wrapped {@code MBeanServerConnection}.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   409
     * This is the method invoked by the default event client factory.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   410
     * @param connection the  wrapped {@code MBeanServerConnection}.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   411
     **/
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   412
    protected EventClient createEventClient(MBeanServerConnection connection)
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   413
        throws Exception {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   414
        final ObjectName name =
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   415
           EventClientDelegate.OBJECT_NAME;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   416
        if (connection.isRegistered(name)) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   417
            return new EventClient(connection);
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   418
        }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   419
        return null;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   420
    }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   421
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   422
    /**
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   423
     * Creates a new {@link MBeanServerConnection} that goes through an
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   424
     * {@link EventClient} to receive/subscribe to notifications.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   425
     * @param connection the underlying {@link MBeanServerConnection}.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   426
     *        The given <code>connection</code> shouldn't be already
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   427
     *        using an {@code EventClient}.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   428
     * @param eventClientFactory a factory object that will be invoked
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   429
     *        to create an {@link EventClient} when needed.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   430
     *        The {@code EventClient} is created lazily, when it is needed
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   431
     *        for the first time. If null, a default factory will be used
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   432
     *        (see {@link #createEventClient}).
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   433
     * @return the
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   434
     **/
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   435
    public static MBeanServerConnection getEventConnectionFor(
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   436
                    MBeanServerConnection connection,
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   437
                    Callable<EventClient> eventClientFactory) {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   438
        // if c already uses an EventClient no need to create a new one.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   439
        //
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   440
        if (connection instanceof EventClientFactory
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   441
            && eventClientFactory != null)
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   442
            throw new IllegalArgumentException("connection already uses EventClient");
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   443
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   444
        if (connection instanceof EventClientFactory)
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   445
            return connection;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   446
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   447
        // create a new proxy using an event client.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   448
        //
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   449
        if (LOG.isLoggable(Level.FINE))
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   450
            LOG.fine("Creating EventClient for: "+connection);
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   451
        return newProxyInstance(connection,
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   452
                MBeanServerConnection.class,
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   453
                eventClientFactory);
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   454
    }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   455
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   456
    private Object invokeEventClientSubscriberMethod(Object proxy,
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   457
            Method method, Object[] args) throws Throwable {
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   458
        return call(this,method,args);
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   459
    }
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   460
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   461
    // Maximum lock timeout in seconds. Obviously arbitrary.
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   462
    //
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   463
    private final static short TRYLOCK_TIMEOUT = 3;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   464
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   465
    private final MBeanServerConnection connection;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   466
    private final Callable<EventClient> eventClientFactory;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   467
    private final Lock lock;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   468
    private volatile EventClient client = null;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   469
    private volatile boolean initialized = false;
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   470
5ba8217eb504 5108776: Add reliable event handling to the JMX API
sjiang
parents:
diff changeset
   471
}