org.wso2.andes.management.ui.views.NavigationView.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.andes.management.ui.views.NavigationView.java

Source

/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */
package org.wso2.andes.management.ui.views;

import static org.wso2.andes.management.ui.Constants.*;
import static org.wso2.andes.management.ui.ApplicationRegistry.DATA_DIR;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

import org.wso2.andes.management.common.mbeans.ConfigurationManagement;
import org.wso2.andes.management.common.mbeans.LoggingManagement;
import org.wso2.andes.management.common.mbeans.ServerInformation;
import org.wso2.andes.management.common.mbeans.UserManagement;
import org.wso2.andes.management.ui.ApiVersion;
import org.wso2.andes.management.ui.ApplicationRegistry;
import org.wso2.andes.management.ui.ManagedBean;
import org.wso2.andes.management.ui.ManagedObject;
import org.wso2.andes.management.ui.ManagedServer;
import org.wso2.andes.management.ui.ServerRegistry;
import org.wso2.andes.management.ui.exceptions.InfoRequiredException;
import org.wso2.andes.management.ui.exceptions.ManagementConsoleException;
import org.wso2.andes.management.ui.jmx.JMXServerRegistry;
import org.wso2.andes.management.ui.jmx.MBeanUtility;
import org.eclipse.jface.preference.PreferenceStore;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.IFontProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.ITreeViewerListener;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeExpansionEvent;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerSorter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ViewPart;

/**
 * Navigation View for navigating the managed servers and managed beans on
 * those servers
 * @author Bhupendra Bhardwaj
 */
public class NavigationView extends ViewPart {
    public static final String ID = "org.wso2.andes.management.ui.navigationView";
    public static final String INI_FILENAME = DATA_DIR + File.separator + "qpidmc_navigation.ini";

    private static final String INI_SERVERS = "Servers";
    private static final String INI_QUEUES = QUEUE + "s";
    private static final String INI_CONNECTIONS = CONNECTION + "s";
    private static final String INI_EXCHANGES = EXCHANGE + "s";

    private TreeViewer _treeViewer = null;
    private TreeObject _serversRootNode = null;

    private PreferenceStore _preferences;
    // Map of connected servers
    private ConcurrentHashMap<ManagedServer, TreeObject> _managedServerMap = new ConcurrentHashMap<ManagedServer, TreeObject>();

    private static HashSet<String> _serverTopLevelMBeans = new HashSet<String>();
    {
        _serverTopLevelMBeans.add(UserManagement.TYPE);
        _serverTopLevelMBeans.add(LoggingManagement.TYPE);
        _serverTopLevelMBeans.add(ConfigurationManagement.TYPE);
        _serverTopLevelMBeans.add(ServerInformation.TYPE);
    }

    private void createTreeViewer(Composite parent) {
        _treeViewer = new TreeViewer(parent);
        _treeViewer.setContentProvider(new ContentProviderImpl());
        _treeViewer.setLabelProvider(new LabelProviderImpl());
        _treeViewer.setSorter(new ViewerSorterImpl());

        // layout the tree viewer below the label field, to cover the area
        GridData layoutData = new GridData();
        layoutData.grabExcessHorizontalSpace = true;
        layoutData.grabExcessVerticalSpace = true;
        layoutData.horizontalAlignment = GridData.FILL;
        layoutData.verticalAlignment = GridData.FILL;
        _treeViewer.getControl().setLayoutData(layoutData);
        _treeViewer.setUseHashlookup(true);

        createListeners();
    }

