1 5 package com.tc.management.remote.protocol.terracotta; 6 7 import com.tc.async.api.AbstractEventHandler; 8 import com.tc.async.api.EventContext; 9 import com.tc.async.api.EventHandlerException; 10 import com.tc.logging.TCLogger; 11 import com.tc.logging.TCLogging; 12 import com.tc.net.protocol.tcm.ChannelEvent; 13 import com.tc.net.protocol.tcm.ChannelEventListener; 14 import com.tc.net.protocol.tcm.ChannelEventType; 15 import com.tc.net.protocol.tcm.MessageChannel; 16 import com.tc.net.protocol.tcm.TCMessage; 17 import com.tc.net.protocol.tcm.TCMessageType; 18 import com.tc.util.concurrent.SetOnceFlag; 19 20 import java.io.IOException ; 21 22 import javax.management.remote.generic.MessageConnection; 23 import javax.management.remote.message.Message; 24 25 public final class TunnelingEventHandler extends AbstractEventHandler implements 26 ChannelEventListener { 27 28 private static final TCLogger logger = TCLogging 29 .getLogger(TunnelingEventHandler.class); 30 31 private final MessageChannel channel; 32 33 private TunnelingMessageConnection messageConnection; 34 35 private boolean acceptOk; 36 37 private Object jmxReadyLock; 38 39 private SetOnceFlag localJmxServerReady; 40 41 private boolean transportConnected; 42 43 private boolean sentReadyMessage; 44 45 public TunnelingEventHandler(final MessageChannel channel) { 46 this.channel = channel; 47 this.channel.addListener(this); 48 acceptOk = false; 49 jmxReadyLock = new Object (); 50 localJmxServerReady = new SetOnceFlag(); 51 transportConnected = false; 52 sentReadyMessage = false; 53 } 54 55 public void handleEvent(final EventContext context) 56 throws EventHandlerException { 57 final JmxRemoteTunnelMessage messageEnvelope = (JmxRemoteTunnelMessage) context; 58 if (messageEnvelope.getCloseConnection()) { 59 reset(); 60 } else { 61 final Message message = messageEnvelope.getTunneledMessage(); 62 synchronized (this) { 63 if (messageEnvelope.getInitConnection()) { 64 if (messageConnection != null) { 65 logger 66 .warn("Received a client connection initialization, resetting existing connection"); 67 reset(); 68 } 69 messageConnection = new TunnelingMessageConnection(channel, 70 true); 71 acceptOk = true; 72 notifyAll(); 73 } else if (messageConnection == null) { 74 logger 75 .warn("Received unexpected data message, connection is not yet established"); 76 } else { 77 if (message != null) { 78 messageConnection.incomingNetworkMessage(message); 79 } else { 80 logger 81 .warn("Received tunneled message with no data, resetting connection"); 82 reset(); 83 } 84 } 85 } 86 } 87 } 88 89 synchronized MessageConnection accept() throws IOException { 90 while (!acceptOk) { 91 try { 92 wait(); 93 } catch (InterruptedException ie) { 94 logger.warn("Interrupted while waiting for a new connection", 95 ie); 96 throw new IOException ( 97 "Interrupted while waiting for new connection: " 98 + ie.getMessage()); 99 } 100 } 101 acceptOk = false; 102 return messageConnection; 103 } 104 105 private synchronized void reset() { 106 if (messageConnection != null) { 107 try { 108 messageConnection.close(); 109 } catch (IOException ioe) { 110 logger 111 .warn("Caught I/O exception while closing tunneled JMX connection"); 112 } 113 } 114 messageConnection = null; 115 acceptOk = false; 116 synchronized (jmxReadyLock) { 117 sentReadyMessage = false; 118 } 119 notifyAll(); 120 } 121 122 public void notifyChannelEvent(final ChannelEvent event) { 123 if (event.getChannel() == channel) { 124 if (event.getType() == ChannelEventType.TRANSPORT_CONNECTED_EVENT) { 125 synchronized (jmxReadyLock) { 126 transportConnected = true; 127 } 128 sendJmxReadyMessageIfNecessary(); 129 } else if (event.getType() == ChannelEventType.CHANNEL_CLOSED_EVENT 130 || event.getType() == ChannelEventType.TRANSPORT_DISCONNECTED_EVENT) { 131 reset(); 132 synchronized (jmxReadyLock) { 133 transportConnected = false; 134 } 135 } 136 } 137 } 138 139 public void jmxIsReady() { 140 synchronized (jmxReadyLock) { 141 localJmxServerReady.set(); 142 } 143 144 sendJmxReadyMessageIfNecessary(); 145 } 146 147 155 private void sendJmxReadyMessageIfNecessary() { 156 final boolean send; 157 synchronized (jmxReadyLock) { 158 send = localJmxServerReady.isSet() && transportConnected 159 && !sentReadyMessage; 160 if (send) { 161 sentReadyMessage = true; 162 } 163 } 164 165 if (send) { 168 logger 169 .info("Client JMX server ready; sending notification to L2 server"); 170 TCMessage readyMessage = channel 171 .createMessage(TCMessageType.CLIENT_JMX_READY_MESSAGE); 172 readyMessage.send(); 173 } 174 175 } 176 } 177 | Popular Tags |