NavigationView.java
0001 /*
0002  *
0003  * Licensed to the Apache Software Foundation (ASF) under one
0004  * or more contributor license agreements.  See the NOTICE file
0005  * distributed with this work for additional information
0006  * regarding copyright ownership.  The ASF licenses this file
0007  * to you under the Apache License, Version 2.0 (the
0008  * "License"); you may not use this file except in compliance
0009  * with the License.  You may obtain a copy of the License at
0010  *
0011  *   http://www.apache.org/licenses/LICENSE-2.0
0012  *
0013  * Unless required by applicable law or agreed to in writing,
0014  * software distributed under the License is distributed on an
0015  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
0016  * KIND, either express or implied.  See the License for the
0017  * specific language governing permissions and limitations
0018  * under the License.
0019  *
0020  */
0021 package org.apache.qpid.management.ui.views;
0022 
0023 import static org.apache.qpid.management.ui.Constants.*;
0024 
0025 import java.io.File;
0026 import java.io.IOException;
0027 import java.util.ArrayList;
0028 import java.util.HashMap;
0029 import java.util.List;
0030 
0031 import org.apache.qpid.management.ui.ApplicationRegistry;
0032 import org.apache.qpid.management.ui.ManagedBean;
0033 import org.apache.qpid.management.ui.ManagedServer;
0034 import org.apache.qpid.management.ui.ServerRegistry;
0035 import org.apache.qpid.management.ui.exceptions.InfoRequiredException;
0036 import org.apache.qpid.management.ui.jmx.JMXServerRegistry;
0037 import org.apache.qpid.management.ui.jmx.MBeanUtility;
0038 import org.eclipse.jface.preference.PreferenceStore;
0039 import org.eclipse.jface.viewers.DoubleClickEvent;
0040 import org.eclipse.jface.viewers.IDoubleClickListener;
0041 import org.eclipse.jface.viewers.IFontProvider;
0042 import org.eclipse.jface.viewers.IStructuredSelection;
0043 import org.eclipse.jface.viewers.ITreeContentProvider;
0044 import org.eclipse.jface.viewers.ITreeViewerListener;
0045 import org.eclipse.jface.viewers.LabelProvider;
0046 import org.eclipse.jface.viewers.StructuredSelection;
0047 import org.eclipse.jface.viewers.TreeExpansionEvent;
0048 import org.eclipse.jface.viewers.TreeViewer;
0049 import org.eclipse.jface.viewers.Viewer;
0050 import org.eclipse.jface.viewers.ViewerSorter;
0051 import org.eclipse.swt.SWT;
0052 import org.eclipse.swt.graphics.Font;
0053 import org.eclipse.swt.graphics.Image;
0054 import org.eclipse.swt.layout.GridData;
0055 import org.eclipse.swt.layout.GridLayout;
0056 import org.eclipse.swt.widgets.Composite;
0057 import org.eclipse.swt.widgets.Display;
0058 import org.eclipse.swt.widgets.Event;
0059 import org.eclipse.swt.widgets.Listener;
0060 import org.eclipse.swt.widgets.Menu;
0061 import org.eclipse.swt.widgets.MenuItem;
0062 import org.eclipse.swt.widgets.Shell;
0063 import org.eclipse.swt.widgets.Tree;
0064 import org.eclipse.swt.widgets.TreeItem;
0065 import org.eclipse.ui.part.ViewPart;
0066 
0067 /**
0068  * Navigation View for navigating the managed servers and managed beans on
0069  * those servers
0070  @author Bhupendra Bhardwaj
0071  */
0072 public class NavigationView extends ViewPart
0073 {
0074     public static final String ID = "org.apache.qpid.management.ui.navigationView";
0075     public static final String INI_FILENAME = System.getProperty("user.home"+ File.separator + "qpidManagementConsole.ini";
0076 
0077     private static final String INI_SERVERS = "Servers";
0078     private static final String INI_QUEUES = QUEUE + "s";
0079     private static final String INI_CONNECTIONS = CONNECTION + "s";
0080     private static final String INI_EXCHANGES = EXCHANGE + "s";
0081 
0082     private TreeViewer _treeViewer = null;
0083     private TreeObject _serversRootNode = null;
0084 
0085     private PreferenceStore _preferences;
0086     // Map of connected servers
0087     private HashMap<ManagedServer, TreeObject> _managedServerMap = new HashMap<ManagedServer, TreeObject>();
0088 
0089     private void createTreeViewer(Composite parent)
0090     {
0091         _treeViewer = new TreeViewer(parent);
0092         _treeViewer.setContentProvider(new ContentProviderImpl());
0093         _treeViewer.setLabelProvider(new LabelProviderImpl());
0094         _treeViewer.setSorter(new ViewerSorterImpl());
0095 
0096         // layout the tree viewer below the label field, to cover the area
0097         GridData layoutData = new GridData();
0098         layoutData = new GridData();
0099         layoutData.grabExcessHorizontalSpace = true;
0100         layoutData.grabExcessVerticalSpace = true;
0101         layoutData.horizontalAlignment = GridData.FILL;
0102         layoutData.verticalAlignment = GridData.FILL;
0103         _treeViewer.getControl().setLayoutData(layoutData);
0104         _treeViewer.setUseHashlookup(true);
0105 
0106         createListeners();
0107     }
0108 
0109     /**
0110      * Creates listeners for the JFace treeviewer
0111      */
0112     private void createListeners()
0113     {
0114         _treeViewer.addDoubleClickListener(new IDoubleClickListener()
0115             {
0116                 public void doubleClick(DoubleClickEvent event)
0117                 {
0118                     IStructuredSelection ss = (IStructuredSelectionevent.getSelection();
0119                     if ((ss == null|| (ss.getFirstElement() == null))
0120                     {
0121                         return;
0122                     }
0123 
0124                     boolean state = _treeViewer.getExpandedState(ss.getFirstElement());
0125                     _treeViewer.setExpandedState(ss.getFirstElement(), !state);
0126                 }
0127             });
0128 
0129         _treeViewer.addTreeListener(new ITreeViewerListener()
0130             {
0131                 public void treeExpanded(TreeExpansionEvent event)
0132                 {
0133                     _treeViewer.setExpandedState(event.getElement()true);
0134                     // Following will cause the selection event to be sent, so commented
0135                     // _treeViewer.setSelection(new StructuredSelection(event.getElement()));
0136                     _treeViewer.refresh();
0137                 }
0138 
0139                 public void treeCollapsed(TreeExpansionEvent event)
0140                 {
0141                     _treeViewer.setExpandedState(event.getElement()false);
0142                     _treeViewer.refresh();
0143                 }
0144             });
0145 
0146         // This listener is for popup menu, which pops up if a queue,exchange or connection is selected
0147         // with right click.
0148         _treeViewer.getTree().addListener(SWT.MenuDetect, new Listener()
0149             {
0150                 Display display = getSite().getShell().getDisplay();
0151                 final Shell shell = new Shell(display);
0152 
0153                 public void handleEvent(Event event)
0154                 {
0155                     Tree widget = (Treeevent.widget;
0156                     TreeItem[] items = widget.getSelection();
0157                     if (items == null)
0158                     {
0159                         return;
0160                     }
0161 
0162                     // Get the selected node
0163                     final TreeObject selectedNode = (TreeObjectitems[0].getData();
0164                     final TreeObject parentNode = selectedNode.getParent();
0165 
0166                     // This popup is only for mbeans and only connection,exchange and queue types
0167                     if ((parentNode == null|| !MBEAN.equals(selectedNode.getType())
0168                             || !(CONNECTION.equals(parentNode.getName()) || QUEUE.equals(parentNode.getName())
0169                                 || EXCHANGE.equals(parentNode.getName())))
0170                     {
0171                         return;
0172                     }
0173 
0174                     Menu menu = new Menu(shell, SWT.POP_UP);
0175                     MenuItem item = new MenuItem(menu, SWT.PUSH);
0176                     // Add the action item, which will remove the node from the tree if selected
0177                     item.setText(ACTION_REMOVE_MBEANNODE);
0178                     item.addListener(SWT.Selection, new Listener()
0179                         {
0180                             public void handleEvent(Event e)
0181                             {
0182                                 removeManagedObject(parentNode, (ManagedBeanselectedNode.getManagedObject());
0183                                 _treeViewer.refresh();
0184                                 // set the selection to the parent node
0185                                 _treeViewer.setSelection(new StructuredSelection(parentNode));
0186                             }
0187                         });
0188                     menu.setLocation(event.x, event.y);
0189                     menu.setVisible(true);
0190                     while (!menu.isDisposed() && menu.isVisible())
0191                     {
0192                         if (!display.readAndDispatch())
0193                         {
0194                             display.sleep();
0195                         }
0196                     }
0197 
0198                     menu.dispose();
0199                 }
0200             });
0201     }
0202 
0203     /**
0204      * Creates Qpid Server connection using JMX RMI protocol
0205      @param server
0206      @throws Exception
0207      */
0208     private void createRMIServerConnection(ManagedServer serverthrows Exception
0209     {
0210         // Currently Qpid Management Console only supports JMX MBeanServer
0211         ServerRegistry serverRegistry = new JMXServerRegistry(server);
0212         ApplicationRegistry.addServer(server, serverRegistry);
0213     }
0214 
0215     /**
0216      * Adds a new server node in the navigation view if server connection is successful.
0217      @param transportProtocol
0218      @param host
0219      @param port
0220      @param domain
0221      @throws Exception
0222      */
0223     public void addNewServer(String transportProtocol, String host, int port, String domain, String user, String pwd)
0224         throws Exception
0225     {
0226         String serverAddress = host + ":" + port;
0227         String url = null;
0228         ManagedServer managedServer = new ManagedServer(host, port, domain, user, pwd);
0229 
0230         if ("RMI".equals(transportProtocol))
0231         {
0232             url = managedServer.getUrl();
0233             List<TreeObject> list = _serversRootNode.getChildren();
0234             for (TreeObject node : list)
0235             {
0236                 ManagedServer nodeServer = (ManagedServer)node.getManagedObject();
0237                 if (url.equals(nodeServer.getUrl()))
0238                 {
0239                     // Server is already in the list of added servers, so now connect it.
0240                     // Set the server node as selected and then connect it.
0241                     _treeViewer.setSelection(new StructuredSelection(node));
0242                     reconnect(user, pwd);
0243 
0244                     return;
0245                 }
0246             }
0247 
0248             // The server is not in the list of already added servers, so now connect and add it.
0249             managedServer.setName(serverAddress);
0250             createRMIServerConnection(managedServer);
0251         }
0252         else
0253         {
0254             throw new InfoRequiredException(transportProtocol + " transport is not supported");
0255         }
0256 
0257         // Server connection is successful. Now add the server in the tree
0258         TreeObject serverNode = new TreeObject(serverAddress, NODE_TYPE_SERVER);
0259         serverNode.setManagedObject(managedServer);
0260         _serversRootNode.addChild(serverNode);
0261 
0262         // Add server in the connected server map
0263         _managedServerMap.put(managedServer, serverNode);
0264 
0265         // populate the server tree
0266         try
0267         {
0268             populateServer(serverNode);
0269         }
0270         catch (SecurityException ex)
0271         {
0272             disconnect(managedServer);
0273             throw ex;
0274         }
0275 
0276         // Add the Queue/Exchanges/Connections from config file into the navigation tree
0277         addConfiguredItems(managedServer);
0278 
0279         _treeViewer.refresh();
0280 
0281         // save server address in file
0282         addServerInConfigFile(serverAddress);
0283     }
0284 
0285     /**
0286      * Create the config file, if it doesn't already exist.
0287      * Exits the application if the file could not be created.
0288      */
0289     private void createConfigFile()
0290     {
0291         File file = new File(INI_FILENAME);
0292         try
0293         {
0294             if (!file.exists())
0295             {
0296                 file.createNewFile();
0297             }
0298         }
0299         catch (IOException ex)
0300         {
0301             System.out.println("Could not write to the file " + INI_FILENAME);
0302             System.out.println(ex);
0303             System.exit(1);
0304         }
0305     }
0306 
0307     /**
0308      * Server addresses are stored in a file. When user launches the application again, the
0309      * server addresses are picked up from the file and shown in the navigfation view. This method
0310      * adds the server address in a file, when a new server is added in the navigation view.
0311      @param serverAddress
0312      */
0313     private void addServerInConfigFile(String serverAddress)
0314     {
0315         // Check if the address already exists
0316         List<String> list = getServerListFromFile();
0317         if ((list != null&& list.contains(serverAddress))
0318         {
0319             return;
0320         }
0321 
0322         // Get the existing server list and add to that
0323         String servers = _preferences.getString(INI_SERVERS);
0324         String value = (servers.length() != 0(servers + "," + serverAddress: serverAddress;
0325         _preferences.putValue(INI_SERVERS, value);
0326         try
0327         {
0328             _preferences.save();
0329         }
0330         catch (IOException ex)
0331         {
0332             System.err.println("Could not add " + serverAddress + " in " + INI_SERVERS + " (" + INI_FILENAME + ")");
0333             System.out.println(ex);
0334         }
0335     }
0336 
0337     /**
0338      * Adds the item (Queue/Exchange/Connection) to the config file
0339      @param server
0340      @param virtualhost
0341      @param type - (Queue or Exchange or Connection)
0342      @param name - item name
0343      */
0344     private void addItemInConfigFile(TreeObject node)
0345     {
0346         ManagedBean mbean = (ManagedBeannode.getManagedObject();
0347         String server = mbean.getServer().getName();
0348         String virtualhost = mbean.getVirtualHostName();
0349         String type = node.getParent().getName() "s";
0350         String name = node.getName();
0351         String itemKey = server + "." + virtualhost + "." + type;
0352 
0353         // Check if the item already exists in the config file
0354         List<String> list = getConfiguredItemsFromFile(itemKey);
0355         if ((list != null&& list.contains(name))
0356         {
0357             return;
0358         }
0359 
0360         // Add this item to the existing list of items
0361         String items = _preferences.getString(itemKey);
0362         String value = (items.length() != 0(items + "," + name: name;
0363         _preferences.putValue(itemKey, value);
0364         try
0365         {
0366             _preferences.save();
0367         }
0368         catch (IOException ex)
0369         {
0370             System.err.println("Could not add " + name + " in " + itemKey + " (" + INI_FILENAME + ")");
0371             System.out.println(ex);
0372         }
0373     }
0374 
0375     private void removeItemFromConfigFile(TreeObject node)
0376     {
0377         ManagedBean mbean = (ManagedBeannode.getManagedObject();
0378         String server = mbean.getServer().getName();
0379         String vHost = mbean.getVirtualHostName();
0380         String type = node.getParent().getName() "s";
0381         String itemKey = server + "." + vHost + "." + type;
0382 
0383         List<String> list = getConfiguredItemsFromFile(itemKey);
0384         if (list.contains(node.getName()))
0385         {
0386             list.remove(node.getName());
0387             String value = "";
0388             for (String item : list)
0389             {
0390                 value += item + ",";
0391             }
0392 
0393             value = (value.lastIndexOf(","!= -1? value.substring(0, value.lastIndexOf(",")) : value;
0394 
0395             _preferences.putValue(itemKey, value);
0396             try
0397             {
0398                 _preferences.save();
0399             }
0400             catch (IOException ex)
0401             {
0402                 System.err.println("Error in updating the config file " + INI_FILENAME);
0403                 System.out.println(ex);
0404             }
0405         }
0406     }
0407 
0408     /**
0409      * Queries the qpid server for MBeans and populates the navigation view with all MBeans for
0410      * the given server node.
0411      @param serverNode
0412      */
0413     private void populateServer(TreeObject serverNodethrows Exception
0414     {
0415         ManagedServer server = (ManagedServerserverNode.getManagedObject();
0416         String domain = server.getDomain();
0417         if (!domain.equals(ALL))
0418         {
0419             TreeObject domainNode = new TreeObject(domain, NODE_TYPE_DOMAIN);
0420             domainNode.setParent(serverNode);
0421 
0422             populateDomain(domainNode);
0423         }
0424         else
0425         {
0426             List<TreeObject> domainList = new ArrayList<TreeObject>();
0427             List<String> domains = MBeanUtility.getAllDomains(server);
0428 
0429             for (String domainName : domains)
0430             {
0431                 TreeObject domainNode = new TreeObject(domainName, NODE_TYPE_DOMAIN);
0432                 domainNode.setParent(serverNode);
0433 
0434                 domainList.add(domainNode);
0435                 populateDomain(domainNode);
0436             }
0437         }
0438     }
0439 
0440     /**
0441      * Queries the Qpid Server and populates the given domain node with all MBeans undser that domain.
0442      @param domain
0443      @throws IOException
0444      @throws Exception
0445      */
0446     private void populateDomain(TreeObject domainthrows IOException, Exception
0447     {
0448         ManagedServer server = (ManagedServerdomain.getParent().getManagedObject();
0449 
0450         // Now populate the mbenas under those types
0451         List<ManagedBean> mbeans = MBeanUtility.getManagedObjectsForDomain(server, domain.getName());
0452         for (ManagedBean mbean : mbeans)
0453         {
0454             mbean.setServer(server);
0455             ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(server);
0456             serverRegistry.addManagedObject(mbean);
0457 
0458             // Add all mbeans other than Connections, Exchanges and Queues. Because these will be added
0459             // manually by selecting from MBeanView
0460             if (!(mbean.isConnection() || mbean.isExchange() || mbean.isQueue()))
0461             {
0462                 addManagedBean(domain, mbean);
0463             }
0464         }
0465         // To make it work with the broker without virtual host implementation.
0466         // This will add the default nodes to the domain node
0467         boolean hasVirtualHost = false;
0468         for (TreeObject child : domain.getChildren())
0469         {
0470             if (child.getName().startsWith(VIRTUAL_HOST))
0471             {
0472                 hasVirtualHost = true;
0473                 break;      
0474             }
0475         }
0476         
0477         if (!hasVirtualHost){
0478             addDefaultNodes(domain);
0479         }
0480     }
0481 
0482     /**
0483      * Add these three types - Connection, Exchange, Queue
0484      * By adding these, these will always be available, even if there are no mbeans under thse types
0485      * This is required because, the mbeans will be added from mbeanview, by selecting from the list
0486      @param parent Node
0487      */
0488     private void addDefaultNodes(TreeObject parent)
0489     {
0490         TreeObject typeChild = new TreeObject(CONNECTION, NODE_TYPE_MBEANTYPE);
0491         typeChild.setParent(parent);
0492         typeChild.setVirtualHost(parent.getVirtualHost());
0493         typeChild = new TreeObject(EXCHANGE, NODE_TYPE_MBEANTYPE);
0494         typeChild.setParent(parent);
0495         typeChild.setVirtualHost(parent.getVirtualHost());
0496         typeChild = new TreeObject(QUEUE, NODE_TYPE_MBEANTYPE);
0497         typeChild.setParent(parent);
0498         typeChild.setVirtualHost(parent.getVirtualHost());
0499         
0500         // Add common notification node for virtual host
0501         TreeObject notificationNode = new TreeObject(NOTIFICATIONS, NOTIFICATIONS);
0502         notificationNode.setParent(parent);
0503         notificationNode.setVirtualHost(parent.getVirtualHost());
0504     }
0505 
0506     /**
0507      * Checks if a particular mbeantype is already there in the navigation view for a domain.
0508      * This is used while populating domain with mbeans.
0509      @param parent
0510      @param typeName
0511      @return Node if given mbeantype already exists, otherwise null
0512      */
0513     private TreeObject getMBeanTypeNode(TreeObject parent, String typeName)
0514     {
0515         List<TreeObject> childNodes = parent.getChildren();
0516         for (TreeObject child : childNodes)
0517         {
0518             if ((NODE_TYPE_MBEANTYPE.equals(child.getType()) || NODE_TYPE_TYPEINSTANCE.equals(child.getType()))
0519                     && typeName.equals(child.getName()))
0520             {
0521                 return child;
0522             }
0523         }
0524 
0525         return null;
0526     }
0527 
0528     private boolean doesMBeanNodeAlreadyExist(TreeObject typeNode, String mbeanName)
0529     {
0530         List<TreeObject> childNodes = typeNode.getChildren();
0531         for (TreeObject child : childNodes)
0532         {
0533             if (MBEAN.equals(child.getType()) && mbeanName.equals(child.getName()))
0534             {
0535                 return true;
0536             }
0537         }
0538 
0539         return false;
0540     }
0541 
0542     /**
0543      * Adds the given MBean to the given domain node. Creates Notification node for the MBean.
0544      * sample ObjectNames -
0545      * org.apache.qpid:type=VirtualHost.VirtualHostManager,VirtualHost=localhost
0546      * org.apache.qpid:type=VirtualHost.Queue,VirtualHost=test,name=ping_1
0547      @param domain
0548      @param mbean
0549      @throws Exception
0550      */
0551     private void addManagedBean(TreeObject domain, ManagedBean mbean// throws Exception
0552     {
0553         String name = mbean.getName();
0554         // Split the mbean type into array of Strings, to create hierarchy
0555         // eg. type=VirtualHost.VirtualHostManager,VirtualHost=localhost will be:
0556         // localhost->VirtualHostManager
0557         // eg. type=org.apache.qpid:type=VirtualHost.Queue,VirtualHost=test,name=ping will be:
0558         // test->Queue->ping
0559         String[] types = mbean.getType().split("\\.");
0560         TreeObject typeNode = null;
0561         TreeObject parentNode = domain;
0562 
0563         // Run this loop till all nodes(hierarchy) for this mbean are created. This loop only creates
0564         // all the required parent nodes for the mbean
0565         for (int i = 0; i < types.length; i++)
0566         {
0567             String type = types[i];
0568             String valueOftype = mbean.getProperty(type);
0569             // If value is not null, then there will be a parent node for this mbean
0570             // eg. for type=VirtualHost the value is "test"
0571             typeNode = getMBeanTypeNode(parentNode, type);
0572 
0573             // create the type node if not already created
0574             if (typeNode == null)
0575             {
0576                 // If the ObjectName doesn't have name property, that means there will be only one instance
0577                 // of this mbean for given "type". So there will be no type node created for this mbean.
0578                 if ((name == null&& (i == (types.length - 1)))
0579                 {
0580                     break;
0581                 }
0582 
0583                 // create a node for "type"
0584                 typeNode = createTypeNode(parentNode, type);
0585                 if (!type.equals(VIRTUAL_HOST))
0586                 {
0587                     typeNode.setVirtualHost(mbean.getVirtualHostName());
0588                 }
0589             }
0590 
0591             // now type node create becomes the parent node for next node in hierarchy
0592             parentNode = typeNode;
0593 
0594             /*
0595              * Now create instances node for this type if value exists.
0596              */
0597             if (valueOftype == null)
0598             {
0599                 // No instance node will be created when value is null (eg type=Queue)
0600                 break;
0601             }
0602 
0603             // For different virtual hosts, the nodes with given value will be created.
0604             // eg type=VirtualHost, value=test
0605             typeNode = getMBeanTypeNode(parentNode, valueOftype);
0606             if (typeNode == null)
0607             {
0608                 typeNode = createTypeInstanceNode(parentNode, valueOftype);
0609                 typeNode.setVirtualHost(mbean.getVirtualHostName());
0610 
0611                 // Create default nodes for VHost instances
0612                 if (type.equals(VIRTUAL_HOST))
0613                 {
0614                     addDefaultNodes(typeNode);
0615                 }
0616             }
0617 
0618             parentNode = typeNode;
0619         }
0620 
0621         if (typeNode == null)
0622         {
0623             typeNode = parentNode;
0624         }
0625 
0626         // Check if an MBean is already added
0627         if (doesMBeanNodeAlreadyExist(typeNode, name))
0628         {
0629             return;
0630         }
0631 
0632         // Add the mbean node now
0633         TreeObject mbeanNode = new TreeObject(mbean);
0634         mbeanNode.setParent(typeNode);
0635 
0636         // Add the mbean to the config file
0637         if (mbean.isQueue() || mbean.isExchange() || mbean.isConnection())
0638         {
0639             addItemInConfigFile(mbeanNode);
0640         }
0641 
0642         // Add notification node
0643         // TODO: show this only if the mbean sends any notification
0644         //TreeObject notificationNode = new TreeObject(NOTIFICATION, NOTIFICATION);
0645         //notificationNode.setParent(mbeanNode);
0646     }
0647 
0648     private TreeObject createTypeNode(TreeObject parent, String name)
0649     {
0650         TreeObject typeNode = new TreeObject(name, NODE_TYPE_MBEANTYPE);
0651         typeNode.setParent(parent);
0652 
0653         return typeNode;
0654     }
0655 
0656     private TreeObject createTypeInstanceNode(TreeObject parent, String name)
0657     {
0658         TreeObject typeNode = new TreeObject(name, NODE_TYPE_TYPEINSTANCE);
0659         typeNode.setParent(parent);
0660 
0661         return typeNode;
0662     }
0663 
0664     /**
0665      * Removes all the child nodes of the given parent node. Used when closing a server.
0666      @param parent
0667      */
0668     private void removeManagedObject(TreeObject parent)
0669     {
0670         List<TreeObject> list = parent.getChildren();
0671         for (TreeObject child : list)
0672         {
0673             removeManagedObject(child);
0674         }
0675 
0676         list.clear();
0677     }
0678 
0679     /**
0680      * Removes the mbean from the tree
0681      @param parent
0682      @param mbean
0683      */
0684     private void removeManagedObject(TreeObject parent, ManagedBean mbean)
0685     {
0686         List<TreeObject> list = parent.getChildren();
0687         TreeObject objectToRemove = null;
0688         for (TreeObject child : list)
0689         {
0690             if (MBEAN.equals(child.getType()))
0691             {
0692                 String name = (mbean.getName() != null? mbean.getName() : mbean.getType();
0693                 if (child.getName().equals(name))
0694                 {
0695                     objectToRemove = child;
0696 
0697                     break;
0698                 }
0699             }
0700             else
0701             {
0702                 removeManagedObject(child, mbean);
0703             }
0704         }
0705 
0706         if (objectToRemove != null)
0707         {
0708             list.remove(objectToRemove);
0709             removeItemFromConfigFile(objectToRemove);
0710         }
0711 
0712     }
0713 
0714     /**
0715      * Closes the Qpid server connection
0716      */
0717     public void disconnect() throws Exception
0718     {
0719         TreeObject selectedNode = getSelectedServerNode();
0720         ManagedServer managedServer = (ManagedServerselectedNode.getManagedObject();
0721         disconnect(managedServer);
0722     }
0723     
0724     private void disconnect(ManagedServer managedServerthrows Exception
0725     {
0726         if (!_managedServerMap.containsKey(managedServer))
0727         {
0728             return;
0729         }
0730 
0731         // Close server connection
0732         ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(managedServer);
0733         if (serverRegistry == null// server connection is already closed
0734         {
0735             return;
0736         }
0737 
0738         serverRegistry.closeServerConnection();
0739         // Add server to the closed server list and the worker thread will remove the server from required places.
0740         ApplicationRegistry.serverConnectionClosed(managedServer);
0741     }
0742 
0743     /**
0744      * Connects the selected server node
0745      @throws Exception
0746      */
0747     public void reconnect(String user, String passwordthrows Exception
0748     {
0749         TreeObject selectedNode = getSelectedServerNode();
0750         ManagedServer managedServer = (ManagedServerselectedNode.getManagedObject();
0751         if (_managedServerMap.containsKey(managedServer))
0752         {
0753             throw new InfoRequiredException("Server " + managedServer.getName() " is already connected");
0754         }
0755 
0756         managedServer.setUser(user);
0757         managedServer.setPassword(password);
0758         createRMIServerConnection(managedServer);
0759 
0760         // put the server in the managed server map
0761         _managedServerMap.put(managedServer, selectedNode);
0762 
0763         try
0764         {
0765             // populate the server tree now
0766             populateServer(selectedNode);
0767         }
0768         catch (SecurityException ex)
0769         {
0770             disconnect(managedServer);
0771             throw ex;
0772         }
0773         
0774 
0775         // Add the Queue/Exchanges/Connections from config file into the navigation tree
0776         addConfiguredItems(managedServer);
0777 
0778         _treeViewer.refresh();
0779     }
0780 
0781     /**
0782      * Adds the items(queues/exchanges/connectins) from config file to the server tree
0783      @param server
0784      */
0785     private void addConfiguredItems(ManagedServer server)
0786     {
0787         ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(server);
0788         List<String> list = serverRegistry.getVirtualHosts();
0789         for (String virtualHost : list)
0790         {
0791             // Add Queues
0792             String itemKey = server.getName() "." + virtualHost + "." + INI_QUEUES;
0793             List<String> items = getConfiguredItemsFromFile(itemKey);
0794             List<ManagedBean> mbeans = serverRegistry.getQueues(virtualHost);
0795             addConfiguredItems(items, mbeans);
0796 
0797             // Add Exchanges
0798             itemKey = server.getName() "." + virtualHost + "." + INI_EXCHANGES;
0799             items = getConfiguredItemsFromFile(itemKey);
0800             mbeans = serverRegistry.getExchanges(virtualHost);
0801             addConfiguredItems(items, mbeans);
0802 
0803             // Add Connections
0804             itemKey = server.getName() "." + virtualHost + "." + INI_CONNECTIONS;
0805             items = getConfiguredItemsFromFile(itemKey);
0806             mbeans = serverRegistry.getConnections(virtualHost);
0807             addConfiguredItems(items, mbeans);
0808         }
0809     }
0810 
0811     /**
0812      * Gets the mbeans corresponding to the items and adds those to the navigation tree
0813      @param items
0814      @param mbeans
0815      */
0816     private void addConfiguredItems(List<String> items, List<ManagedBean> mbeans)
0817     {
0818         if ((items == null|| (items.isEmpty() (mbeans == null)) || mbeans.isEmpty())
0819         {
0820             return;
0821         }
0822 
0823         for (String item : items)
0824         {
0825             for (ManagedBean mbean : mbeans)
0826             {
0827                 if (item.equals(mbean.getName()))
0828                 {
0829                     addManagedBean(mbean);
0830 
0831                     break;
0832                 }
0833             }
0834         }
0835     }
0836 
0837     /**
0838      * Closes the Qpid server connection if not already closed and removes the server node from the navigation view and
0839      * also from the ini file stored in the system.
0840      @throws Exception
0841      */
0842     public void removeServer() throws Exception
0843     {
0844         disconnect();
0845 
0846         // Remove from the Tree
0847         String serverNodeName = getSelectedServerNode().getName();
0848         List<TreeObject> list = _serversRootNode.getChildren();
0849         TreeObject objectToRemove = null;
0850         for (TreeObject child : list)
0851         {
0852             if (child.getName().equals(serverNodeName))
0853             {
0854                 objectToRemove = child;
0855 
0856                 break;
0857             }
0858         }
0859 
0860         if (objectToRemove != null)
0861         {
0862             list.remove(objectToRemove);
0863         }
0864 
0865         _treeViewer.refresh();
0866 
0867         // Remove from the ini file
0868         removeServerFromConfigFile(serverNodeName);
0869     }
0870 
0871     private void removeServerFromConfigFile(String serverNodeName)
0872     {
0873         List<String> serversList = getServerListFromFile();
0874         serversList.remove(serverNodeName);
0875 
0876         String value = "";
0877         for (String item : serversList)
0878         {
0879             value += item + ",";
0880         }
0881 
0882         value = (value.lastIndexOf(","!= -1? value.substring(0, value.lastIndexOf(",")) : value;
0883 
0884         _preferences.putValue(INI_SERVERS, value);
0885 
0886         try
0887         {
0888             _preferences.save();
0889         }
0890         catch (IOException ex)
0891         {
0892             System.err.println("Error in updating the config file " + INI_FILENAME);
0893             System.out.println(ex);
0894         }
0895     }
0896 
0897     /**
0898      @return the server addresses from the ini file
0899      @throws Exception
0900      */
0901     private List<String> getServerListFromFile()
0902     {
0903         return getConfiguredItemsFromFile(INI_SERVERS);
0904     }
0905 
0906     /**
0907      * Returns the list of items from the config file.
0908      * sample ini file:
0909      * Servers=localhost:8999,127.0.0.1:8999
0910      * localhost.virtualhost1.Queues=queue1,queue2
0911      * localhost.virtualhost1.Exchanges=exchange1,exchange2
0912      * localhost.virtualhost2.Connections=conn1
0913      @param key
0914      @return
0915      */
0916     private List<String> getConfiguredItemsFromFile(String key)
0917     {
0918         List<String> list = new ArrayList<String>();
0919         String items = _preferences.getString(key);
0920         if (items.length() != 0)
0921         {
0922             String[] array = items.split(",");
0923             for (String item : array)
0924             {
0925                 list.add(item);
0926             }
0927         }
0928 
0929         return list;
0930     }
0931 
0932     public TreeObject getSelectedServerNode() throws Exception
0933     {
0934         IStructuredSelection ss = (IStructuredSelection_treeViewer.getSelection();
0935         TreeObject selectedNode = (TreeObjectss.getFirstElement();
0936         if (ss.isEmpty() || (selectedNode == null|| (!selectedNode.getType().equals(NODE_TYPE_SERVER)))
0937         {
0938             throw new InfoRequiredException("Please select the server");
0939         }
0940 
0941         return selectedNode;
0942     }
0943 
0944     /**
0945      * This is a callback that will allow us to create the viewer and initialize
0946      * it.
0947      */
0948     public void createPartControl(Composite parent)
0949     {
0950         Composite composite = new Composite(parent, SWT.NONE);
0951         GridLayout gridLayout = new GridLayout();
0952         gridLayout.marginHeight = 2;
0953         gridLayout.marginWidth = 2;
0954         gridLayout.horizontalSpacing = 0;
0955         gridLayout.verticalSpacing = 2;
0956         composite.setLayout(gridLayout);
0957 
0958         createTreeViewer(composite);
0959         _serversRootNode = new TreeObject(NAVIGATION_ROOT, "ROOT");
0960 
0961         _treeViewer.setInput(_serversRootNode);
0962         // set viewer as selection event provider for MBeanView
0963         getSite().setSelectionProvider(_treeViewer);
0964 
0965         // Start worker thread to refresh tree for added or removed objects
0966         (new Thread(new Worker())).start();
0967 
0968         createConfigFile();
0969         _preferences = new PreferenceStore(INI_FILENAME);
0970 
0971         try
0972         {
0973             _preferences.load();
0974         }
0975         catch (IOException ex)
0976         {
0977             System.out.println(ex);
0978         }
0979 
0980         // load the list of servers already added from file
0981         List<String> serversList = getServerListFromFile();
0982         if (serversList != null)
0983         {
0984             for (String serverAddress : serversList)
0985             {
0986                 String[] server = serverAddress.split(":");
0987                 ManagedServer managedServer = new ManagedServer(server[0], Integer.parseInt(server[1])"org.apache.qpid");
0988                 TreeObject serverNode = new TreeObject(serverAddress, NODE_TYPE_SERVER);
0989                 serverNode.setManagedObject(managedServer);
0990                 _serversRootNode.addChild(serverNode);
0991             }
0992         }
0993 
0994         _treeViewer.refresh();
0995 
0996     }
0997 
0998     /**
0999      * Passing the focus request to the viewer's control.
1000      */
1001     public void setFocus()
1002     { }
1003 
1004     public void refresh()
1005     {
1006         _treeViewer.refresh();
1007     }
1008 
1009     /**
1010      * Content provider class for the tree viewer
1011      */
1012     private class ContentProviderImpl implements ITreeContentProvider
1013     {
1014         public Object[] getElements(Object parent)
1015         {
1016             return getChildren(parent);
1017         }
1018 
1019         public Object[] getChildren(final Object parentElement)
1020         {
1021             final TreeObject node = (TreeObjectparentElement;
1022 
1023             return node.getChildren().toArray(new TreeObject[0]);
1024         }
1025 
1026         public Object getParent(final Object element)
1027         {
1028             final TreeObject node = (TreeObjectelement;
1029 
1030             return node.getParent();
1031         }
1032 
1033         public boolean hasChildren(final Object element)
1034         {
1035             final TreeObject node = (TreeObjectelement;
1036 
1037             return !node.getChildren().isEmpty();
1038         }
1039 
1040         public void inputChanged(final Viewer viewer, final Object oldInput, final Object newInput)
1041         {
1042             // Do nothing
1043         }
1044 
1045         public void dispose()
1046         {
1047             // Do nothing
1048         }
1049     }
1050 
1051     /**
1052      * Label provider class for the tree viewer
1053      */
1054     private class LabelProviderImpl extends LabelProvider implements IFontProvider
1055     {
1056         public Image getImage(Object element)
1057         {
1058             TreeObject node = (TreeObjectelement;
1059             if (node.getType().equals(NOTIFICATIONS))
1060             {
1061                 return ApplicationRegistry.getImage(NOTIFICATION_IMAGE);
1062             }
1063             else if (!node.getType().equals(MBEAN))
1064             {
1065                 if (_treeViewer.getExpandedState(node))
1066                 {
1067                     return ApplicationRegistry.getImage(OPEN_FOLDER_IMAGE);
1068                 }
1069                 else
1070                 {
1071                     return ApplicationRegistry.getImage(CLOSED_FOLDER_IMAGE);
1072                 }
1073 
1074             }
1075             else
1076             {
1077                 return ApplicationRegistry.getImage(MBEAN_IMAGE);
1078             }
1079         }
1080 
1081         public String getText(Object element)
1082         {
1083             TreeObject node = (TreeObjectelement;
1084             if (node.getType().equals(NODE_TYPE_MBEANTYPE))
1085             {
1086                 return node.getName() "s";
1087             }
1088             else
1089             {
1090                 return node.getName();
1091             }
1092         }
1093 
1094         public Font getFont(Object element)
1095         {
1096             TreeObject node = (TreeObjectelement;
1097             if (node.getType().equals(NODE_TYPE_SERVER))
1098             {
1099                 if (node.getChildren().isEmpty())
1100                 {
1101                     return ApplicationRegistry.getFont(FONT_NORMAL);
1102                 }
1103                 else
1104                 {
1105                     return ApplicationRegistry.getFont(FONT_BOLD);
1106                 }
1107             }
1108 
1109             return ApplicationRegistry.getFont(FONT_NORMAL);
1110         }
1111     // End of LabelProviderImpl
1112 
1113     private class ViewerSorterImpl extends ViewerSorter
1114     {
1115         public int category(Object element)
1116         {
1117             TreeObject node = (TreeObjectelement;
1118             if (node.getType().equals(MBEAN))
1119             {
1120                 return 1;
1121             }
1122             if (node.getType().equals(NOTIFICATIONS))
1123             {
1124                 return 2;
1125             }
1126             return 3;
1127         }
1128     }
1129 
1130     /**
1131      * Worker thread, which keeps looking for new ManagedObjects to be added and
1132      * unregistered objects to be removed from the tree.
1133      @author Bhupendra Bhardwaj
1134      */
1135     private class Worker implements Runnable
1136     {
1137         public void run()
1138         {
1139             while (true)
1140             {
1141                 if (!_managedServerMap.isEmpty())
1142                 {
1143                     refreshRemovedObjects();
1144                     refreshClosedServerConnections();
1145                 }
1146 
1147                 try
1148                 {
1149                     Thread.sleep(3000);
1150                 }
1151                 catch (Exception ex)
1152                 { }
1153 
1154             // end of while loop
1155         // end of run method.
1156     // end of Worker class
1157 
1158     /**
1159      * Adds the mbean to the navigation tree
1160      @param mbean
1161      @throws Exception
1162      */
1163     public void addManagedBean(ManagedBean mbean// throws Exception
1164     {
1165         TreeObject treeServerObject = _managedServerMap.get(mbean.getServer());
1166         List<TreeObject> domains = treeServerObject.getChildren();
1167         TreeObject domain = null;
1168         for (TreeObject child : domains)
1169         {
1170             if (child.getName().equals(mbean.getDomain()))
1171             {
1172                 domain = child;
1173 
1174                 break;
1175             }
1176         }
1177 
1178         addManagedBean(domain, mbean);
1179         _treeViewer.refresh();
1180     }
1181 
1182     private void refreshRemovedObjects()
1183     {
1184         for (ManagedServer server : _managedServerMap.keySet())
1185         {
1186             final ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(server);
1187             if (serverRegistry == null// server connection is closed
1188             {
1189                 continue;
1190             }
1191 
1192             final List<ManagedBean> removalList = serverRegistry.getObjectsToBeRemoved();
1193             if (removalList != null)
1194             {
1195                 Display display = getSite().getShell().getDisplay();
1196                 display.syncExec(new Runnable()
1197                     {
1198                         public void run()
1199                         {
1200                             for (ManagedBean mbean : removalList)
1201                             {
1202                                 TreeObject treeServerObject = _managedServerMap.get(mbean.getServer());
1203                                 List<TreeObject> domains = treeServerObject.getChildren();
1204                                 TreeObject domain = null;
1205                                 for (TreeObject child : domains)
1206                                 {
1207                                     if (child.getName().equals(mbean.getDomain()))
1208                                     {
1209                                         domain = child;
1210 
1211                                         break;
1212                                     }
1213                                 }
1214 
1215                                 removeManagedObject(domain, mbean);
1216                                 // serverRegistry.removeManagedObject(mbean);
1217                             }
1218 
1219                             _treeViewer.refresh();
1220                         }
1221                     });
1222             }
1223         }
1224     }
1225 
1226     /**
1227      * Gets the list of closed server connection from the ApplicationRegistry and then removes
1228      * the closed server nodes from the navigation view
1229      */
1230     private void refreshClosedServerConnections()
1231     {
1232         final List<ManagedServer> closedServers = ApplicationRegistry.getClosedServers();
1233         if (closedServers != null)
1234         {
1235             Display display = getSite().getShell().getDisplay();
1236             display.syncExec(new Runnable()
1237                 {
1238                     public void run()
1239                     {
1240                         for (ManagedServer server : closedServers)
1241                         {
1242                             removeManagedObject(_managedServerMap.get(server));
1243                             _managedServerMap.remove(server);
1244                             ApplicationRegistry.removeServer(server);
1245                         }
1246 
1247                         _treeViewer.refresh();
1248                     }
1249                 });
1250         }
1251     }
1252 
1253 }