14804 panels should know about/recover from from lost connections to server
authorStephen Talley <stephen.talley@sun.com>
Wed, 24 Feb 2010 22:28:58 -0500
changeset 459 abb4563e4968
parent 458 6d794371572b
child 460 41472791eb62
14804 panels should know about/recover from from lost connections to server
usr/src/java/util/org/opensolaris/os/vp/util/swing/glass/BusyGlassPane.java
usr/src/java/vpanels/client/org/opensolaris/os/vp/client/common/ConnectionManager.java
usr/src/java/vpanels/client/org/opensolaris/os/vp/client/swing/App.java
usr/src/java/vpanels/client/org/opensolaris/os/vp/client/swing/AppInstance.java
usr/src/java/vpanels/client/org/opensolaris/os/vp/client/swing/resources/Resources.properties
usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/common/ConnectionEvent.java
usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/common/ConnectionListener.java
usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/common/ConnectionListeners.java
usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/common/model/AbstractPanelDescriptor.java
usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/common/smf/AbstractServicePanelDescriptor.java
usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/common/smf/RepoManagedObject.java
usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/swing/control/PanelFrameControl.java
usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/swing/control/SystemTrayControl.java
usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/swing/control/WindowControl.java
usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/swing/control/resources/Resources.properties
usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/swing/smf/ServiceStatusPanel.java
usr/src/java/vpanels/panels/browser/org/opensolaris/os/vp/panels/browser/client/swing/BrowserPanelDescriptor.java
usr/src/java/vpanels/panels/examples/org/opensolaris/os/vp/panels/example/time2/client/swing/TimePanelDescriptor.java
usr/src/java/vpanels/panels/firewall/org/opensolaris/os/vp/panels/firewall/client/swing/ServiceManagedObject.java
usr/src/java/vpanels/panels/sharemgr/org/opensolaris/os/vp/panels/sharemgr/client/common/SharemgrEventMonitor.java
usr/src/java/vpanels/panels/smf/org/opensolaris/os/vp/panels/smf/client/swing/SMFEditPanel.java
usr/src/java/vpanels/panels/sysid/org/opensolaris/os/vp/panels/sysid/client/swing/SysIdPanelDescriptor.java
--- a/usr/src/java/util/org/opensolaris/os/vp/util/swing/glass/BusyGlassPane.java	Wed Feb 24 21:04:57 2010 -0500
+++ b/usr/src/java/util/org/opensolaris/os/vp/util/swing/glass/BusyGlassPane.java	Wed Feb 24 22:28:58 2010 -0500
@@ -102,7 +102,7 @@
 
     private String message;
     private JProgressBar progressBar;
-    private JLabel messageLabel;
+    private WrappingText messageLabel;
     private FadablePanel fadePanel;
 
     //
@@ -115,8 +115,7 @@
 	progressBar.setOpaque(false);
 	progressBar.setBorderPainted(false);
 
-	messageLabel = new JLabel();
-	messageLabel.setHorizontalAlignment(SwingConstants.CENTER);
+	messageLabel = new WrappingText();
 
 	int gap = GUIUtil.getGap();
 	ColumnLayout layout = new ColumnLayout();
@@ -126,7 +125,8 @@
 	BusyDialog dialog = new BusyDialog();
 	dialog.setLayout(layout);
 	dialog.add(progressBar, c);
-	dialog.add(messageLabel, c);
+        dialog.add(messageLabel,
+	    c.setHorizontalAnchor(HorizontalAnchor.CENTER));
 
 	JPanel shadowPanel = new ShadowPanel();
 	shadowPanel.setOpaque(false);
@@ -176,6 +176,7 @@
 
 	String m = message == null ? _MESSAGE : message;
 	messageLabel.setText(m);
+	messageLabel.setPreferredWidthInColumns(25);
 	messageLabel.setVisible(m != null && !m.isEmpty());
     }
 
--- a/usr/src/java/vpanels/client/org/opensolaris/os/vp/client/common/ConnectionManager.java	Wed Feb 24 21:04:57 2010 -0500
+++ b/usr/src/java/vpanels/client/org/opensolaris/os/vp/client/common/ConnectionManager.java	Wed Feb 24 22:28:58 2010 -0500
@@ -26,10 +26,12 @@
 
 package org.opensolaris.os.vp.client.common;
 
-import java.io.IOException;
 import java.util.*;
+import javax.management.*;
+import javax.management.remote.JMXConnectionNotification;
 import javax.management.remote.JMXConnector;
