Package com.salesforce.ide.ui.views.log

Source Code of com.salesforce.ide.ui.views.log.LogView

/*******************************************************************************
* Copyright (c) 2014 Salesforce.com, inc..
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*     Salesforce.com, inc. - initial API and implementation
******************************************************************************/
package com.salesforce.ide.ui.views.log;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import org.apache.log4j.Logger;
import org.eclipse.core.runtime.ILogListener;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.viewers.ITableFontProvider;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jface.viewers.ITreeContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerComparator;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeColumn;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IViewReference;
import org.eclipse.ui.IViewSite;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.dialogs.FilteredTree;
import org.eclipse.ui.dialogs.PatternFilter;
import org.eclipse.ui.part.ViewPart;

import com.salesforce.ide.core.internal.utils.Constants;
import com.salesforce.ide.core.internal.utils.Utils;
import com.salesforce.ide.ui.internal.ForceImages;
import com.salesforce.ide.ui.internal.utils.UIMessages;
import com.salesforce.ide.ui.internal.utils.UIUtils;

/**
* Displays Force.com IDE logs found in the Platform log file
*
* @author cwall
*
*/
public class LogView extends ViewPart implements ILogListener {

    private static final Logger logger = Logger.getLogger(LogView.class);

    protected static final String EXCEPTION = "Exception";
    protected static final String OPEN_LOG_EXCEPTION = "(Open log file for full message and/or stacktrace)";
    protected static final String OPEN_LOG_EXCEPTION_FULL = "... " + OPEN_LOG_EXCEPTION;
    protected static final String OPEN_LOG_FULL = "... (Open log file for full message)";
    protected static final int MAX_LABEL_LENGTH = 200;
    protected static final byte SEVERITY = 0x0;
    protected static final byte MESSAGE = 0x1;
    protected static final byte DATE = 0x2;
    protected static final int ASCENDING = 1;
    protected static final int DESCENDING = -1;
    private static final int MAX_LOG_VIEW_ENTRIES = 500;

    private int severityOrder;
    private int messageOrder;
    private int dateOrder;
    private List<LogEntry> logEntries = null;
    private List<LogEntry> batchedLogEntries = null;
    private boolean batchEntries;
    private File logFile = null;
    private Comparator<? extends LogEntry> logComparator = null;
    private boolean firstEvent = true;
    private TreeColumn logSeverityColumn = null;
    private TreeColumn logMessageColumn = null;
    private TreeColumn logDateColumn = null;
    private Tree logTree = null;
    private FilteredTree logFilteredTree = null;
    private final LogViewLabelProvider logViewLabelProvider = new LogViewLabelProvider();
    private Action openLogFileAction = null;
    private Action openLogFolderAction = null;
    private LogView instance = null;

    public LogView() {
      this( Platform.getLogFileLocation().toFile());
    }
    public LogView(File logFile) {
        logEntries = new ArrayList<LogEntry>();
        batchedLogEntries = new ArrayList<LogEntry>();
        this.logFile = logFile;
        // maintain instance of self so that the perspective listener focus on the particular log view instance
        instance = this;
    }

    protected File getLogFile() {
        return logFile;
    }

    public boolean isBatchEntries() {
        return batchEntries;
    }

    public List<LogEntry> getLogEntries() {
        return logEntries;
    }

    public List<LogEntry> getBatchedLogEntries() {
        return batchedLogEntries;
    }

    public int getBatchedLogEntriesCount() {
        return Utils.isNotEmpty(batchedLogEntries) ? batchedLogEntries.size() : 0;
    }

    public TreeColumn getLogMessageColumn() {
        return logMessageColumn;
    }

    public TreeColumn getLogDateColumn() {
        return logDateColumn;
    }

    public TreeColumn getLogSeverityColumn() {
        return logSeverityColumn;
    }

    public void setLogSeverityColumn(TreeColumn logSeverityColumn) {
        this.logSeverityColumn = logSeverityColumn;
    }

    public Tree getLogTree() {
        return logTree;
    }

    public FilteredTree getLogFilteredTree() {
        return logFilteredTree;
    }

    public LogViewLabelProvider getLogViewLabelProvider() {
        return logViewLabelProvider;
    }

