KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > admin > ServerConnectionManager


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.admin;
6
7 import com.tc.config.schema.L2Info;
8
9 import java.io.IOException JavaDoc;
10 import java.util.EventListener JavaDoc;
11 import java.util.HashMap JavaDoc;
12 import java.util.Map JavaDoc;
13 import java.util.Timer JavaDoc;
14 import java.util.TimerTask JavaDoc;
15 import java.util.logging.Level JavaDoc;
16 import java.util.logging.Logger JavaDoc;
17
18 import javax.management.AttributeChangeNotification JavaDoc;
19 import javax.management.Notification JavaDoc;
20 import javax.management.NotificationListener JavaDoc;
21 import javax.management.ObjectName JavaDoc;
22 import javax.management.remote.JMXConnector JavaDoc;
23 import javax.management.remote.JMXConnectorFactory JavaDoc;
24 import javax.management.remote.JMXServiceURL JavaDoc;
25
26 public class ServerConnectionManager implements NotificationListener JavaDoc {
27   private L2Info m_l2Info;
28   private boolean m_autoConnect;
29   private ConnectionContext m_connectCntx;
30   private ConnectionListener m_connectListener;
31   private JMXServiceURL JavaDoc m_serviceURL;
32   private HashMap JavaDoc m_connectEnv;
33   private ServerHelper m_serverHelper;
34   private boolean m_connected;
35   private boolean m_started;
36   private boolean m_active;
37   private Exception JavaDoc m_connectException;
38   private ConnectThread m_connectThread;
39   private ConnectionMonitorAction m_connectMonitorAction;
40   private Timer JavaDoc m_connectMonitorTimer;
41   private AutoConnectListener m_autoConnectListener;
42
43   private static final Map JavaDoc m_credentialsMap = new HashMap JavaDoc();
44   
45   private static final int CONNECT_MONITOR_PERIOD = 1000;
46
47   private static final Object JavaDoc m_connectTestLock = new Object JavaDoc();
48   
49   static {
50     Logger.getLogger("javax.management.remote.rmi").setLevel(Level.OFF);
51   }
52
53   public ServerConnectionManager(String JavaDoc host, int port, boolean autoConnect, ConnectionListener listener) {
54     this(new L2Info(host, host, port), autoConnect, listener);
55   }
56
57   public ServerConnectionManager(L2Info l2Info, boolean autoConnect, ConnectionListener listener) {
58     m_autoConnect = autoConnect;
59     m_connectListener = listener;
60     m_serverHelper = ServerHelper.getHelper();
61
62     setL2Info(l2Info);
63   }
64
65   public L2Info getL2Info() {
66     return m_l2Info;
67   }
68   
69   public void setL2Info(L2Info l2Info) {
70     cancelActiveServices();
71
72     m_l2Info = l2Info;
73     m_connectCntx = new ConnectionContext(l2Info);
74
75     try {
76       m_serviceURL = new JMXServiceURL JavaDoc(getSecureJMXServicePath());
77       if (isAutoConnect()) {
78         startConnect();
79       }
80     } catch (Exception JavaDoc e) {/**/
81     }
82   }
83
84   public void setHostname(String JavaDoc hostname) {
85     setL2Info(new L2Info(m_l2Info.name(), hostname, m_l2Info.jmxPort()));
86   }
87
88   public void setJMXPortNumber(int port) {
89     setL2Info(new L2Info(m_l2Info.name(), m_l2Info.host(), port));
90   }
91
92   public void setCredentials(String JavaDoc username, String JavaDoc password) {
93     Map JavaDoc connEnv = getConnectionEnvironment();
94     connEnv.put("jmx.remote.credentials", new String JavaDoc[] { username, password });
95   }
96   
97   public String JavaDoc[] getCredentials() {
98     Map JavaDoc connEnv = getConnectionEnvironment();
99     return (String JavaDoc[])connEnv.get("jmx.remote.credentials");
100   }
101
102   static void cacheCredentials(ServerConnectionManager scm, String JavaDoc[] credentials) {
103     m_credentialsMap.put(scm.toString(), credentials);
104     m_credentialsMap.put(scm.getHostname(), credentials);
105   }
106   
107   public static String JavaDoc[] getCachedCredentials(ServerConnectionManager scm) {
108     String JavaDoc[] result = (String JavaDoc[])m_credentialsMap.get(scm.toString());
109     if(result == null) {
110       result = (String JavaDoc[])m_credentialsMap.get(scm.getHostname());
111     }
112     return result;
113   }
114   
115   public void setAutoConnect(boolean autoConnect) {
116     if (m_autoConnect != autoConnect) {
117       if ((m_autoConnect = autoConnect) == true) {
118         if (!m_connected) {
119           startConnect();
120         }
121       } else {
122         cancelActiveServices();
123       }
124     }
125   }
126
127   public boolean isAutoConnect() {
128     return m_autoConnect;
129   }
130
131   public void setConnectionContext(ConnectionContext cc) {
132     m_connectCntx = cc;
133   }
134
135   public ConnectionContext getConnectionContext() {
136     return m_connectCntx;
137   }
138
139   public void setJMXConnector(JMXConnector JavaDoc jmxc) throws IOException JavaDoc {
140     m_connectException = null;
141     m_connectCntx.jmxc = jmxc;
142     m_connectCntx.mbsc = jmxc.getMBeanServerConnection();
143     setConnected(true);
144   }
145
146   protected synchronized void setConnected(boolean connected) {
147     if (m_connected != connected) {
148       m_connected = connected;
149       if (m_connected == false) {
150         cancelActiveServices();
151         m_active = m_started = false;
152         if (isAutoConnect()) {
153           startConnect();
154         }
155       } else { // connected
156
cacheCredentials(ServerConnectionManager.this, getCredentials());
157         m_started = true;
158         if ((m_active = internalIsActive()) == false) {
159           addActivationListener();
160         }
161         initConnectionMonitor();
162       }
163
164       // Notify listener that the connection state changed.
165
if (m_connectListener != null) {
166         m_connectListener.handleConnection();
167       }
168     }
169   }
170
171   /**
172    * Mark not-connected, notify, cancel connection monitor, don't startup auto-connect thread.
173    */

174   void disconnectOnExit() {
175     cancelActiveServices();
176     if (m_connected) {
177       m_connected = false;
178       if (m_connectListener != null) {
179         m_connectListener.handleConnection();
180       }
181     }
182   }
183
184   /**
185    * Since we have all of this infrastructure, turn off the JMXRemote connection monitoring stuff.
186    */

187   Map JavaDoc getConnectionEnvironment() {
188     if (m_connectEnv == null) {
189       m_connectEnv = new HashMap JavaDoc();
190       m_connectEnv.put("jmx.remote.x.client.connection.check.period", new Long JavaDoc(0));
191       m_connectEnv.put("jmx.remote.default.class.loader", getClass().getClassLoader());
192     }
193     return m_connectEnv;
194   }
195
196   private void initConnector() throws Exception JavaDoc {
197     m_connectCntx.jmxc = JMXConnectorFactory.newJMXConnector(m_serviceURL, getConnectionEnvironment());
198   }
199
200   private void startConnect() {
201     try {
202       cancelConnectThread();
203       initConnector();
204       m_connectThread = new ConnectThread();
205       m_connectThread.start();
206     } catch (Exception JavaDoc e) {
207       m_connectException = e;
208       if (m_connectListener != null) {
209         m_connectListener.handleException();
210       }
211     }
212   }
213
214   private void cancelConnectThread() {
215     if (m_connectThread != null && m_connectThread.isAlive()) {
216       try {
217         m_connectThread.cancel();
218         m_connectThread = null;
219       } catch (Exception JavaDoc ignore) {/**/
220       }
221     }
222   }
223
224   public boolean testIsConnected() throws Exception JavaDoc {
225     synchronized(m_connectTestLock) {
226       if (m_connectCntx.jmxc == null) {
227         initConnector();
228       }
229       m_connectCntx.jmxc.connect(getConnectionEnvironment());
230       m_connectCntx.mbsc = m_connectCntx.jmxc.getMBeanServerConnection();
231       m_connectException = null;
232   
233       return true;
234     }
235   }
236
237   class ConnectThread extends Thread JavaDoc {
238     private boolean m_cancel = false;
239     
240     ConnectThread() {
241       super();
242       setPriority(MIN_PRIORITY);
243     }
244
245     public void run() {
246       try {
247         sleep(500);
248       } catch (InterruptedException JavaDoc ie) {/**/}
249       
250       while (!m_cancel && !m_connected) {
251         try {
252           boolean isConnected = testIsConnected();
253           if(!m_cancel) {
254             setConnected(isConnected);
255           }
256           return;
257         } catch (Exception JavaDoc e) {
258           if(m_cancel) {
259             return;
260           } else {
261             m_connectException = e;
262             if (m_connectListener != null) {
263               if (e instanceof SecurityException JavaDoc) {
264                 setAutoConnect(false);
265                 fireToggleAutoConnectEvent();
266                 m_connectListener.handleException();
267                 return;
268               }
269               m_connectListener.handleException();
270             }
271           }
272         }
273
274         try {
275           sleep(2000);
276         } catch (InterruptedException JavaDoc ie) {
277           // We may interrupt the connect thread when a new host or port comes in
278
// because we have to recreate the connection context, JMX service URL,
279
// and connect thread.
280
return;
281         }
282       }
283     }
284
285     void cancel() {
286       m_cancel = true;
287     }
288   }
289
290   void addToggleAutoConnectListener(AutoConnectListener listener) {
291     m_autoConnectListener = listener;
292   }
293
294   private void fireToggleAutoConnectEvent() {
295     if (m_autoConnectListener != null) m_autoConnectListener.handleEvent();
296   }
297
298   JMXServiceURL JavaDoc getJMXServiceURL() {
299     return m_serviceURL;
300   }
301
302   private String JavaDoc getSecureJMXServicePath() {
303     return "service:jmx:rmi:///jndi/rmi://" + this + "/jmxrmi";
304   }
305
306   public String JavaDoc getName() {
307     return m_l2Info.name();
308   }
309
310   public String JavaDoc getHostname() {
311     return m_l2Info.host();
312   }
313
314   public int getJMXPortNumber() {
315     return m_l2Info.jmxPort();
316   }
317
318   public boolean isConnected() {
319     return m_connected;
320   }
321
322   public Exception JavaDoc getConnectionException() {
323     return m_connectException;
324   }
325
326   public boolean isActive() {
327     return m_active;
328   }
329
330   private boolean internalIsActive() {
331     try {
332       return m_serverHelper.isActive(m_connectCntx);
333     } catch (Exception JavaDoc e) {
334       return false;
335     }
336   }
337
338   public boolean isStarted() {
339     return m_started;
340   }
341
342   void initConnectionMonitor() {
343     if (m_connectMonitorAction == null) {
344       m_connectMonitorAction = new ConnectionMonitorAction();
345     }
346     if (m_connectMonitorTimer == null) {
347       m_connectMonitorTimer = new Timer JavaDoc();
348       m_connectMonitorTimer.schedule(m_connectMonitorAction, CONNECT_MONITOR_PERIOD, CONNECT_MONITOR_PERIOD);
349     }
350    }
351
352   private class ConnectionMonitorAction extends TimerTask JavaDoc {
353     public void run() {
354       if (m_connectCntx.isConnected()) {
355         try {
356           m_connectCntx.testConnection();
357         } catch (Exception JavaDoc e) {
358           cancelConnectionMonitor();
359           setConnected(false);
360         }
361       }
362     }
363   }
364
365   void cancelConnectionMonitor() {
366     if (m_connectMonitorTimer != null) {
367       m_connectMonitorTimer.cancel();
368       m_connectMonitorAction.cancel();
369       m_connectMonitorAction = null;
370       m_connectMonitorTimer = null;
371     }
372   }
373
374   /**
375    * Register for a JMX callback when the server transitions from started->...->active.
376    * We do this when we notice that the server is started but not yet active.
377    */

378   void addActivationListener() {
379     try {
380       ObjectName JavaDoc infoMBean = m_serverHelper.getServerInfoMBean(m_connectCntx);
381       m_connectCntx.addNotificationListener(infoMBean, this);
382       if ((m_active = internalIsActive()) == true) {
383         m_connectCntx.removeNotificationListener(infoMBean, this);
384       }
385     } catch (Exception JavaDoc e) {/**/
386     }
387   }
388
389   void removeActivationListener() {
390     try {
391       ObjectName JavaDoc infoMBean = m_serverHelper.getServerInfoMBean(m_connectCntx);
392       m_connectCntx.removeNotificationListener(infoMBean, this);
393     } catch (Exception JavaDoc e) {/**/
394     }
395   }
396
397   /**
398    * JMX callback notifying that the server has transitioned from started->active.
399    */

400   public void handleNotification(Notification JavaDoc notice, Object JavaDoc handback) {
401     if (notice instanceof AttributeChangeNotification JavaDoc) {
402       AttributeChangeNotification JavaDoc acn = (AttributeChangeNotification JavaDoc) notice;
403
404       if (acn.getAttributeType().equals("jmx.terracotta.L2.active")) {
405         m_active = true;
406         removeActivationListener();
407         if (m_connectListener != null) {
408           m_connectListener.handleConnection();
409         }
410       }
411     }
412   }
413
414   public String JavaDoc toString() {
415     return getHostname() + ":" + getJMXPortNumber();
416   }
417
418   public void dump(String JavaDoc prefix) {
419     System.out.println(prefix+this+",connected="+m_connected+",autoConnect="+m_autoConnect+",started="+m_started+",exception="+m_connectException);
420   }
421   
422   void cancelActiveServices() {
423     cancelConnectThread();
424     cancelConnectionMonitor();
425
426     if (m_started) {
427       removeActivationListener();
428     }
429     if (m_connectCntx != null) {
430       m_connectCntx.reset();
431     }
432   }
433
434   void tearDown() {
435     cancelActiveServices();
436
437     m_l2Info = null;
438     m_serverHelper = null;
439     m_connectCntx = null;
440     m_connectListener = null;
441     m_serviceURL = null;
442     m_connectThread = null;
443   }
444
445   // --------------------------------------------------------------------------------
446

447   public static interface AutoConnectListener extends EventListener JavaDoc {
448     void handleEvent();
449   }
450 }
451
Popular Tags