/** * {@inheritDoc} * * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, * java.lang.Object[]) */ @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (MBeanServerConnection.class != method.getDeclaringClass()) { return method.invoke(Modifier.isStatic(method.getModifiers()) ? null : this, args); } if (channel.getPipeline().get(getClass().getSimpleName()) == null) { throw new IOException("This MBeanServerConnection has been closed", new Throwable()); } // SimpleLogger.debug("MBeanServerConnection [", method.getName(), "] Payload Size [", // sargs.length+6+4, "]"); final int reqId = requestId.incrementAndGet(); if ("addNotificationListener".equals(method.getName()) && !method.getParameterTypes()[1].equals(ObjectName.class)) { NotificationListener listener = (NotificationListener) args[1]; args[1] = reqId; addRegisteredListener(reqId, listener); } else if ("removeNotificationListener".equals(method.getName()) && !method.getParameterTypes()[1].equals(ObjectName.class)) { removeRegisteredListener((NotificationListener) args[1]); args = new Object[0]; } byte[] sargs = getOutput(args); ChannelBuffer cb = ChannelBuffers.directBuffer(1 + domainInfoData.length + 4 + 1 + 4 + sargs.length); cb.writeByte(OpCode.JMX_REQUEST.op()); // 1 cb.writeBytes(domainInfoData); // domain data cb.writeInt(reqId); // 4 cb.writeByte(methodToKey.get(method)); // 1 cb.writeInt(sargs.length); // 4 cb.writeBytes(sargs); // sargs.length if (listener == null) { synchTimeoutMap.addListener( new TimeoutListener<Integer, CountDownLatch>() { @Override public void onTimeout(Integer key, CountDownLatch value) { if (reqId == key) { synchTimeoutMap.remove(key); synchTimeoutMap.removeListener(this); onSynchronousResponse( reqId, new IOException( "Operation timed out after [" + timeout + "] ms.", new Throwable())); } } }); } else { asynchTimeoutMap.put(reqId, listener, timeout); asynchTimeoutMap.addListener( new TimeoutListener<Integer, AsynchJMXResponseListener>() { @Override public void onTimeout(Integer key, AsynchJMXResponseListener value) { if (reqId == key) { asynchTimeoutMap.remove(key); listener.onTimeout(reqId, timeout); asynchTimeoutMap.removeListener(this); } } }); } channel .write(cb, remoteAddress) .addListener( new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception { if (future.isSuccess()) { SimpleLogger.debug("Sent JMX Request to [", remoteAddress, "]"); } else { SimpleLogger.error( "Failed to send JMX Request to [", remoteAddress, "]", future.getCause()); } } }); if (listener == null) { waitForSynchronousResponse(reqId, timeout); Object result = synchResultMap.get(reqId); if (result != null && result instanceof Throwable) { throw (Throwable) result; } return result; } return null; }