001 /*
002 *
003 * Licensed to the Apache Software Foundation (ASF) under one
004 * or more contributor license agreements. See the NOTICE file
005 * distributed with this work for additional information
006 * regarding copyright ownership. The ASF licenses this file
007 * to you under the Apache License, Version 2.0 (the
008 * "License"); you may not use this file except in compliance
009 * with the License. You may obtain a copy of the License at
010 *
011 * http://www.apache.org/licenses/LICENSE-2.0
012 *
013 * Unless required by applicable law or agreed to in writing,
014 * software distributed under the License is distributed on an
015 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
016 * KIND, either express or implied. See the License for the
017 * specific language governing permissions and limitations
018 * under the License.
019 *
020 */
021 package org.apache.qpid.management.ui.views;
022
023 import java.io.UnsupportedEncodingException;
024 import java.nio.charset.Charset;
025 import java.security.MessageDigest;
026 import java.security.NoSuchAlgorithmException;
027 import java.util.ArrayList;
028 import java.util.Collections;
029 import java.util.Comparator;
030 import java.util.List;
031 import java.util.Map;
032 import java.util.Set;
033
034 import javax.management.openmbean.ArrayType;
035 import javax.management.openmbean.CompositeData;
036 import javax.management.openmbean.CompositeDataSupport;
037 import javax.management.openmbean.CompositeType;
038 import javax.management.openmbean.OpenType;
039 import javax.management.openmbean.TabularDataSupport;
040 import javax.management.openmbean.TabularType;
041
042 import org.apache.qpid.management.ui.ApplicationWorkbenchAdvisor;
043 import org.eclipse.core.runtime.IStatus;
044 import org.eclipse.core.runtime.Status;
045 import org.eclipse.jface.dialogs.ErrorDialog;
046 import org.eclipse.swt.SWT;
047 import org.eclipse.swt.events.SelectionAdapter;
048 import org.eclipse.swt.events.SelectionEvent;
049 import org.eclipse.swt.events.SelectionListener;
050 import org.eclipse.swt.layout.GridData;
051 import org.eclipse.swt.layout.GridLayout;
052 import org.eclipse.swt.widgets.Button;
053 import org.eclipse.swt.widgets.Composite;
054 import org.eclipse.swt.widgets.Control;
055 import org.eclipse.swt.widgets.Display;
056 import org.eclipse.swt.widgets.Label;
057 import org.eclipse.swt.widgets.MessageBox;
058 import org.eclipse.swt.widgets.Shell;
059 import org.eclipse.swt.widgets.Text;
060 import org.eclipse.ui.forms.widgets.FormToolkit;
061
062 /**
063 * Utility Class for displaying OpenMbean data types by creating required SWT widgets
064 * @author Bhupendra Bhardwaj
065 */
066 public class ViewUtility
067 {
068 public static final String OP_NAME = "operation_name";
069 public static final String OP_PARAMS = "parameters";
070 public static final String PARAMS_TEXT = "text";
071
072 public static final String FIRST = "First";
073 public static final String LAST = "Last";
074 public static final String NEXT = "Next";
075 public static final String PREV = "Previous";
076 public static final String INDEX = "Index";
077
078 private static final Comparator tabularDataComparator = new TabularDataComparator();
079
080 private static List<String> SUPPORTED_ARRAY_DATATYPES = new ArrayList<String>();
081 static
082 {
083 SUPPORTED_ARRAY_DATATYPES.add("java.lang.String");
084 SUPPORTED_ARRAY_DATATYPES.add("java.lang.Boolean");
085 SUPPORTED_ARRAY_DATATYPES.add("java.lang.Character");
086 SUPPORTED_ARRAY_DATATYPES.add("java.lang.Integer");
087 SUPPORTED_ARRAY_DATATYPES.add("java.lang.Long");
088 SUPPORTED_ARRAY_DATATYPES.add("java.lang.Double");
089 SUPPORTED_ARRAY_DATATYPES.add("java.util.Date");
090 }
091
092 /**
093 * Populates the composite with given openmbean data type (TabularType or CompositeType)
094 * @param toolkit
095 * @param parent composite
096 * @param data open mbean data type(either composite type or tabular data type)
097 */
098 public static void populateCompositeWithData(FormToolkit toolkit, Composite parent, Object data)
099 {
100 if (data instanceof TabularDataSupport)
101 {
102 ViewUtility.createTabularDataHolder(toolkit, parent, (TabularDataSupport)data);
103 }
104 else if (data instanceof CompositeDataSupport)
105 {
106 ViewUtility.populateCompositeWithCompositeData(toolkit, parent, (CompositeDataSupport)data);
107 }
108 }
109
110 @SuppressWarnings("unchecked")
111 private static void createTabularDataHolder(FormToolkit toolkit, Composite parent, TabularDataSupport tabularData)
112 {
113 Composite composite = toolkit.createComposite(parent, SWT.BORDER);
114 GridLayout layout = new GridLayout(4, true);
115 layout.horizontalSpacing = 0;
116 layout.marginWidth = 0;
117 layout.marginHeight = 10;
118 layout.verticalSpacing = 10;
119 composite.setLayout(layout);
120 composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
121
122 Set entrySet = tabularData.entrySet();
123 ArrayList<Map.Entry> list = new ArrayList<Map.Entry>(entrySet);
124 if (list.size() == 0)
125 {
126 Text text = toolkit.createText(composite, " No records ", SWT.CENTER | SWT.SINGLE | SWT.READ_ONLY);
127 GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true, true, 4, 1);
128 text.setLayoutData(layoutData);
129 return;
130 }
131
132 Collections.sort(list, tabularDataComparator);
133
134 // Attach the tabular record to be retrieved and shown later when record is traversed
135 // using first/next/previous/last buttons
136 composite.setData(list);
137
138 // Create button and the composite for CompositeData
139 Composite compositeDataHolder = createCompositeDataHolder(toolkit, composite,
140 tabularData.getTabularType().getRowType());
141
142 // display the first record
143 CompositeData data = (CompositeData)(list.get(0)).getValue();
144 composite.setData(INDEX, 0);
145 populateCompositeWithCompositeData(toolkit, compositeDataHolder, data);
146 enableOrDisableTraversalButtons(composite);
147 }
148
149 private static void enableOrDisableTraversalButtons(Composite composite)
150 {
151 int index = (Integer)composite.getData(INDEX);
152 int size = ((List)composite.getData()).size();
153
154 ((Button)composite.getData(FIRST)).setEnabled(true);
155 ((Button)composite.getData(PREV)).setEnabled(true);
156 ((Button)composite.getData(NEXT)).setEnabled(true);
157 ((Button)composite.getData(LAST)).setEnabled(true);
158
159 if (index == 0)
160 {
161 ((Button)composite.getData(FIRST)).setEnabled(false);
162 ((Button)composite.getData(PREV)).setEnabled(false);
163 }
164 if (index == size -1)
165 {
166 ((Button)composite.getData(NEXT)).setEnabled(false);
167 ((Button)composite.getData(LAST)).setEnabled(false);
168 }
169 }
170
171 /**
172 * Sets up the given composite for holding a CompositeData. Create traversal buttons, label etc and
173 * creates a child Composite, which should be populated with the CompositeData
174 * @param toolkit
175 * @param dataHolder
176 * @param compositeType
177 * @return
178 */
179 private static Composite createCompositeDataHolder(final FormToolkit toolkit, final Composite dataHolder, CompositeType compositeType)
180 {
181 String desc = compositeType.getDescription();
182 Label description = toolkit.createLabel(dataHolder, desc, SWT.CENTER);
183 description.setLayoutData(new GridData(SWT.CENTER, SWT.TOP, true, false, 4, 1));
184 // TODO nameLabel.setFont(font);
185 description.setText(desc);
186
187 // Add traversal buttons
188 final Button firstRecordButton = toolkit.createButton(dataHolder, FIRST, SWT.PUSH);
189 GridData layoutData = new GridData (GridData.HORIZONTAL_ALIGN_END);
190 layoutData.widthHint = 80;
191 firstRecordButton.setLayoutData(layoutData);
192
193 final Button nextRecordButton = toolkit.createButton(dataHolder, NEXT, SWT.PUSH);
194 layoutData = new GridData (GridData.HORIZONTAL_ALIGN_END);
195 layoutData.widthHint = 80;
196 nextRecordButton.setLayoutData(layoutData);
197
198 final Button previousRecordButton = toolkit.createButton(dataHolder, PREV, SWT.PUSH);
199 layoutData = new GridData (GridData.HORIZONTAL_ALIGN_BEGINNING);
200 layoutData.widthHint = 80;
201 previousRecordButton.setLayoutData(layoutData);
202
203 final Button lastRecordButton = toolkit.createButton(dataHolder, LAST, SWT.PUSH);
204 layoutData = new GridData (GridData.HORIZONTAL_ALIGN_BEGINNING);
205 layoutData.widthHint = 80;
206 lastRecordButton.setLayoutData(layoutData);
207
208 // Now create the composite, which will hold the CompositeData
209 final Composite composite = toolkit.createComposite(dataHolder, SWT.NONE);
210 GridLayout layout = new GridLayout();
211 layout.horizontalSpacing = layout.verticalSpacing = 0;
212 layout.marginHeight = layout.marginWidth = 0;
213 composite.setLayout(layout);
214 composite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 4, 1));
215
216 // Add button references. These references will be used when buttons
217 // are to enabled or disabled based of record index. e.g. for first record
218 // First and Previous buttons will be disabled.
219 dataHolder.setData(FIRST, firstRecordButton);
220 dataHolder.setData(NEXT, nextRecordButton);
221 dataHolder.setData(PREV, previousRecordButton);
222 dataHolder.setData(LAST, lastRecordButton);
223
224 // Listener for the traversal buttons. When a button is clicked the respective
225 // CompositeData will be populated in the composite
226 SelectionListener listener = new SelectionAdapter()
227 {
228 public void widgetSelected(SelectionEvent e)
229 {
230 if (!(e.widget instanceof Button))
231 return;
232
233 Button traverseButton =(Button)e.widget;
234 // Get the CompositeData respective to the button selected
235 CompositeData data = getCompositeData(dataHolder, traverseButton.getText());
236 populateCompositeWithCompositeData(toolkit, composite, data);
237 enableOrDisableTraversalButtons(dataHolder);
238 }
239 };
240
241 firstRecordButton.addSelectionListener(listener);
242 nextRecordButton.addSelectionListener(listener);
243 previousRecordButton.addSelectionListener(listener);
244 lastRecordButton.addSelectionListener(listener);
245
246 return composite;
247 }
248
249 /**
250 * The CompositeData is set as data with the Composite and using the index, this method will
251 * return the corresponding CompositeData
252 * @param compositeHolder
253 * @param dataIndex
254 * @return the CompositeData respective to the index
255 */
256 private static CompositeData getCompositeData(Composite compositeHolder, String dataIndex)
257 {
258 List objectData = (List)compositeHolder.getData();
259 if (objectData == null || objectData.isEmpty())
260 {
261 // TODO
262 }
263
264 // Get the index of record to be shown.
265 int index = 0;
266 if (compositeHolder.getData(INDEX) != null)
267 {
268 index = (Integer)compositeHolder.getData(INDEX);
269 }
270
271 if (FIRST.equals(dataIndex))
272 {
273 index = 0;
274 }
275 else if (NEXT.equals(dataIndex))
276 {
277 index = index + 1;
278 }
279 else if (PREV.equals(dataIndex))
280 {
281 index = (index != 0) ? (index = index - 1) : index;
282 }
283 else if (LAST.equals(dataIndex))
284 {
285 index = objectData.size() -1;
286 }
287
288 // Set the index being shown.
289 compositeHolder.setData(INDEX, index);
290
291 return (CompositeData)((Map.Entry)objectData.get(index)).getValue();
292 }
293
294 /**
295 * Populates the given composite with the CompositeData. Creates required widgets to hold the data types
296 * @param toolkit
297 * @param parent
298 * @param data CompositeData
299 */
300 @SuppressWarnings("unchecked")
301 private static void populateCompositeWithCompositeData(FormToolkit toolkit, Composite parent, CompositeData data)
302 {
303 Control[] oldControls = parent.getChildren();
304 for (int i = 0; i < oldControls.length; i++)
305 {
306 oldControls[i].dispose();
307 }
308
309 Composite compositeHolder = toolkit.createComposite(parent, SWT.NONE);
310 GridLayout layout = new GridLayout(4, false);
311 layout.horizontalSpacing = 10;
312 compositeHolder.setLayout(layout);
313 compositeHolder.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
314
315
316 // ItemNames in composite data
317 List<String> itemNames = new ArrayList<String>(data.getCompositeType().keySet());
318
319 for (String itemName : itemNames)
320 {
321 OpenType itemType = data.getCompositeType().getType(itemName);
322 Label keyLabel = toolkit.createLabel(compositeHolder, itemName, SWT.TRAIL);
323 GridData layoutData = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1);
324 layoutData.minimumWidth = 70;
325 keyLabel.setLayoutData(layoutData);
326
327 if (itemType.isArray())
328 {
329 OpenType type = ((ArrayType)itemType).getElementOpenType();
330 // If Byte array and mimetype is text, convert to text string
331 if (type.getClassName().equals(Byte.class.getName()))
332 {
333 String mimeType = null;
334 String encoding = null;
335 if (data.containsKey("MimeType"))
336 {
337 mimeType = (String)data.get("MimeType");
338 }
339 if (data.containsKey("Encoding"))
340 {
341 encoding = (String)data.get("Encoding");
342 }
343
344 if (encoding == null || encoding.length() == 0)
345 {
346 encoding = Charset.defaultCharset().name();
347 }
348
349 if ("text/plain".equals(mimeType))
350 {
351 convertByteArray(toolkit, compositeHolder, data, itemName, encoding);
352 }
353 else
354 {
355 setNotSupportedDataType(toolkit, compositeHolder);
356 }
357 }
358 // If array of any other supported type, show as a list of String array
359 else if (SUPPORTED_ARRAY_DATATYPES.contains(type.getClassName()))
360 {
361 convertArrayItemForDisplay(compositeHolder, data, itemName);
362 }
363 else
364 {
365 setNotSupportedDataType(toolkit, compositeHolder);
366 }
367 }
368 else if (itemType instanceof TabularType)
369 {
370 Composite composite = toolkit.createComposite(compositeHolder, SWT.NONE);
371 composite.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 3, 1));
372 layout = new GridLayout();
373 layout.marginHeight = 0;
374 layout.marginWidth = 0;
375 composite.setLayout(layout);
376 createTabularDataHolder(toolkit, composite, (TabularDataSupport)data.get(itemName));
377 }
378 else
379 {
380 Text valueText = toolkit.createText(compositeHolder, String.valueOf(data.get(itemName)), SWT.READ_ONLY | SWT.BORDER);
381 valueText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 3, 1));
382 }
383 }
384
385 // layout the composite after creating new widgets.
386 parent.layout();
387 } //end of method
388
389
390 private static void convertByteArray(FormToolkit toolkit, Composite compositeHolder, CompositeData data, String itemName, String encoding)
391 {
392 Byte[] arrayItems = (Byte[])data.get(itemName);
393 byte[] byteArray = new byte[arrayItems.length];
394
395 for (int i = 0; i < arrayItems.length; i++)
396 {
397 byteArray[i] = arrayItems[i];
398 }
399 try
400 {
401 String textMessage = new String(byteArray, encoding);
402
403 Text valueText = toolkit.createText(compositeHolder, textMessage, SWT.READ_ONLY | SWT.BORDER |
404 SWT.MULTI | SWT.WRAP | SWT.V_SCROLL);
405 GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1);
406 gridData.heightHint = 300;
407 valueText.setLayoutData(gridData);
408 }
409 catch(Exception ex)
410 {
411 ex.printStackTrace();
412 }
413 }
414
415 private static Shell getShell()
416 {
417 Shell shell = Display.getCurrent().getActiveShell();
418
419 // Under linux GTK getActiveShell returns null so we need to make a new shell for display.
420 // Under windows this is fine.
421 if (shell == null)
422 {
423 // This occurs under linux gtk
424 shell = new Shell(Display.getCurrent(), SWT.BORDER | SWT.CLOSE | SWT.MIN | SWT.MAX);
425 }
426
427 return shell;
428 }
429
430 private static int showBox(String title, String message, int icon)
431 {
432 MessageBox messageBox = new MessageBox(getShell(), icon);
433 messageBox.setMessage(message);
434 messageBox.setText(title);
435
436 return messageBox.open();
437 }
438
439 public static int popupInfoMessage(String title, String message)
440 {
441 return showBox(title, message, SWT.ICON_INFORMATION | SWT.OK);
442 }
443
444 public static int popupErrorMessage(String title, String message)
445 {
446 return showBox(title, message, SWT.ICON_ERROR | SWT.OK);
447 }
448
449 public static int popupConfirmationMessage(String title, String message)
450 {
451 return showBox(title, message,SWT.ICON_QUESTION | SWT.YES | SWT.NO | SWT.CANCEL);
452 }
453
454
455 public static Shell createPopupShell(String title, int width, int height)
456 {
457 Display display = Display.getCurrent();
458 Shell shell = new Shell(display, SWT.BORDER | SWT.CLOSE | SWT.MIN |SWT.MAX);
459 shell.setText(title);
460 shell.setLayout(new GridLayout());
461 int x = display.getBounds().width;
462 int y = display.getBounds().height;
463 shell.setBounds(x/4, y/4, width, height);
464
465 return shell;
466 }
467
468 /**
469 * Creates a List widget for displaying array of strings
470 * @param compositeHolder
471 * @param data - containing the array item value
472 * @param itemName - item name
473 */
474 private static void convertArrayItemForDisplay(Composite compositeHolder, CompositeData data, String itemName)
475 {
476 Object[] arrayItems = (Object[])data.get(itemName);
477 String[] items = new String[arrayItems.length];
478 for (int i = 0; i < arrayItems.length; i++)
479 {
480 items[i] = String.valueOf(arrayItems[i]);
481 }
482 org.eclipse.swt.widgets.List list = new org.eclipse.swt.widgets.List(compositeHolder,
483 SWT.MULTI | SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.READ_ONLY);
484 list.setItems(items);
485 //list.setBackground(compositeHolder.getBackground());
486 list.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1));
487 }
488
489 private static void setNotSupportedDataType(FormToolkit toolkit, Composite compositeHolder)
490 {
491 Text valueText = toolkit.createText(compositeHolder, "--- Content can not be displayed ---", SWT.READ_ONLY);
492 valueText.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false, 3, 1));
493 }
494
495 /**
496 * Converts the input string to displayable format by converting some character case or inserting space
497 * @param input
498 * @return formatted string
499 */
500 public static String getDisplayText(String input)
501 {
502 StringBuffer result = new StringBuffer(input);
503 if (Character.isLowerCase(result.charAt(0)))
504 {
505 result.setCharAt(0, Character.toUpperCase(result.charAt(0)));
506 }
507 for (int i = 1; i < input.length(); i++)
508 {
509 if (Character.isUpperCase(result.charAt(i)) && !Character.isWhitespace(result.charAt(i - 1))
510 && Character.isLowerCase(result.charAt(i - 1)))
511 {
512 result.insert(i, " ");
513 i++;
514 }
515 else if (Character.isLowerCase(result.charAt(i)) && Character.isWhitespace(result.charAt(i - 1)))
516 {
517 result.setCharAt(i, Character.toUpperCase(result.charAt(i)));
518 }
519
520 }
521
522 return result.toString();
523 }
524
525 /**
526 * Disposes the children of given Composite if not null and not already disposed
527 * @param parent composite
528 */
529 public static void disposeChildren(Composite parent)
530 {
531 if (parent == null || parent.isDisposed())
532 return;
533
534 Control[] oldControls = parent.getChildren();
535 for (int i = 0; i < oldControls.length; i++)
536 {
537 oldControls[i].dispose();
538 }
539 }
540
541 public static char[] getHash(String text) throws NoSuchAlgorithmException, UnsupportedEncodingException
542 {
543 byte[] data = text.getBytes("utf-8");
544
545 MessageDigest md = MessageDigest.getInstance("MD5");
546
547 for (byte b : data)
548 {
549 md.update(b);
550 }
551
552 byte[] digest = md.digest();
553
554 char[] hash = new char[digest.length ];
555
556 int index = 0;
557 for (byte b : digest)
558 {
559 hash[index++] = (char) b;
560 }
561
562 return hash;
563 }
564
565 private static class TabularDataComparator implements java.util.Comparator<Map.Entry>
566 {
567 public int compare(Map.Entry data1, Map.Entry data2)
568 {
569 if (data1.getKey() instanceof List)
570 {
571 Object obj1 = ((List)data1.getKey()).get(0);
572 Object obj2 = ((List)data2.getKey()).get(0);
573 String str1 = obj1.toString();
574 String str2 = obj2.toString();
575 if (obj1 instanceof String)
576 {
577 return str1.compareTo(str2);
578 }
579
580 try
581 {
582 return Long.valueOf(str1).compareTo(Long.valueOf(str2));
583 }
584 catch (Exception ex)
585 {
586 return -1;
587 }
588 }
589
590 return -1;
591 }
592 }
593 }
|