    /**
     * Creates listeners for the JFace treeviewer
     */
    private void createListeners() {
        _treeViewer.addDoubleClickListener(new IDoubleClickListener() {
            public void doubleClick(DoubleClickEvent event) {
                IStructuredSelection ss = (IStructuredSelection) event.getSelection();
                if ((ss == null) || (ss.getFirstElement() == null)) {
                    return;
                }

                boolean state = _treeViewer.getExpandedState(ss.getFirstElement());
                _treeViewer.setExpandedState(ss.getFirstElement(), !state);
            }
        });

        _treeViewer.addTreeListener(new ITreeViewerListener() {
            public void treeExpanded(TreeExpansionEvent event) {
                getSite().getShell().getDisplay().asyncExec(new Runnable() {
                    public void run() {
                        _treeViewer.refresh();
                    }
                });
            }

            public void treeCollapsed(TreeExpansionEvent event) {
                getSite().getShell().getDisplay().asyncExec(new Runnable() {
                    public void run() {
                        _treeViewer.refresh();
                    }
                });
            }
        });

        // This listener is for popup menu, which pops up if a queue,exchange or connection is selected
        // with right click.
        _treeViewer.getTree().addListener(SWT.MenuDetect, new Listener() {
            Display display = getSite().getShell().getDisplay();
            final Shell shell = new Shell(display);

            public void handleEvent(Event event) {
                Tree widget = (Tree) event.widget;
                TreeItem[] items = widget.getSelection();
                if (items == null) {
                    return;
                }

                // Get the selected node
                final TreeObject selectedNode = (TreeObject) items[0].getData();
                final TreeObject parentNode = selectedNode.getParent();

                // This popup is only for mbeans and only connection,exchange and queue types
                if ((parentNode == null) || !MBEAN.equals(selectedNode.getType())
                        || !(CONNECTION.equals(parentNode.getName()) || QUEUE.equals(parentNode.getName())
                                || EXCHANGE.equals(parentNode.getName()))) {
                    return;
                }

                Menu menu = new Menu(shell, SWT.POP_UP);
                MenuItem item = new MenuItem(menu, SWT.PUSH);
                // Add the action item, which will remove the node from the tree if selected
                item.setText(ACTION_REMOVE_MBEANNODE);
                item.addListener(SWT.Selection, new Listener() {
                    public void handleEvent(Event e) {
                        removeManagedObject(parentNode, (ManagedBean) selectedNode.getManagedObject(), true);
                        _treeViewer.refresh();
                        // set the selection to the parent node
                        _treeViewer.setSelection(new StructuredSelection(parentNode));
                    }
                });
                menu.setLocation(event.x, event.y);
                menu.setVisible(true);
                while (!menu.isDisposed() && menu.isVisible()) {
                    if (!display.readAndDispatch()) {
                        display.sleep();
                    }
                }

                menu.dispose();
            }
        });
    }

    /**
     * Creates Qpid Server connection
     * @param server
     * @throws Exception
     */
    private void createJMXServerConnection(ManagedServer server) throws Exception {
        // Currently Qpid Management Console only supports JMX MBeanServer
        JMXServerRegistry serverRegistry = new JMXServerRegistry(server);

        try {
            //determine the management API version of the server just connected to
            MBeanUtility.classifyManagementApiVersion(server, serverRegistry);
        } catch (Exception e) {
            //Exception classifying the server API, clean up the connection and rethrow
            serverRegistry.closeServerConnection();
            throw e;
        }

        //check that the console supports the API major version encountered, otherwise abort.
        ApiVersion serverAPI = serverRegistry.getManagementApiVersion();

        int serverMajor = serverAPI.getMajor();
        int supportedMajor = ApplicationRegistry.SUPPORTED_QPID_JMX_API_MAJOR_VERSION;

        if (serverMajor > supportedMajor) {
            serverRegistry.closeServerConnection();
            throw new ManagementConsoleException("The server management API version encountered is not supported"
                    + " by this console release. Please check for an updated console release.");
        }

        //connection succeeded, add the ServerRegistry to the ApplicationRegistry
        ApplicationRegistry.addServer(server, serverRegistry);
    }

    /**
     * Adds a new server node in the navigation view if server connection is successful.
     * @param transportProtocol
     * @param host
     * @param port
     * @param domain
     * @throws Exception
     */
    public void addNewServer(String host, int port, String domain, String user, String pwd) throws Exception {
        ManagedServer managedServer = new ManagedServer(host, port, domain, user, pwd);

        String server = managedServer.getName();
        List<TreeObject> list = _serversRootNode.getChildren();
        for (TreeObject node : list) {
            ManagedServer nodeServer = (ManagedServer) node.getManagedObject();
            if (server.equals(nodeServer.getName())) {
                // Server is already in the list of added servers, so now connect it.
                // Set the server node as selected and then connect it.
                _treeViewer.setSelection(new StructuredSelection(node));
                reconnect(user, pwd);

                return;
            }
        }

        // The server is not in the list of already added servers, so now connect and add it.
        createJMXServerConnection(managedServer);

        // Server connection is successful. Now add the server in the tree
        TreeObject serverNode = new TreeObject(server, NODE_TYPE_SERVER);
        serverNode.setManagedObject(managedServer);
        _serversRootNode.addChild(serverNode);

        // Add server in the connected server map
        _managedServerMap.put(managedServer, serverNode);

        // populate the server tree
        try {
            populateServer(serverNode);
        } catch (SecurityException ex) {
            disconnect(managedServer);
            throw ex;
        }

        // Add the Queue/Exchanges/Connections from config file into the navigation tree
        addConfiguredItems(managedServer);

        _treeViewer.refresh();

        expandInitialMBeanView(serverNode);

        //(re)select the server node now that it is connected to force a selectionEvent
        _treeViewer.setSelection(new StructuredSelection(serverNode));
        _treeViewer.refresh();

        // save server address in file
        addServerInConfigFile(server);
    }

