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 = (IStructuredSelection) event.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 = (Tree) event.widget;
0156 TreeItem[] items = widget.getSelection();
0157 if (items == null)
0158 {
0159 return;
0160 }
0161
0162 // Get the selected node
0163 final TreeObject selectedNode = (TreeObject) items[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, (ManagedBean) selectedNode.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 server) throws 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 = (ManagedBean) node.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 = (ManagedBean) node.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 serverNode) throws Exception
0414 {
0415 ManagedServer server = (ManagedServer) serverNode.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 domain) throws IOException, Exception
0447 {
0448 ManagedServer server = (ManagedServer) domain.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 = (ManagedServer) selectedNode.getManagedObject();
0721 disconnect(managedServer);
0722 }
0723
0724 private void disconnect(ManagedServer managedServer) throws 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 password) throws Exception
0748 {
0749 TreeObject selectedNode = getSelectedServerNode();
0750 ManagedServer managedServer = (ManagedServer) selectedNode.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 = (TreeObject) ss.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 = (TreeObject) parentElement;
1022
1023 return node.getChildren().toArray(new TreeObject[0]);
1024 }
1025
1026 public Object getParent(final Object element)
1027 {
1028 final TreeObject node = (TreeObject) element;
1029
1030 return node.getParent();
1031 }
1032
1033 public boolean hasChildren(final Object element)
1034 {
1035 final TreeObject node = (TreeObject) element;
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 = (TreeObject) element;
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 = (TreeObject) element;
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 = (TreeObject) element;
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 = (TreeObject) element;
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 }
|