    public Action getOpenLogFileAction() {
        return openLogFileAction;
    }

    public Action getOpenLogFolderAction() {
        return openLogFolderAction;
    }

    @Override
    public void createPartControl(Composite parent) {
        Composite composite = new Composite(parent, SWT.NONE);
        GridLayout layout = new GridLayout();
        layout.horizontalSpacing = 0;
        layout.verticalSpacing = 0;
        layout.marginWidth = 0;
        layout.marginHeight = 0;
        composite.setLayout(layout);

        readLogFile();
        initViewer(composite);
        initActions();
        initializeViewerSorter();
        getSite().setSelectionProvider(logFilteredTree.getViewer());

        logTree.setToolTipText("View Force.com IDE Log");

        Platform.addLogListener(this);

        // batch entries when view is hidden; display batched entries when view is visible
        getSite().getPage().addPartListener(new org.eclipse.ui.IPartListener2() {
            public void partHidden(IWorkbenchPartReference partRef) {
                if (!(partRef instanceof IViewReference)) {
                    return;
                }

                IWorkbenchPart part = partRef.getPart(false);
                if (part == null || !part.equals(instance)) {
                    return;
                }

                batchEntries = true;
            }

            public void partVisible(IWorkbenchPartReference partRef) {
                if (!(partRef instanceof IViewReference)) {
                    return;
                }

                IWorkbenchPart part = partRef.getPart(false);
                if (part == null || !part.equals(instance)) {
                    return;
                }

                if (Utils.isNotEmpty(batchedLogEntries)) {
                    displayBatchedEntries();
                }

                batchEntries = false;
            }

            public void partActivated(IWorkbenchPartReference partRef) {}

            public void partDeactivated(IWorkbenchPartReference partRef) {}

            public void partBroughtToTop(IWorkbenchPartReference partRef) {}

            public void partInputChanged(IWorkbenchPartReference partRef) {}

            public void partOpened(IWorkbenchPartReference partRef) {}

            public void partClosed(IWorkbenchPartReference partRef) {}
        });

        UIUtils.setHelpContext(logFilteredTree, this.getClass().getSimpleName());
    }

    private void initActions() {
        IActionBars bars = getViewSite().getActionBars();
        IToolBarManager toolBarManager = bars.getToolBarManager();

        // init open file and folder actions
        openLogFileAction = new OpenLogFileAction();
        toolBarManager.add(openLogFileAction);
        openLogFolderAction = new OpenLogFolderAction();
        toolBarManager.add(openLogFolderAction);
    }