    /**
     * Create the config file, if it doesn't already exist.
     * Exits the application if the file could not be created.
     */
    private void createConfigFile() {
        File dir = new File(DATA_DIR);
        if (!dir.exists()) {
            if (!dir.mkdir()) {
                System.out.println("Could not create application data directory " + DATA_DIR);
                System.exit(1);
            }
        }

        File file = new File(INI_FILENAME);
        try {
            if (!file.exists()) {
                file.createNewFile();
            }
        } catch (IOException ex) {
            System.out.println("Could not write to the file " + INI_FILENAME);
            System.out.println(ex);
            System.exit(1);
        }
    }

    /**
     * Server addresses are stored in a file. When user launches the application again, the
     * server addresses are picked up from the file and shown in the navigfation view. This method
     * adds the server address in a file, when a new server is added in the navigation view.
     * @param serverAddress
     */
    private void addServerInConfigFile(String serverAddress) {
        // Check if the address already exists
        List<String> list = getServerListFromFile();
        if ((list != null) && list.contains(serverAddress)) {
            return;
        }

        // Get the existing server list and add to that
        String servers = _preferences.getString(INI_SERVERS);
        String value = (servers.length() != 0) ? (servers + "," + serverAddress) : serverAddress;
        _preferences.putValue(INI_SERVERS, value);
        try {
            _preferences.save();
        } catch (IOException ex) {
            System.err.println("Could not add " + serverAddress + " in " + INI_SERVERS + " (" + INI_FILENAME + ")");
            System.out.println(ex);
        }
    }

    /**
     * Adds the item (Queue/Exchange/Connection) to the config file
     * @param server
     * @param virtualhost
     * @param type - (Queue or Exchange or Connection)
     * @param name - item name
     */
    private void addItemInConfigFile(TreeObject node) {
        ManagedBean mbean = (ManagedBean) node.getManagedObject();
        String server = mbean.getServer().getName();
        String virtualhost = mbean.getVirtualHostName();
        String type = node.getParent().getName() + "s";
        String name = node.getName();
        String itemKey = server + "." + virtualhost + "." + type;

        // Check if the item already exists in the config file
        List<String> list = getConfiguredItemsFromFile(itemKey);
        if ((list != null) && list.contains(name)) {
            return;
        }

        // Add this item to the existing list of items
        String items = _preferences.getString(itemKey);
        String value = (items.length() != 0) ? (items + "," + name) : name;
        _preferences.putValue(itemKey, value);
        try {
            _preferences.save();
        } catch (IOException ex) {
            System.err.println("Could not add " + name + " in " + itemKey + " (" + INI_FILENAME + ")");
            System.out.println(ex);
        }
    }

    private void removeItemFromConfigFile(TreeObject node) {
        ManagedBean mbean = (ManagedBean) node.getManagedObject();
        String server = mbean.getServer().getName();
        String vHost = mbean.getVirtualHostName();
        String type = node.getParent().getName() + "s";
        String itemKey = server + "." + vHost + "." + type;

        List<String> list = getConfiguredItemsFromFile(itemKey);
        if (list.contains(node.getName())) {
            list.remove(node.getName());
            String value = "";
            for (String item : list) {
                value += item + ",";
            }

            value = (value.lastIndexOf(",") != -1) ? value.substring(0, value.lastIndexOf(",")) : value;

            _preferences.putValue(itemKey, value);
            try {
                _preferences.save();
            } catch (IOException ex) {
                System.err.println("Error in updating the config file " + INI_FILENAME);
                System.out.println(ex);
            }
        }
    }

    //check if the MBeanInfo can be retrieved.
    private boolean haveAccessPermission(ManagedBean mbean) {
        try {
            MBeanUtility.getMBeanInfo(mbean);
        } catch (Exception ex) {
            return false;
        }

        return true;
    }

