All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jboss.remotingjmx.protocol.v1.ClientConnection Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up with different versions on classes on the class path).

The newest version!
/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2023 Red Hat, Inc., and individual contributors
 * as indicated by the @author tags.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.jboss.remotingjmx.protocol.v1;

import static org.jboss.remotingjmx.Constants.TIMEOUT_KEY;
import static org.jboss.remotingjmx.protocol.v1.Constants.ADD_NOTIFICATION_LISTENER;
import static org.jboss.remotingjmx.protocol.v1.Constants.ATTRIBUTE;
import static org.jboss.remotingjmx.protocol.v1.Constants.ATTRIBUTE_LIST;
import static org.jboss.remotingjmx.protocol.v1.Constants.BOOLEAN;
import static org.jboss.remotingjmx.protocol.v1.Constants.CREATE_MBEAN;
import static org.jboss.remotingjmx.protocol.v1.Constants.EXCEPTION;
import static org.jboss.remotingjmx.protocol.v1.Constants.FAILURE;
import static org.jboss.remotingjmx.protocol.v1.Constants.GET_ATTRIBUTE;
import static org.jboss.remotingjmx.protocol.v1.Constants.GET_ATTRIBUTES;
import static org.jboss.remotingjmx.protocol.v1.Constants.GET_DEFAULT_DOMAIN;
import static org.jboss.remotingjmx.protocol.v1.Constants.GET_DOMAINS;
import static org.jboss.remotingjmx.protocol.v1.Constants.GET_MBEAN_COUNT;
import static org.jboss.remotingjmx.protocol.v1.Constants.GET_MBEAN_INFO;
import static org.jboss.remotingjmx.protocol.v1.Constants.GET_OBJECT_INSTANCE;
import static org.jboss.remotingjmx.protocol.v1.Constants.INSTANCE_OF;
import static org.jboss.remotingjmx.protocol.v1.Constants.INTEGER;
import static org.jboss.remotingjmx.protocol.v1.Constants.INTEGER_ARRAY;
import static org.jboss.remotingjmx.protocol.v1.Constants.INVOKE;
import static org.jboss.remotingjmx.protocol.v1.Constants.IS_REGISTERED;
import static org.jboss.remotingjmx.protocol.v1.Constants.MBEAN_INFO;
import static org.jboss.remotingjmx.protocol.v1.Constants.NOTIFICATION;
import static org.jboss.remotingjmx.protocol.v1.Constants.NOTIFICATION_FILTER;
import static org.jboss.remotingjmx.protocol.v1.Constants.OBJECT;
import static org.jboss.remotingjmx.protocol.v1.Constants.OBJECT_ARRAY;
import static org.jboss.remotingjmx.protocol.v1.Constants.OBJECT_INSTANCE;
import static org.jboss.remotingjmx.protocol.v1.Constants.OBJECT_NAME;
import static org.jboss.remotingjmx.protocol.v1.Constants.QUERY_EXP;
import static org.jboss.remotingjmx.protocol.v1.Constants.QUERY_MBEANS;
import static org.jboss.remotingjmx.protocol.v1.Constants.QUERY_NAMES;
import static org.jboss.remotingjmx.protocol.v1.Constants.REMOVE_NOTIFICATION_LISTENER;
import static org.jboss.remotingjmx.protocol.v1.Constants.RESPONSE_MASK;
import static org.jboss.remotingjmx.protocol.v1.Constants.SEND_NOTIFICATION;
import static org.jboss.remotingjmx.protocol.v1.Constants.SET_ATTRIBUTE;
import static org.jboss.remotingjmx.protocol.v1.Constants.SET_ATTRIBUTES;
import static org.jboss.remotingjmx.protocol.v1.Constants.SET_OBJECT_INSTANCE;
import static org.jboss.remotingjmx.protocol.v1.Constants.SET_OBJECT_NAME;
import static org.jboss.remotingjmx.protocol.v1.Constants.STRING;
import static org.jboss.remotingjmx.protocol.v1.Constants.STRING_ARRAY;
import static org.jboss.remotingjmx.protocol.v1.Constants.SUCCESS;
import static org.jboss.remotingjmx.protocol.v1.Constants.UNREGISTER_MBEAN;
import static org.jboss.remotingjmx.protocol.v1.Constants.VOID;

import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.IOException;
import java.security.AccessController;
import java.security.PrivilegedAction;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.IntrospectionException;
import javax.management.InvalidAttributeValueException;
import javax.management.JMRuntimeException;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServerConnection;
import javax.management.NotCompliantMBeanException;
import javax.management.Notification;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.QueryExp;
import javax.management.ReflectionException;
import javax.security.auth.Subject;

import org.jboss.logging.Logger;
import org.jboss.marshalling.Marshaller;
import org.jboss.marshalling.Unmarshaller;
import org.jboss.remoting3.Channel;
import org.jboss.remoting3.Connection;
import org.jboss.remoting3.MessageInputStream;
import org.jboss.remotingjmx.RemotingMBeanServerConnection;
import org.jboss.remotingjmx.VersionedConnection;
import org.xnio.IoFuture;
import org.xnio.IoUtils;

/**
 * The VersionOne client connection.
 *
 * @author Darran Lofthouse
 */
class ClientConnection extends Common implements VersionedConnection {

    private static final String REMOTING_JMX = "remoting-jmx";
    private static final String CLIENT_THREAD = "client-thread-";
    private static final AtomicInteger THREAD_NUMBER = new AtomicInteger(1);

    public static final int DEFAULT_TIMEOUT = 60;

    private static final Logger log = Logger.getLogger(ClientConnection.class);

    private final Channel channel;
    // Registry of handlers for the incoming messages.
    private final Map handlerRegistry;
    private boolean manageExecutor = false;
    private final Executor executor;
    private final int timeoutSeconds;

    private String connectionId;
    private TheConnection mbeanServerConnection;
    private LocalNotificationManager localNotificationManager;

    private int nextCorrelationId = 1;

    static final ThreadGroup THREAD_GROUP;
    static {
        THREAD_GROUP = AccessController.doPrivileged(new PrivilegedAction() {
            public ThreadGroup run() {
                ThreadGroup t = Thread.currentThread().getThreadGroup();
                while (t.getParent() != null) t = t.getParent();
                return t;
            }
        });
    }

    /**
     * The in-progress requests awaiting a response.
     */
    private final Map requests = new HashMap();

