1 5 package com.tc.admin; 6 7 import com.tc.config.schema.L2Info; 8 9 import java.io.IOException ; 10 import java.util.EventListener ; 11 import java.util.HashMap ; 12 import java.util.Map ; 13 import java.util.Timer ; 14 import java.util.TimerTask ; 15 import java.util.logging.Level ; 16 import java.util.logging.Logger ; 17 18 import javax.management.AttributeChangeNotification ; 19 import javax.management.Notification ; 20 import javax.management.NotificationListener ; 21 import javax.management.ObjectName ; 22 import javax.management.remote.JMXConnector ; 23 import javax.management.remote.JMXConnectorFactory ; 24 import javax.management.remote.JMXServiceURL ; 25 26 public class ServerConnectionManager implements NotificationListener { 27 private L2Info m_l2Info; 28 private boolean m_autoConnect; 29 private ConnectionContext m_connectCntx; 30 private ConnectionListener m_connectListener; 31 private JMXServiceURL m_serviceURL; 32 private HashMap 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 m_connectException; 38 private ConnectThread m_connectThread; 39 private ConnectionMonitorAction m_connectMonitorAction; 40 private Timer m_connectMonitorTimer; 41 private AutoConnectListener m_autoConnectListener; 42 43 private static final Map m_credentialsMap = new HashMap (); 44 45 private static final int CONNECT_MONITOR_PERIOD = 1000; 46 47 private static final Object m_connectTestLock = new Object (); 48 49 static { 50 Logger.getLogger("javax.management.remote.rmi").setLevel(Level.OFF); 51 } 52 53 public ServerConnectionManager(String 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 (getSecureJMXServicePath()); 77 if (isAutoConnect()) { 78 startConnect(); 79 } 80 } catch (Exception e) { 81 } 82 } 83 84 public void setHostname(String 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 username, String password) { 93 Map connEnv = getConnectionEnvironment(); 94 connEnv.put("jmx.remote.credentials", new String [] { username, password }); 95 } 96 97 public String [] getCredentials() { 98 Map connEnv = getConnectionEnvironment(); 99 return (String [])connEnv.get("jmx.remote.credentials"); 100 } 101 102 static void cacheCredentials(ServerConnectionManager scm, String [] credentials) { 103 m_credentialsMap.put(scm.toString(), credentials); 104 m_credentialsMap.put(scm.getHostname(), credentials); 105 } 106 107 public static String [] getCachedCredentials(ServerConnectionManager scm) { 108 String [] result = (String [])m_credentialsMap.get(scm.toString()); 109 if(result == null) { 110 result = (String [])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 jmxc) throws IOException { 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 { cacheCredentials(ServerConnectionManager.this, getCredentials()); 157 m_started = true; 158 if ((m_active = internalIsActive()) == false) { 159 addActivationListener(); 160 } 161 initConnectionMonitor(); 162 } 163 164 if (m_connectListener != null) { 166 m_connectListener.handleConnection(); 167 } 168 } 169 } 170 171 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 187 Map getConnectionEnvironment() { 188 if (m_connectEnv == null) { 189 m_connectEnv = new HashMap (); 190 m_connectEnv.put("jmx.remote.x.client.connection.check.period", new Long (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 { 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 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 ignore) { 220 } 221 } 222 } 223 224 public boolean testIsConnected() throws Exception { 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 { 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 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 e) { 258 if(m_cancel) { 259 return; 260 } else { 261 m_connectException = e; 262 if (m_connectListener != null) { 263 if (e instanceof SecurityException ) { 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 ie) { 277 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 getJMXServiceURL() { 299 return m_serviceURL; 300 } 301 302 private String getSecureJMXServicePath() { 303 return "service:jmx:rmi:///jndi/rmi://" + this + "/jmxrmi"; 304 } 305 306 public String getName() { 307 return m_l2Info.name(); 308 } 309 310 public String 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 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 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 (); 348 m_connectMonitorTimer.schedule(m_connectMonitorAction, CONNECT_MONITOR_PERIOD, CONNECT_MONITOR_PERIOD); 349 } 350 } 351 352 private class ConnectionMonitorAction extends TimerTask { 353 public void run() { 354 if (m_connectCntx.isConnected()) { 355 try { 356 m_connectCntx.testConnection(); 357 } catch (Exception 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 378 void addActivationListener() { 379 try { 380 ObjectName 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 e) { 386 } 387 } 388 389 void removeActivationListener() { 390 try { 391 ObjectName infoMBean = m_serverHelper.getServerInfoMBean(m_connectCntx); 392 m_connectCntx.removeNotificationListener(infoMBean, this); 393 } catch (Exception e) { 394 } 395 } 396 397 400 public void handleNotification(Notification notice, Object handback) { 401 if (notice instanceof AttributeChangeNotification ) { 402 AttributeChangeNotification acn = (AttributeChangeNotification ) 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 toString() { 415 return getHostname() + ":" + getJMXPortNumber(); 416 } 417 418 public void dump(String 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 447 public static interface AutoConnectListener extends EventListener { 448 void handleEvent(); 449 } 450 } 451 | Popular Tags |