    /**
     * Queries the qpid server for MBeans and populates the navigation view with all MBeans for
     * the given server node.
     * @param serverNode
     * @throws Exception
     */
    private void populateServer(TreeObject serverNode) throws Exception {
        ManagedServer server = (ManagedServer) serverNode.getManagedObject();
        String domain = server.getDomain();

        List<ManagedBean> mbeans = MBeanUtility.getManagedObjectsForDomain(server, domain);
        for (ManagedBean mbean : mbeans) {
            mbean.setServer(server);
            ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(server);
            serverRegistry.addManagedObject(mbean);

            // Add all mbeans other than Connections, Exchanges and Queues. Because these will be added
            // manually by selecting from MBeanView
            if (!(mbean.isConnection() || mbean.isExchange() || mbean.isQueue())) {
                //if we cant get the MBeanInfo then we cant display the mbean, so dont add it to the tree
                if (haveAccessPermission(mbean)) {
                    addManagedBean(serverNode, mbean);
                }
            }
        }
        // To make it work with the broker without virtual host implementation.
        // This will add the default nodes to the domain node
        boolean hasVirtualHost = false;
        for (TreeObject child : serverNode.getChildren()) {
            if (child.getName().startsWith(VIRTUAL_HOST)) {
                hasVirtualHost = true;
                break;
            }
        }

        if (!hasVirtualHost) {
            addDefaultNodes(serverNode);
        }
    }

    /**
     * Add these three types - Connection, Exchange, Queue
     * By adding these, these will always be available, even if there are no mbeans under thse types
     * This is required because, the mbeans will be added from mbeanview, by selecting from the list
     * @param parent Node
     */
    private void addDefaultNodes(TreeObject parent) {
        TreeObject typeChild = new TreeObject(CONNECTION, NODE_TYPE_MBEANTYPE);
        typeChild.setParent(parent);
        typeChild.setVirtualHost(parent.getVirtualHost());
        typeChild = new TreeObject(EXCHANGE, NODE_TYPE_MBEANTYPE);
        typeChild.setParent(parent);
        typeChild.setVirtualHost(parent.getVirtualHost());
        typeChild = new TreeObject(QUEUE, NODE_TYPE_MBEANTYPE);
        typeChild.setParent(parent);
        typeChild.setVirtualHost(parent.getVirtualHost());

        // Add common notification node for virtual host
        TreeObject notificationNode = new TreeObject(NOTIFICATIONS, NOTIFICATIONS);
        notificationNode.setParent(parent);
        notificationNode.setVirtualHost(parent.getVirtualHost());
    }

    /**
     * Checks if a particular mbeantype is already there in the navigation view for a domain.
     * This is used while populating domain with mbeans.
     * @param parent
     * @param typeName
     * @return Node if given mbeantype already exists, otherwise null
     */
    private TreeObject getMBeanTypeNode(TreeObject parent, String typeName) {
        List<TreeObject> childNodes = parent.getChildren();
        for (TreeObject child : childNodes) {
            if ((NODE_TYPE_MBEANTYPE.equals(child.getType()) || NODE_TYPE_TYPEINSTANCE.equals(child.getType()))
                    && typeName.equals(child.getName())) {
                return child;
            }
        }

        return null;
    }

    private boolean doesMBeanNodeAlreadyExist(TreeObject typeNode, String mbeanName) {
        List<TreeObject> childNodes = typeNode.getChildren();
        for (TreeObject child : childNodes) {
            if (MBEAN.equals(child.getType()) && mbeanName.equals(child.getName())) {
                return true;
            }
        }

        return false;
    }