    ClientConnection(final Channel channel, final Map environment) {
        super(channel);
        this.channel = channel;
        handlerRegistry = createHandlerRegistry();
        Integer seconds = null;
        if (environment != null && environment.containsKey(TIMEOUT_KEY)) {
            final Object timeout = environment.get(TIMEOUT_KEY);
            if (timeout instanceof Number) {
                seconds = ((Number) timeout).intValue();
            } else if (timeout instanceof String) {
                try {
                    seconds = Integer.parseInt((String) timeout);
                } catch (NumberFormatException e) {
                    log.warnf(e, "Could not parse configured timeout %s", timeout);
                }
            } else {
                log.warnf("Timeout %s configured via environment is not valid ", timeout);
            }
        } else {
            seconds = Integer.getInteger(TIMEOUT_KEY, DEFAULT_TIMEOUT);
        }
        if (environment != null && environment.containsKey(Executor.class.getName())) {
            executor = (Executor) environment.get(Executor.class.getName());
        } else {
            executor = Executors.newCachedThreadPool(new ThreadFactory() {

                public Thread newThread(Runnable r) {
                    return new Thread(THREAD_GROUP, r, REMOTING_JMX + " " + CLIENT_THREAD + THREAD_NUMBER.getAndIncrement());
                }
            });
            manageExecutor = true;
        }
        timeoutSeconds = seconds == null ? DEFAULT_TIMEOUT : seconds;
    }

    private Map createHandlerRegistry() {
        Map registry = new HashMap();
        registry.put((byte) (ADD_NOTIFICATION_LISTENER ^ RESPONSE_MASK), new MarshalledResponseHandler(VOID));
        registry.put((byte) (CREATE_MBEAN ^ RESPONSE_MASK), new MarshalledResponseHandler(OBJECT_INSTANCE));
        registry.put((byte) (GET_ATTRIBUTE ^ RESPONSE_MASK), new MarshalledResponseHandler(OBJECT));
        registry.put((byte) (GET_ATTRIBUTES ^ RESPONSE_MASK), new MarshalledResponseHandler(ATTRIBUTE_LIST));
        registry.put((byte) (GET_DEFAULT_DOMAIN ^ RESPONSE_MASK), new StringResponseHandler());
        registry.put((byte) (GET_DOMAINS ^ RESPONSE_MASK), new StringArrayResponseHandler());
        registry.put((byte) (GET_MBEAN_COUNT ^ RESPONSE_MASK), new IntegerResponseHandler());
        registry.put((byte) (GET_MBEAN_INFO ^ RESPONSE_MASK), new MarshalledResponseHandler(MBEAN_INFO));
        registry.put((byte) (GET_OBJECT_INSTANCE ^ RESPONSE_MASK), new MarshalledResponseHandler(
                OBJECT_INSTANCE));
        registry.put((byte) (INSTANCE_OF ^ RESPONSE_MASK), new BooleanResponseHandler());
        registry.put((byte) (IS_REGISTERED ^ RESPONSE_MASK), new BooleanResponseHandler());
        registry.put((byte) (INVOKE ^ RESPONSE_MASK), new MarshalledResponseHandler(OBJECT));
        registry.put((byte) (QUERY_MBEANS ^ RESPONSE_MASK), new MarshalledResponseHandler>(
                SET_OBJECT_INSTANCE));
        registry.put((byte) (QUERY_NAMES ^ RESPONSE_MASK), new MarshalledResponseHandler>(SET_OBJECT_NAME));
        registry.put((byte) (REMOVE_NOTIFICATION_LISTENER ^ RESPONSE_MASK), new MarshalledResponseHandler(VOID));
        registry.put((byte) (SET_ATTRIBUTE ^ RESPONSE_MASK), new MarshalledResponseHandler(VOID));
        registry.put((byte) (SET_ATTRIBUTES ^ RESPONSE_MASK), new MarshalledResponseHandler(ATTRIBUTE_LIST));
        registry.put((byte) (UNREGISTER_MBEAN ^ RESPONSE_MASK), new MarshalledResponseHandler(VOID));

        registry.put(SEND_NOTIFICATION, new NotificationHandler());

        return Collections.unmodifiableMap(registry);
    }

    void start() throws IOException {
        sendVersionHeader();
        IoFuture futureConnectionId = ConnectionIdReceiver.getConnectionId(channel);
        IoFuture.Status result = futureConnectionId.await(timeoutSeconds, TimeUnit.SECONDS);
        switch (result) {
            case DONE:
                connectionId = futureConnectionId.get();
                mbeanServerConnection = new TheConnection();
                localNotificationManager = new LocalNotificationManager();
                channel.receiveMessage(new MessageReceiver());
                break;
            case FAILED:
                throw futureConnectionId.getException();
            default:
                throw new IOException("Unable to obtain connectionId, status=" + result.toString());
        }
    }

    private void sendVersionHeader() throws IOException {
        write(new MessageWriter() {
            @Override
            public void write(DataOutput output) throws IOException {
                output.writeBytes("JMX");
                output.writeByte(VersionOne.getVersionIdentifier());
            }
        });
    }

    public String getConnectionId() {
        if (connectionId == null) {
            throw new IllegalStateException("Connection ID not set");
        }

        return connectionId;
    }

    public MBeanServerConnection getMBeanServerConnection(Subject subject) {
        if (subject != null) {
            throw new UnsupportedOperationException("Subject delegation not supported for getMBeanServerConnection");
        }

        // It is normal for only a single instance of MBeanServerConnection to be used.
        return mbeanServerConnection;
    }

    public void close() {
        if (manageExecutor && executor instanceof ExecutorService) {
            ((ExecutorService) executor).shutdown();
        }
    }