-import org.opensolaris.os.vp.panel.common.ConnectionInfo;
+import org.opensolaris.os.vp.panel.common.*;
+import org.opensolaris.os.vp.util.misc.IOUtil;
 
 public class ConnectionManager {
     //
@@ -37,33 +39,92 @@
     //
 
     // Map between ConnectionInfo and objects (clients) that are using it
-    private Map<ConnectionInfo, Set<Object>> connections =
-	new HashMap<ConnectionInfo, Set<Object>>();
+    private Map<ConnectionInfo, Set<ConnectionListener>> clientMap =
+	new HashMap<ConnectionInfo, Set<ConnectionListener>>();
+
+    // Map between ConnectionInfo and ConnectionRecreator to reestablish it
+    private Map<ConnectionInfo, ConnectionRecreator> recreatorMap =
+	new HashMap<ConnectionInfo, ConnectionRecreator>();
+
+    private NotificationListener nListener =
+	new NotificationListener() {
+	    @Override
+	    public void handleNotification(Notification notification,
+		Object handback) {
+
+		if (notification.getType().equals(
+		    JMXConnectionNotification.FAILED)) {
+
+		    ConnectionInfo info = (ConnectionInfo)handback;
+		    ConnectionEvent event = new ConnectionEvent(this, info);
+		    for (ConnectionListener client : clientMap.get(info)) {
+			client.connectionFailed(event);
+		    }
+
+		    ConnectionRecreator recreator = recreatorMap.get(info);
+		    if (recreator != null) {
+			ConnectionInfo newInfo = recreator.recreate(info);
+			if (newInfo != null) {
+			    changeConnection(newInfo, info);
+			}
+		    }
+		}
+	    }
+	};
 
     //
     // ConnectionManager methods
     //
 
-    public void addConnection(ConnectionInfo info, Object client) {
-	synchronized (connections) {
-	    Set<Object> clients = connections.get(info);
+    public void addConnection(ConnectionInfo info,
+	ConnectionRecreator recreator, ConnectionListener client) {
+
+	synchronized (clientMap) {
+	    Set<ConnectionListener> clients = clientMap.get(info);
 	    if (clients == null) {
-		clients = new HashSet<Object>();
-		connections.put(info, clients);
+		clients = new HashSet<ConnectionListener>();
+		clientMap.put(info, clients);
+
+		if (recreator != null) {
+		    recreatorMap.put(info, recreator);
+		}
+
+                info.getConnector().addConnectionNotificationListener(nListener,
+		    null, info);
 	    }
 	    clients.add(client);
 	}
     }
 
+    public void changeConnection(ConnectionInfo info, ConnectionInfo oldInfo) {
+	assert clientMap.get(info) == null;
+
+	Set<ConnectionListener> clients = clientMap.get(oldInfo);
+	assert clients != null;
+
+	Set<ConnectionListener> newClients =
+	    new HashSet<ConnectionListener>(clients);
+
+	ConnectionRecreator recreator = recreatorMap.get(oldInfo);
+	ConnectionEvent event = new ConnectionEvent(this, info, oldInfo);
+	for (ConnectionListener client : newClients) {
+	    addConnection(info, recreator, client);
+	    client.connectionChanged(event);
+	    removeConnection(oldInfo, client);
+	}
+
+	assert clientMap.get(oldInfo) == null;
+    }
+
     public Set<ConnectionInfo> getConnections() {
-	return Collections.unmodifiableSet(connections.keySet());
+	return Collections.unmodifiableSet(clientMap.keySet());
     }
 
     public ConnectionInfo getConnection(
 	String host, int port, String user, String role) {
 
-	synchronized (connections) {
-	    for (ConnectionInfo info : connections.keySet()) {
+	synchronized (clientMap) {
+	    for (ConnectionInfo info : clientMap.keySet()) {
 		if (info.matches(host, port, user, role)) {
 		    return info;
 		}
@@ -72,21 +133,26 @@
 	return null;
     }
 
-    public boolean removeConnection(ConnectionInfo info, Object client) {
-	synchronized (connections) {
-	    Set<Object> clients = connections.get(info);
+    public boolean removeConnection(ConnectionInfo info,
+	ConnectionListener client) {
+
+	synchronized (clientMap) {
+	    Set<ConnectionListener> clients = clientMap.get(info);
 	    if (clients == null) {
 		return false;
 	    }
 
 	    boolean removed = clients.remove(client);
 	    if (removed && clients.isEmpty()) {
-		connections.remove(info);
+		clientMap.remove(info);
+		recreatorMap.remove(info);
+
+		JMXConnector connector = info.getConnector();
 		try {
-		    info.getConnector().close();
-		} catch (IOException e) {
-		    // Perhaps this should be logged
+		    connector.removeConnectionNotificationListener(nListener);
+		} catch (ListenerNotFoundException ignore) {
 		}
+		IOUtil.closeIgnore(connector);
 	    }
 
 	    return removed;
--- a/usr/src/java/vpanels/client/org/opensolaris/os/vp/client/swing/App.java	Wed Feb 24 21:04:57 2010 -0500
+++ b/usr/src/java/vpanels/client/org/opensolaris/os/vp/client/swing/App.java	Wed Feb 24 22:28:58 2010 -0500
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -31,13 +31,13 @@
 import java.util.*;
 import java.util.logging.*;
 import javax.management.remote.*;
+import org.opensolaris.os.rad.jmx.RadConnector;
 import org.opensolaris.os.uds.*;
 import org.opensolaris.os.vp.client.common.*;
+import org.opensolaris.os.vp.panel.common.*;
 import org.opensolaris.os.vp.panel.common.action.ActionAbortedException;
 import org.opensolaris.os.vp.panel.common.control.*;
 import org.opensolaris.os.vp.util.cli.*;
-import org.opensolaris.os.rad.jmx.RadConnector;
-import org.opensolaris.os.vp.panel.common.ConnectionInfo;
 import org.opensolaris.os.vp.util.misc.*;
 
 /**
@@ -512,29 +512,47 @@
 	}
     }
 
+    //
+    // Private methods
+    //
+
     /**
      * Attempt to establish a local JMX connection as ourselves (password
      * unnecessary), and add it to the {@link ConnectionManager}.  This
      * connection will then be available for all subsequent logins.
      */
     private void attemptLocalConnection() {
+	ConnectionRecreator recreator =
+	    new ConfirmableConnectionRecreator() {
+		@Override
+                public ConnectionInfo confirmedRecreate(ConnectionInfo oldInfo)
+                {
+		    return createLocalConnection();
+		}
+	    };
+
+	ConnectionInfo info = createLocalConnection();
+	if (info != null) {
+            connManager.addConnection(info, recreator, new ConnectionAdapter());
+	}
+    }
+
+    private ConnectionInfo createLocalConnection() {
+	ConnectionInfo info = null;
 	try {
-	    JMXServiceURL url = new JMXServiceURL(
+            JMXServiceURL url = new JMXServiceURL(
 		RadConnector.PROTOCOL_UDS, "", 0, "/var/run/radsocket");
+
 	    JMXConnector connector = JMXConnectorFactory.connect(url, null);
-	    ConnectionInfo info = new ConnectionInfo(
-		LOCAL_HOST, -1, LOCAL_USER, null, connector);
-
-	    connManager.addConnection(info, this);
+            info = new ConnectionInfo(LOCAL_HOST, -1, LOCAL_USER, null,
+		connector);
 	} catch (IOException e) {
 	    log.log(Level.WARNING, "unable to create local connector", e);
 	}
+
+	return info;
     }
 
-    //
-    // Private methods
-    //
-
     private void exitIfNoInstances() {
 	synchronized (instances) {
 	    if (instances.isEmpty()) {
--- a/usr/src/java/vpanels/client/org/opensolaris/os/vp/client/swing/AppInstance.java	Wed Feb 24 21:04:57 2010 -0500
+++ b/usr/src/java/vpanels/client/org/opensolaris/os/vp/client/swing/AppInstance.java	Wed Feb 24 22:28:58 2010 -0500
@@ -45,7 +45,7 @@
 import org.opensolaris.os.vp.util.misc.DialogMessage;
 
 @SuppressWarnings({"serial"})
-public class AppInstance implements SwingClientContext {
+public class AppInstance implements SwingClientContext, ConnectionListener {
 
     static {
 	// Force early load of runtime properties
@@ -145,6 +145,26 @@
     }
 
     //
+    // ConnectionListener methods
+    //
+
+    @Override
+    public void connectionChanged(ConnectionEvent event) {
+        // This method should only called by the ConnectionManager when a failed
+        // connection has been restored
+	assert info == event.getOldConnectionInfo();
+
+	setConnectionInfo(event.getConnectionInfo());
+    }
+
+    @Override
+    public void connectionFailed(ConnectionEvent event) {
+	// XXX Need to stop any pending actions and close login first
+	cListeners.connectionFailed(
+	    new ConnectionEvent(this, event.getConnectionInfo()));
+    }
+
+    //
     // ClientContext methods
     //
 
@@ -338,12 +358,6 @@
 	app.instanceClosed(this);
     }
 
-    protected void fireConnectionEvent(
-	ConnectionInfo oldInfo, ConnectionInfo info) {
-
-	cListeners.connectionChanged(new ConnectionEvent(this, oldInfo, info));
-    }
-
     public App getApp() {
 	return app;
     }
@@ -479,11 +493,12 @@
 	ConnectionInfo oldInfo = getConnectionInfo();
 	if (oldInfo != info) {
 	    ConnectionManager connManager = app.getConnectionManager();
-	    connManager.addConnection(info, this);
+	    connManager.addConnection(info, null, this);
 
 	    // Set and notify any listeners (ie, panels) of change
 	    this.info = info;
-	    fireConnectionEvent(oldInfo, info);
+	    cListeners.connectionChanged(
+		new ConnectionEvent(this, info, oldInfo));
 
 	    if (oldInfo != null) {
 		// Now that listeners have been notified of the change, remove
--- a/usr/src/java/vpanels/client/org/opensolaris/os/vp/client/swing/resources/Resources.properties	Wed Feb 24 21:04:57 2010 -0500
+++ b/usr/src/java/vpanels/client/org/opensolaris/os/vp/client/swing/resources/Resources.properties	Wed Feb 24 22:28:58 2010 -0500
@@ -85,3 +85,8 @@
         <tr><td><b>Version:</b></td><td>{8}</td></tr>\
     </table>
 certificate.view.unknown = Unknown certificate type ({0})<br><br>{1}
+
+connection.failed.title = Connection Failed
+connection.failed.message = The connection to {0} has been lost.  Verify that {0} is reachable and its network/rad SMF service is enabled.
+connection.failed.option.reconnect = Reconnect
+connection.failed.option.quit = Quit
--- a/usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/common/ConnectionEvent.java	Wed Feb 24 21:04:57 2010 -0500
+++ b/usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/common/ConnectionEvent.java	Wed Feb 24 22:28:58 2010 -0500
@@ -34,8 +34,8 @@
     // Instance data
     //
 
-    private ConnectionInfo info;
-    private ConnectionInfo other;
+    private ConnectionInfo newInfo;
+    private ConnectionInfo oldInfo;
 
     //
     // Constructors
@@ -47,18 +47,31 @@
      * @param	    source
      *		    the source of this event
      *
-     * @param	    oldInfo
-     *		    the old {@link ConnectionInfo}
-     *
      * @param	    newInfo
      *		    the new {@link ConnectionInfo}
+     *
+     * @param	    oldInfo
+     *		    the old {@link ConnectionInfo}
      */
-    public ConnectionEvent(Object source, ConnectionInfo oldInfo,
-	ConnectionInfo newInfo) {
+    public ConnectionEvent(Object source, ConnectionInfo newInfo,
+	ConnectionInfo oldInfo) {
 
 	super(source);
-	other = oldInfo;
-	info = newInfo;
+	this.newInfo = newInfo;
+	this.oldInfo = oldInfo;
+    }
+
+    /**
+     * Constructs a {@code ConnectionEvent}.
+     *
+     * @param	    source
+     *		    the source of this event
+     *
+     * @param	    info
+     *		    the current {@link ConnectionInfo}
+     */
+    public ConnectionEvent(Object source, ConnectionInfo info) {
+	this(source, info, null);
     }
 
     //
@@ -69,13 +82,13 @@
      * Gets the primary {@link ConnectionInfo} involved in this event.
      */
     public ConnectionInfo getConnectionInfo() {
-	return info;
+	return newInfo;
     }
 
     /**
-     * Gets the old {@link ConnectionInfo} involved in this event.
+     * Gets the old {@link ConnectionInfo}, if any, involved in this event.
      */
     public ConnectionInfo getOldConnectionInfo() {
-	return other;
+	return oldInfo;
     }
 }
--- a/usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/common/ConnectionListener.java	Wed Feb 24 21:04:57 2010 -0500
+++ b/usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/common/ConnectionListener.java	Wed Feb 24 22:28:58 2010 -0500
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -28,4 +28,6 @@
 
 public interface ConnectionListener {
     void connectionChanged(ConnectionEvent event);
+
+    void connectionFailed(ConnectionEvent event);
 }
--- a/usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/common/ConnectionListeners.java	Wed Feb 24 21:04:57 2010 -0500
+++ b/usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/common/ConnectionListeners.java	Wed Feb 24 22:28:58 2010 -0500
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -31,23 +31,41 @@
 public class ConnectionListeners extends EventListeners<ConnectionListener>
     implements ConnectionListener {
 
-    private static final EventDispatcher<ConnectionEvent,
-	ConnectionListener> ccd =
+    //
+    // Static data
+    //
+
+    private static final EventDispatcher<ConnectionEvent, ConnectionListener>
+	changeDispatcher =
 	new EventDispatcher<ConnectionEvent, ConnectionListener>() {
+	    @Override
 	    public void dispatch(ConnectionListener listener,
-		ConnectionEvent event)
-	    {
+		ConnectionEvent event) {
 		listener.connectionChanged(event);
 	    }
 	};
 
+    private static final EventDispatcher<ConnectionEvent, ConnectionListener>
+	failDispatcher =
+	new EventDispatcher<ConnectionEvent, ConnectionListener>() {
+	    @Override
+	    public void dispatch(ConnectionListener listener,
+		ConnectionEvent event) {
+		listener.connectionFailed(event);
+	    }
+	};
+
     //
     // ConnectionListener methods
     //
 
     @Override
-    public void connectionChanged(ConnectionEvent e)
-    {
-	dispatch(ccd, e);
+    public void connectionChanged(ConnectionEvent e) {
+	dispatch(changeDispatcher, e);
+    }
+
+    @Override
+    public void connectionFailed(ConnectionEvent e) {
+	dispatch(failDispatcher, e);
     }
 }
--- a/usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/common/model/AbstractPanelDescriptor.java	Wed Feb 24 21:04:57 2010 -0500
+++ b/usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/common/model/AbstractPanelDescriptor.java	Wed Feb 24 22:28:58 2010 -0500
@@ -58,6 +58,12 @@
 		    dispose();
 		}
 	    }
+
+	    @Override
+	    public void connectionFailed(ConnectionEvent event) {
+                // There's nothing particularly helpful we can do here except
+                // wait for the repaired connection in connectionChanged
+	    }
 	};
 
     //
--- a/usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/common/smf/AbstractServicePanelDescriptor.java	Wed Feb 24 21:04:57 2010 -0500
+++ b/usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/common/smf/AbstractServicePanelDescriptor.java	Wed Feb 24 22:28:58 2010 -0500
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -187,6 +187,20 @@
 	}
     }
 
+    @Override
+    public void connectionFailed(ConnectionEvent event) {
+	if (mbsc != null) {
+	    try {
+		mbsc.removeNotificationListener(oName, this);
+
+	    // The connection is likely already closed
+	    } catch (Throwable ignore) {
+	    }
+
+	    mbsc = null;
+	}
+    }
+
     //
     // NotificationListener methods
     //
@@ -310,8 +324,12 @@
 	if (mbsc != null) {
 	    try {
 		mbsc.removeNotificationListener(oName, this);
-	    } catch (ListenerNotFoundException ignore) {
+
+	    // If something prevented us from removing ourselves as a
+	    // notification listener, it probably doesn't matter anymore.
+	    } catch (Throwable ignore) {
 	    }
+	    mbsc = null;
 	}
 
 	mbsc = info.getConnector().getMBeanServerConnection();
--- a/usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/common/smf/RepoManagedObject.java	Wed Feb 24 21:04:57 2010 -0500
+++ b/usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/common/smf/RepoManagedObject.java	Wed Feb 24 22:28:58 2010 -0500
@@ -93,6 +93,20 @@
 	newConnection(event.getConnectionInfo(), false);
     }
 
+    @Override
+    public void connectionFailed(ConnectionEvent event) {
+	if (mbsc != null) {
+	    try {
+		mbsc.removeNotificationListener(on, this);
+
+	    // The connection is likely already closed
+	    } catch (Throwable ignore) {
+	    }
+
+	    mbsc = null;
+	}
+    }
+
     //
     // NotificationListener methods
     //
@@ -151,21 +165,20 @@
      * @param async whether the update should occur asynchronously or not
      */
     private void newConnection(ConnectionInfo cinfo, final boolean async) {
-	try {
-	    if (mbsc != null) {
+	if (mbsc != null) {
+	    try {
 		mbsc.removeNotificationListener(on, this);
+
+	    // If something prevented us from removing ourselves as a
+	    // notification listener, it probably doesn't matter anymore.
+	    } catch (Throwable ignore) {
 	    }
-	} catch (Exception e) {
-	    /*
-	     * If something prevented us from removing ourselves as a
-	     * notification listener, it probably doesn't matter anymore.
-	     */
+	    mbsc = null;
 	}
-	mbsc = null;
 
 	try {
 	    mbsc = cinfo.getConnector().getMBeanServerConnection();
-            AggregatorMXBean aggbean = JMX.newMXBeanProxy(mbsc, on,
+	    AggregatorMXBean aggbean = JMX.newMXBeanProxy(mbsc, on,
 		AggregatorMXBean.class);
 	    mbsc.addNotificationListener(on, this, null, null);
 	    services = new HashSet<Service>(aggbean.getServices());
--- a/usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/swing/control/PanelFrameControl.java	Wed Feb 24 21:04:57 2010 -0500
+++ b/usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/swing/control/PanelFrameControl.java	Wed Feb 24 22:28:58 2010 -0500
@@ -72,6 +72,12 @@
 		privilegedChanged();
 		titleChanged();
 	    }
+
+	    @Override
+	    public void connectionFailed(ConnectionEvent event) {
+                // There's nothing particularly helpful we can do here except
+                // wait for the repaired connection in connectionChanged
+	    }
 	};
 
     private PropertyChangeListener healthListener =
--- a/usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/swing/control/SystemTrayControl.java	Wed Feb 24 21:04:57 2010 -0500
+++ b/usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/swing/control/SystemTrayControl.java	Wed Feb 24 22:28:58 2010 -0500
@@ -74,6 +74,12 @@
 	}
     }
 
+    @Override
+    public void connectionFailed(ConnectionEvent event) {
+        // There's nothing particularly helpful we can do here except wait for
+        // the repaired connection in connectionChanged
+    }
+
     //
     // ActionListener methods
     //
--- a/usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/swing/control/WindowControl.java	Wed Feb 24 21:04:57 2010 -0500
+++ b/usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/swing/control/WindowControl.java	Wed Feb 24 22:28:58 2010 -0500
@@ -31,10 +31,12 @@
 import java.util.*;
 import java.util.List;
 import javax.swing.RootPaneContainer;
+import org.opensolaris.os.vp.panel.common.*;
 import org.opensolaris.os.vp.panel.common.control.*;
 import org.opensolaris.os.vp.panel.common.model.PanelDescriptor;
 import org.opensolaris.os.vp.panel.common.view.*;
 import org.opensolaris.os.vp.panel.swing.view.SwingBusyIndicator;
+import org.opensolaris.os.vp.util.misc.Finder;
 import org.opensolaris.os.vp.util.swing.*;
 import org.opensolaris.os.vp.util.swing.glass.*;
 
@@ -114,6 +116,23 @@
 	    }
 	};
 
+    private ConnectionListener connListener =
+	new ConnectionListener() {
+	    @Override
+	    public void connectionChanged(ConnectionEvent event) {
+		busy.setBusyIndicatorDisplayed(false);
+	    }
+
+	    @Override
+	    public void connectionFailed(ConnectionEvent event) {
+		// Prevent interaction with GUI until connection is repaired
+		busy.setMessage(Finder.getString("connection.failed.message",
+		    event.getConnectionInfo().getHost()));
+		busy.setDelay(0);
+		busy.setBusyIndicatorDisplayed(true);
+	    }
+	};
+
     //
     // Constructors
     //
@@ -213,6 +232,9 @@
 
 	navigator.addNavigationListener(noFlicker);
 	noFlicker.navigationStarted(null);
+
+        getPanelDescriptor().getClientContext().addConnectionListener(
+	    connListener);
     }
 
     @Override
@@ -228,6 +250,9 @@
 
 	noFlicker.navigationStopped(null);
 	navigator.removeNavigationListener(noFlicker);
+
+	getPanelDescriptor().getClientContext().removeConnectionListener(
+	    connListener);
     }
 
     //
--- a/usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/swing/control/resources/Resources.properties	Wed Feb 24 21:04:57 2010 -0500
+++ b/usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/swing/control/resources/Resources.properties	Wed Feb 24 22:28:58 2010 -0500
@@ -20,7 +20,7 @@
 #
 
 #
-# Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 
@@ -52,3 +52,5 @@
 tray.popup.login = Change host...
 tray.popup.help = Help...
 tray.popup.exit = Exit
+
+connection.failed.message = The connection to {0} has been lost.  Waiting for connection to be reestablished...
--- a/usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/swing/smf/ServiceStatusPanel.java	Wed Feb 24 21:04:57 2010 -0500
+++ b/usr/src/java/vpanels/panel/org/opensolaris/os/vp/panel/swing/smf/ServiceStatusPanel.java	Wed Feb 24 22:28:58 2010 -0500
@@ -39,9 +39,9 @@
 import org.opensolaris.os.vp.panel.common.*;
 import org.opensolaris.os.vp.panel.common.smf.*;
 import org.opensolaris.os.vp.panel.swing.view.SettingsPanel;
+import org.opensolaris.os.vp.util.misc.*;
 import org.opensolaris.os.vp.util.swing.*;
 import org.opensolaris.os.vp.util.swing.layout.*;
-import org.opensolaris.os.vp.util.misc.*;
 
 @SuppressWarnings({"serial"})
 public class ServiceStatusPanel extends SettingsPanel
@@ -134,6 +134,20 @@
 	}
     }
 
+    @Override
+    public void connectionFailed(ConnectionEvent event) {
+	if (mbsc != null) {
+	    try {
+		mbsc.removeNotificationListener(oName, this);
+
+	    // The connection is likely already closed
+	    } catch (Throwable ignore) {
+	    }
+
+	    mbsc = null;
+	}
+    }
+
     //
     // NotificationListener methods
     //
@@ -222,8 +236,7 @@
 	context.removeConnectionListener(this);
 
 	try {
-	    getMBeanServerConnection().removeNotificationListener(
-		getObjectName(), this);
+	    mbsc.removeNotificationListener(oName, this);
 	} catch (Throwable e) {
 	    context.getLog().log(
 		Level.SEVERE, Finder.getString("error.jmx.general"), e);
@@ -450,11 +463,15 @@
     private void setConnectionInfo(ConnectionInfo info)
 	throws InstanceNotFoundException, IOException {
 
-	if (mbsc != null && oName != null) {
+	if (mbsc != null) {
 	    try {
 		mbsc.removeNotificationListener(oName, this);
-	    } catch (ListenerNotFoundException ignore) {
+
+	    // If something prevented us from removing ourselves as a
+	    // notification listener, it probably doesn't matter anymore.
+	    } catch (Throwable ignore) {
 	    }
+	    mbsc = null;
 	}
 
 	mbsc = info.getConnector().getMBeanServerConnection();
--- a/usr/src/java/vpanels/panels/browser/org/opensolaris/os/vp/panels/browser/client/swing/BrowserPanelDescriptor.java	Wed Feb 24 21:04:57 2010 -0500
+++ b/usr/src/java/vpanels/panels/browser/org/opensolaris/os/vp/panels/browser/client/swing/BrowserPanelDescriptor.java	Wed Feb 24 22:28:58 2010 -0500
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -93,6 +93,12 @@
 	control_.newConnection();
     }
 
+    @Override
+    public void connectionFailed(ConnectionEvent event) {
+        // There's nothing particularly helpful we can do here except wait for
+        // the repaired connection in connectionChanged
+    }
+
     //
     // BrowserPanelDescriptor methods
     //
--- a/usr/src/java/vpanels/panels/examples/org/opensolaris/os/vp/panels/example/time2/client/swing/TimePanelDescriptor.java	Wed Feb 24 21:04:57 2010 -0500
+++ b/usr/src/java/vpanels/panels/examples/org/opensolaris/os/vp/panels/example/time2/client/swing/TimePanelDescriptor.java	Wed Feb 24 22:28:58 2010 -0500
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -81,6 +81,12 @@
 	setBean(event.getConnectionInfo());
     }
 
+    @Override
+    public void connectionFailed(ConnectionEvent event) {
+        // There's nothing particularly helpful we can do here except wait for
+        // the repaired connection in connectionChanged
+    }
+
     //
     // ManagedObject methods
     //
--- a/usr/src/java/vpanels/panels/firewall/org/opensolaris/os/vp/panels/firewall/client/swing/ServiceManagedObject.java	Wed Feb 24 21:04:57 2010 -0500
+++ b/usr/src/java/vpanels/panels/firewall/org/opensolaris/os/vp/panels/firewall/client/swing/ServiceManagedObject.java	Wed Feb 24 22:28:58 2010 -0500
@@ -174,6 +174,20 @@
 	}
     }
 
+    @Override
+    public void connectionFailed(ConnectionEvent event) {
+	if (mbsc != null) {
+	    try {
+		mbsc.removeNotificationListener(oName, this);
+
+	    // The connection is likely already closed
+	    } catch (Throwable ignore) {
+	    }
+
+	    mbsc = null;
+	}
+    }
+
     //
     // NotificationListener methods
     //
@@ -215,8 +229,12 @@
 	if (mbsc != null) {
 	    try {
 		mbsc.removeNotificationListener(oName, this);
-	    } catch (ListenerNotFoundException ignore) {
+
+	    // If something prevented us from removing ourselves as a
+	    // notification listener, it probably doesn't matter anymore.
+	    } catch (Throwable ignore) {
 	    }
+	    mbsc = null;
 	}
 
 	try {
@@ -249,7 +267,6 @@
     public void refresh() throws ScfException {
 	setAccessPolicy(new SimpleAccessPolicy(pgInfo));
 	enabled = bean.isEnabled();
-	System.out.printf("service: %s: %s\n", getId(), policy.getType());
 	setStatusText(policy.getType());
     }
 
--- a/usr/src/java/vpanels/panels/sharemgr/org/opensolaris/os/vp/panels/sharemgr/client/common/SharemgrEventMonitor.java	Wed Feb 24 21:04:57 2010 -0500
+++ b/usr/src/java/vpanels/panels/sharemgr/org/opensolaris/os/vp/panels/sharemgr/client/common/SharemgrEventMonitor.java	Wed Feb 24 22:28:58 2010 -0500
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -40,7 +40,6 @@
 import org.opensolaris.os.vp.panels.sharemgr.rad.GroupId;
 import org.opensolaris.os.vp.panels.sharemgr.rad.ShareChange;
 import org.opensolaris.os.vp.panels.sharemgr.rad.ShareId;
-import org.opensolaris.os.vp.util.misc.Finder;
 
 @SuppressWarnings({"serial"})
 public class SharemgrEventMonitor implements NotificationListener, Runnable {
@@ -250,10 +249,12 @@
 	if (mbsc != null) {
 	    try {
 		mbsc.removeNotificationListener(SharemgrUtil.OBJECT_NAME, this);
-	    } catch (Throwable e) {
-		descriptor.getClientContext().getLog().log(Level.SEVERE,
-		    Finder.getString("error.jmx.general"), e);
+
+	    // If something prevented us from removing ourselves as a
+	    // notification listener, it probably doesn't matter anymore.
+	    } catch (Throwable ignore) {
 	    }
+	    mbsc = null;
 	}
 
 	add(STOP);
--- a/usr/src/java/vpanels/panels/smf/org/opensolaris/os/vp/panels/smf/client/swing/SMFEditPanel.java	Wed Feb 24 21:04:57 2010 -0500
+++ b/usr/src/java/vpanels/panels/smf/org/opensolaris/os/vp/panels/smf/client/swing/SMFEditPanel.java	Wed Feb 24 22:28:58 2010 -0500
@@ -26,8 +26,6 @@
 
 package org.opensolaris.os.vp.panels.smf.client.swing;
 
-import org.opensolaris.os.vp.panel.common.smf.SMFManagedObject;
-import org.opensolaris.os.vp.panel.common.smf.depend.DependenciesModel;
 import java.awt.*;
 import java.io.IOException;
 import java.util.List;
@@ -38,14 +36,13 @@
 import org.opensolaris.os.vp.panel.common.*;
 import org.opensolaris.os.vp.panel.common.action.StructuredAction;
 import org.opensolaris.os.vp.panel.common.model.ManagedObject;
-import org.opensolaris.os.vp.panel.common.smf.SimpleSmfServiceInfo;
-import org.opensolaris.os.vp.panel.swing.smf.ServiceSettingsPanel;
-import org.opensolaris.os.vp.panel.swing.smf.ServiceStatusPanel;
-import org.opensolaris.os.vp.panel.swing.view.SelectorPanel;
-import org.opensolaris.os.vp.panel.swing.view.SettingsPanel;
+import org.opensolaris.os.vp.panel.common.smf.*;
+import org.opensolaris.os.vp.panel.common.smf.depend.DependenciesModel;
+import org.opensolaris.os.vp.panel.swing.smf.*;
+import org.opensolaris.os.vp.panel.swing.view.*;
+import org.opensolaris.os.vp.util.misc.*;
 import org.opensolaris.os.vp.util.swing.*;
 import org.opensolaris.os.vp.util.swing.layout.*;
-import org.opensolaris.os.vp.util.misc.*;
 
 public abstract class SMFEditPanel<T extends SMFManagedObject>
     extends SettingsPanel implements ConnectionListener
@@ -99,6 +96,12 @@
 	}
     }
 
+    @Override
+    public void connectionFailed(ConnectionEvent event) {
+        // There's nothing particularly helpful we can do here except wait for
+        // the repaired connection in connectionChanged
+    }
+
     /*
      * SMFEditPanel methods
      */
--- a/usr/src/java/vpanels/panels/sysid/org/opensolaris/os/vp/panels/sysid/client/swing/SysIdPanelDescriptor.java	Wed Feb 24 21:04:57 2010 -0500
+++ b/usr/src/java/vpanels/panels/sysid/org/opensolaris/os/vp/panels/sysid/client/swing/SysIdPanelDescriptor.java	Wed Feb 24 22:28:58 2010 -0500
@@ -20,7 +20,7 @@
  */
 
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -90,6 +90,12 @@
 	setBean(event.getConnectionInfo());
     }
 
+    @Override
+    public void connectionFailed(ConnectionEvent event) {
+        // There's nothing particularly helpful we can do here except wait for
+        // the repaired connection in connectionChanged
+    }
+
     //
     // ManagedObject methods
     //