    /**
     * Adds the given MBean to the given domain node.
     * sample ObjectNames -
     * org.wso2.andes:type=VirtualHost.VirtualHostManager,VirtualHost=localhost
     * org.wso2.andes:type=VirtualHost.Queue,VirtualHost=test,name=ping_1
     * @param parent parent tree node to add the mbean to
     * @param mbean mbean to add
     */
    private void addManagedBean(TreeObject parent, ManagedBean mbean) {
        String name = mbean.getName();
        // Split the mbean type into array of Strings, to create hierarchy
        // eg. type=VirtualHost.VirtualHostManager,VirtualHost=localhost will be:
        // localhost->VirtualHostManager
        // eg. type=org.wso2.andes:type=VirtualHost.Queue,VirtualHost=test,name=ping will be:
        // test->Queue->ping
        String[] types = mbean.getType().split("\\.");
        TreeObject typeNode = null;
        TreeObject parentNode = parent;

        // Run this loop till all nodes(hierarchy) for this mbean are created. This loop only creates
        // all the required parent nodes for the mbean
        for (int i = 0; i < types.length; i++) {
            String type = types[i];

            if (types.length == 1 && _serverTopLevelMBeans.contains(type)) {
                //This mbean is not to be contained in a type hierarchy
                //Just add it as a child of the server node.
                break;
            }

            String valueOftype = mbean.getProperty(type);
            // If value is not null, then there will be a parent node for this mbean
            // eg. for type=VirtualHost the value is "test"
            typeNode = getMBeanTypeNode(parentNode, type);

            // create the type node if not already created
            if (typeNode == null) {
                // If the ObjectName doesn't have name property, that means there will be only one instance
                // of this mbean for given "type". So there will be no type node created for this mbean.
                if ((name == null) && (i == (types.length - 1))) {
                    break;
                }

                // create a node for "type"
                typeNode = createTypeNode(parentNode, type);
                if (!type.equals(VIRTUAL_HOST)) {
                    typeNode.setVirtualHost(mbean.getVirtualHostName());
                }
            }

            // now type node create becomes the parent node for next node in hierarchy
            parentNode = typeNode;

            /*
             * Now create instances node for this type if value exists.
             */
            if (valueOftype == null) {
                // No instance node will be created when value is null (eg type=Queue)
                break;
            }

            // For different virtual hosts, the nodes with given value will be created.
            // eg type=VirtualHost, value=test
            typeNode = getMBeanTypeNode(parentNode, valueOftype);
            if (typeNode == null) {
                typeNode = createTypeInstanceNode(parentNode, valueOftype);
                typeNode.setVirtualHost(mbean.getVirtualHostName());

                // Create default nodes for VHost instances
                if (type.equals(VIRTUAL_HOST)) {
                    addDefaultNodes(typeNode);
                }
            }

            parentNode = typeNode;
        }

        if (typeNode == null) {
            typeNode = parentNode;
        }

        // Check if an MBean is already added
        if (doesMBeanNodeAlreadyExist(typeNode, name)) {
            return;
        }

        // Add the mbean node now
        TreeObject mbeanNode = new TreeObject(mbean);
        mbeanNode.setVirtualHost(mbean.getVirtualHostName());
        mbeanNode.setParent(typeNode);

        // Add the mbean to the config file
        if (mbean.isQueue() || mbean.isExchange() || mbean.isConnection()) {
            addItemInConfigFile(mbeanNode);
        }
    }

    private TreeObject createTypeNode(TreeObject parent, String name) {
        TreeObject typeNode = new TreeObject(name, NODE_TYPE_MBEANTYPE);
        typeNode.setParent(parent);

        return typeNode;
    }

    private TreeObject createTypeInstanceNode(TreeObject parent, String name) {
        TreeObject typeNode = new TreeObject(name, NODE_TYPE_TYPEINSTANCE);
        typeNode.setParent(parent);

        return typeNode;
    }

    /**
     * Removes all the child nodes of the given parent node. Used when closing a server.
     * @param parent
     */
    private void removeManagedObject(TreeObject parent) {
        if (parent == null) {
            return;
        }

        List<TreeObject> list = parent.getChildren();
        for (TreeObject child : list) {
            removeManagedObject(child);
        }

        list.clear();
    }

    /**
     * Removes the mbean from the tree
     * @param parent
     * @param mbean
     */
    private void removeManagedObject(TreeObject parent, ManagedBean mbean, boolean removeFromConfigFile) {
        List<TreeObject> list = parent.getChildren();
        TreeObject objectToRemove = null;
        for (TreeObject child : list) {
            if (MBEAN.equals(child.getType())) {
                String name = (mbean.getName() != null) ? mbean.getName() : mbean.getType();
                if (child.getName().equals(name)) {
                    objectToRemove = child;

                    break;
                }
            } else {
                removeManagedObject(child, mbean, removeFromConfigFile);
            }
        }

        if (objectToRemove != null) {
            list.remove(objectToRemove);
            if (removeFromConfigFile) {
                removeItemFromConfigFile(objectToRemove);
            }
        }

    }

    /**
     * Closes the Qpid server connection
     */
    public void disconnect() throws Exception {
        TreeObject selectedNode = getSelectedServerNode();
        ManagedServer managedServer = (ManagedServer) selectedNode.getManagedObject();
        disconnect(managedServer);
    }

    private void disconnect(ManagedServer managedServer) throws Exception {
        if (!_managedServerMap.containsKey(managedServer)) {
            return;
        }

        // Close server connection
        ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(managedServer);
        if (serverRegistry == null) // server connection is already closed
        {
            return;
        }

        // Add server to the closed server list and the worker thread will remove the server from required places.
        ApplicationRegistry.serverConnectionClosed(managedServer);

        //close the connection
        serverRegistry.closeServerConnection();
    }

