2 * Copyright 2015 Samsung Electronics All Rights Reserved.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package oic.simulator.serviceprovider.view;
19 import java.io.BufferedWriter;
20 import java.io.FileWriter;
21 import java.io.IOException;
22 import java.text.DateFormat;
23 import java.text.SimpleDateFormat;
24 import java.util.HashMap;
25 import java.util.List;
27 import oic.simulator.logger.LogContentProvider;
28 import oic.simulator.logger.LogEntry;
29 import oic.simulator.logger.LogLabelProvider;
30 import oic.simulator.serviceprovider.Activator;
31 import oic.simulator.serviceprovider.listener.ILogUIListener;
32 import oic.simulator.serviceprovider.manager.LogManager;
33 import oic.simulator.serviceprovider.utils.Constants;
34 import oic.simulator.serviceprovider.view.dialogs.FilterDialog;
35 import oic.simulator.serviceprovider.view.dialogs.LogDetailsDialog;
37 import org.eclipse.jface.action.Action;
38 import org.eclipse.jface.action.IAction;
39 import org.eclipse.jface.action.IContributionItem;
40 import org.eclipse.jface.action.IMenuManager;
41 import org.eclipse.jface.action.IToolBarManager;
42 import org.eclipse.jface.action.MenuManager;
43 import org.eclipse.jface.action.Separator;
44 import org.eclipse.jface.dialogs.MessageDialog;
45 import org.eclipse.jface.resource.ImageDescriptor;
46 import org.eclipse.jface.viewers.DoubleClickEvent;
47 import org.eclipse.jface.viewers.IDoubleClickListener;
48 import org.eclipse.jface.viewers.ISelectionChangedListener;
49 import org.eclipse.jface.viewers.IStructuredSelection;
50 import org.eclipse.jface.viewers.SelectionChangedEvent;
51 import org.eclipse.jface.viewers.StructuredSelection;
52 import org.eclipse.jface.viewers.TreeViewer;
53 import org.eclipse.jface.viewers.Viewer;
54 import org.eclipse.jface.viewers.ViewerComparator;
55 import org.eclipse.jface.window.Window;
56 import org.eclipse.swt.SWT;
57 import org.eclipse.swt.events.KeyEvent;
58 import org.eclipse.swt.events.KeyListener;
59 import org.eclipse.swt.events.SelectionAdapter;
60 import org.eclipse.swt.events.SelectionEvent;
61 import org.eclipse.swt.layout.GridData;
62 import org.eclipse.swt.widgets.Composite;
63 import org.eclipse.swt.widgets.Display;
64 import org.eclipse.swt.widgets.FileDialog;
65 import org.eclipse.swt.widgets.Text;
66 import org.eclipse.swt.widgets.Tree;
67 import org.eclipse.swt.widgets.TreeColumn;
68 import org.eclipse.swt.widgets.TreeItem;
69 import org.eclipse.ui.IActionBars;
70 import org.eclipse.ui.IWorkbenchActionConstants;
71 import org.eclipse.ui.IWorkbenchPage;
72 import org.eclipse.ui.dialogs.FilteredTree;
73 import org.eclipse.ui.dialogs.PatternFilter;
74 import org.eclipse.ui.part.ViewPart;
75 import org.oic.simulator.ILogger.Level;
78 * This class manages and shows the log view in the perspective.
80 public class LogView extends ViewPart {
82 public static final String VIEW_ID = "oic.simulator.serviceprovider.view.log";
84 private LogManager logManager;
85 private ILogUIListener logListener;
87 private LogContentProvider treeContentProvider;
89 private FilteredTree tree;
90 private TreeColumn severityColumn;
91 private TreeColumn dateColumn;
92 private TreeColumn messageColumn;
94 private IAction exportLogAction;
95 private IAction clearLogAction;
96 private IAction deleteLogAction;
97 private IAction scrollLockAction;
98 private IAction logDetailsAction;
99 private IAction filterAction;
100 private IAction activateViewAction;
101 private IAction showTextFilter;
102 private IContributionItem groupByAction;
104 private HashMap<Integer, Boolean> shownSeverities = new HashMap<Integer, Boolean>();
106 private boolean activateOnChange = false;
108 private boolean hideTextFilter = false;
110 private boolean scrollLockDisabled;
112 public static final int ORDER_BY_TIME = 0;
113 public static final int ORDER_BY_SEVERITY = 1;
114 public static final int ORDER_BY_MESSAGE = 2;
116 int sortCandidate = ORDER_BY_TIME;
118 SortAction sortByTimeAction = new SortAction(
121 SortAction sortBySeverityAction = new SortAction(
124 SortAction sortByMessageAction = new SortAction(
128 private ViewerComparator dateComparator;
129 private ViewerComparator severityComparator;
130 private ViewerComparator messageComparator;
132 private TreeColumn sortColumn = null;
133 private static int DOWN = 1;
134 private static int UP = -1;
135 private int sortDirection = DOWN;
139 logListener = new ILogUIListener() {
142 public void logChanged(final List<LogEntry> entry) {
143 Display.getDefault().asyncExec(new Runnable() {
147 TreeViewer viewer = tree.getViewer();
148 if (viewer.getControl().isDisposed()) {
151 viewer.setInput(entry);
158 public void logAdded(final LogEntry added) {
159 Display.getDefault().asyncExec(new Runnable() {
163 TreeViewer viewer = tree.getViewer();
164 if (viewer.getControl().isDisposed()) {
167 LogContentProvider provider = (LogContentProvider) viewer
168 .getContentProvider();
169 provider.addLog(added);
170 tree.getViewer().add(viewer.getInput(), added);
171 @SuppressWarnings("unchecked")
172 List<LogEntry> input = (List<LogEntry>) viewer
174 if (input.size() > Constants.LOG_SIZE) {
175 viewer.remove(viewer.getInput(), 0);
182 private void updateTree(boolean needscroll) {
183 if (activateOnChange) {
184 IWorkbenchPage page = Activator.getDefault().getWorkbench()
185 .getActiveWorkbenchWindow().getActivePage();
187 page.bringToTop(LogView.this);
190 if (scrollLockDisabled && needscroll) {
191 Tree tree2 = tree.getViewer().getTree();
192 if (tree2.getItemCount() > 0) {
193 TreeItem item = tree2.getItem(tree2.getItemCount() - 1);
194 tree2.setTopItem(item);
195 deleteLogAction.setEnabled(true);
201 logManager = Activator.getDefault().getLogManager();
203 // Initially state of scroll lock
204 scrollLockDisabled = true;
208 public void createPartControl(Composite parent) {
209 PatternFilter filter = new PatternFilter() {
211 DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss.SSS");
214 protected boolean isLeafMatch(Viewer viewer, Object element) {
215 if (element instanceof LogEntry) {
216 LogEntry logEntry = (LogEntry) element;
217 String severity = LogManager.getSeverityName(logEntry
219 String date = dateFormat.format(logEntry.getDate());
220 String message = logEntry.getMessage();
221 return wordMatches(severity) || wordMatches(date)
222 || wordMatches(message);
227 filter.setIncludeLeadingWildcard(true);
228 tree = new FilteredTree(parent, SWT.SINGLE | SWT.H_SCROLL
229 | SWT.V_SCROLL | SWT.FULL_SELECTION, filter, true);
233 createColumnComparators();
237 setDefaultShownSeverities();
239 IActionBars actionBars = getViewSite().getActionBars();
240 IToolBarManager toolBarManager = actionBars.getToolBarManager();
241 toolBarManager.add(exportLogAction);
242 toolBarManager.add(clearLogAction);
243 toolBarManager.add(deleteLogAction);
244 toolBarManager.add(scrollLockAction);
246 .add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
248 IMenuManager mgr = actionBars.getMenuManager();
249 mgr.add(groupByAction);
250 mgr.add(new Separator());
251 mgr.add(filterAction);
252 mgr.add(new Separator());
253 mgr.add(activateViewAction);
254 mgr.add(showTextFilter);
256 addManagerListeners();
258 if (sortCandidate == ORDER_BY_TIME) {
259 sortByTimeAction.run();
260 } else if (sortCandidate == ORDER_BY_SEVERITY) {
261 sortBySeverityAction.run();
262 } else { // order_selected == ORDER_BY_NONE
263 sortByMessageAction.run();
268 private void setupFilteredTree() {
269 tree.setLayoutData(new GridData(GridData.FILL_BOTH));
270 final Tree innerTree = tree.getViewer().getTree();
271 innerTree.setLinesVisible(true);
273 severityColumn = new TreeColumn(innerTree, SWT.LEFT);
274 severityColumn.setText("Severity");
275 severityColumn.setWidth(110);
276 severityColumn.addSelectionListener(new SelectionAdapter() {
279 public void widgetSelected(SelectionEvent e) {
280 sortBySeverityAction.run();
283 dateColumn = new TreeColumn(innerTree, SWT.LEFT);
284 dateColumn.setText("Time");
285 dateColumn.setWidth(110);
286 dateColumn.addSelectionListener(new SelectionAdapter() {
289 public void widgetSelected(SelectionEvent e) {
290 sortByTimeAction.run();
293 messageColumn = new TreeColumn(innerTree, SWT.LEFT);
294 messageColumn.setText("Message");
295 messageColumn.setWidth(180);
296 messageColumn.addSelectionListener(new SelectionAdapter() {
298 public void widgetSelected(SelectionEvent e) {
299 sortByMessageAction.run();
303 innerTree.setHeaderVisible(true);
305 treeContentProvider = new LogContentProvider();
307 tree.getViewer().setContentProvider(treeContentProvider);
308 tree.getViewer().setLabelProvider(new LogLabelProvider());
310 tree.getViewer().setInput(logManager.getLogEntries());
312 tree.getViewer().addSelectionChangedListener(
313 new ISelectionChangedListener() {
316 public void selectionChanged(SelectionChangedEvent event) {
317 deleteLogAction.setEnabled(!tree.getViewer()
318 .getSelection().isEmpty());
319 logDetailsAction.setEnabled(!tree.getViewer()
320 .getSelection().isEmpty());
324 tree.getViewer().getTree().addKeyListener(new KeyListener() {
327 public void keyReleased(KeyEvent e) {
331 public void keyPressed(KeyEvent e) {
332 if (e.character == (char) 127) { // If delete key is pressed
333 if (deleteLogAction.isEnabled()) {
334 deleteLogAction.run();
340 tree.getViewer().addDoubleClickListener(new IDoubleClickListener() {
343 public void doubleClick(DoubleClickEvent event) {
344 logDetailsAction.run();
349 private void createColumnComparators() {
350 dateComparator = new ViewerComparator() {
353 public int compare(Viewer viewer, Object e1, Object e2) {
354 LogEntry l1 = (LogEntry) e1;
355 LogEntry l2 = (LogEntry) e2;
356 return l1.getDate().compareTo(l2.getDate()) * sortDirection;
360 severityComparator = new ViewerComparator() {
363 public int compare(Viewer viewer, Object e1, Object e2) {
364 LogEntry l1 = (LogEntry) e1;
365 LogEntry l2 = (LogEntry) e2;
366 if (l1.getSeverity() < l2.getSeverity()) {
367 return -1 * sortDirection;
369 if (l1.getSeverity() > l2.getSeverity()) {
370 return 1 * sortDirection;
376 messageComparator = new ViewerComparator() {
379 public int compare(Viewer viewer, Object e1, Object e2) {
380 LogEntry l1 = (LogEntry) e1;
381 LogEntry l2 = (LogEntry) e2;
382 return l1.getMessage().compareTo(l2.getMessage())
389 private void setDefaultShownSeverities() {
390 shownSeverities.put(Level.INFO.ordinal(), true);
391 shownSeverities.put(Level.DEBUG.ordinal(), true);
392 shownSeverities.put(Level.WARNING.ordinal(), true);
393 shownSeverities.put(Level.ERROR.ordinal(), true);
396 private void addManagerListeners() {
397 logManager.addLogListener(logListener);
398 logManager.applyFilter(shownSeverities);
401 private void createActions() {
402 exportLogAction = createExportLogAction();
403 clearLogAction = createClearLogAction();
404 deleteLogAction = createDeleteLogAction();
405 scrollLockAction = createScrollLockAction();
406 logDetailsAction = createLogDetailsAction();
408 filterAction = createFilterAction();
409 activateViewAction = createActivateViewAction();
410 showTextFilter = createShowTextFilter();
411 groupByAction = createGroupByAction();
414 private IAction createExportLogAction() {
415 Action action = new Action("Export log") {
418 FileDialog fd = new FileDialog(Display.getDefault()
419 .getActiveShell(), SWT.SAVE);
420 fd.setOverwrite(true);
421 fd.setFileName("OIC_Simulator_ServerLog.log");
422 fd.setFilterExtensions(Constants.SAVE_LOG_FILTER_EXTENSIONS);
423 String name = fd.open();
424 List<LogEntry> logEntries = logManager.getLogEntries();
425 StringBuilder sb = new StringBuilder();
426 for (LogEntry entry : logEntries) {
427 sb.append(entry.toString());
429 String data = sb.toString();
430 BufferedWriter out = null;
432 out = new BufferedWriter(new FileWriter(name));
434 } catch (IOException e) {
436 MessageDialog.openError(
437 Display.getDefault().getActiveShell(),
439 "Could not export log. IO exception: "
446 } catch (IOException e) {
447 System.out.println("Error occurred during close.");
452 action.setToolTipText("Export log");
454 action.setImageDescriptor(ImageDescriptor.createFromFile(
455 this.getClass(), "/icons/export_log_e.gif"));
456 action.setDisabledImageDescriptor(ImageDescriptor.createFromFile(
457 this.getClass(), "/icons/export_log_d.gif"));
458 action.setEnabled(true);
463 private IAction createClearLogAction() {
464 Action action = new Action("Clear log") {
468 logManager.clearLog();
471 action.setToolTipText("Clear log");
473 action.setImageDescriptor(ImageDescriptor.createFromFile(
474 this.getClass(), "/icons/clear_e.gif"));
475 action.setDisabledImageDescriptor(ImageDescriptor.createFromFile(
476 this.getClass(), "/icons/clear_d.gif"));
477 action.setEnabled(true);
481 private IAction createDeleteLogAction() {
482 Action action = new Action("Delete log entry") {
485 @SuppressWarnings("unchecked")
487 IStructuredSelection selection = (IStructuredSelection) tree
488 .getViewer().getSelection();
489 List<LogEntry> entries = (List<LogEntry>) tree.getViewer()
491 LogEntry selectedEntry = (LogEntry) selection.getFirstElement();
492 if (null != selectedEntry) {
493 LogEntry toBeShownEntry = null;
494 for (LogEntry entry : entries) {
495 if (entry.equals(selectedEntry)) {
496 int size = entries.size();
497 int index = entries.indexOf(selectedEntry);
498 if (index + 1 < size) {
499 toBeShownEntry = entries.get(index + 1);
500 } else if (index > 0) {
501 toBeShownEntry = entries.get(index - 1);
506 logManager.removeEntry(selectedEntry);
507 if (null != toBeShownEntry) {
508 tree.getViewer().setSelection(
509 new StructuredSelection(toBeShownEntry));
514 action.setToolTipText("Delete log entry");
515 action.setImageDescriptor(ImageDescriptor.createFromFile(
516 this.getClass(), "/icons/delete_e.gif"));
517 action.setDisabledImageDescriptor(ImageDescriptor.createFromFile(
518 this.getClass(), "/icons/delete_d.gif"));
519 action.setEnabled(false);
523 private IAction createScrollLockAction() {
524 Action action = new Action("Scroll lock") {
528 scrollLockDisabled = !this.isChecked();
532 public int getStyle() {
533 return IAction.AS_CHECK_BOX;
536 action.setToolTipText("Scroll lock");
537 action.setImageDescriptor(ImageDescriptor.createFromFile(
538 this.getClass(), "/icons/lock_e.gif"));
539 action.setDisabledImageDescriptor(ImageDescriptor.createFromFile(
540 this.getClass(), "/icons/lock_d.gif"));
541 action.setEnabled(true);
545 private IAction createLogDetailsAction() {
546 Action action = new Action("Details...") {
550 Display.getDefault().asyncExec(new Runnable() {
554 LogEntry x = (LogEntry) ((IStructuredSelection) tree
555 .getViewer().getSelection()).getFirstElement();
557 new LogDetailsDialog(Display.getDefault()
558 .getActiveShell(), LogManager.getSeverityName(x
559 .getSeverity()), LogManager.getSeverityIcon(x
560 .getSeverity()), x.getDate(), x.getMessage())
566 action.setToolTipText("Details...");
567 action.setImageDescriptor(ImageDescriptor.createFromFile(
568 this.getClass(), "/icons/log_details_e.gif"));
569 action.setDisabledImageDescriptor(ImageDescriptor.createFromFile(
570 this.getClass(), "/icons/log_details_e.gif"));
571 action.setEnabled(false);
575 private IAction createFilterAction() {
576 Action action = new Action("Filters ...") {
580 FilterDialog fd = new FilterDialog(Display.getDefault()
581 .getActiveShell(), shownSeverities);
582 if (fd.open() == Window.OK) {
583 logManager.applyFilter(shownSeverities);
585 tree.getViewer().refresh();
588 action.setToolTipText("Filters ...");
590 action.setImageDescriptor(ImageDescriptor.createFromFile(
591 this.getClass(), "/icons/filter_e.gif"));
592 action.setDisabledImageDescriptor(ImageDescriptor.createFromFile(
593 this.getClass(), "/icons/filter_d.gif"));
594 action.setEnabled(true);
598 private IAction createActivateViewAction() {
599 Action action = new Action("Activate view on new events",
600 IAction.AS_CHECK_BOX) {
604 activateOnChange = this.isChecked();
607 action.setChecked(activateOnChange);
608 action.setToolTipText("Activate view on new events");
610 action.setImageDescriptor(ImageDescriptor.createFromFile(
611 this.getClass(), "/icons/prop_e.gif"));
612 action.setDisabledImageDescriptor(ImageDescriptor.createFromFile(
613 this.getClass(), "/icons/prop_d.gif"));
614 action.setEnabled(true);
618 private IAction createShowTextFilter() {
619 Action action = new Action("Show text filter", IAction.AS_CHECK_BOX) {
623 Text filterControl = tree.getFilterControl();
624 Composite filterComposite = filterControl.getParent();
625 GridData gd = (GridData) filterComposite.getLayoutData();
626 boolean visible = isChecked();
627 gd.exclude = !visible;
628 filterComposite.setVisible(visible);
629 filterControl.setText("");
631 filterControl.selectAll();
635 hideTextFilter = !visible;
638 action.setToolTipText("Show text filter");
640 action.setImageDescriptor(ImageDescriptor.createFromFile(
641 this.getClass(), "/icons/tree_mode_e.gif"));
642 action.setDisabledImageDescriptor(ImageDescriptor.createFromFile(
643 this.getClass(), "/icons/tree_mode_d.gif"));
644 action.setEnabled(true);
645 action.setChecked(!hideTextFilter);
646 if (hideTextFilter) {
652 private IContributionItem createGroupByAction() {
653 IMenuManager manager = new MenuManager("Order by");
654 manager.add(sortByTimeAction);
655 manager.add(sortBySeverityAction);
656 manager.add(sortByMessageAction);
660 class SortAction extends Action {
662 private final int sortBy;
664 public SortAction(String text, int sortBy) {
665 super(text, IAction.AS_RADIO_BUTTON);
666 this.sortBy = sortBy;
668 if (sortCandidate == sortBy) {
675 sortBySeverityAction.setChecked(false);
676 sortByTimeAction.setChecked(false);
677 sortCandidate = sortBy;
680 ViewerComparator comparator;
682 if (sortBy == ORDER_BY_SEVERITY) {
683 comparator = severityComparator;
684 column = severityColumn;
685 } else if (sortBy == ORDER_BY_TIME) {
686 comparator = dateComparator;
688 } else { // Order by message
689 comparator = messageComparator;
690 column = messageColumn;
692 TreeViewer viewer = tree.getViewer();
693 viewer.setComparator(comparator);
694 viewer.getTree().setSortColumn(column);
695 if (column.equals(sortColumn)) { // reverse sorting order
696 sortDirection = viewer.getTree().getSortDirection() == SWT.UP ? DOWN
698 viewer.getTree().setSortDirection(
699 sortDirection == UP ? SWT.UP : SWT.DOWN);
701 } else { // set this column as the one to sort by
702 sortDirection = DOWN;
703 viewer.getTree().setSortDirection(SWT.DOWN);
710 private void refresh() {
711 tree.getViewer().refresh();
715 public void setFocus() {
720 public void dispose() {
721 logManager.removeLogListener(logListener);