    /**
     * Get the next correlation ID, returning to the beginning once all integers have been used.
     * 

* THIS METHOD IS NOT TO BE USED DIRECTLY WHERE A CORRELATION ID NEEDS TO BE RESERVED. * * @return The next correlationId. */ private synchronized int getNextCorrelationId() { int next = nextCorrelationId++; // After the maximum integer start back at the beginning. if (next < 0) { nextCorrelationId = 2; next = 1; } return next; } /** * Reserves a correlation ID by taking the next value and ensuring it is stored in the Map. * * @return the next reserved correlation ID */ private synchronized int reserveNextCorrelationId(VersionedIoFuture future) { Integer next = getNextCorrelationId(); // Not likely but possible to use all IDs and start back at beginning while // old request still in progress. while (requests.containsKey(next)) { next = getNextCorrelationId(); } requests.put(next, future); return next; } private synchronized VersionedIoFuture getFuture(int correlationId) { // TODO - How to check this? return requests.get(correlationId); } private synchronized void releaseCorrelationId(int correlationId) { // TODO - Will maybe move to not removing by default and timeout failed requests. requests.remove(correlationId); } private synchronized void cancelAllRequests(final IOException io) { for (VersionedIoFuture current : requests.values()) { current.setException(io); } requests.clear(); } /** * The local management of notifications. */ private class LocalNotificationManager { private int nextNotificationId = 1; private Map listeners = new HashMap(); private synchronized int getNextNotificationId() { int next = nextNotificationId++; // After the maximum integer start back at the beginning. if (next < 0) { nextNotificationId = 2; next = 1; } return next; } private synchronized int associate(ObjectName target, NotificationListener listener, NotificationFilter filter, Object handBack) { Integer next = getNextNotificationId(); // Not likely but possible to use all IDs and start back at beginning while // old request still in progress. while (listeners.containsKey(next)) { next = getNextNotificationId(); } Association association = new Association(); association.target = target; association.listener = listener; association.filter = filter; association.handBack = handBack; listeners.put(next, association); return next; } private synchronized void cancel(int id) { listeners.remove(id); } private synchronized Association get(int id) { return listeners.get(id); } /* * The message received will already be being processed on a Thread obtained from the local Executor, for this reason * there is no point in creating a new Runnable and passing it to the executor to process the Notification. */ private void notify(int id, Notification n, Object handback) { Association association = get(id); if (association != null) { association.listener.handleNotification(n, handback); } else { // If an invalid ID is received don't throw an error, instead just send // a message to the server canceling the notification by id. try { log.warnf("Notification recieved for non existant NotificationListener %d", id); mbeanServerConnection.removeNotificationListener(new int[] { id }); } catch (InstanceNotFoundException e) { } catch (ListenerNotFoundException e) { } catch (IOException e) { } } } private synchronized int[] matchToRemove(ObjectName name, NotificationListener listener) { List toRemove = new ArrayList(); for (Integer current : listeners.keySet()) { Association association = listeners.get(current); if ((name == association.target || name.equals(association.target) && listener == association.listener)) { toRemove.add(current); } } int[] response = new int[toRemove.size()]; for (int i = 0; i < response.length; i++) { response[i] = toRemove.get(i); listeners.remove(response[i]); } return response; } private synchronized int[] matchToRemove(ObjectName name, NotificationListener listener, NotificationFilter filter, Object handback) { List toRemove = new ArrayList(); for (Integer current : listeners.keySet()) { Association association = listeners.get(current); if ((name == association.target || name.equals(association.target)) && listener == association.listener && filter == association.filter && handback == association.handBack) { toRemove.add(current); } } int[] response = new int[toRemove.size()]; for (int i = 0; i < response.length; i++) { response[i] = toRemove.get(i); listeners.remove(response[i]); } return response; } private class Association { private ObjectName target; private NotificationListener listener; private NotificationFilter filter; private Object handBack; } } private class MessageReceiver implements Channel.Receiver { @Override public void handleMessage(Channel channel, MessageInputStream message) { final DataInputStream dis = new DataInputStream(message); try { byte messageId = dis.readByte(); final int correlationId = dis.readInt(); log.tracef("Message Received id(%h), correlationId(%d)", messageId, correlationId); final Common.MessageHandler mh = handlerRegistry.get(messageId); if (mh != null) { executor.execute(new Runnable() { @Override public void run() { try { mh.handle(dis, correlationId); } catch (IOException e) { log.error(e); } finally { IoUtils.safeClose(dis); } } }); } else { throw new IOException("Unrecognised Message ID"); } } catch (IOException e) { log.error(e); IoUtils.safeClose(dis); } finally { // TODO - Proper shut down logic. channel.receiveMessage(this); } } public void handleError(Channel channel, IOException error) { cancelAllRequests(error); } public void handleEnd(Channel channel) { cancelAllRequests(new IOException("Connection Ended")); } } private class TheConnection implements RemotingMBeanServerConnection { public Connection getConnection() { return channel.getConnection(); } // TODO - Consider a proxy so the specific methods only need to marshall their specific // portion of the protocol. public ObjectInstance createMBean(final String className, final ObjectName name) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, IOException { VersionedIoFuture> future = new VersionedIoFuture>(); final int correlationId = reserveNextCorrelationId(future); try { write(new MessageWriter() { @Override public void write(DataOutput output) throws IOException { output.writeByte(CREATE_MBEAN); output.writeInt(correlationId); output.writeByte(INTEGER); output.writeInt(2); // Sending 2 parameters. Marshaller marshaller = prepareForMarshalling(output); marshaller.writeByte(STRING); marshaller.writeUTF(className); marshaller.writeByte(OBJECT_NAME); marshaller.writeObject(name); marshaller.close(); } }); log.tracef("[%d] createMBean - Request Sent", correlationId); IoFuture.Status result = future.await(timeoutSeconds, TimeUnit.SECONDS); switch (result) { case FAILED: throw future.getException(); case DONE: TypeExceptionHolder response = future.get(); if (response.e == null) { return response.value; } reflectionException(response.e); instanceAlreadyExistsException(response.e); mbeanRegistrationException(response.e); mbeanException(response.e); notCompliantMBeanException(response.e); jmRuntimeException(response.e); throw toIoException(response.e); default: throw new IOException("Unable to obtain createMBean, status=" + result.toString()); } } finally { releaseCorrelationId(correlationId); } } public ObjectInstance createMBean(final String className, final ObjectName name, final ObjectName loaderName) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, InstanceNotFoundException, IOException { VersionedIoFuture> future = new VersionedIoFuture>(); final int correlationId = reserveNextCorrelationId(future); try { write(new MessageWriter() { @Override public void write(DataOutput output) throws IOException { output.writeByte(CREATE_MBEAN); output.writeInt(correlationId); output.writeByte(INTEGER); output.writeInt(3); // Sending 3 parameters. Marshaller marshaller = prepareForMarshalling(output); marshaller.writeByte(STRING); marshaller.writeUTF(className); marshaller.writeByte(OBJECT_NAME); marshaller.writeObject(name); marshaller.writeByte(OBJECT_NAME); marshaller.writeObject(loaderName); marshaller.close(); } }); log.tracef("[%d] createMBean - Request Sent", correlationId); IoFuture.Status result = future.await(timeoutSeconds, TimeUnit.SECONDS); switch (result) { case FAILED: throw future.getException(); case DONE: TypeExceptionHolder response = future.get(); if (response.e == null) { return response.value; } reflectionException(response.e); instanceAlreadyExistsException(response.e); mbeanRegistrationException(response.e); mbeanException(response.e); notCompliantMBeanException(response.e); instanceNotFoundException(response.e); jmRuntimeException(response.e); throw toIoException(response.e); default: throw new IOException("Unable to obtain isRegistered, status=" + result.toString()); } } finally { releaseCorrelationId(correlationId); } } public ObjectInstance createMBean(final String className, final ObjectName name, final Object[] params, final String[] signature) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, IOException { VersionedIoFuture> future = new VersionedIoFuture>(); final int correlationId = reserveNextCorrelationId(future); try { write(new MessageWriter() { @Override public void write(DataOutput output) throws IOException { output.writeByte(CREATE_MBEAN); output.writeInt(correlationId); output.writeByte(INTEGER); output.writeInt(4); // Sending 4 parameters. Marshaller marshaller = prepareForMarshalling(output); marshaller.writeByte(STRING); marshaller.writeUTF(className); marshaller.writeByte(OBJECT_NAME); marshaller.writeObject(name); marshaller.writeByte(OBJECT_ARRAY); marshaller.writeInt(params.length); for (Object current : params) { marshaller.writeObject(current); } marshaller.writeByte(STRING_ARRAY); marshaller.writeInt(signature.length); for (String current : signature) { marshaller.writeUTF(current); } marshaller.close(); } }); log.tracef("[%d] createMBean - Request Sent", correlationId); IoFuture.Status result = future.await(timeoutSeconds, TimeUnit.SECONDS); switch (result) { case FAILED: throw future.getException(); case DONE: TypeExceptionHolder response = future.get(); if (response.e == null) { return response.value; } reflectionException(response.e); instanceAlreadyExistsException(response.e); mbeanRegistrationException(response.e); mbeanException(response.e); notCompliantMBeanException(response.e); jmRuntimeException(response.e); throw toIoException(response.e); default: throw new IOException("Unable to invoke createMBean, status=" + result.toString()); } } finally { releaseCorrelationId(correlationId); } } public ObjectInstance createMBean(final String className, final ObjectName name, final ObjectName loaderName, final Object[] params, final String[] signature) throws ReflectionException, InstanceAlreadyExistsException, MBeanRegistrationException, MBeanException, NotCompliantMBeanException, InstanceNotFoundException, IOException { VersionedIoFuture> future = new VersionedIoFuture>(); final int correlationId = reserveNextCorrelationId(future); try { write(new MessageWriter() { @Override public void write(DataOutput output) throws IOException { output.writeByte(CREATE_MBEAN); output.writeInt(correlationId); output.writeByte(INTEGER); output.writeInt(5); // Sending 5 parameters. Marshaller marshaller = prepareForMarshalling(output); marshaller.writeByte(STRING); marshaller.writeUTF(className); marshaller.writeByte(OBJECT_NAME); marshaller.writeObject(name); marshaller.writeByte(OBJECT_NAME); marshaller.writeObject(loaderName); marshaller.writeByte(OBJECT_ARRAY); marshaller.writeInt(params.length); for (Object current : params) { marshaller.writeObject(current); } marshaller.writeByte(STRING_ARRAY); marshaller.writeInt(signature.length); for (String current : signature) { marshaller.writeUTF(current); } marshaller.close(); } }); log.tracef("[%d] createMBean - Request Sent", correlationId); IoFuture.Status result = future.await(timeoutSeconds, TimeUnit.SECONDS); switch (result) { case FAILED: throw future.getException(); case DONE: TypeExceptionHolder response = future.get(); if (response.e == null) { return response.value; } reflectionException(response.e); instanceAlreadyExistsException(response.e); mbeanRegistrationException(response.e); mbeanException(response.e); notCompliantMBeanException(response.e); jmRuntimeException(response.e); throw toIoException(response.e); default: throw new IOException("Unable to invoke createMBean, status=" + result.toString()); } } finally { releaseCorrelationId(correlationId); } } public void unregisterMBean(final ObjectName name) throws InstanceNotFoundException, MBeanRegistrationException, IOException { VersionedIoFuture> future = new VersionedIoFuture>(); final int correlationId = reserveNextCorrelationId(future); try { write(new MessageWriter() { @Override public void write(DataOutput output) throws IOException { output.writeByte(UNREGISTER_MBEAN); output.writeInt(correlationId); output.writeByte(OBJECT_NAME); Marshaller marshaller = prepareForMarshalling(output); marshaller.writeObject(name); marshaller.close(); } }); log.tracef("[%d] unregisterMBean - Request Sent", correlationId); IoFuture.Status result = future.await(timeoutSeconds, TimeUnit.SECONDS); switch (result) { case FAILED: throw future.getException(); case DONE: TypeExceptionHolder response = future.get(); if (response.e == null) { return; } instanceNotFoundException(response.e); mbeanRegistrationException(response.e); jmRuntimeException(response.e); throw toIoException(response.e); default: throw new IOException("Unable to invoke unregisterMBean, status=" + result.toString()); } } finally { releaseCorrelationId(correlationId); } } public ObjectInstance getObjectInstance(final ObjectName name) throws InstanceNotFoundException, IOException { VersionedIoFuture> future = new VersionedIoFuture>(); final int correlationId = reserveNextCorrelationId(future); try { write(new MessageWriter() { @Override public void write(DataOutput output) throws IOException { output.writeByte(GET_OBJECT_INSTANCE); output.writeInt(correlationId); output.writeByte(OBJECT_NAME); Marshaller marshaller = prepareForMarshalling(output); marshaller.writeObject(name); marshaller.close(); } }); log.tracef("[%d] getObjectInstance - Request Sent", correlationId); IoFuture.Status result = future.await(timeoutSeconds, TimeUnit.SECONDS); switch (result) { case FAILED: throw future.getException(); case DONE: TypeExceptionHolder response = future.get(); if (response.e == null) { return response.value; } instanceNotFoundException(response.e); jmRuntimeException(response.e); throw toIoException(response.e); default: throw new IOException("Unable to invoke getObjectInstance, status=" + result.toString()); } } finally { releaseCorrelationId(correlationId); } } public Set queryMBeans(final ObjectName name, final QueryExp query) throws IOException { VersionedIoFuture>> future = new VersionedIoFuture>>(); final int correlationId = reserveNextCorrelationId(future); try { write(new MessageWriter() { @Override public void write(DataOutput output) throws IOException { output.writeByte(QUERY_MBEANS); output.writeInt(correlationId); output.writeByte(OBJECT_NAME); Marshaller marshaller = prepareForMarshalling(output); marshaller.writeObject(name); marshaller.writeByte(QUERY_EXP); marshaller.writeObject(query); marshaller.close(); } }); log.tracef("[%d] queryMBeans - Request Sent", correlationId); IoFuture.Status result = future.await(timeoutSeconds, TimeUnit.SECONDS); switch (result) { case FAILED: throw future.getException(); case DONE: TypeExceptionHolder> response = future.get(); if (response.e == null) { return response.value; } jmRuntimeException(response.e); throw toIoException(response.e); default: throw new IOException("Unable to invoke queryMBeans, status=" + result.toString()); } } finally { releaseCorrelationId(correlationId); } } public Set queryNames(final ObjectName name, final QueryExp query) throws IOException { VersionedIoFuture>> future = new VersionedIoFuture>>(); final int correlationId = reserveNextCorrelationId(future); try { write(new MessageWriter() { @Override public void write(DataOutput output) throws IOException { output.writeByte(QUERY_NAMES); output.writeInt(correlationId); output.writeByte(OBJECT_NAME); Marshaller marshaller = prepareForMarshalling(output); marshaller.writeObject(name); marshaller.writeByte(QUERY_EXP); marshaller.writeObject(query); marshaller.close(); } }); log.tracef("[%d] queryNames - Request Sent", correlationId); IoFuture.Status result = future.await(timeoutSeconds, TimeUnit.SECONDS); switch (result) { case FAILED: throw future.getException(); case DONE: TypeExceptionHolder> response = future.get(); if (response.e == null) { return response.value; } jmRuntimeException(response.e); throw toIoException(response.e); default: throw new IOException("Unable to obtain isRegistered, status=" + result.toString()); } } finally { releaseCorrelationId(correlationId); } } public boolean isRegistered(final ObjectName name) throws IOException { VersionedIoFuture> future = new VersionedIoFuture>(); final int correlationId = reserveNextCorrelationId(future); try { write(new MessageWriter() { @Override public void write(DataOutput output) throws IOException { output.writeByte(IS_REGISTERED); output.writeInt(correlationId); output.writeByte(OBJECT_NAME); Marshaller marshaller = prepareForMarshalling(output); marshaller.writeObject(name); marshaller.close(); } }); log.tracef("[%d] isRegistered - Request Sent", correlationId); IoFuture.Status result = future.await(timeoutSeconds, TimeUnit.SECONDS); switch (result) { case DONE: TypeExceptionHolder response = future.get(); if (response.e == null) { return response.value; } jmRuntimeException(response.e); throw toIoException(response.e); case FAILED: throw future.getException(); default: throw new IOException("Unable to obtain isRegistered, status=" + result.toString()); } } finally { releaseCorrelationId(correlationId); } } public Integer getMBeanCount() throws IOException { VersionedIoFuture> future = new VersionedIoFuture>(); final int correlationId = reserveNextCorrelationId(future); try { write(new MessageWriter() { @Override public void write(DataOutput output) throws IOException { output.writeByte(GET_MBEAN_COUNT); output.writeInt(correlationId); } }); log.tracef("[%d] getMBeanCount - Request Sent", correlationId); IoFuture.Status result = future.await(timeoutSeconds, TimeUnit.SECONDS); switch (result) { case DONE: TypeExceptionHolder response = future.get(); if (response.e == null) { return response.value; } jmRuntimeException(response.e); throw toIoException(response.e); case FAILED: throw future.getException(); default: throw new IOException("Unable to obtain MBeanCount, status=" + result.toString()); } } finally { releaseCorrelationId(correlationId); } } public Object getAttribute(final ObjectName name, final String attribute) throws MBeanException, AttributeNotFoundException, InstanceNotFoundException, ReflectionException, IOException { VersionedIoFuture> future = new VersionedIoFuture>(); final int correlationId = reserveNextCorrelationId(future); try { write(new MessageWriter() { @Override public void write(DataOutput output) throws IOException { output.writeByte(GET_ATTRIBUTE); output.writeInt(correlationId); output.writeByte(OBJECT_NAME); Marshaller marshaller = prepareForMarshalling(output); marshaller.writeObject(name); marshaller.writeByte(STRING); marshaller.writeUTF(attribute); marshaller.close(); } }); log.tracef("[%d] getAttribute - Request Sent", correlationId); IoFuture.Status result = future.await(timeoutSeconds, TimeUnit.SECONDS); switch (result) { case FAILED: throw future.getException(); case DONE: TypeExceptionHolder response = future.get(); if (response.e == null) { return response.value; } mbeanException(response.e); attributeNotFoundException(response.e); instanceNotFoundException(response.e); reflectionException(response.e); jmRuntimeException(response.e); throw toIoException(response.e); default: throw new IOException("Unable to obtain isRegistered, status=" + result.toString()); } } finally { releaseCorrelationId(correlationId); } } public AttributeList getAttributes(final ObjectName name, final String[] attributes) throws InstanceNotFoundException, ReflectionException, IOException { VersionedIoFuture> future = new VersionedIoFuture>(); final int correlationId = reserveNextCorrelationId(future); try { write(new MessageWriter() { @Override public void write(DataOutput output) throws IOException { output.writeByte(GET_ATTRIBUTES); output.writeInt(correlationId); output.writeByte(OBJECT_NAME); Marshaller marshaller = prepareForMarshalling(output); marshaller.writeObject(name); marshaller.writeByte(STRING_ARRAY); marshaller.writeInt(attributes.length); for (String current : attributes) { marshaller.writeUTF(current); } marshaller.close(); } }); log.tracef("[%d] getAttributes - Request Sent", correlationId); IoFuture.Status result = future.await(timeoutSeconds, TimeUnit.SECONDS); switch (result) { case FAILED: throw future.getException(); case DONE: TypeExceptionHolder response = future.get(); if (response.e == null) { return response.value; } instanceNotFoundException(response.e); reflectionException(response.e); jmRuntimeException(response.e); throw toIoException(response.e); default: throw new IOException("Unable to invoke getAttributes, status=" + result.toString()); } } finally { releaseCorrelationId(correlationId); } } public void setAttribute(final ObjectName name, final Attribute attribute) throws InstanceNotFoundException, AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException, IOException { VersionedIoFuture> future = new VersionedIoFuture>(); final int correlationId = reserveNextCorrelationId(future); try { write(new MessageWriter() { @Override public void write(DataOutput output) throws IOException { output.writeByte(SET_ATTRIBUTE); output.writeInt(correlationId); output.writeByte(OBJECT_NAME); Marshaller marshaller = prepareForMarshalling(output); marshaller.writeObject(name); marshaller.writeByte(ATTRIBUTE); marshaller.writeObject(attribute); marshaller.close(); } }); log.tracef("[%d] setAttribute - Request Sent", correlationId); IoFuture.Status result = future.await(timeoutSeconds, TimeUnit.SECONDS); switch (result) { case FAILED: throw future.getException(); case DONE: TypeExceptionHolder response = future.get(); if (response.e == null) { return; } instanceNotFoundException(response.e); attributeNotFoundException(response.e); invalidAttributeValueException(response.e); mbeanException(response.e); reflectionException(response.e); jmRuntimeException(response.e); throw toIoException(response.e); default: throw new IOException("Unable to invoke setAttribute, status=" + result.toString()); } } finally { releaseCorrelationId(correlationId); } } public AttributeList setAttributes(final ObjectName name, final AttributeList attributes) throws InstanceNotFoundException, ReflectionException, IOException { VersionedIoFuture> future = new VersionedIoFuture>(); final int correlationId = reserveNextCorrelationId(future); try { write(new MessageWriter() { @Override public void write(DataOutput output) throws IOException { output.writeByte(SET_ATTRIBUTES); output.writeInt(correlationId); output.writeByte(OBJECT_NAME); Marshaller marshaller = prepareForMarshalling(output); marshaller.writeObject(name); marshaller.writeByte(ATTRIBUTE_LIST); marshaller.writeObject(attributes); marshaller.close(); } }); log.tracef("[%d] setAttributes - Request Sent", correlationId); IoFuture.Status result = future.await(timeoutSeconds, TimeUnit.SECONDS); switch (result) { case FAILED: throw future.getException(); case DONE: TypeExceptionHolder response = future.get(); if (response.e == null) { return response.value; } instanceNotFoundException(response.e); reflectionException(response.e); jmRuntimeException(response.e); throw toIoException(response.e); default: throw new IOException("Unable to invoke setAttributes, status=" + result.toString()); } } finally { releaseCorrelationId(correlationId); } } public Object invoke(final ObjectName name, final String operationName, final Object[] params, final String[] signature) throws InstanceNotFoundException, MBeanException, ReflectionException, IOException { VersionedIoFuture> future = new VersionedIoFuture>(); final int correlationId = reserveNextCorrelationId(future); try { write(new MessageWriter() { @Override public void write(DataOutput output) throws IOException { output.writeByte(INVOKE); output.writeInt(correlationId); output.writeByte(OBJECT_NAME); Marshaller marshaller = prepareForMarshalling(output); marshaller.writeObject(name); marshaller.writeByte(STRING); marshaller.writeUTF(operationName); marshaller.writeByte(OBJECT_ARRAY); if (params != null) { marshaller.writeInt(params.length); for (Object current : params) { marshaller.writeObject(current); } } else { marshaller.writeInt(0); } marshaller.writeByte(STRING_ARRAY); if (signature != null) { marshaller.writeInt(signature.length); for (String current : signature) { marshaller.writeUTF(current); } } else { marshaller.writeInt(0); } marshaller.close(); } }); log.tracef("[%d] invoke - Request Sent", correlationId); IoFuture.Status result = future.await(timeoutSeconds, TimeUnit.SECONDS); switch (result) { case FAILED: throw future.getException(); case DONE: TypeExceptionHolder response = future.get(); if (response.e == null) { return response.value; } instanceNotFoundException(response.e); mbeanException(response.e); reflectionException(response.e); jmRuntimeException(response.e); throw toIoException(response.e); default: throw new IOException("Unable to invoke invoke(), status=" + result.toString()); } } finally { releaseCorrelationId(correlationId); } } public String getDefaultDomain() throws IOException { VersionedIoFuture> future = new VersionedIoFuture>(); final int correlationId = reserveNextCorrelationId(future); try { write(new MessageWriter() { @Override public void write(DataOutput output) throws IOException { output.writeByte(GET_DEFAULT_DOMAIN); output.writeInt(correlationId); } }); log.tracef("[%d] getDefaultDomain - Request Sent", correlationId); IoFuture.Status result = future.await(timeoutSeconds, TimeUnit.SECONDS); switch (result) { case DONE: TypeExceptionHolder response = future.get(); if (response.e == null) { return response.value; } jmRuntimeException(response.e); throw toIoException(response.e); case FAILED: throw future.getException(); default: throw new IOException("Unable to obtain DefaultDomain, status=" + result.toString()); } } finally { releaseCorrelationId(correlationId); } } public String[] getDomains() throws IOException { VersionedIoFuture> future = new VersionedIoFuture>(); final int correlationId = reserveNextCorrelationId(future); try { write(new MessageWriter() { @Override public void write(DataOutput output) throws IOException { output.writeByte(GET_DOMAINS); output.writeInt(correlationId); } }); log.tracef("[%d] getDomains - Request Sent", correlationId); IoFuture.Status result = future.await(timeoutSeconds, TimeUnit.SECONDS); switch (result) { case DONE: TypeExceptionHolder response = future.get(); if (response.e == null) { return response.value; } jmRuntimeException(response.e); throw toIoException(response.e); case FAILED: throw future.getException(); default: throw new IOException("Unable to obtain Domains, status=" + result.toString()); } } finally { releaseCorrelationId(correlationId); } } public void addNotificationListener(final ObjectName name, NotificationListener listener, final NotificationFilter filter, final Object handback) throws InstanceNotFoundException, IOException { final int notificationId = localNotificationManager.associate(name, listener, filter, handback); VersionedIoFuture> future = new VersionedIoFuture>(); final int correlationId = reserveNextCorrelationId(future); try { write(new MessageWriter() { @Override public void write(DataOutput output) throws IOException { output.writeByte(ADD_NOTIFICATION_LISTENER); output.writeInt(correlationId); output.writeByte(OBJECT_NAME); Marshaller marshaller = prepareForMarshalling(output); marshaller.writeObject(name); // This indicates that the target is remote. marshaller.writeByte(INTEGER); marshaller.writeInt(notificationId); marshaller.writeByte(NOTIFICATION_FILTER); marshaller.writeObject(filter); marshaller.writeByte(OBJECT); marshaller.writeObject(handback); marshaller.close(); } }); log.tracef("[%d] addNotificationListener - Request Sent", correlationId); IoFuture.Status result = future.await(timeoutSeconds, TimeUnit.SECONDS); switch (result) { case FAILED: localNotificationManager.cancel(notificationId); throw future.getException(); case DONE: TypeExceptionHolder response = future.get(); if (response.e == null) { return; } localNotificationManager.cancel(notificationId); instanceNotFoundException(response.e); jmRuntimeException(response.e); throw toIoException(response.e); default: localNotificationManager.cancel(notificationId); throw new IOException("Unable to invoke addNotificationListener, status=" + result.toString()); } } finally { releaseCorrelationId(correlationId); } } public void addNotificationListener(final ObjectName name, final ObjectName listener, final NotificationFilter filter, final Object handback) throws InstanceNotFoundException, IOException { VersionedIoFuture> future = new VersionedIoFuture>(); final int correlationId = reserveNextCorrelationId(future); try { write(new MessageWriter() { @Override public void write(DataOutput output) throws IOException { output.writeByte(ADD_NOTIFICATION_LISTENER); output.writeInt(correlationId); output.writeByte(OBJECT_NAME); Marshaller marshaller = prepareForMarshalling(output); marshaller.writeObject(name); marshaller.writeByte(OBJECT_NAME); marshaller.writeObject(listener); marshaller.writeByte(NOTIFICATION_FILTER); marshaller.writeObject(filter); marshaller.writeByte(OBJECT); marshaller.writeObject(handback); marshaller.close(); } }); log.tracef("[%d] addNotificationListener - Request Sent", correlationId); IoFuture.Status result = future.await(timeoutSeconds, TimeUnit.SECONDS); switch (result) { case FAILED: throw future.getException(); case DONE: TypeExceptionHolder response = future.get(); if (response.e == null) { return; } jmRuntimeException(response.e); instanceNotFoundException(response.e); throw toIoException(response.e); default: throw new IOException("Unable to invoke addNotificationListener, status=" + result.toString()); } } finally { releaseCorrelationId(correlationId); } } public void removeNotificationListener(final ObjectName name, final ObjectName listener) throws InstanceNotFoundException, ListenerNotFoundException, IOException { VersionedIoFuture> future = new VersionedIoFuture>(); final int correlationId = reserveNextCorrelationId(future); try { write(new MessageWriter() { @Override public void write(DataOutput output) throws IOException { output.writeByte(REMOVE_NOTIFICATION_LISTENER); output.writeInt(correlationId); output.writeByte(INTEGER); output.writeInt(2); // Sending 2 parameters. output.writeByte(OBJECT_NAME); Marshaller marshaller = prepareForMarshalling(output); marshaller.writeObject(name); marshaller.writeByte(OBJECT_NAME); marshaller.writeObject(listener); marshaller.close(); } }); log.tracef("[%d] removeNotificationListener - Request Sent", correlationId); IoFuture.Status result = future.await(timeoutSeconds, TimeUnit.SECONDS); switch (result) { case FAILED: throw future.getException(); case DONE: TypeExceptionHolder response = future.get(); if (response.e == null) { return; } jmRuntimeException(response.e); instanceNotFoundException(response.e); throw toIoException(response.e); default: throw new IOException("Unable to invoke removeNotificationListener, status=" + result.toString()); } } finally { releaseCorrelationId(correlationId); } } public void removeNotificationListener(final ObjectName name, final ObjectName listener, final NotificationFilter filter, final Object handback) throws InstanceNotFoundException, ListenerNotFoundException, IOException { VersionedIoFuture> future = new VersionedIoFuture>(); final int correlationId = reserveNextCorrelationId(future); try { write(new MessageWriter() { @Override public void write(DataOutput output) throws IOException { output.writeByte(REMOVE_NOTIFICATION_LISTENER); output.writeInt(correlationId); output.writeByte(INTEGER); output.writeInt(4); // Sending 4 parameters. output.writeByte(OBJECT_NAME); Marshaller marshaller = prepareForMarshalling(output); marshaller.writeObject(name); marshaller.writeByte(OBJECT_NAME); marshaller.writeObject(listener); marshaller.writeByte(NOTIFICATION_FILTER); marshaller.writeObject(filter); marshaller.writeByte(OBJECT); marshaller.writeObject(handback); marshaller.close(); } }); log.tracef("[%d] removeNotificationListener - Request Sent", correlationId); IoFuture.Status result = future.await(timeoutSeconds, TimeUnit.SECONDS); switch (result) { case FAILED: throw future.getException(); case DONE: TypeExceptionHolder response = future.get(); if (response.e == null) { return; } jmRuntimeException(response.e); instanceNotFoundException(response.e); throw toIoException(response.e); default: throw new IOException("Unable to invoke removeNotificationListener, status=" + result.toString()); } } finally { releaseCorrelationId(correlationId); } } private void removeNotificationListener(final int[] listenerIds) throws InstanceNotFoundException, ListenerNotFoundException, IOException { VersionedIoFuture> future = new VersionedIoFuture>(); final int correlationId = reserveNextCorrelationId(future); try { write(new MessageWriter() { @Override public void write(DataOutput output) throws IOException { output.writeByte(REMOVE_NOTIFICATION_LISTENER); output.writeInt(correlationId); output.writeByte(INTEGER); output.writeInt(1); // Sending 2 parameters. output.writeByte(INTEGER_ARRAY); output.writeInt(listenerIds.length); for (int current : listenerIds) { output.writeInt(current); } } }); log.tracef("[%d] removeNotificationListener - Request Sent", correlationId); IoFuture.Status result = future.await(timeoutSeconds, TimeUnit.SECONDS); switch (result) { case FAILED: throw future.getException(); case DONE: TypeExceptionHolder response = future.get(); if (response.e == null) { return; } instanceNotFoundException(response.e); listenerNotFoundException(response.e); jmRuntimeException(response.e); throw toIoException(response.e); default: throw new IOException("Unable to invoke removeNotificationListener, status=" + result.toString()); } } finally { releaseCorrelationId(correlationId); } } public void removeNotificationListener(ObjectName name, NotificationListener listener) throws InstanceNotFoundException, ListenerNotFoundException, IOException { removeNotificationListener(localNotificationManager.matchToRemove(name, listener)); } public void removeNotificationListener(ObjectName name, NotificationListener listener, NotificationFilter filter, Object handback) throws InstanceNotFoundException, ListenerNotFoundException, IOException { removeNotificationListener(localNotificationManager.matchToRemove(name, listener, filter, handback)); } public MBeanInfo getMBeanInfo(final ObjectName name) throws InstanceNotFoundException, IntrospectionException, ReflectionException, IOException { VersionedIoFuture> future = new VersionedIoFuture>(); final int correlationId = reserveNextCorrelationId(future); try { write(new MessageWriter() { @Override public void write(DataOutput output) throws IOException { output.writeByte(GET_MBEAN_INFO); output.writeInt(correlationId); output.writeByte(OBJECT_NAME); Marshaller marshaller = prepareForMarshalling(output); marshaller.writeObject(name); marshaller.close(); } }); log.tracef("[%d] getMBeanInfo - Request Sent", correlationId); IoFuture.Status result = future.await(timeoutSeconds, TimeUnit.SECONDS); switch (result) { case FAILED: throw future.getException(); case DONE: TypeExceptionHolder response = future.get(); if (response.e == null) { return response.value; } instanceNotFoundException(response.e); introspectionException(response.e); reflectionException(response.e); jmRuntimeException(response.e); throw toIoException(response.e); default: throw new IOException("Unable to obtain isRegistered, status=" + result.toString()); } } finally { releaseCorrelationId(correlationId); } } public boolean isInstanceOf(final ObjectName name, final String className) throws InstanceNotFoundException, IOException { VersionedIoFuture> future = new VersionedIoFuture>(); final int correlationId = reserveNextCorrelationId(future); try { write(new MessageWriter() { @Override public void write(DataOutput output) throws IOException { output.writeByte(INSTANCE_OF); output.writeInt(correlationId); output.writeByte(OBJECT_NAME); Marshaller marshaller = prepareForMarshalling(output); marshaller.writeObject(name); marshaller.writeByte(STRING); marshaller.writeUTF(className); } }); log.tracef("[%d] isInstanceOf - Request Sent", correlationId); IoFuture.Status result = future.await(timeoutSeconds, TimeUnit.SECONDS); switch (result) { case FAILED: throw future.getException(); case DONE: TypeExceptionHolder response = future.get(); if (response.e == null) { return response.value; } instanceNotFoundException(response.e); jmRuntimeException(response.e); throw toIoException(response.e); default: throw new IOException("Unable to obtain isRegistered, status=" + result.toString()); } } finally { releaseCorrelationId(correlationId); } } private void attributeNotFoundException(Exception e) throws AttributeNotFoundException { if (e != null && e instanceof AttributeNotFoundException) { throw (AttributeNotFoundException) e; } } private void instanceAlreadyExistsException(Exception e) throws InstanceAlreadyExistsException { if (e != null && e instanceof InstanceAlreadyExistsException) { throw (InstanceAlreadyExistsException) e; } } private void instanceNotFoundException(Exception e) throws InstanceNotFoundException { if (e != null && e instanceof InstanceNotFoundException) { throw (InstanceNotFoundException) e; } } private void introspectionException(Exception e) throws IntrospectionException { if (e != null && e instanceof IntrospectionException) { throw (IntrospectionException) e; } } private void invalidAttributeValueException(Exception e) throws InvalidAttributeValueException { if (e != null && e instanceof InvalidAttributeValueException) { throw (InvalidAttributeValueException) e; } } private void listenerNotFoundException(Exception e) throws ListenerNotFoundException { if (e != null && e instanceof ListenerNotFoundException) { throw (ListenerNotFoundException) e; } } private void mbeanRegistrationException(Exception e) throws MBeanRegistrationException { if (e != null && e instanceof MBeanRegistrationException) { throw (MBeanRegistrationException) e; } } private void mbeanException(Exception e) throws MBeanException { if (e != null && e instanceof MBeanException) { throw (MBeanException) e; } } private void notCompliantMBeanException(Exception e) throws NotCompliantMBeanException { if (e != null && e instanceof NotCompliantMBeanException) { throw (NotCompliantMBeanException) e; } } private void reflectionException(Exception e) throws ReflectionException { if (e != null && e instanceof ReflectionException) { throw (ReflectionException) e; } } private void jmRuntimeException(Exception e) { if (e instanceof JMRuntimeException) { throw (JMRuntimeException) e; } } /** * This Exception conversion needs to return the IOException instead of throwing it, this is so that the compiler can * detect that for the final Exception check something is actually thrown. */ private IOException toIoException(Exception e) { if (e instanceof IOException) { return (IOException) e; } else { return new IOException("Unexpected failure", e); } } } private class TypeExceptionHolder { private T value; private Exception e; } private abstract class BaseResponseHandler implements Common.MessageHandler { public void handle(DataInput input, int correlationId) { VersionedIoFuture> future = getFuture(correlationId); try { TypeExceptionHolder response = new TypeExceptionHolder(); byte outcome = input.readByte(); if (outcome == SUCCESS) { final byte expectedType = getExpectedType(); if (expectedType != VOID) { byte parameterType = input.readByte(); if (parameterType != expectedType) { throw new IOException("Unexpected response parameter received."); } response.value = readValue(input); } } else if (outcome == FAILURE) { byte parameterType = input.readByte(); if (parameterType != EXCEPTION) { throw new IOException("Unexpected response parameter received."); } Unmarshaller unmarshaller = prepareForUnMarshalling(input); response.e = unmarshaller.readObject(Exception.class); } else { future.setException(new IOException("Outcome not understood")); } future.setResult(response); } catch (ClassCastException e) { future.setException(new IOException(e)); } catch (ClassNotFoundException e) { future.setException(new IOException(e)); } catch (IOException e) { future.setException(e); } } protected abstract byte getExpectedType(); protected abstract T readValue(DataInput input) throws IOException; } private class BooleanResponseHandler extends BaseResponseHandler { @Override protected byte getExpectedType() { return BOOLEAN; } @Override protected Boolean readValue(DataInput input) throws IOException { return input.readBoolean(); } } private class IntegerResponseHandler extends BaseResponseHandler { @Override protected byte getExpectedType() { return INTEGER; } @Override protected Integer readValue(DataInput input) throws IOException { return input.readInt(); } } private class StringResponseHandler extends BaseResponseHandler { @Override protected byte getExpectedType() { return STRING; } @Override protected String readValue(DataInput input) throws IOException { return input.readUTF(); } } private class StringArrayResponseHandler extends BaseResponseHandler { @Override protected byte getExpectedType() { return STRING_ARRAY; } @Override protected String[] readValue(DataInput input) throws IOException { int count = input.readInt(); String[] response = new String[count]; for (int i = 0; i < count; i++) { response[i] = input.readUTF(); } return response; } } private class MarshalledResponseHandler extends BaseResponseHandler { private final byte expectedType; private MarshalledResponseHandler(final byte expectedType) { this.expectedType = expectedType; } @Override protected byte getExpectedType() { return expectedType; } @SuppressWarnings("unchecked") @Override protected T readValue(DataInput input) throws IOException { Unmarshaller unmarshaller = prepareForUnMarshalling(input); try { return ((T) unmarshaller.readObject()); } catch (ClassNotFoundException e) { throw new IOException(e); } catch (ClassCastException e) { throw new IOException(e); } } } private class NotificationHandler implements MessageHandler { /* * The message received will already be being processed on a Thread obtained from the local Executor, for this reason * there is no point in creating a new Runnable and passing it to the executor to process the Notification. */ @Override public void handle(DataInput input, int correlationId) throws IOException { log.trace("Notification"); byte paramType = input.readByte(); if (paramType != INTEGER) { throw new IOException("Unexpected paramType"); } int listenerId = input.readInt(); paramType = input.readByte(); if (paramType != NOTIFICATION) { throw new IOException("Unexpected paramType"); } try { Unmarshaller unmarshaller = prepareForUnMarshalling(input); Notification notification = unmarshaller.readObject(Notification.class); paramType = unmarshaller.readByte(); if (paramType != OBJECT) { throw new IOException("Unexpected paramType"); } Object handBack = unmarshaller.readObject(); localNotificationManager.notify(listenerId, notification, handBack); } catch (ClassNotFoundException cnfe) { throw new IOException(cnfe); } } } }