    private void initViewer(Composite parent) {
        logFilteredTree = new FilteredTree(parent, SWT.FULL_SELECTION, new PatternFilter() {
            @Override
            protected boolean isLeafMatch(Viewer viewer, Object element) {
                if (element instanceof LogEntry) {
                    LogEntry logEntry = (LogEntry) element;
                    String message = logEntry.getMessage();
                    String date = logEntry.getFormattedDate();
                    return wordMatches(message) || wordMatches(date);
                }
                return false;
            }
        });

        logFilteredTree.setInitialText(UIMessages.getString("FilterInitialText"));
        logTree = logFilteredTree.getViewer().getTree();
        logTree.setLinesVisible(true);

        logSeverityColumn = new TreeColumn(logTree, SWT.LEFT);
        logSeverityColumn.setText("Severity");
        logSeverityColumn.setWidth(70);
        logSeverityColumn.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                severityOrder *= -1;
                ViewerComparator comparator = getViewerComparator(SEVERITY);
                logFilteredTree.getViewer().setComparator(comparator);
                setComparator(SEVERITY);
                setColumnSorting(logSeverityColumn, severityOrder);
            }
        });

        logMessageColumn = new TreeColumn(logTree, SWT.LEFT);
        logMessageColumn.setText("Message");
        logMessageColumn.setWidth(500);
        logMessageColumn.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                messageOrder *= -1;
                ViewerComparator comparator = getViewerComparator(MESSAGE);
                logFilteredTree.getViewer().setComparator(comparator);
                setComparator(MESSAGE);
                setColumnSorting(logMessageColumn, messageOrder);
            }
        });

        logDateColumn = new TreeColumn(logTree, SWT.LEFT);
        logDateColumn.setText("Date");
        logDateColumn.setWidth(75);
        logDateColumn.addSelectionListener(new SelectionAdapter() {
            @Override
            public void widgetSelected(SelectionEvent e) {
                dateOrder *= -1;
                ViewerComparator comparator = getViewerComparator(DATE);
                logFilteredTree.getViewer().setComparator(comparator);
                setComparator(DATE);
                setColumnSorting(logDateColumn, dateOrder);
            }
        });

        logTree.setHeaderVisible(true);

        logFilteredTree.getViewer().setContentProvider(new LogViewContentProvider(this));
        logFilteredTree.getViewer().setLabelProvider(logViewLabelProvider);
        logFilteredTree.getViewer().setInput(this);
    }

    private void initializeViewerSorter() {
        byte orderType = DATE;
        ViewerComparator comparator = getViewerComparator(orderType);
        logFilteredTree.getViewer().setComparator(comparator);
        if (orderType == MESSAGE) {
            setColumnSorting(logMessageColumn, messageOrder);
        } else if (orderType == DATE) {
            setColumnSorting(logDateColumn, dateOrder);
        }
    }

    private void setColumnSorting(TreeColumn column, int order) {
        logTree.setSortColumn(column);
        logTree.setSortDirection(order == ASCENDING ? SWT.UP : SWT.DOWN);
    }

    @Override
    public void dispose() {
        Platform.removeLogListener(instance);
        logViewLabelProvider.dispose();
        logFilteredTree.dispose();
        super.dispose();
    }

    public LogEntry[] getElements() {
        return logEntries.toArray(new LogEntry[logEntries.size()]);
    }

    private void readLogFile() {
        logEntries.clear();

        try {
            // parse log file and create log entries
            List<LogEntry> result = new ArrayList<LogEntry>();
            LogReader.parseLogFile(logFile, result);
            logEntries.addAll(result);
            limitEntriesCount();
        } catch (Exception e) {
            logger.error("Unable to read Force.com IDE log file", e);
            Utils.openError(e, true, "Unable to read Force.com IDE log file");
        }
    }

    private void limitEntriesCount() {
        int entriesCount = getEntriesCount();

        if (entriesCount <= MAX_LOG_VIEW_ENTRIES) {
            return;
        }

        logEntries.subList(0, logEntries.size() - MAX_LOG_VIEW_ENTRIES).clear();
    }

    private int getEntriesCount() {
        return logEntries.size();
    }

    public void logging(IStatus status, String plugin) {
        // skip non-Force.com log events
        if (Utils.isEmpty(status.getPlugin()) || !status.getPlugin().contains(Constants.FORCE_PLUGIN_PREFIX)) {
            return;
        }

        if (batchEntries) {
            LogEntry entry = new LogEntry(status);
            batchedLogEntries.add(entry);
            return;
        }

        if (firstEvent) {
            readLogFile();
            asyncRefresh(true);
            firstEvent = false;
        } else {
            LogEntry entry = new LogEntry(status);
            if (!batchedLogEntries.isEmpty()) {
                batchedLogEntries.add(entry);
                displayBatchedEntries();
            } else {
                pushEntry(entry);
            }
        }
    }

    private void displayBatchedEntries() {
        Job job = new Job("Batching Force.com IDE log entries...") {
            @Override
            protected IStatus run(IProgressMonitor monitor) {
                for (int i = 0; i < batchedLogEntries.size(); i++) {
                    if (!monitor.isCanceled()) {
                        LogEntry entry = batchedLogEntries.get(i);
                        pushEntry(entry);
                        batchedLogEntries.remove(i);
                    }
                }

                if (batchedLogEntries.size() > 0) {
                    batchedLogEntries.clear();
                }

                asyncRefresh(true);
                return Status.OK_STATUS;
            }
        };
        job.schedule();
    }

    private synchronized void pushEntry(LogEntry entry) {
        logEntries.addAll(Collections.singletonList(entry));
        limitEntriesCount();
        asyncRefresh(true);
    }

    private void asyncRefresh(final boolean activate) {
        if (logTree.isDisposed()) {
            return;
        }

        Display display = logTree.getDisplay();
        if (display != null) {
            display.asyncExec(new Runnable() {
                public void run() {
                    if (!logTree.isDisposed()) {
                        TreeViewer viewer = logFilteredTree.getViewer();
                        viewer.refresh();
                    }
                }
            });
        }
    }

    @Override
    public void setFocus() {
        if (logFilteredTree != null && !logFilteredTree.isDisposed()) {
            logFilteredTree.setFocus();
        }
    }

    @Override
    public void init(IViewSite site) throws PartInitException {
        super.init(site);
        dateOrder = DESCENDING;
        messageOrder = DESCENDING;
        severityOrder = DESCENDING;
        setComparator(DATE);
    }

    public Comparator<? extends LogEntry> getComparator() {
        return logComparator;
    }

    private void setComparator(byte sortType) {
        if (sortType == DATE) {
            logComparator = new Comparator<LogEntry>() {
                public int compare(LogEntry entry1, LogEntry entry2) {
                    long date1 = (entry1).getDate().getTime();
                    long date2 = (entry2).getDate().getTime();

                    if (date1 == date2) {
                        int result = logEntries.indexOf(entry2) - logEntries.indexOf(entry1);
                        if (dateOrder == DESCENDING) {
                            result *= DESCENDING;
                        }
                        return result;
                    }
                    if (dateOrder == DESCENDING) {
                        return date1 > date2 ? DESCENDING : ASCENDING;
                    }

                    return date1 < date2 ? DESCENDING : ASCENDING;
                }
            };
        } else if (sortType == MESSAGE) {
            logComparator = new Comparator<LogEntry>() {
                public int compare(LogEntry entry1, LogEntry entry2) {
                    return String.CASE_INSENSITIVE_ORDER.compare(entry1.getMessage(true), entry2.getMessage(true))
                            * messageOrder;
                }
            };
        } else {
            logComparator = new Comparator<LogEntry>() {
                public int compare(LogEntry entry1, LogEntry entry2) {
                    if (entry1.getSeverity() == entry2.getSeverity()) {
                        return 0;
                    } else if (entry1.getSeverity() > entry2.getSeverity()) {
                        return 1 * severityOrder;
                    } else {
                        return -1 * severityOrder;
                    }
                }
            };
        }
    }

    private ViewerComparator getViewerComparator(byte sortType) {
        if (sortType == SEVERITY) {
            return new ViewerComparator() {
                @Override
                public int compare(Viewer viewer, Object e1, Object e2) {
                    if ((e1 instanceof LogEntry) && (e2 instanceof LogEntry)) {
                        LogEntry entry1 = (LogEntry) e1;
                        LogEntry entry2 = (LogEntry) e2;
                        if (entry1.getSeverity() == entry2.getSeverity()) {
                            return 0;
                        } else if (entry1.getSeverity() > entry2.getSeverity()) {
                            return 1 * severityOrder;
                        } else {
                            return -1 * severityOrder;
                        }
                    }
                    return 0;
                }
            };
        } else if (sortType == MESSAGE) {
            return new ViewerComparator() {
                @Override
                public int compare(Viewer viewer, Object e1, Object e2) {
                    if ((e1 instanceof LogEntry) && (e2 instanceof LogEntry)) {
                        LogEntry entry1 = (LogEntry) e1;
                        LogEntry entry2 = (LogEntry) e2;
                        return String.CASE_INSENSITIVE_ORDER.compare(entry1.getMessage(true), entry2.getMessage(true))
                                * messageOrder;
                    }
                    return 0;
                }
            };
        } else {
            return new ViewerComparator() {
                @Override
                public int compare(Viewer viewer, Object e1, Object e2) {
                    long date1 = 0;
                    long date2 = 0;
                    if ((e1 instanceof LogEntry) && (e2 instanceof LogEntry)) {
                        date1 = ((LogEntry) e1).getDate().getTime();
                        date2 = ((LogEntry) e2).getDate().getTime();
                    }

                    if (date1 == date2) {
                        int result = logEntries.indexOf(e2) - logEntries.indexOf(e1);
                        if (dateOrder == DESCENDING)
                            result *= DESCENDING;
                        return result;
                    }
                    if (dateOrder == DESCENDING)
                        return date1 > date2 ? DESCENDING : ASCENDING;
                    return date1 < date2 ? DESCENDING : ASCENDING;
                }
            };
        }
    }

    public void sortByDateDescending() {
        setColumnSorting(logDateColumn, DESCENDING);
    }

    // content and label providers
    class LogViewContentProvider implements ITreeContentProvider {
        private LogView logView = null;

        public LogViewContentProvider(LogView logView) {
            this.logView = logView;
        }

        public void dispose() {}

        public Object[] getChildren(Object element) {
            return ((LogEntry) element).getChildren(element);
        }

        public Object[] getElements(Object element) {
            return logView.getElements();
        }

        public Object getParent(Object element) {
            return ((LogEntry) element).getParent(element);
        }

        public boolean hasChildren(Object element) {
            return ((LogEntry) element).getChildren(element).length > 0;
        }

        public void inputChanged(Viewer viewer, Object oldInput, Object newInput) {}

        public boolean isDeleted(Object element) {
            return false;
        }
    }

    class LogViewLabelProvider extends LabelProvider implements ITableLabelProvider, ITableFontProvider {
      
       

        public LogViewLabelProvider() {}

        @Override
        public void dispose() {
            super.dispose();
        }

        public Image getColumnImage(Object element, int columnIndex) {
          LogEntry entry = (LogEntry) element;
            if (columnIndex == 0) {
                switch (entry.getSeverity()) {
                case IStatus.INFO:
                    return ForceImages.get(ForceImages.INFO_ICON);
                case IStatus.OK:
                    return ForceImages.get(ForceImages.DEBUG_ICON);
                case IStatus.WARNING:
                    return ForceImages.get(ForceImages.WARNING_ICON);
                case LogEntry.TRACE_SEVERITY:
                    return ForceImages.get(ForceImages.TRACE_ICON);
                default:
                    return ForceImages.get(ForceImages.ERROR_ICON);
                }
            }
            return null;
        }

        public String getColumnText(Object element, int columnIndex) {
        if (!(element instanceof LogEntry)) {
                return "Log statement not found";
            }

            LogEntry entry = (LogEntry) element;
            switch (columnIndex) {
            case 1:
                String message = entry.getMessage(true);
                if (Utils.isNotEmpty(message)) {
                    message = message.trim();
                    if (entry.getSeverity() == IStatus.WARNING || entry.getSeverity() == IStatus.ERROR) {
                        return getExceptionMessage(message, entry);
                    } else if (message.length() > MAX_LABEL_LENGTH) {
                        return getTruncatedMessage(message, OPEN_LOG_FULL);
                    } else {
                        return message;
                    }
                }
        return "No message found";
            case 2:
                return new SimpleDateFormat(Constants.STANDARD_DATE_FORMAT).format(entry.getDate());
            default:
                return Constants.EMPTY_STRING;
            }
        }

        public String getExceptionMessage(String message, LogEntry entry) {
            if (Utils.isNotEmpty(entry.getStack()) && entry.getStack().contains(EXCEPTION)) {
                String exception =
                        entry.getStack().substring(0, entry.getStack().indexOf(EXCEPTION) + EXCEPTION.length());
                if (exception.contains(Constants.DOT)) {
                    exception = exception.substring(exception.lastIndexOf(Constants.DOT) + 1);
                }
                StringBuffer sb = new StringBuffer("(");
                sb.append(exception).append(") ");
                message = sb.toString() + message;
            }

            if (message.length() > MAX_LABEL_LENGTH
                    || (message.length() + OPEN_LOG_EXCEPTION_FULL.length()) > MAX_LABEL_LENGTH) {
                message = getTruncatedMessage(message, OPEN_LOG_EXCEPTION_FULL);
            } else {
                message += " "+OPEN_LOG_EXCEPTION;
            }

            return message;
        }

        private String getTruncatedMessage(String message, String truncateStr) {
            if (Utils.isEmpty(message) || message.length() < MAX_LABEL_LENGTH) {
                return message;
            }
      StringBuffer sb = new StringBuffer(message.substring(0, MAX_LABEL_LENGTH - truncateStr.length()));
      sb.append(truncateStr);
      return sb.toString();
        }

        public Font getFont(Object element, int columnIndex) {
            return null;
        }
    }
}
TOP

Related Classes of com.salesforce.ide.ui.views.log.LogView

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.