    /**
     * Connects the selected server node
     * @throws Exception
     */
    public void reconnect(String user, String password) throws Exception {
        TreeObject selectedNode = getSelectedServerNode();
        ManagedServer managedServer = (ManagedServer) selectedNode.getManagedObject();
        if (_managedServerMap.containsKey(managedServer)) {
            throw new InfoRequiredException("Server " + managedServer.getName() + " is already connected");
        }

        managedServer.setUser(user);
        managedServer.setPassword(password);
        createJMXServerConnection(managedServer);

        // put the server in the managed server map
        _managedServerMap.put(managedServer, selectedNode);

        try {
            // populate the server tree now
            populateServer(selectedNode);
        } catch (SecurityException ex) {
            disconnect(managedServer);
            throw ex;
        }

        // Add the Queue/Exchanges/Connections from config file into the navigation tree
        addConfiguredItems(managedServer);

        expandInitialMBeanView(selectedNode);

        //(re)select the server node now that it is connected to force a selectionEvent
        _treeViewer.setSelection(new StructuredSelection(selectedNode));
        _treeViewer.refresh();
    }

    private void expandInitialMBeanView(TreeObject serverNode) {
        if (serverNode.getChildren().size() == 0) {
            return;
        } else {
            _treeViewer.setExpandedState(serverNode, true);
        }

        List<TreeObject> children = serverNode.getChildren();
        for (TreeObject child : children) {
            if (child.getChildren().size() > 0) {
                _treeViewer.setExpandedState(child, true);
            }
        }
    }

    /**
     * Adds the items(queues/exchanges/connectins) from config file to the server tree
     * @param server
     */
    private void addConfiguredItems(ManagedServer server) {
        ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(server);
        List<String> list = serverRegistry.getVirtualHosts();
        for (String virtualHost : list) {
            // Add Queues
            String itemKey = server.getName() + "." + virtualHost + "." + INI_QUEUES;
            List<String> items = getConfiguredItemsFromFile(itemKey);
            List<ManagedBean> mbeans = serverRegistry.getQueues(virtualHost);
            addConfiguredItems(items, mbeans);

            // Add Exchanges
            itemKey = server.getName() + "." + virtualHost + "." + INI_EXCHANGES;
            items = getConfiguredItemsFromFile(itemKey);
            mbeans = serverRegistry.getExchanges(virtualHost);
            addConfiguredItems(items, mbeans);

            // Add Connections
            itemKey = server.getName() + "." + virtualHost + "." + INI_CONNECTIONS;
            items = getConfiguredItemsFromFile(itemKey);
            mbeans = serverRegistry.getConnections(virtualHost);
            addConfiguredItems(items, mbeans);
        }
    }

    /**
     * Gets the mbeans corresponding to the items and adds those to the navigation tree
     * @param items
     * @param mbeans
     */
    private void addConfiguredItems(List<String> items, List<ManagedBean> mbeans) {
        if ((items == null) || (items.isEmpty() || (mbeans == null)) || mbeans.isEmpty()) {
            return;
        }

        for (String item : items) {
            for (ManagedBean mbean : mbeans) {
                if (item.equals(mbean.getName())) {
                    addManagedBean(mbean);

                    break;
                }
            }
        }
    }

    /**
     * Closes the Qpid server connection if not already closed and removes the server node from the navigation view and
     * also from the ini file stored in the system.
     * @throws Exception
     */
    public void removeServer() throws Exception {
        disconnect();

        // Remove from the Tree
        String serverNodeName = getSelectedServerNode().getName();
        List<TreeObject> list = _serversRootNode.getChildren();
        TreeObject objectToRemove = null;
        for (TreeObject child : list) {
            if (child.getName().equals(serverNodeName)) {
                objectToRemove = child;

                break;
            }
        }

        if (objectToRemove != null) {
            list.remove(objectToRemove);
        }

        _treeViewer.refresh();

        // Remove from the ini file
        removeServerFromConfigFile(serverNodeName);
    }

    private void removeServerFromConfigFile(String serverNodeName) {
        List<String> serversList = getServerListFromFile();
        serversList.remove(serverNodeName);

        String value = "";
        for (String item : serversList) {
            value += item + ",";
        }

        value = (value.lastIndexOf(",") != -1) ? value.substring(0, value.lastIndexOf(",")) : value;

        _preferences.putValue(INI_SERVERS, value);

        try {
            _preferences.save();
        } catch (IOException ex) {
            System.err.println("Error in updating the config file " + INI_FILENAME);
            System.out.println(ex);
        }
    }

    /**
     * @return the server addresses from the ini file
     * @throws Exception
     */
    private List<String> getServerListFromFile() {
        return getConfiguredItemsFromFile(INI_SERVERS);
    }

