001: /*
002: * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
003: * notice. All rights reserved.
004: */
005: package com.tc.admin;
006:
007: import org.dijon.AbstractTreeCellRenderer;
008:
009: import EDU.oswego.cs.dl.util.concurrent.SynchronizedBoolean;
010:
011: import com.tc.admin.common.ComponentNode;
012: import com.tc.admin.common.StatusView;
013: import com.tc.admin.common.XAbstractAction;
014: import com.tc.admin.common.XTreeNode;
015: import com.tc.admin.dso.DSOHelper;
016: import com.tc.admin.dso.DSONode;
017: import com.tc.config.schema.L2Info;
018: import com.tc.management.beans.L2MBeanNames;
019:
020: import java.awt.Color;
021: import java.awt.Frame;
022: import java.awt.Graphics;
023: import java.awt.event.ActionEvent;
024: import java.awt.event.KeyEvent;
025: import java.io.IOException;
026: import java.lang.reflect.InvocationTargetException;
027: import java.net.ConnectException;
028: import java.net.UnknownHostException;
029: import java.text.MessageFormat;
030: import java.util.prefs.Preferences;
031:
032: import javax.management.MBeanServerNotification;
033: import javax.management.Notification;
034: import javax.management.NotificationListener;
035: import javax.management.ObjectName;
036: import javax.management.remote.JMXConnector;
037: import javax.management.remote.generic.ConnectionClosedException;
038: import javax.naming.CommunicationException;
039: import javax.naming.ServiceUnavailableException;
040: import javax.swing.Icon;
041: import javax.swing.JCheckBoxMenuItem;
042: import javax.swing.JComponent;
043: import javax.swing.JDialog;
044: import javax.swing.JOptionPane;
045: import javax.swing.JPopupMenu;
046: import javax.swing.JSeparator;
047: import javax.swing.JTree;
048: import javax.swing.KeyStroke;
049: import javax.swing.SwingUtilities;
050:
051: /**
052: * All connection actions go through the ServerConnectionManager, which calls back through ConnectionListener. The
053: * ServerConnectionManager handles auto-connecting, active-connection monitoring, and connection-state messaging. A JMX
054: * notification handler (handleNotification) informs when the server goes from started->active state.
055: */
056:
057: public class ServerNode extends ComponentNode implements
058: ConnectionListener, NotificationListener {
059: private AdminClientContext m_acc;
060: private ServerConnectionManager m_connectManager;
061: private Exception m_connectException;
062: private ServerPanel m_serverPanel;
063: private ConnectDialog m_connectDialog;
064: private JDialog m_versionMismatchDialog;
065: private JPopupMenu m_popupMenu;
066: private ConnectAction m_connectAction;
067: private DisconnectAction m_disconnectAction;
068: private DeleteAction m_deleteAction;
069: private AutoConnectAction m_autoConnectAction;
070: private JCheckBoxMenuItem m_autoConnectMenuItem;
071: private ShutdownAction m_shutdownAction;
072:
073: private static final String CONNECT_ACTION = "Connect";
074: private static final String DISCONNECT_ACTION = "Disconnect";
075: private static final String DELETE_ACTION = "Delete";
076: private static final String AUTO_CONNECT_ACTION = "AutoConnect";
077:
078: private static final String HOST = ServersHelper.HOST;
079: private static final String PORT = ServersHelper.PORT;
080: private static final String AUTO_CONNECT = ServersHelper.AUTO_CONNECT;
081:
082: ServerNode() {
083: this (ConnectionContext.DEFAULT_HOST,
084: ConnectionContext.DEFAULT_PORT,
085: ConnectionContext.DEFAULT_AUTO_CONNECT);
086: }
087:
088: ServerNode(final String host, final int jmxPort,
089: final boolean autoConnect) {
090: super ();
091:
092: m_acc = AdminClient.getContext();
093: setRenderer(new ServerNodeTreeCellRenderer());
094: AutoConnectionListener acl = new AutoConnectionListener();
095: m_connectManager = new ServerConnectionManager(host, jmxPort,
096: autoConnect, acl);
097: if (autoConnect) {
098: String[] creds = ServerConnectionManager
099: .getCachedCredentials(m_connectManager);
100: if (creds != null) {
101: m_connectManager.setCredentials(creds[0], creds[1]);
102: }
103: }
104: initMenu(autoConnect);
105: setComponent(m_serverPanel = new ServerPanel(this ));
106: }
107:
108: /**
109: * We need to use invokeLater here because this is being called from a background thread and all Swing stuff has to be
110: * done in the primary event loop.
111: */
112: private class AutoConnectionListener implements ConnectionListener {
113: public void handleConnection() {
114: if (m_connectManager != null) {
115: final boolean isConnected = m_connectManager
116: .isConnected();
117:
118: if (SwingUtilities.isEventDispatchThread()) {
119: SwingUtilities.invokeLater(new Runnable() {
120: public void run() {
121: if (m_connectManager != null) {
122: setConnected(isConnected);
123: }
124: }
125: });
126: } else {
127: try {
128: SwingUtilities.invokeAndWait(new Runnable() {
129: public void run() {
130: if (m_connectManager != null) {
131: setConnected(isConnected);
132: }
133: }
134: });
135: } catch (InterruptedException ex) {/**/
136: } catch (InvocationTargetException ite) {
137: m_acc.log(ite);
138: }
139: }
140: }
141: }
142:
143: public void handleException() {
144: if (m_connectManager != null) {
145: final Exception e = m_connectManager
146: .getConnectionException();
147:
148: if (SwingUtilities.isEventDispatchThread()) {
149: SwingUtilities.invokeLater(new Runnable() {
150: public void run() {
151: if (m_connectManager != null) {
152: reportConnectionException(e);
153: }
154: }
155: });
156: } else {
157: try {
158: SwingUtilities.invokeAndWait(new Runnable() {
159: public void run() {
160: if (m_connectManager != null) {
161: reportConnectionException(e);
162: }
163: }
164: });
165: } catch (InterruptedException ex) {/**/
166: } catch (InvocationTargetException ite) {
167: m_acc.log(ite);
168: }
169: }
170: }
171: }
172: }
173:
174: ServerConnectionManager getServerConnectionManager() {
175: return m_connectManager;
176: }
177:
178: ConnectionContext getConnectionContext() {
179: return m_connectManager.getConnectionContext();
180: }
181:
182: void setHost(String host) {
183: m_connectManager.setHostname(host);
184: }
185:
186: String getHost() {
187: return m_connectManager.getHostname();
188: }
189:
190: void setPort(int port) {
191: m_connectManager.setJMXPortNumber(port);
192: }
193:
194: int getPort() {
195: return m_connectManager.getJMXPortNumber();
196: }
197:
198: private void initMenu(boolean autoConnect) {
199: m_popupMenu = new JPopupMenu("Server Actions");
200:
201: m_connectAction = new ConnectAction();
202: m_disconnectAction = new DisconnectAction();
203: m_shutdownAction = new ShutdownAction();
204: m_deleteAction = new DeleteAction();
205: m_autoConnectAction = new AutoConnectAction();
206:
207: addActionBinding(CONNECT_ACTION, m_connectAction);
208: addActionBinding(DISCONNECT_ACTION, m_disconnectAction);
209: addActionBinding(DELETE_ACTION, m_deleteAction);
210: addActionBinding(AUTO_CONNECT_ACTION, m_autoConnectAction);
211:
212: m_connectManager
213: .addToggleAutoConnectListener(new ServerConnectionManager.AutoConnectListener() {
214: public void handleEvent() {
215: m_autoConnectMenuItem.setSelected(false);
216: Thread reActivator = new Thread() {
217: public void run() {
218: boolean ready = false;
219: try {
220: while (!ready) {
221: Thread.sleep(500);
222: if (m_serverPanel != null
223: && m_serverPanel
224: .getConnectButton() != null
225: && m_acc.controller != null) {
226: ready = true;
227: }
228: }
229: } catch (InterruptedException e) {
230: try {
231: Thread.sleep(2000);
232: } catch (InterruptedException ie) {
233: ie.printStackTrace();
234: System.exit(0);
235: // let's hope it never comes to this
236: }
237: }
238: m_serverPanel.getConnectButton()
239: .setEnabled(true);
240: m_acc.controller.updateServerPrefs();
241: }
242: };
243: reActivator.start();
244: }
245: });
246:
247: m_popupMenu.add(m_connectAction);
248: m_popupMenu.add(m_disconnectAction);
249: m_popupMenu.add(new JSeparator());
250: m_popupMenu.add(m_shutdownAction);
251: m_popupMenu.add(m_deleteAction);
252: m_popupMenu.add(new JSeparator());
253:
254: m_popupMenu.add(m_autoConnectMenuItem = new JCheckBoxMenuItem(
255: m_autoConnectAction));
256: m_autoConnectMenuItem.setSelected(autoConnect);
257: }
258:
259: ShutdownAction getShutdownAction() {
260: return m_shutdownAction;
261: }
262:
263: void setVersionMismatchDialog(JDialog dialog) {
264: m_versionMismatchDialog = dialog;
265: }
266:
267: private void setConnected(boolean connected) {
268: if (m_acc == null) {
269: return;
270: }
271: if (connected) {
272: if (m_versionMismatchDialog != null)
273: return;
274: if (!m_serverPanel.isRuntimeInfoShowing()
275: && !m_acc.controller.testServerMatch(this )) {
276: SwingUtilities.invokeLater(new Runnable() {
277: public void run() {
278: if (m_connectManager.isConnected()) {
279: disconnect();
280: }
281: }
282: });
283: return;
284: }
285: m_acc.controller.block();
286: m_connectException = null;
287: if (m_connectManager.isConnected()) {
288: if (m_connectManager.isActive()) {
289: handleActivation();
290: } else if (m_connectManager.isPassiveStandby()) {
291: handlePassiveStandby();
292: } else if (m_connectManager.isPassiveUninitialized()) {
293: handlePassiveUninitialized();
294: } else if (m_connectManager.isStarted()) {
295: handleStarting();
296: }
297: } else {
298: handleDisconnect();
299: }
300: m_acc.controller.unblock();
301: } else {
302: if (m_versionMismatchDialog != null) {
303: m_versionMismatchDialog.setVisible(false);
304: }
305: handleDisconnect();
306: }
307:
308: m_connectAction.setEnabled(!connected);
309: m_disconnectAction.setEnabled(connected);
310: }
311:
312: boolean isConnected() {
313: return m_connectManager != null
314: && m_connectManager.isConnected();
315: }
316:
317: boolean isStarted() {
318: return m_connectManager != null && m_connectManager.isStarted();
319: }
320:
321: boolean isActive() {
322: return m_connectManager != null && m_connectManager.isActive();
323: }
324:
325: boolean isPassiveUninitialized() {
326: return m_connectManager != null
327: && m_connectManager.isPassiveUninitialized();
328: }
329:
330: boolean isPassiveStandby() {
331: return m_connectManager != null
332: && m_connectManager.isPassiveStandby();
333: }
334:
335: boolean hasConnectionException() {
336: return m_connectException != null;
337: }
338:
339: ConnectDialog getConnectDialog(ConnectionListener listener) {
340: if (m_connectDialog == null) {
341: Frame frame = (Frame) m_serverPanel
342: .getAncestorOfClass(java.awt.Frame.class);
343: m_connectDialog = new ConnectDialog(frame,
344: m_connectManager, listener);
345: } else {
346: m_connectDialog
347: .setServerConnectionManager(m_connectManager);
348: m_connectDialog.setConnectionListener(listener);
349: }
350:
351: return m_connectDialog;
352: }
353:
354: /**
355: * Called when the user clicks the Connect button. Not used when auto-connect is enabled.
356: */
357: void connect() {
358: try {
359: beginConnect();
360: } catch (Exception e) {
361: m_acc.controller.log(e);
362: }
363: }
364:
365: private void beginConnect() throws Exception {
366: m_acc.controller.block();
367:
368: m_connectException = null;
369:
370: ConnectDialog cd = getConnectDialog(this );
371: Frame frame = (Frame) m_serverPanel
372: .getAncestorOfClass(java.awt.Frame.class);
373:
374: String[] creds = ServerConnectionManager
375: .getCachedCredentials(getServerConnectionManager());
376: if (creds != null) {
377: m_connectManager.setCredentials(creds[0], creds[1]);
378: }
379:
380: cd.center(frame);
381: cd.setVisible(true);
382: }
383:
384: /**
385: * Callback from the ConnectDialog.
386: */
387: public void handleConnection() {
388: JMXConnector jmxc;
389: if ((jmxc = m_connectDialog.getConnector()) != null) {
390: try {
391: m_connectManager.setJMXConnector(jmxc);
392: } catch (IOException ioe) {
393: reportConnectionException(ioe);
394: }
395: }
396:
397: m_acc.controller.unblock();
398: }
399:
400: /**
401: * Callback from the ConnectDialog.
402: */
403: public void handleException() {
404: Exception e = m_connectDialog.getError();
405:
406: if (e != null) {
407: reportConnectionException(e);
408: }
409:
410: m_acc.controller.unblock();
411: }
412:
413: public static String getConnectionExceptionString(Exception e,
414: Object connectionObject) {
415: AdminClientContext acc = AdminClient.getContext();
416: String msg = null;
417:
418: if (e instanceof ServiceUnavailableException
419: || e.getCause() instanceof ServiceUnavailableException) {
420: String tmpl = acc.getMessage("service.unavailable");
421: MessageFormat form = new MessageFormat(tmpl);
422: Object[] args = new Object[] { connectionObject };
423:
424: msg = form.format(args);
425: } else if (e.getCause() instanceof ConnectException) {
426: String tmpl = acc.getMessage("cannot.connect.to");
427: MessageFormat form = new MessageFormat(tmpl);
428: Object[] args = new Object[] { connectionObject };
429:
430: msg = form.format(args);
431: } else if (e.getCause() instanceof UnknownHostException
432: || (e.getCause() != null && e.getCause().getCause() instanceof java.rmi.UnknownHostException)) {
433: String tmpl = acc.getMessage("unknown.host");
434: MessageFormat form = new MessageFormat(tmpl);
435: Object[] args = new Object[] { connectionObject };
436:
437: msg = form.format(args);
438: } else if (e.getCause() instanceof CommunicationException) {
439: String tmpl = acc.getMessage("cannot.connect.to");
440: MessageFormat form = new MessageFormat(tmpl);
441: Object[] args = new Object[] { connectionObject };
442:
443: msg = form.format(args);
444:
445: } else {
446: msg = e.getMessage();
447: }
448:
449: return "<html>" + msg + "</html>";
450: }
451:
452: private void reportConnectionException(Exception e) {
453: String msg = getConnectionExceptionString(e, this );
454:
455: m_connectException = e;
456: if (msg != null && m_serverPanel != null) {
457: m_serverPanel.setStatusLabel(msg);
458: }
459: m_acc.controller.nodeChanged(ServerNode.this );
460: }
461:
462: /**
463: * Called when the user clicks the Disconnect button. Used whether or not auto-connect is enabled.
464: */
465: void disconnect() {
466: String msg = m_acc.getMessage("disconnecting.from");
467: MessageFormat form = new MessageFormat(msg);
468: Object[] args = new Object[] { this };
469:
470: m_acc.controller.setStatus(form.format(args));
471: m_connectManager.setAutoConnect(false);
472: m_acc.controller.updateServerPrefs();
473: m_autoConnectMenuItem.setSelected(false);
474: m_connectManager.setConnected(false);
475: }
476:
477: void disconnectOnExit() {
478: String msg = m_acc.getMessage("disconnecting.from");
479: MessageFormat form = new MessageFormat(msg);
480: Object[] args = new Object[] { this };
481:
482: m_acc.controller.setStatus(form.format(args));
483: m_connectManager.disconnectOnExit();
484: }
485:
486: void shutdown() {
487: AdminClientPanel topPanel = (AdminClientPanel) m_serverPanel
488: .getAncestorOfClass(AdminClientPanel.class);
489: Frame frame = (Frame) topPanel
490: .getAncestorOfClass(java.awt.Frame.class);
491: String msg = "Are you sure you want to shutdown '" + this
492: + "'?";
493:
494: int result = JOptionPane.showConfirmDialog(frame, msg, frame
495: .getTitle(), JOptionPane.OK_CANCEL_OPTION);
496: if (result == JOptionPane.OK_OPTION) {
497: doShutdown();
498: }
499: }
500:
501: void doShutdown() {
502: try {
503: ConnectionContext cntx = getConnectionContext();
504: ObjectName serverInfo = getServerInfo(cntx);
505:
506: cntx.invoke(serverInfo, "shutdown", new Object[] {},
507: new String[] {});
508: } catch (ConnectionClosedException ignore) {
509: /* expected */
510: } catch (Exception e) {
511: m_acc.log(e);
512: }
513: }
514:
515: public Icon getIcon() {
516: return ServersHelper.getHelper().getServerIcon();
517: }
518:
519: public JPopupMenu getPopupMenu() {
520: return m_popupMenu;
521: }
522:
523: public void setPreferences(Preferences prefs) {
524: prefs.put(HOST, getHost());
525: prefs.putInt(PORT, getPort());
526: prefs.putBoolean(AUTO_CONNECT, isAutoConnect());
527: }
528:
529: public String toString() {
530: return m_connectManager.toString();
531: }
532:
533: private class ConnectAction extends XAbstractAction {
534: ConnectAction() {
535: super ("Connect", ServersHelper.getHelper().getConnectIcon());
536:
537: setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C,
538: MENU_SHORTCUT_KEY_MASK, true));
539: }
540:
541: public void actionPerformed(ActionEvent ae) {
542: connect();
543: }
544: }
545:
546: private class DisconnectAction extends XAbstractAction {
547: DisconnectAction() {
548: super ("Disconnect", ServersHelper.getHelper()
549: .getDisconnectIcon());
550:
551: setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_D,
552: MENU_SHORTCUT_KEY_MASK, true));
553: setEnabled(false);
554: }
555:
556: public void actionPerformed(ActionEvent ae) {
557: disconnect();
558: }
559: }
560:
561: private class ShutdownAction extends XAbstractAction implements
562: Runnable {
563: ShutdownAction() {
564: super ("Shutdown", ServersHelper.getHelper()
565: .getShutdownIcon());
566:
567: setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_S,
568: MENU_SHORTCUT_KEY_MASK, true));
569: setEnabled(false);
570: }
571:
572: public void run() {
573: shutdown();
574: }
575:
576: public void actionPerformed(ActionEvent ae) {
577: SwingUtilities.invokeLater(this );
578: }
579: }
580:
581: private class DeleteAction extends XAbstractAction {
582: DeleteAction() {
583: super ("Delete", ServersHelper.getHelper().getDeleteIcon());
584:
585: setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X,
586: MENU_SHORTCUT_KEY_MASK, true));
587: }
588:
589: public void actionPerformed(ActionEvent ae) {
590: if (isConnected()) {
591: disconnectOnExit();
592: }
593:
594: // Need to allow possible disconnect message from ServerConnectionManager to
595: // come through.
596:
597: SwingUtilities.invokeLater(new Runnable() {
598: public void run() {
599: AdminClientController controller = m_acc.controller;
600:
601: String name = ServerNode.this .toString();
602: MessageFormat form = new MessageFormat(m_acc
603: .getMessage("deleted.server"));
604:
605: controller.setStatus(form
606: .format(new Object[] { name }));
607:
608: // this must be last because as a side effect this node is tornDown (see tearDown)
609: controller.remove(ServerNode.this );
610:
611: // Update the prefs after removing this node or it'll keep coming back.
612: // We saved off the controller above because it gets nulled out in tearDown.
613: controller.updateServerPrefs();
614: }
615: });
616: }
617: }
618:
619: private class AutoConnectAction extends XAbstractAction {
620: AutoConnectAction() {
621: super ("Auto-connect");
622: setShortDescription("Attempt to connect automatically");
623: }
624:
625: public void actionPerformed(ActionEvent ae) {
626: JCheckBoxMenuItem menuitem = (JCheckBoxMenuItem) ae
627: .getSource();
628: boolean autoConnect = menuitem.isSelected();
629:
630: if (autoConnect) {
631: String[] creds = ServerConnectionManager
632: .getCachedCredentials(getServerConnectionManager());
633: if (creds != null) {
634: m_connectManager.setCredentials(creds[0], creds[1]);
635: }
636: }
637:
638: m_connectManager.setAutoConnect(autoConnect);
639: m_serverPanel.setupConnectButton();
640: m_acc.controller.updateServerPrefs();
641: }
642: }
643:
644: boolean isAutoConnect() {
645: return m_connectManager.isAutoConnect();
646: }
647:
648: void handleStarting() {
649: m_acc.controller.nodeChanged(ServerNode.this );
650: m_shutdownAction.setEnabled(false);
651: m_serverPanel.started();
652: }
653:
654: SynchronizedBoolean m_tryAddingDSONode = new SynchronizedBoolean(
655: false);
656:
657: void tryAddDSONode() throws Exception {
658: if (m_tryAddingDSONode.get()) {
659: return;
660: }
661:
662: try {
663: m_tryAddingDSONode.set(true);
664: if (getChildCount() == 0) {
665: ConnectionContext cntx = getConnectionContext();
666:
667: if (DSOHelper.getHelper().getDSOMBean(cntx) != null) {
668: DSONode dsoNode = null;
669:
670: add(dsoNode = new DSONode(cntx));
671: m_acc.controller.nodeStructureChanged(this );
672: m_acc.controller.expand(dsoNode);
673: } else {
674: ObjectName mbsd = cntx
675: .queryName("JMImplementation:type=MBeanServerDelegate");
676: if (mbsd != null) {
677: try {
678: cntx.removeNotificationListener(mbsd, this );
679: } catch (Exception e) {/**/
680: }
681: cntx.addNotificationListener(mbsd, this );
682: }
683: }
684: }
685: m_acc.controller.nodeChanged(ServerNode.this );
686: } catch (Exception e) {
687: m_acc.log(e);
688: } finally {
689: m_tryAddingDSONode.set(false);
690: }
691: }
692:
693: void handlePassiveUninitialized() {
694: try {
695: tryAddDSONode();
696: m_shutdownAction.setEnabled(false);
697: m_serverPanel.passiveUninitialized();
698: } catch (Exception e) {
699: // just wait for disconnect message to come in
700: }
701: }
702:
703: void handlePassiveStandby() {
704: try {
705: tryAddDSONode();
706: m_shutdownAction.setEnabled(true);
707: m_serverPanel.passiveStandby();
708: } catch (Exception e) {
709: // just wait for disconnect message to come in
710: }
711: }
712:
713: void handleActivation() {
714: try {
715: tryAddDSONode();
716: m_shutdownAction.setEnabled(true);
717: m_serverPanel.activated();
718: } catch (Exception e) {
719: // just wait for disconnect message to come in
720: }
721: }
722:
723: static ObjectName getServerInfo(ConnectionContext cntx)
724: throws Exception {
725: return ServerHelper.getHelper().getServerInfoMBean(cntx);
726: }
727:
728: public ProductInfo getProductInfo() {
729: ProductInfo info;
730:
731: try {
732: info = getProductInfo(getConnectionContext());
733: } catch (Exception e) {
734: m_acc.log(e);
735: info = new ProductInfo();
736: }
737:
738: return info;
739: }
740:
741: public static ProductInfo getProductInfo(ConnectionContext cntx)
742: throws Exception {
743: ObjectName serverInfo = getServerInfo(cntx);
744:
745: String version = cntx.getStringAttribute(serverInfo, "Version");
746: String buildID = cntx.getStringAttribute(serverInfo, "BuildID");
747: String license = cntx.getStringAttribute(serverInfo,
748: "DescriptionOfCapabilities");
749: String copyright = cntx.getStringAttribute(serverInfo,
750: "Copyright");
751:
752: return new ProductInfo(version, buildID, license, copyright);
753: }
754:
755: long getStartTime() {
756: try {
757: ConnectionContext cntx = getConnectionContext();
758: ObjectName serverInfo = getServerInfo(cntx);
759:
760: return cntx.getLongAttribute(serverInfo, "StartTime");
761: } catch (Exception e) {
762: m_acc.log(e);
763: return 0L;
764: }
765: }
766:
767: long getActivateTime() {
768: try {
769: ConnectionContext cntx = getConnectionContext();
770: ObjectName serverInfo = getServerInfo(cntx);
771:
772: return cntx.getLongAttribute(serverInfo, "ActivateTime");
773: } catch (Exception e) {
774: m_acc.log(e);
775: return 0L;
776: }
777: }
778:
779: public void handleNotification(Notification notification,
780: Object handback) {
781: if (notification instanceof MBeanServerNotification) {
782: MBeanServerNotification mbsn = (MBeanServerNotification) notification;
783: String type = notification.getType();
784: ObjectName name = mbsn.getMBeanName();
785:
786: if (type
787: .equals(MBeanServerNotification.REGISTRATION_NOTIFICATION)) {
788: if (name.getCanonicalName().equals(
789: L2MBeanNames.DSO.getCanonicalName())) {
790: SwingUtilities.invokeLater(new Runnable() {
791: public void run() {
792: try {
793: DSONode dsoNode = new DSONode(
794: getConnectionContext());
795:
796: add(dsoNode);
797: m_acc.controller
798: .nodeStructureChanged(ServerNode.this );
799: m_acc.controller.expand(dsoNode);
800: m_acc.controller
801: .nodeChanged(ServerNode.this );
802: } catch (Exception e) {
803: // just wait for disconnect message to come in
804: }
805: }
806: });
807: }
808: }
809: }
810: }
811:
812: L2Info[] getClusterMembers() {
813: ConnectionContext cc = getConnectionContext();
814: L2Info[] result = null;
815:
816: try {
817: result = (L2Info[]) cc.getAttribute(getServerInfo(cc),
818: "L2Info");
819: } catch (Exception e) {
820: m_acc.log(e);
821: }
822:
823: return result != null ? result : new L2Info[0];
824: }
825:
826: void handleDisconnect() {
827: for (int i = getChildCount() - 1; i >= 0; i--) {
828: ((XTreeNode) getChildAt(i)).tearDown();
829: remove(i);
830: }
831:
832: m_shutdownAction.setEnabled(false);
833: m_serverPanel.disconnected();
834: m_acc.controller.nodeStructureChanged(ServerNode.this );
835: m_acc.controller.select(this );
836: }
837:
838: Color getServerStatusColor() {
839: return getServerStatusColor(getServerConnectionManager());
840: }
841:
842: static Color getServerStatusColor(ServerConnectionManager scm) {
843: if (scm != null) {
844: if (scm.isActive()) {
845: return Color.GREEN;
846: } else if (scm.isPassiveStandby()) {
847: return Color.CYAN;
848: } else if (scm.isPassiveUninitialized()) {
849: return Color.ORANGE;
850: } else if (scm.isStarted()) {
851: return Color.YELLOW;
852: } else if (scm.getConnectionException() != null) {
853: return Color.RED;
854: }
855: }
856: return Color.LIGHT_GRAY;
857: }
858:
859: private class ServerNodeTreeCellRenderer extends
860: AbstractTreeCellRenderer {
861: protected StatusView m_statusView;
862:
863: public ServerNodeTreeCellRenderer() {
864: super ();
865:
866: m_statusView = new StatusView() {
867: public void setForeground(Color fg) {
868: super .setForeground(fg);
869: if (m_label != null) {
870: m_label.setForeground(fg);
871: }
872: }
873:
874: public void paint(Graphics g) {
875: super .paint(g);
876: if (hasFocus) {
877: paintFocus(g, 0, 0, getWidth(), getHeight());
878: }
879: }
880: };
881: }
882:
883: public JComponent getComponent() {
884: return m_statusView;
885: }
886:
887: public void setValue(JTree tree, Object value, boolean sel,
888: boolean expanded, boolean leaf, int row, boolean focused) {
889: m_statusView.setIndicator(ServerNode.this
890: .getServerStatusColor());
891: m_statusView.setLabel(value.toString());
892: }
893: }
894:
895: public void tearDown() {
896: if (m_connectDialog != null) {
897: m_connectDialog.tearDown();
898: }
899: m_connectManager.tearDown();
900:
901: m_acc = null;
902: m_connectManager = null;
903: m_serverPanel = null;
904: m_connectDialog = null;
905: m_popupMenu = null;
906: m_connectAction = null;
907: m_disconnectAction = null;
908: m_shutdownAction = null;
909: m_deleteAction = null;
910: m_autoConnectAction = null;
911:
912: super.tearDown();
913: }
914: }
|