KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > management > remote > connect > ClientConnectEventHandler


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
3  * notice. All rights reserved.
4  */

5 package com.tc.management.remote.connect;
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.management.TerracottaMBean;
13 import com.tc.management.TerracottaManagement;
14 import com.tc.management.remote.protocol.ProtocolProvider;
15 import com.tc.management.remote.protocol.terracotta.ClientProvider;
16 import com.tc.management.remote.protocol.terracotta.TunnelingMessageConnection;
17 import com.tc.management.remote.protocol.terracotta.ClientTunnelingEventHandler.L1ConnectionMessage;
18 import com.tc.net.TCSocketAddress;
19 import com.tc.net.protocol.tcm.MessageChannel;
20
21 import java.io.IOException JavaDoc;
22 import java.net.MalformedURLException JavaDoc;
23 import java.util.ArrayList JavaDoc;
24 import java.util.HashMap JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.List JavaDoc;
27 import java.util.Map JavaDoc;
28 import java.util.Set JavaDoc;
29
30 import javax.management.MBeanServer JavaDoc;
31 import javax.management.MBeanServerConnection JavaDoc;
32 import javax.management.MBeanServerInvocationHandler JavaDoc;
33 import javax.management.Notification JavaDoc;
34 import javax.management.NotificationFilter JavaDoc;
35 import javax.management.NotificationListener JavaDoc;
36 import javax.management.ObjectName JavaDoc;
37 import javax.management.StandardMBean JavaDoc;
38 import javax.management.remote.JMXConnectionNotification JavaDoc;
39 import javax.management.remote.JMXConnector JavaDoc;
40 import javax.management.remote.JMXConnectorFactory JavaDoc;
41 import javax.management.remote.JMXServiceURL JavaDoc;
42
43 public class ClientConnectEventHandler extends AbstractEventHandler {
44
45   private static final class ConnectorClosedFilter implements NotificationFilter JavaDoc {
46
47     public boolean isNotificationEnabled(final Notification JavaDoc notification) {
48       boolean enabled = false;
49       if (notification instanceof JMXConnectionNotification JavaDoc) {
50         final JMXConnectionNotification JavaDoc jmxcn = (JMXConnectionNotification JavaDoc) notification;
51         enabled = jmxcn.getType().equals(JMXConnectionNotification.CLOSED);
52       }
53       return enabled;
54     }
55
56   }
57
58   private static final class ConnectorClosedListener implements NotificationListener JavaDoc {
59
60     private static final TCLogger logger = TCLogging.getLogger(ConnectorClosedListener.class);
61
62     private final MBeanServerConnection JavaDoc mBeanServerConnection;
63
64     ConnectorClosedListener(final MBeanServerConnection JavaDoc mBeanServerConnection) {
65       this.mBeanServerConnection = mBeanServerConnection;
66     }
67
68     final public void handleNotification(final Notification JavaDoc notification, final Object JavaDoc context) {
69       for (Iterator JavaDoc beanNames = ((List JavaDoc) context).iterator(); beanNames.hasNext();) {
70         final ObjectName JavaDoc dsoClientBeanName = (ObjectName JavaDoc) beanNames.next();
71         try {
72           mBeanServerConnection.unregisterMBean(dsoClientBeanName);
73         } catch (Exception JavaDoc e) {
74           logger.warn("Unable to unregister DSO client bean[" + dsoClientBeanName + "]", e);
75         }
76       }
77     }
78   }
79
80   private static final TCLogger logger = TCLogging.getLogger(ClientConnectEventHandler.class);
81
82   public void handleEvent(EventContext context) throws EventHandlerException {
83     L1ConnectionMessage msg = (L1ConnectionMessage) context;
84     if (msg.isConnectingMsg()) {
85       addJmxConnection(msg);
86     } else {
87       removeJmxConnection(msg);
88     }
89   }
90
91   private void addJmxConnection(final L1ConnectionMessage msg) {
92     final MessageChannel channel = msg.getChannel();
93     final TCSocketAddress remoteAddress = channel != null ? channel.getRemoteAddress() : null;
94     if (remoteAddress == null) { return; }
95
96     final MBeanServer JavaDoc l2MBeanServer = msg.getMBeanServer();
97     final Map JavaDoc channelIdToJmxConnector = msg.getChannelIdToJmxConnector();
98     final Map JavaDoc channelIdToMsgConnection = msg.getChannelIdToMsgConnector();
99     synchronized (channelIdToJmxConnector) {
100       if (!channelIdToJmxConnector.containsKey(channel.getChannelID())) {
101         JMXServiceURL JavaDoc serviceURL;
102         try {
103           serviceURL = new JMXServiceURL JavaDoc("terracotta", remoteAddress.getAddress().getHostName(), remoteAddress
104               .getPort());
105         } catch (MalformedURLException JavaDoc murle) {
106           logger.error("Unable to construct a JMX service URL using DSO client channel from host["
107               + channel.getRemoteAddress() + "]; tunneled JMX connection will not be established", murle);
108           return;
109         }
110         Map JavaDoc environment = new HashMap JavaDoc();
111         ProtocolProvider.addTerracottaJmxProvider(environment);
112         environment.put(ClientProvider.JMX_MESSAGE_CHANNEL, channel);
113         environment.put(ClientProvider.CONNECTION_LIST, channelIdToMsgConnection);
114         final JMXConnector JavaDoc jmxConnector;
115         try {
116           jmxConnector = JMXConnectorFactory.connect(serviceURL, environment);
117
118           final MBeanServerConnection JavaDoc l1MBeanServerConnection = jmxConnector.getMBeanServerConnection();
119           Set JavaDoc mBeans = l1MBeanServerConnection.queryNames(null, TerracottaManagement.matchAllTerracottaMBeans());
120           List JavaDoc modifiedObjectNames = new ArrayList JavaDoc();
121           for (Iterator JavaDoc iter = mBeans.iterator(); iter.hasNext();) {
122             ObjectName JavaDoc objName = (ObjectName JavaDoc) iter.next();
123             try {
124               TerracottaMBean mBeanProxy = (TerracottaMBean) MBeanServerInvocationHandler.newProxyInstance(
125                   l1MBeanServerConnection, objName, TerracottaMBean.class, false);
126               ObjectName JavaDoc modifiedObjName = TerracottaManagement.addNodeInfo(objName, channel.getRemoteAddress());
127               Class JavaDoc interfaceClass = Class.forName(mBeanProxy.getInterfaceClassName());
128               Object JavaDoc obj = MBeanServerInvocationHandler.newProxyInstance(l1MBeanServerConnection, objName,
129                   interfaceClass, mBeanProxy.isNotificationBroadcaster());
130               l2MBeanServer.registerMBean(new StandardMBean JavaDoc(obj, interfaceClass), modifiedObjName);
131               modifiedObjectNames.add(modifiedObjName);
132             } catch (Exception JavaDoc e) {
133               logger.error("Unable to register remote DSO client MBean[" + objName.getCanonicalName() + "] for host["
134                   + channel.getRemoteAddress() + "], this bean will not show up in monitoring tools!!", e);
135             }
136           }
137           try {
138             jmxConnector.addConnectionNotificationListener(new ConnectorClosedListener(l2MBeanServer),
139                 new ConnectorClosedFilter(), modifiedObjectNames);
140           } catch (Exception JavaDoc e) {
141             logger.error("Unable to register a JMX connection listener for the DSO client["
142                 + channel.getRemoteAddress()
143                 + "], if the DSO client disconnects the then its (dead) beans will not be unregistered", e);
144           }
145         } catch (IOException JavaDoc ioe) {
146           logger.error("Unable to create tunneled JMX connection to the DSO client on host["
147               + channel.getRemoteAddress() + "], this DSO client will not show up in monitoring tools!!", ioe);
148           return;
149         }
150         channelIdToJmxConnector.put(channel.getChannelID(), jmxConnector);
151       } else {
152         logger.warn("We are trying to create a new tunneled JMX connection but already have one for channel["
153             + channel.getRemoteAddress() + "], ignoring new connection message");
154       }
155     }
156   }
157
158   private void removeJmxConnection(final L1ConnectionMessage msg) {
159     final MessageChannel channel = msg.getChannel();
160     final Map JavaDoc channelIdToJmxConnector = msg.getChannelIdToJmxConnector();
161     final Map JavaDoc channelIdToMsgConnection = msg.getChannelIdToMsgConnector();
162
163     synchronized (channelIdToMsgConnection) {
164       final TunnelingMessageConnection tmc = (TunnelingMessageConnection) channelIdToMsgConnection.remove(channel
165           .getChannelID());
166       if (tmc != null) {
167         try {
168           tmc.close();
169         } catch (IOException JavaDoc ioe) {
170           logger.warn("Unable to close JMX tunneling message connection to DSO client[" + channel + "]", ioe);
171         }
172       }
173     }
174
175     synchronized (channelIdToJmxConnector) {
176       if (channelIdToJmxConnector.containsKey(channel.getChannelID())) {
177         final JMXConnector JavaDoc jmxConnector = (JMXConnector JavaDoc) channelIdToJmxConnector.remove(channel.getChannelID());
178         if (jmxConnector != null) {
179           try {
180             jmxConnector.close();
181           } catch (IOException JavaDoc ioe) {
182             logger.debug("Unable to close JMX connector to DSO client[" + channel + "]", ioe);
183           }
184         }
185       } else {
186         logger.warn("DSO client channel closed without a corresponding tunneled JMX connection");
187       }
188     }
189   }
190
191 }
192
Popular Tags