/* * * 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.apache.qpid.management.ui.views.exchange; import static org.apache.qpid.management.common.mbeans.ManagedExchange.HDR_BINDING_NUMBER; import static org.apache.qpid.management.common.mbeans.ManagedExchange.HDR_QUEUE_BINDINGS; import static org.apache.qpid.management.common.mbeans.ManagedExchange.HDR_QUEUE_NAME; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import javax.management.MBeanServerConnection; import javax.management.MBeanServerInvocationHandler; import javax.management.openmbean.CompositeData; import javax.management.openmbean.CompositeDataSupport; import javax.management.openmbean.TabularDataSupport; import org.apache.qpid.management.ui.ApplicationRegistry; import org.apache.qpid.management.ui.ManagedBean; import org.apache.qpid.management.ui.ServerRegistry; import org.apache.qpid.management.common.mbeans.ManagedExchange; import org.apache.qpid.management.ui.jmx.JMXManagedObject; import org.apache.qpid.management.ui.jmx.MBeanUtility; import org.apache.qpid.management.ui.views.MBeanView; import org.apache.qpid.management.ui.views.TabControl; import org.apache.qpid.management.ui.views.ViewUtility; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.IStructuredContentProvider; import org.eclipse.jface.viewers.ITableLabelProvider; import org.eclipse.jface.viewers.LabelProvider; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.TableViewer; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.viewers.ViewerSorter; import org.eclipse.swt.SWT; import org.eclipse.swt.custom.ScrolledComposite; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Combo; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.TabFolder; import org.eclipse.swt.widgets.Table; import org.eclipse.swt.widgets.TableColumn; import org.eclipse.swt.widgets.Text; import org.eclipse.ui.IWorkbenchWindow; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.forms.widgets.FormToolkit; import org.eclipse.ui.forms.widgets.ScrolledForm; /** * Control class for the Headers Exchange mbean Operations tab. */ public class HeadersExchangeOperationsTabControl extends TabControl { private FormToolkit _toolkit; private ScrolledForm _form; private Table _bindingNumberTable = null; private TableViewer _bindingNumberTableViewer = null; private Table _headersTable = null; private TableViewer _headersTableViewer = null; private Composite _paramsComposite = null; private TabularDataSupport _bindings = null; private ManagedExchange _emb; public HeadersExchangeOperationsTabControl(TabFolder tabFolder, JMXManagedObject mbean, MBeanServerConnection mbsc) { super(tabFolder); _mbean = mbean; _emb = (ManagedExchange) MBeanServerInvocationHandler.newProxyInstance(mbsc, mbean.getObjectName(), ManagedExchange.class, false); _toolkit = new FormToolkit(_tabFolder.getDisplay()); _form = _toolkit.createScrolledForm(_tabFolder); _form.getBody().setLayout(new GridLayout()); createComposites(); createWidgets(); } private void createComposites() { _paramsComposite = _toolkit.createComposite(_form.getBody(), SWT.NONE); _paramsComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); _paramsComposite.setLayout(new GridLayout()); } /** * @see TabControl#getControl() */ public Control getControl() { return _form; } /** * @see TabControl#setFocus() */ public void setFocus() { _bindingNumberTable.setFocus(); } @Override public void refresh(ManagedBean mbean) { _bindings = null; try { //gather a list of all keys and queues for display and selection _bindings = (TabularDataSupport) _emb.bindings(); } catch (Exception e) { MBeanUtility.handleException(_mbean,e); } _bindingNumberTableViewer.setInput(_bindings); layout(); } public void layout() { _form.layout(true); _form.getBody().layout(true, true); } private void createWidgets() { Group bindingsGroup = new Group(_paramsComposite, SWT.SHADOW_NONE); bindingsGroup.setBackground(_paramsComposite.getBackground()); bindingsGroup.setText("Bindings"); bindingsGroup.setLayout(new GridLayout(2,false)); GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true); bindingsGroup.setLayoutData(gridData); Composite tablesComposite = _toolkit.createComposite(bindingsGroup); gridData = new GridData(SWT.FILL, SWT.FILL, true, true); gridData.minimumHeight = 250; gridData.heightHint = 250; tablesComposite.setLayoutData(gridData); tablesComposite.setLayout(new GridLayout(2,false)); //table of bindings for the exchange _bindingNumberTable = new Table (tablesComposite, SWT.SINGLE | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION); _bindingNumberTable.setLinesVisible(true); _bindingNumberTable.setHeaderVisible(true); GridData data = new GridData(SWT.FILL, SWT.FILL, true, true); data.minimumHeight = 300; data.heightHint = 300; _bindingNumberTable.setLayoutData(data); _bindingNumberTableViewer = new TableViewer(_bindingNumberTable); final TableSorter tableSorter = new TableSorter(HDR_BINDING_NUMBER); String[] titles = {"Binding Number", "Queue Name"}; int[] bounds = {135, 175}; for (int i = 0; i < titles.length; i++) { final int index = i; final TableColumn column = new TableColumn (_bindingNumberTable, SWT.NONE); column.setText(titles[i]); column.setWidth(bounds[i]); column.setResizable(true); //Setting the right sorter column.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { tableSorter.setColumn(index); final TableViewer viewer = _bindingNumberTableViewer; int dir = viewer .getTable().getSortDirection(); if (viewer.getTable().getSortColumn() == column) { dir = dir == SWT.UP ? SWT.DOWN : SWT.UP; } else { dir = SWT.UP; } viewer.getTable().setSortDirection(dir); viewer.getTable().setSortColumn(column); viewer.refresh(); } }); } _bindingNumberTableViewer.setContentProvider(new ContentProviderImpl(HDR_BINDING_NUMBER)); _bindingNumberTableViewer.setLabelProvider(new LabelProviderImpl(HDR_BINDING_NUMBER)); _bindingNumberTableViewer.setSorter(tableSorter); _bindingNumberTable.setSortColumn(_bindingNumberTable.getColumn(0)); _bindingNumberTable.setSortDirection(SWT.UP); //table of header bindings _headersTable = new Table (tablesComposite, SWT.SINGLE | SWT.SCROLL_LINE | SWT.BORDER | SWT.FULL_SELECTION); _headersTable.setLinesVisible (true); _headersTable.setHeaderVisible (true); data = new GridData(SWT.FILL, SWT.FILL, true, true); data.minimumHeight = 300; data.heightHint = 300; _headersTable.setLayoutData(data); _headersTableViewer = new TableViewer(_headersTable); final TableSorter queuesTableSorter = new TableSorter(HDR_QUEUE_BINDINGS); titles = new String[]{"Header Bindings"}; bounds = new int[]{225}; for (int i = 0; i < titles.length; i++) { final int index = i; final TableColumn column = new TableColumn (_headersTable, SWT.NONE); column.setText(titles[i]); column.setWidth(bounds[i]); column.setResizable(true); //Setting the right sorter column.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { queuesTableSorter.setColumn(index); final TableViewer viewer = _headersTableViewer; int dir = viewer .getTable().getSortDirection(); if (viewer.getTable().getSortColumn() == column) { dir = dir == SWT.UP ? SWT.DOWN : SWT.UP; } else { dir = SWT.UP; } viewer.getTable().setSortDirection(dir); viewer.getTable().setSortColumn(column); viewer.refresh(); } }); } _headersTableViewer.setContentProvider(new ContentProviderImpl(HDR_QUEUE_BINDINGS)); _headersTableViewer.setLabelProvider(new LabelProviderImpl(HDR_QUEUE_BINDINGS)); _headersTableViewer.setSorter(queuesTableSorter); _headersTable.setSortColumn(_headersTable.getColumn(0)); _headersTable.setSortDirection(SWT.UP); _headersTableViewer.setInput(new String[]{"Select a binding to view key-value pairs"}); _bindingNumberTableViewer.addSelectionChangedListener(new ISelectionChangedListener(){ public void selectionChanged(SelectionChangedEvent evt) { int selectionIndex = _bindingNumberTable.getSelectionIndex(); if (selectionIndex != -1) { final CompositeData selectedMsg = (CompositeData)_bindingNumberTable.getItem(selectionIndex).getData(); String[] bindings = (String[]) selectedMsg.get(HDR_QUEUE_BINDINGS); _headersTableViewer.setInput(bindings); } else { _headersTableViewer.setInput(new String[]{"Select a binding to view key-value pairs"}); } } }); //listener for double clicking to open the selection mbean _bindingNumberTable.addMouseListener(new MouseListener() { // MouseListener implementation public void mouseDoubleClick(MouseEvent event) { openMBean(_bindingNumberTable); } public void mouseDown(MouseEvent e){} public void mouseUp(MouseEvent e){} }); //Side Buttons Composite buttonsComposite = _toolkit.createComposite(bindingsGroup); gridData = new GridData(SWT.FILL, SWT.FILL, false, true); buttonsComposite.setLayoutData(gridData); buttonsComposite.setLayout(new GridLayout()); final Button createBindingButton = _toolkit.createButton(buttonsComposite, "Create ...", SWT.PUSH); createBindingButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { createNewBinding(createBindingButton.getShell()); } }); } /** * Content Provider class for the table viewer */ private static class ContentProviderImpl implements IStructuredContentProvider { String type; public ContentProviderImpl(String type) { this.type = type; } public void inputChanged(Viewer v, Object oldInput, Object newInput) { } public void dispose() { } public Object[] getElements(Object parent) { if(type.equals(HDR_BINDING_NUMBER)) { Collection rowCollection = ((TabularDataSupport) parent).values(); return rowCollection.toArray(); } else { //we have the list of bindings, return directly return (String[]) parent; } } } /** * Label Provider class for the routing key table viewer */ private static class LabelProviderImpl extends LabelProvider implements ITableLabelProvider { String type; public LabelProviderImpl(String type) { this.type = type; } public String getColumnText(Object element, int columnIndex) { if(type.equals(HDR_BINDING_NUMBER)) //binding num and queue name table { switch (columnIndex) { case 0 : // binding number column return String.valueOf(((CompositeDataSupport) element).get(HDR_BINDING_NUMBER)); case 1 : // queue name column return (String) ((CompositeDataSupport) element).get(HDR_QUEUE_NAME); default : return ""; } } else //binding key-value pair table { switch (columnIndex) { case 0 : //header binding column return String.valueOf(element); default : return ""; } } } public Image getColumnImage(Object element, int columnIndex) { return null; } } /** * Sorter class for the table viewer. * */ public static class TableSorter extends ViewerSorter { private int column; private static final int ASCENDING = 0; private static final int DESCENDING = 1; private int direction = DESCENDING; private String type; public TableSorter(String type) { this.type = type; this.column = 0; direction = ASCENDING; } public void setColumn(int column) { if (column == this.column) { // Same column as last sort; toggle the direction direction = 1 - direction; } else { // New column; do an ascending sort this.column = column; direction = ASCENDING; } } @Override public int compare(Viewer viewer, Object e1, Object e2) { int comparison = 0; if(type.equals(HDR_BINDING_NUMBER)) //binding num and queue name table { CompositeData binding1 = (CompositeData) e1; CompositeData binding2 = (CompositeData) e2; switch(column) { case 0: // binding number column comparison = ((Integer) binding1.get(HDR_BINDING_NUMBER)).compareTo((Integer) binding2.get(HDR_BINDING_NUMBER)); break; case 1: // queue name column comparison = ((String) binding1.get(HDR_QUEUE_NAME)).compareTo((String) binding2.get(HDR_QUEUE_NAME)); break; default: comparison = 0; } } else //binding key-value pair table { switch(column) { case 0: //header binding column comparison = ((String)e1).compareTo((String) e2); break; default: comparison = 0; } } // If descending order, flip the direction if(direction == DESCENDING) { comparison = -comparison; } return comparison; } } private void createNewBinding(Shell parent) { final Shell shell = ViewUtility.createModalDialogShell(parent, "Create New Binding"); Composite queueNameComposite = _toolkit.createComposite(shell, SWT.NONE); queueNameComposite.setBackground(shell.getBackground()); GridData layoutData = new GridData(SWT.CENTER, SWT.TOP, true, false); layoutData.minimumWidth = 300; queueNameComposite.setLayoutData(layoutData); queueNameComposite.setLayout(new GridLayout(2,false)); _toolkit.createLabel(queueNameComposite,"Queue:").setBackground(shell.getBackground()); final Combo destinationCombo = new Combo(queueNameComposite,SWT.NONE | SWT.READ_ONLY); destinationCombo.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); final ScrolledComposite scrolledComposite = new ScrolledComposite(shell, SWT.V_SCROLL); scrolledComposite.setExpandHorizontal(true); scrolledComposite.setLayout(new GridLayout()); scrolledComposite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); scrolledComposite.setBackground(shell.getBackground()); final Composite bindingComposite = _toolkit.createComposite(scrolledComposite, SWT.NONE); bindingComposite.setBackground(scrolledComposite.getBackground()); bindingComposite.setLayout(new GridLayout(2,true)); layoutData = new GridData(SWT.FILL, SWT.TOP, true, false); bindingComposite.setLayoutData(layoutData); scrolledComposite.setContent(bindingComposite); Composite addMoreButtonComp = _toolkit.createComposite(shell); addMoreButtonComp.setBackground(shell.getBackground()); addMoreButtonComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true)); addMoreButtonComp.setLayout(new GridLayout()); final Button addMoreButton = _toolkit.createButton(addMoreButtonComp, "Add additional field", SWT.PUSH); Composite okCancelButtonsComp = _toolkit.createComposite(shell); okCancelButtonsComp.setBackground(shell.getBackground()); okCancelButtonsComp.setLayoutData(new GridData(SWT.RIGHT, SWT.FILL, true, true)); okCancelButtonsComp.setLayout(new GridLayout(2,false)); Button okButton = _toolkit.createButton(okCancelButtonsComp, "OK", SWT.PUSH); okButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false)); Button cancelButton = _toolkit.createButton(okCancelButtonsComp, "Cancel", SWT.PUSH); cancelButton.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false)); List queueList = ApplicationRegistry.getServerRegistry(_mbean).getQueueNames(_mbean.getVirtualHostName()); if(queueList.size() == 0) { destinationCombo.setItems(new String[]{"No queues available"}); okButton.setEnabled(false); } else { Collections.sort(queueList); destinationCombo.setItems(queueList.toArray(new String[0])); } destinationCombo.select(0); final HashMap headerBindingHashMap = new HashMap(); //add headings Label keyLabel = _toolkit.createLabel(bindingComposite,"Key:"); keyLabel.setBackground(bindingComposite.getBackground()); keyLabel.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, true, false)); Label valueLabel = _toolkit.createLabel(bindingComposite,"Value:"); valueLabel.setBackground(bindingComposite.getBackground()); valueLabel.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, true, false)); //add the x-match key by default and offer a comobo to select its value final Text xmatchKeyText = new Text(bindingComposite, SWT.BORDER); xmatchKeyText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); xmatchKeyText.setText("x-match"); xmatchKeyText.setEditable(false); final Combo xmatchValueCombo = new Combo(bindingComposite,SWT.NONE | SWT.READ_ONLY); xmatchValueCombo.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); xmatchValueCombo.setItems(new String[]{"any", "all"}); xmatchValueCombo.select(0); //make some empty key-value fields for(int i=0; i < 4; i++) { Text keyText = new Text(bindingComposite, SWT.BORDER); Text valueText = new Text(bindingComposite, SWT.BORDER); keyText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); valueText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); headerBindingHashMap.put(keyText, valueText); } bindingComposite.setSize(bindingComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT)); //allow adding more fields for additional key-value pairs addMoreButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { Text keyText = new Text(bindingComposite, SWT.BORDER); Text valueText = new Text(bindingComposite, SWT.BORDER); keyText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); valueText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false)); headerBindingHashMap.put(keyText, valueText); bindingComposite.setSize(bindingComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT)); bindingComposite.layout(true); scrolledComposite.layout(true); } }); okButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { String xMatchString = xmatchValueCombo.getText(); String destQueue = destinationCombo.getItem(destinationCombo.getSelectionIndex()).toString(); StringBuffer bindingValue = new StringBuffer(); //insert the x-match key-value pair if (xMatchString.equalsIgnoreCase("any")) { bindingValue.append("x-match=any"); } else { bindingValue.append("x-match=all"); } //insert the other key-value pairs for (Text keyText : headerBindingHashMap.keySet()) { String key = keyText.getText(); if(key == null || key.length() == 0) { continue; } Text valueText = headerBindingHashMap.get(keyText); String value = valueText.getText(); bindingValue.append(","); bindingValue.append(key + "="); //empty values are permitted, signalling only key-presence is required if(value != null && value.length() > 0) { bindingValue.append(value); } } shell.dispose(); try { _emb.createNewBinding(destQueue, bindingValue.toString()); ViewUtility.operationResultFeedback(null, "Created new Binding", null); } catch (Exception e4) { ViewUtility.operationFailedStatusBarMessage("Error creating new Binding"); MBeanUtility.handleException(_mbean, e4); } refresh(_mbean); } }); cancelButton.addSelectionListener(new SelectionAdapter() { public void widgetSelected(SelectionEvent e) { shell.dispose(); } }); shell.setDefaultButton(okButton); shell.pack(); ViewUtility.centerChildInParentShell(parent, shell); shell.open(); } private void openMBean(Table table) { int selectionIndex = table.getSelectionIndex(); if (selectionIndex == -1) { return; } CompositeData bindingResult = (CompositeData) table.getItem(selectionIndex).getData(); String queueName = (String) bindingResult.get(HDR_QUEUE_NAME); ServerRegistry serverRegistry = ApplicationRegistry.getServerRegistry(_mbean); ManagedBean selectedMBean = serverRegistry.getQueue(queueName, _mbean.getVirtualHostName()); if(selectedMBean == null) { ViewUtility.popupErrorMessage("Error", "Unable to retrieve the selected MBean to open it"); return; } IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow(); MBeanView view = (MBeanView) window.getActivePage().findView(MBeanView.ID); try { view.openMBean(selectedMBean); } catch (Exception ex) { MBeanUtility.handleException(selectedMBean, ex); } } }