    /**
     * Returns the list of items from the config file.
     * sample ini file:
     * Servers=localhost:8999,127.0.0.1:8999
     * localhost.virtualhost1.Queues=queue1,queue2
     * localhost.virtualhost1.Exchanges=exchange1,exchange2
     * localhost.virtualhost2.Connections=conn1
     * @param key
     * @return
     */
    private List<String> getConfiguredItemsFromFile(String key) {
        List<String> list = new ArrayList<String>();
        String items = _preferences.getString(key);
        if (items.length() != 0) {
            String[] array = items.split(",");
            for (String item : array) {
                list.add(item);
            }
        }

        return list;
    }

    public TreeObject getSelectedServerNode() throws Exception {
        IStructuredSelection ss = (IStructuredSelection) _treeViewer.getSelection();
        TreeObject selectedNode = (TreeObject) ss.getFirstElement();
        if (ss.isEmpty() || (selectedNode == null) || (!selectedNode.getType().equals(NODE_TYPE_SERVER))) {
            throw new InfoRequiredException("Please select the server");
        }

        return selectedNode;
    }

    /**
     * This is a callback that will allow us to create the viewer and initialize
     * it.
     */
    public void createPartControl(Composite parent) {
        Composite composite = new Composite(parent, SWT.NONE);
        GridLayout gridLayout = new GridLayout();
        gridLayout.marginHeight = 2;
        gridLayout.marginWidth = 2;
        gridLayout.horizontalSpacing = 0;
        gridLayout.verticalSpacing = 2;
        composite.setLayout(gridLayout);

        createTreeViewer(composite);
        _serversRootNode = new TreeObject(NAVIGATION_ROOT, "ROOT");

        _treeViewer.setInput(_serversRootNode);
        // set viewer as selection event provider for MBeanView
        getSite().setSelectionProvider(_treeViewer);

        // Start worker thread to refresh tree for added or removed objects
        (new Thread(new Worker())).start();

        createConfigFile();
        _preferences = new PreferenceStore(INI_FILENAME);

        try {
            _preferences.load();
        } catch (IOException ex) {
            System.out.println(ex);
        }

        // load the list of servers already added from file
        List<String> serversList = getServerListFromFile();
        if (serversList != null) {
            for (String serverAddress : serversList) {
                String[] server = serverAddress.split(":");
                ManagedServer managedServer = new ManagedServer(server[0], Integer.parseInt(server[1]),
                        "org.wso2.andes");
                TreeObject serverNode = new TreeObject(serverAddress, NODE_TYPE_SERVER);
                serverNode.setManagedObject(managedServer);
                _serversRootNode.addChild(serverNode);
            }
        }

        _treeViewer.refresh();

    }

    /**
     * Passing the focus request to the viewer's control.
     */
    public void setFocus() {
    }

    public void refresh() {
        _treeViewer.refresh();
    }

    /**
     * Content provider class for the tree viewer
     */
    private static class ContentProviderImpl implements ITreeContentProvider {
        public Object[] getElements(Object parent) {
            return getChildren(parent);
        }

        public Object[] getChildren(final Object parentElement) {
            final TreeObject node = (TreeObject) parentElement;

            return node.getChildren().toArray(new TreeObject[0]);
        }

        public Object getParent(final Object element) {
            final TreeObject node = (TreeObject) element;

            return node.getParent();
        }

        public boolean hasChildren(final Object element) {
            final TreeObject node = (TreeObject) element;

            return !node.getChildren().isEmpty();
        }

        public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput) {
            // Do nothing
        }

