1 package oic.simulator.serviceprovider.view;
3 import java.io.BufferedWriter;
4 import java.io.FileWriter;
5 import java.io.IOException;
6 import java.text.DateFormat;
7 import java.text.SimpleDateFormat;
8 import java.util.HashMap;
11 import oic.simulator.logger.LogContentProvider;
12 import oic.simulator.logger.LogEntry;
13 import oic.simulator.logger.LogLabelProvider;
14 import oic.simulator.serviceprovider.Activator;
15 import oic.simulator.serviceprovider.listener.ILogUIListener;
16 import oic.simulator.serviceprovider.manager.LogManager;
17 import oic.simulator.serviceprovider.utils.Constants;
18 import oic.simulator.serviceprovider.view.dialogs.FilterDialog;
20 import org.eclipse.jface.action.Action;
21 import org.eclipse.jface.action.IAction;
22 import org.eclipse.jface.action.IContributionItem;
23 import org.eclipse.jface.action.IMenuManager;
24 import org.eclipse.jface.action.IToolBarManager;
25 import org.eclipse.jface.action.MenuManager;
26 import org.eclipse.jface.action.Separator;
27 import org.eclipse.jface.dialogs.MessageDialog;
28 import org.eclipse.jface.resource.ImageDescriptor;
29 import org.eclipse.jface.viewers.DoubleClickEvent;
30 import org.eclipse.jface.viewers.IDoubleClickListener;
31 import org.eclipse.jface.viewers.ISelectionChangedListener;
32 import org.eclipse.jface.viewers.IStructuredSelection;
33 import org.eclipse.jface.viewers.SelectionChangedEvent;
34 import org.eclipse.jface.viewers.StructuredSelection;
35 import org.eclipse.jface.viewers.TreeViewer;
36 import org.eclipse.jface.viewers.Viewer;
37 import org.eclipse.jface.viewers.ViewerComparator;
38 import org.eclipse.jface.window.Window;
39 import org.eclipse.swt.SWT;
40 import org.eclipse.swt.events.KeyEvent;
41 import org.eclipse.swt.events.KeyListener;
42 import org.eclipse.swt.events.SelectionAdapter;
43 import org.eclipse.swt.events.SelectionEvent;
44 import org.eclipse.swt.layout.GridData;
45 import org.eclipse.swt.widgets.Composite;
46 import org.eclipse.swt.widgets.Display;
47 import org.eclipse.swt.widgets.FileDialog;
48 import org.eclipse.swt.widgets.Text;
49 import org.eclipse.swt.widgets.Tree;
50 import org.eclipse.swt.widgets.TreeColumn;
51 import org.eclipse.swt.widgets.TreeItem;
52 import org.eclipse.ui.IActionBars;
53 import org.eclipse.ui.IWorkbenchActionConstants;
54 import org.eclipse.ui.IWorkbenchPage;
55 import org.eclipse.ui.dialogs.FilteredTree;
56 import org.eclipse.ui.dialogs.PatternFilter;
57 import org.eclipse.ui.part.ViewPart;
58 import org.oic.simulator.ILogger.Level;
60 public class LogView extends ViewPart {
62 public static final String VIEW_ID = "oic.simulator.serviceprovider.view.log";
64 private LogManager logManager;
65 private ILogUIListener logListener;
67 private LogContentProvider treeContentProvider;
69 private FilteredTree tree;
70 private TreeColumn severityColumn;
71 private TreeColumn dateColumn;
72 private TreeColumn messageColumn;
74 private IAction exportLogAction;
75 private IAction clearLogAction;
76 private IAction deleteLogAction;
77 private IAction scrollLockAction;
78 private IAction logDetailsAction;
79 private IAction filterAction;
80 private IAction activateViewAction;
81 private IAction showTextFilter;
82 private IContributionItem groupByAction;
84 private HashMap<Integer, Boolean> shownSeverities = new HashMap<Integer, Boolean>();
86 private boolean activateOnChange = false;
88 private boolean hideTextFilter = false;
90 private boolean scrollLockDisabled;
92 public static final int ORDER_BY_TIME = 0;
93 public static final int ORDER_BY_SEVERITY = 1;
94 public static final int ORDER_BY_MESSAGE = 2;
96 int sortCandidate = ORDER_BY_TIME;
98 SortAction sortByTimeAction = new SortAction(
101 SortAction sortBySeverityAction = new SortAction(
104 SortAction sortByMessageAction = new SortAction(
108 private ViewerComparator dateComparator;
109 private ViewerComparator severityComparator;
110 private ViewerComparator messageComparator;
112 private TreeColumn sortColumn = null;
113 private static int DOWN = 1;
114 private static int UP = -1;
115 private int sortDirection = DOWN;
119 logListener = new ILogUIListener() {
122 public void logChanged(final List<LogEntry> entry) {
123 Display.getDefault().asyncExec(new Runnable() {
127 TreeViewer viewer = tree.getViewer();
128 if (viewer.getControl().isDisposed()) {
131 viewer.setInput(entry);
138 public void logAdded(final LogEntry added) {
139 Display.getDefault().asyncExec(new Runnable() {
143 TreeViewer viewer = tree.getViewer();
144 if (viewer.getControl().isDisposed()) {
147 LogContentProvider provider = (LogContentProvider) viewer
148 .getContentProvider();
149 provider.addLog(added);
150 tree.getViewer().add(viewer.getInput(), added);
151 @SuppressWarnings("unchecked")
152 List<LogEntry> input = (List<LogEntry>) viewer
154 if (input.size() > Constants.LOG_SIZE) {
155 viewer.remove(viewer.getInput(), 0);
162 private void updateTree(boolean needscroll) {
163 if (activateOnChange) {
164 IWorkbenchPage page = Activator.getDefault().getWorkbench()
165 .getActiveWorkbenchWindow().getActivePage();
167 page.bringToTop(LogView.this);
170 if (scrollLockDisabled && needscroll) {
171 Tree tree2 = tree.getViewer().getTree();
172 if (tree2.getItemCount() > 0) {
173 TreeItem item = tree2.getItem(tree2.getItemCount() - 1);
174 tree2.setTopItem(item);
175 deleteLogAction.setEnabled(true);
181 logManager = Activator.getDefault().getLogManager();
183 // Initially state of scroll lock
184 scrollLockDisabled = true;
188 public void createPartControl(Composite parent) {
189 PatternFilter filter = new PatternFilter() {
191 DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
194 protected boolean isLeafMatch(Viewer viewer, Object element) {
195 if (element instanceof LogEntry) {
196 LogEntry logEntry = (LogEntry) element;
197 String severity = LogManager.getSeverityName(logEntry
199 String date = dateFormat.format(logEntry.getDate());
200 String message = logEntry.getMessage();
201 return wordMatches(severity) || wordMatches(date)
202 || wordMatches(message);
207 filter.setIncludeLeadingWildcard(true);
208 tree = new FilteredTree(parent, SWT.SINGLE | SWT.H_SCROLL
209 | SWT.V_SCROLL | SWT.FULL_SELECTION, filter, true);
213 createColumnComparators();
217 setDefaultShownSeverities();
219 IActionBars actionBars = getViewSite().getActionBars();
220 IToolBarManager toolBarManager = actionBars.getToolBarManager();
221 toolBarManager.add(exportLogAction);
222 toolBarManager.add(clearLogAction);
223 toolBarManager.add(deleteLogAction);
224 toolBarManager.add(scrollLockAction);
226 .add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
228 IMenuManager mgr = actionBars.getMenuManager();
229 mgr.add(groupByAction);
230 mgr.add(new Separator());
231 mgr.add(filterAction);
232 mgr.add(new Separator());
233 mgr.add(activateViewAction);
234 mgr.add(showTextFilter);
236 addManagerListeners();
238 if (sortCandidate == ORDER_BY_TIME) {
239 sortByTimeAction.run();
240 } else if (sortCandidate == ORDER_BY_SEVERITY) {
241 sortBySeverityAction.run();
242 } else { // order_selected == ORDER_BY_NONE
243 sortByMessageAction.run();
248 private void setupFilteredTree() {
249 tree.setLayoutData(new GridData(GridData.FILL_BOTH));
250 final Tree innerTree = tree.getViewer().getTree();
251 innerTree.setLinesVisible(true);
253 severityColumn = new TreeColumn(innerTree, SWT.LEFT);
254 severityColumn.setText("Severity");
255 severityColumn.setWidth(110);
256 severityColumn.addSelectionListener(new SelectionAdapter() {
259 public void widgetSelected(SelectionEvent e) {
260 sortBySeverityAction.run();
263 dateColumn = new TreeColumn(innerTree, SWT.LEFT);
264 dateColumn.setText("Time");
265 dateColumn.setWidth(110);
266 dateColumn.addSelectionListener(new SelectionAdapter() {
269 public void widgetSelected(SelectionEvent e) {
270 sortByTimeAction.run();
273 messageColumn = new TreeColumn(innerTree, SWT.LEFT);
274 messageColumn.setText("Message");
275 messageColumn.setWidth(180);
276 messageColumn.addSelectionListener(new SelectionAdapter() {
278 public void widgetSelected(SelectionEvent e) {
279 sortByMessageAction.run();
283 innerTree.setHeaderVisible(true);
285 treeContentProvider = new LogContentProvider();
287 tree.getViewer().setContentProvider(treeContentProvider);
288 tree.getViewer().setLabelProvider(new LogLabelProvider());
290 tree.getViewer().setInput(logManager.getLogEntries());
292 tree.getViewer().addSelectionChangedListener(
293 new ISelectionChangedListener() {
296 public void selectionChanged(SelectionChangedEvent event) {
297 deleteLogAction.setEnabled(!tree.getViewer()
298 .getSelection().isEmpty());
299 logDetailsAction.setEnabled(!tree.getViewer()
300 .getSelection().isEmpty());
304 tree.getViewer().getTree().addKeyListener(new KeyListener() {
307 public void keyReleased(KeyEvent e) {
311 public void keyPressed(KeyEvent e) {
312 if (e.character == (char) 127) { // If delete key is pressed
313 if (deleteLogAction.isEnabled()) {
314 deleteLogAction.run();
320 tree.getViewer().addDoubleClickListener(new IDoubleClickListener() {
323 public void doubleClick(DoubleClickEvent event) {
324 logDetailsAction.run();
329 private void createColumnComparators() {
330 dateComparator = new ViewerComparator() {
333 public int compare(Viewer viewer, Object e1, Object e2) {
334 LogEntry l1 = (LogEntry) e1;
335 LogEntry l2 = (LogEntry) e2;
336 return l1.getDate().compareTo(l2.getDate()) * sortDirection;
340 severityComparator = new ViewerComparator() {
343 public int compare(Viewer viewer, Object e1, Object e2) {
344 LogEntry l1 = (LogEntry) e1;
345 LogEntry l2 = (LogEntry) e2;
346 if (l1.getSeverity() < l2.getSeverity()) {
347 return -1 * sortDirection;
349 if (l1.getSeverity() > l2.getSeverity()) {
350 return 1 * sortDirection;
356 messageComparator = new ViewerComparator() {
359 public int compare(Viewer viewer, Object e1, Object e2) {
360 LogEntry l1 = (LogEntry) e1;
361 LogEntry l2 = (LogEntry) e2;
362 return l1.getMessage().compareTo(l2.getMessage())
369 private void setDefaultShownSeverities() {
370 shownSeverities.put(Level.INFO.ordinal(), true);
371 shownSeverities.put(Level.DEBUG.ordinal(), true);
372 shownSeverities.put(Level.WARNING.ordinal(), true);
373 shownSeverities.put(Level.ERROR.ordinal(), true);
376 private void addManagerListeners() {
377 logManager.addLogListener(logListener);
378 logManager.applyFilter(shownSeverities);
381 private void createActions() {
382 exportLogAction = createExportLogAction();
383 clearLogAction = createClearLogAction();
384 deleteLogAction = createDeleteLogAction();
385 scrollLockAction = createScrollLockAction();
386 logDetailsAction = createLogDetailsAction();
388 filterAction = createFilterAction();
389 activateViewAction = createActivateViewAction();
390 showTextFilter = createShowTextFilter();
391 groupByAction = createGroupByAction();
394 private IAction createExportLogAction() {
395 Action action = new Action("Export log") {
398 FileDialog fd = new FileDialog(Display.getDefault()
399 .getActiveShell(), SWT.SAVE);
400 fd.setOverwrite(true);
401 fd.setFileName("OIC_Simulator_ServerLog.log");
402 fd.setFilterExtensions(Constants.SAVE_LOG_FILTER_EXTENSIONS);
403 String name = fd.open();
404 List<LogEntry> logEntries = logManager.getLogEntries();
405 StringBuilder sb = new StringBuilder();
406 for (LogEntry entry : logEntries) {
407 sb.append(entry.toString());
409 String data = sb.toString();
410 BufferedWriter out = null;
412 out = new BufferedWriter(new FileWriter(name));
414 } catch (IOException e) {
416 MessageDialog.openError(
417 Display.getDefault().getActiveShell(),
419 "Could not export log. IO exception: "
424 } catch (IOException e) {
425 // Error occurred during close. Ignoring
430 action.setToolTipText("Export log");
432 action.setImageDescriptor(ImageDescriptor.createFromFile(
433 this.getClass(), "/icons/export_log_e.gif"));
434 action.setDisabledImageDescriptor(ImageDescriptor.createFromFile(
435 this.getClass(), "/icons/export_log_d.gif"));
436 action.setEnabled(true);
441 private IAction createClearLogAction() {
442 Action action = new Action("Clear log") {
446 logManager.clearLog();
449 action.setToolTipText("Clear log");
451 action.setImageDescriptor(ImageDescriptor.createFromFile(
452 this.getClass(), "/icons/clear_e.gif"));
453 action.setDisabledImageDescriptor(ImageDescriptor.createFromFile(
454 this.getClass(), "/icons/clear_d.gif"));
455 action.setEnabled(true);
459 private IAction createDeleteLogAction() {
460 Action action = new Action("Delete log entry") {
463 @SuppressWarnings("unchecked")
465 IStructuredSelection selection = (IStructuredSelection) tree
466 .getViewer().getSelection();
467 List<LogEntry> entries = (List<LogEntry>) tree.getViewer()
469 LogEntry selectedEntry = (LogEntry) selection.getFirstElement();
470 if (null != selectedEntry) {
471 LogEntry toBeShownEntry = null;
472 for (LogEntry entry : entries) {
473 if (entry.equals(selectedEntry)) {
474 int size = entries.size();
475 int index = entries.indexOf(selectedEntry);
476 if (index + 1 < size) {
477 toBeShownEntry = entries.get(index + 1);
478 } else if (index > 0) {
479 toBeShownEntry = entries.get(index - 1);
484 logManager.removeEntry(selectedEntry);
485 if (null != toBeShownEntry) {
486 tree.getViewer().setSelection(
487 new StructuredSelection(toBeShownEntry));
492 action.setToolTipText("Delete log entry");
493 action.setImageDescriptor(ImageDescriptor.createFromFile(
494 this.getClass(), "/icons/delete_e.gif"));
495 action.setDisabledImageDescriptor(ImageDescriptor.createFromFile(
496 this.getClass(), "/icons/delete_d.gif"));
497 action.setEnabled(false);
501 private IAction createScrollLockAction() {
502 Action action = new Action("Scroll lock") {
506 scrollLockDisabled = !this.isChecked();
510 public int getStyle() {
511 return IAction.AS_CHECK_BOX;
514 action.setToolTipText("Scroll lock");
515 action.setImageDescriptor(ImageDescriptor.createFromFile(
516 this.getClass(), "/icons/lock_e.gif"));
517 action.setDisabledImageDescriptor(ImageDescriptor.createFromFile(
518 this.getClass(), "/icons/lock_d.gif"));
519 action.setEnabled(true);
523 private IAction createLogDetailsAction() {
524 Action action = new Action("Details...") {
528 Display.getDefault().asyncExec(new Runnable() {
532 LogEntry x = (LogEntry) ((IStructuredSelection) tree
533 .getViewer().getSelection()).getFirstElement();
535 new LogDetailsDialog(Display.getDefault()
536 .getActiveShell(), LogManager.getSeverityName(x
537 .getSeverity()), LogManager.getSeverityIcon(x
538 .getSeverity()), x.getDate(), x.getMessage())
544 action.setToolTipText("Details...");
545 action.setImageDescriptor(ImageDescriptor.createFromFile(
546 this.getClass(), "/icons/log_details_e.gif"));
547 action.setDisabledImageDescriptor(ImageDescriptor.createFromFile(
548 this.getClass(), "/icons/log_details_e.gif"));
549 action.setEnabled(false);
553 private IAction createFilterAction() {
554 Action action = new Action("Filters ...") {
558 FilterDialog fd = new FilterDialog(Display.getDefault()
559 .getActiveShell(), shownSeverities);
560 if (fd.open() == Window.OK) {
561 logManager.applyFilter(shownSeverities);
563 tree.getViewer().refresh();
566 action.setToolTipText("Filters ...");
568 action.setImageDescriptor(ImageDescriptor.createFromFile(
569 this.getClass(), "/icons/filter_e.gif"));
570 action.setDisabledImageDescriptor(ImageDescriptor.createFromFile(
571 this.getClass(), "/icons/filter_d.gif"));
572 action.setEnabled(true);
576 private IAction createActivateViewAction() {
577 Action action = new Action("Activate view on new events",
578 IAction.AS_CHECK_BOX) {
582 activateOnChange = this.isChecked();
585 action.setChecked(activateOnChange);
586 action.setToolTipText("Activate view on new events");
588 action.setImageDescriptor(ImageDescriptor.createFromFile(
589 this.getClass(), "/icons/prop_e.gif"));
590 action.setDisabledImageDescriptor(ImageDescriptor.createFromFile(
591 this.getClass(), "/icons/prop_d.gif"));
592 action.setEnabled(true);
596 private IAction createShowTextFilter() {
597 Action action = new Action("Show text filter", IAction.AS_CHECK_BOX) {
601 Text filterControl = tree.getFilterControl();
602 Composite filterComposite = filterControl.getParent();
603 GridData gd = (GridData) filterComposite.getLayoutData();
604 boolean visible = isChecked();
605 gd.exclude = !visible;
606 filterComposite.setVisible(visible);
607 filterControl.setText("");
609 filterControl.selectAll();
613 hideTextFilter = !visible;
616 action.setToolTipText("Show text filter");
618 action.setImageDescriptor(ImageDescriptor.createFromFile(
619 this.getClass(), "/icons/tree_mode_e.gif"));
620 action.setDisabledImageDescriptor(ImageDescriptor.createFromFile(
621 this.getClass(), "/icons/tree_mode_d.gif"));
622 action.setEnabled(true);
623 action.setChecked(!hideTextFilter);
624 if (hideTextFilter) {
630 private IContributionItem createGroupByAction() {
631 IMenuManager manager = new MenuManager("Order by");
632 manager.add(sortByTimeAction);
633 manager.add(sortBySeverityAction);
634 manager.add(sortByMessageAction);
638 class SortAction extends Action {
640 private final int sortBy;
642 public SortAction(String text, int sortBy) {
643 super(text, IAction.AS_RADIO_BUTTON);
644 this.sortBy = sortBy;
646 if (sortCandidate == sortBy) {
653 sortBySeverityAction.setChecked(false);
654 sortByTimeAction.setChecked(false);
655 sortCandidate = sortBy;
658 ViewerComparator comparator;
660 if (sortBy == ORDER_BY_SEVERITY) {
661 comparator = severityComparator;
662 column = severityColumn;
663 } else if (sortBy == ORDER_BY_TIME) {
664 comparator = dateComparator;
666 } else { // Order by message
667 comparator = messageComparator;
668 column = messageColumn;
670 TreeViewer viewer = tree.getViewer();
671 viewer.setComparator(comparator);
672 viewer.getTree().setSortColumn(column);
673 if (column.equals(sortColumn)) { // reverse sorting order
674 sortDirection = viewer.getTree().getSortDirection() == SWT.UP ? DOWN
676 viewer.getTree().setSortDirection(
677 sortDirection == UP ? SWT.UP : SWT.DOWN);
679 } else { // set this column as the one to sort by
680 sortDirection = DOWN;
681 viewer.getTree().setSortDirection(SWT.DOWN);
688 private void refresh() {
689 tree.getViewer().refresh();
693 public void setFocus() {
698 public void dispose() {
699 logManager.removeLogListener(logListener);