Web UI - reflect logged-in-username back to UI in the bootstrap event.

Change-Id: I771b0d1d426cc2435d8c8e5953d3e52d410f6293
diff --git a/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocket.java b/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocket.java
index 731840e..d1d7950 100644
--- a/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocket.java
+++ b/web/gui/src/main/java/org/onosproject/ui/impl/UiWebSocket.java
@@ -25,8 +25,8 @@
 import org.onosproject.cluster.ControllerNode;
 import org.onosproject.ui.UiConnection;
 import org.onosproject.ui.UiExtensionService;
-import org.onosproject.ui.UiMessageHandlerFactory;
 import org.onosproject.ui.UiMessageHandler;
+import org.onosproject.ui.UiMessageHandlerFactory;
 import org.onosproject.ui.UiTopoOverlayFactory;
 import org.onosproject.ui.impl.topo.UiTopoSession;
 import org.onosproject.ui.impl.topo.model.UiSharedTopologyModel;
@@ -46,6 +46,17 @@
 
     private static final Logger log = LoggerFactory.getLogger(UiWebSocket.class);
 
+    private static final String EVENT = "event";
+    private static final String SID = "sid";
+    private static final String PAYLOAD = "payload";
+    private static final String UNKNOWN = "unknown";
+
+    private static final String ID = "id";
+    private static final String IP = "ip";
+    private static final String CLUSTER_NODES = "clusterNodes";
+    private static final String USER = "user";
+    private static final String BOOTSTRAP = "bootstrap";
+
     private static final long MAX_AGE_MS = 30_000;
 
     private static final byte PING = 0x9;
@@ -69,7 +80,7 @@
      * Creates a new web-socket for serving data to the Web UI.
      *
      * @param directory service directory
-     * @param userName user name of the logged-in user
+     * @param userName  user name of the logged-in user
      */
     public UiWebSocket(ServiceDirectory directory, String userName) {
         this.directory = directory;
@@ -121,8 +132,8 @@
         try {
             topoSession.init();
             createHandlersAndOverlays();
-            sendInstanceData();
-            log.info("GUI client connected");
+            sendBootstrapData();
+            log.info("GUI client connected -- user <{}>", userName);
 
         } catch (ServiceNotFoundException e) {
             log.warn("Unable to open GUI connection; services have been shut-down", e);
@@ -137,7 +148,7 @@
         topoSession.destroy();
         destroyHandlersAndOverlays();
         log.info("GUI client disconnected [close-code={}, message={}]",
-                 closeCode, message);
+                closeCode, message);
     }
 
     @Override
@@ -152,7 +163,7 @@
         lastActive = System.currentTimeMillis();
         try {
             ObjectNode message = (ObjectNode) mapper.reader().readTree(data);
-            String type = message.path("event").asText("unknown");
+            String type = message.path(EVENT).asText(UNKNOWN);
             UiMessageHandler handler = handlers.get(type);
             if (handler != null) {
                 handler.process(message);
@@ -180,17 +191,17 @@
     @Override
     public synchronized void sendMessage(String type, long sid, ObjectNode payload) {
         ObjectNode message = mapper.createObjectNode();
-        message.put("event", type);
+        message.put(EVENT, type);
         if (sid > 0) {
-            message.put("sid", sid);
+            message.put(SID, sid);
         }
-        message.set("payload", payload != null ? payload : mapper.createObjectNode());
+        message.set(PAYLOAD, payload != null ? payload : mapper.createObjectNode());
         sendMessage(message);
     }
 
     // Creates new message handlers.
     private synchronized void createHandlersAndOverlays() {
-        log.debug("creating handlers and overlays...");
+        log.debug("Creating handlers and overlays...");
         handlers = new HashMap<>();
         overlayCache = new TopoOverlayCache();
 
@@ -219,12 +230,12 @@
             }
         });
         log.debug("#handlers = {}, #overlays = {}", handlers.size(),
-                  overlayCache.size());
+                overlayCache.size());
     }
 
     // Destroys message handlers.
     private synchronized void destroyHandlersAndOverlays() {
-        log.debug("destroying handlers and overlays...");
+        log.debug("Destroying handlers and overlays...");
         handlers.forEach((type, handler) -> handler.destroy());
         handlers.clear();
 
@@ -234,23 +245,26 @@
         }
     }
 
-    // Sends cluster node/instance information to allow GUI to fail-over.
-    private void sendInstanceData() {
+    // Sends initial information (username and cluster member information)
+    // to allow GUI to display logged-in user, and to be able to
+    // fail-over to an alternate cluster member if necessary.
+    private void sendBootstrapData() {
         ClusterService service = directory.get(ClusterService.class);
         ArrayNode instances = mapper.createArrayNode();
 
         for (ControllerNode node : service.getNodes()) {
             ObjectNode instance = mapper.createObjectNode()
-                    .put("id", node.id().toString())
-                    .put("ip", node.ip().toString())
+                    .put(ID, node.id().toString())
+                    .put(IP, node.ip().toString())
                     .put(TopoConstants.Glyphs.UI_ATTACHED,
-                         node.equals(service.getLocalNode()));
+                            node.equals(service.getLocalNode()));
             instances.add(instance);
         }
 
         ObjectNode payload = mapper.createObjectNode();
-        payload.set("clusterNodes", instances);
-        sendMessage("bootstrap", 0, payload);
+        payload.set(CLUSTER_NODES, instances);
+        payload.put(USER, userName);
+        sendMessage(BOOTSTRAP, 0, payload);
     }
 
 }
diff --git a/web/gui/src/main/webapp/app/fw/remote/websocket.js b/web/gui/src/main/webapp/app/fw/remote/websocket.js
index 91606c5..940cdec 100644
--- a/web/gui/src/main/webapp/app/fw/remote/websocket.js
+++ b/web/gui/src/main/webapp/app/fw/remote/websocket.js
@@ -36,13 +36,16 @@
         clusterIndex = -1,      // the instance to which we are connected
         connectRetries = 0,     // limit our attempts at reconnecting
         openListeners = {},     // registered listeners for websocket open()
-        nextListenerId = 1;     // internal ID for open listeners
+        nextListenerId = 1,     // internal ID for open listeners
+        loggedInUser = null;    // name of logged-in user
 
     // =======================
     // === Bootstrap Handler
 
     var builtinHandlers = {
         bootstrap: function (data) {
+            $log.debug('bootstrap data', data);
+            loggedInUser = data.user;
             clusterNodes = data.clusterNodes;
             clusterNodes.forEach(function (d, i) {
                 if (d.uiAttached) {
@@ -332,6 +335,7 @@
                 removeOpenListener: removeOpenListener,
                 sendEvent: sendEvent,
                 isConnected: function () { return wsUp; },
+                loggedInUser: function () { return loggedInUser || '(no-one)'; },
 
                 _setVeilDelegate: setVeilDelegate,
                 _setLoadingDelegate: setLoadingDelegate