        public void dispose() {
            // Do nothing
        }
    }

    /**
     * Label provider class for the tree viewer
     */
    private class LabelProviderImpl extends LabelProvider implements IFontProvider {
        public Image getImage(Object element) {
            TreeObject node = (TreeObject) element;
            if (node.getType().equals(NOTIFICATIONS)) {
                return ApplicationRegistry.getImage(NOTIFICATION_IMAGE);
            } else if (!node.getType().equals(MBEAN)) {
                if (_treeViewer.getExpandedState(node)) {
                    return ApplicationRegistry.getImage(OPEN_FOLDER_IMAGE);
                } else {
                    return ApplicationRegistry.getImage(CLOSED_FOLDER_IMAGE);
                }

            } else {
                ManagedObject obj = node.getManagedObject();
                if (obj instanceof ManagedBean) {
                    ManagedBean mbean = (ManagedBean) obj;
                    String mbeanType = mbean.getType();

                    if (mbeanType.equals(LoggingManagement.TYPE)) {
                        return ApplicationRegistry.getImage(LOGGING_MANAGEMENT_IMAGE);
                    } else if (mbeanType.equals(UserManagement.TYPE)) {
                        return ApplicationRegistry.getImage(USER_MANAGEMENT_IMAGE);
                    } else if (mbeanType.equals(ConfigurationManagement.TYPE)) {
                        return ApplicationRegistry.getImage(CONFIGURATION_MANAGEMENT_IMAGE);
                    } else if (mbeanType.equals(ServerInformation.TYPE)) {
                        return ApplicationRegistry.getImage(SERVER_INFO_IMAGE);
                    } else if (mbeanType.equals("VirtualHost.VirtualHostManager")) {
                        return ApplicationRegistry.getImage(VHOST_MANAGER_IMAGE);
                    } else {
                        return ApplicationRegistry.getImage(MBEAN_IMAGE);
                    }

                } else {
                    return ApplicationRegistry.getImage(MBEAN_IMAGE);
                }
            }
        }

        public String getText(Object element) {
            TreeObject node = (TreeObject) element;
            if (node.getType().equals(NODE_TYPE_MBEANTYPE)) {
                return node.getName() + "s";
            } else {
                return node.getName();
            }
        }

        public Font getFont(Object element) {
            TreeObject node = (TreeObject) element;
            if (node.getType().equals(NODE_TYPE_SERVER)) {
                if (node.getChildren().isEmpty()) {
                    return ApplicationRegistry.getFont(FONT_NORMAL);
                } else {
                    return ApplicationRegistry.getFont(FONT_BOLD);
                }
            }

            return ApplicationRegistry.getFont(FONT_NORMAL);
        }
    } // End of LabelProviderImpl

    private static class ViewerSorterImpl extends ViewerSorter {
        public int category(Object element) {
            TreeObject node = (TreeObject) element;
            if (node.getType().equals(MBEAN)) {
                return 1;
            }
            if (node.getType().equals(NOTIFICATIONS)) {
                return 2;
            }
            return 3;
        }
    }

    /**
     * Worker thread, which keeps looking for new ManagedObjects to be added and
     * unregistered objects to be removed from the tree.
     * @author Bhupendra Bhardwaj
     */
    private class Worker implements Runnable {
        public void run() {
            while (true) {
                if (!_managedServerMap.isEmpty()) {
                    refreshRemovedObjects();
                    refreshClosedServerConnections();
                }

                try {
                    Thread.sleep(2000);
                } catch (InterruptedException ex) {
                    //ignore
                }

            } // end of while loop
        } // end of run method.
    } // end of Worker class

    /**
     * Adds the mbean to the navigation tree
     * @param mbean mbean to add to the tree
     */
    public void addManagedBean(ManagedBean mbean) {
        TreeObject treeServerObject = _managedServerMap.get(mbean.getServer());
        addManagedBean(treeServerObject, mbean);
        _treeViewer.refresh();
    }

    private void refreshRemovedObjects() {
        for (ManagedServer server : _managedServerMap.keySet()) {
            final ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(server);
            if (serverRegistry == null) // server connection is closed
            {
                continue;
            }

            final List<ManagedBean> removalList = serverRegistry.getObjectsToBeRemoved();
            if (removalList != null) {
                Display display = getSite().getShell().getDisplay();
                display.syncExec(new Runnable() {
                    public void run() {
                        IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
                        final MBeanView view = (MBeanView) window.getActivePage().findView(MBeanView.ID);

                        for (ManagedBean mbean : removalList) {
                            TreeObject treeServerObject = _managedServerMap.get(mbean.getServer());

                            if (view != null) {
                                //notify the MBeanView in case the unregistered mbean is being viewed
                                view.mbeanUnregistered(mbean);
                            }

                            removeManagedObject(treeServerObject, mbean, false);
                        }

                        _treeViewer.refresh();
                    }
                });
            }
        }
    }

    /**
     * Gets the list of closed server connection from the ApplicationRegistry and then removes
     * the closed server nodes from the navigation view
     */
    private void refreshClosedServerConnections() {
        final List<ManagedServer> closedServers = ApplicationRegistry.getClosedServers();
        if (closedServers != null) {
            Display display = getSite().getShell().getDisplay();
            display.syncExec(new Runnable() {
                public void run() {
                    for (ManagedServer server : closedServers) {
                        if (server == null) {
                            continue;
                        }

                        TreeObject node = _managedServerMap.get(server);
                        if (node == null) {
                            continue;
                        }

                        removeManagedObject(node);
                        _managedServerMap.remove(server);
                        ApplicationRegistry.removeServer(server);
                    }

                    _treeViewer.refresh();
                }
            });
        }
    }

}