com.centurylink.mdw.plugin.designer.views.JavaProcessConsole.java Source code

Java tutorial

Introduction

Here is the source code for com.centurylink.mdw.plugin.designer.views.JavaProcessConsole.java

Source

/*
 * Copyright (C) 2017 CenturyLink, Inc.
 *
 * Licensed 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 com.centurylink.mdw.plugin.designer.views;

import java.util.ResourceBundle;

import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.FindReplaceDocumentAdapter;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IFindReplaceTarget;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.TextViewer;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.MouseTrackListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.console.actions.ClearOutputAction;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.progress.UIJob;
import org.eclipse.ui.texteditor.FindReplaceAction;
import org.eclipse.ui.texteditor.IUpdate;

import com.centurylink.mdw.plugin.MdwPlugin;
import com.centurylink.mdw.plugin.PluginMessages;
import com.centurylink.mdw.plugin.PluginUtil;
import com.centurylink.mdw.plugin.server.JavaSourceHyperlink;

/**
 * Console view for external java processes. Runtime output is displayed here.
 * Provides actions for copy/scroll-lock, etc. Also handles mouse events to
 * display source modules as links whose click action opens the source file to
 * the appropriate line number (in stack traces, etc).
 */
public class JavaProcessConsole extends ViewPart implements IAdaptable, IFindReplaceTarget, MouseListener,
        MouseTrackListener, MouseMoveListener, PaintListener {
    private IJavaProject javaProject;

    public IJavaProject getJavaProject() {
        return javaProject;
    }

    public void setJavaProject(IJavaProject jp) {
        javaProject = jp;
    }

    private static String consoleId = null;

    public static String getConsoleId() {
        return consoleId;
    }

    public static void setConsoleId(String s) {
        consoleId = s;
    }

    public static final int LINE_TYPE_NORMAL = 0;
    public static final int LINE_TYPE_STATUS = 1 << 1;
    public static final int LINE_TYPE_ERROR = 1 << 2;
    public static final int LINE_TYPE_HIGHLIGHT = 1 << 3;

    private int bufferSize;

    public int getBufferSize() {
        return bufferSize;
    }

    public void setBufferSize(int i) {
        bufferSize = i;
    }

    // actions
    private Action copyAction;
    private Action selectAllAction;
    private Action scrollLockAction;
    private boolean scrollLocked = false;
    private ClearOutputAction clearOutputAction;
    private FindReplaceAction findReplaceAction;

    // resources
    @SuppressWarnings("unused")
    private static Color cyan, magenta, red, white;
    private Cursor handCursor;
    private Cursor textCursor;

    private TextViewer viewer;

    public TextViewer getViewer() {
        return viewer;
    }

    private JavaSourceHyperlink hyperLink;

    public StyledText getTextWidget() {
        return viewer.getTextWidget();
    }

    public IDocument getDocument() {
        return viewer.getDocument();
    }

    /**
     * Gets a handle to a runtime instance of the console. This method must be
     * run before show() or clear().
     *
     * @param id
     *            the console_id of the console to find
     * @return the console
     */
    public static JavaProcessConsole find(String id) {
        setConsoleId(id);
        IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
        JavaProcessConsole console = (JavaProcessConsole) page.findView(id);

        if (console == null) {
            show();
            console = (JavaProcessConsole) page.findView(id);
            setConsoleId(id);
            return console;
        } else {
            setConsoleId(id);
            return console;
        }
    }

    /**
     * @see org.eclipse.ui.IWorkbenchPart#createPartControl(Composite)
     */
    public void createPartControl(Composite parent) {
        viewer = new TextViewer(parent, SWT.V_SCROLL | SWT.H_SCROLL);
        GridData viewerData = new GridData(GridData.FILL_BOTH);
        getViewer().getControl().setLayoutData(viewerData);
        getViewer().setEditable(false);
        getViewer().enableOperation(TextViewer.COPY, true);
        getViewer().setDocument(new Document());

        // colors
        cyan = getViewer().getControl().getDisplay().getSystemColor(SWT.COLOR_CYAN);
        magenta = getViewer().getControl().getDisplay().getSystemColor(SWT.COLOR_MAGENTA);
        red = getViewer().getControl().getDisplay().getSystemColor(SWT.COLOR_RED);
        white = getViewer().getControl().getDisplay().getSystemColor(SWT.COLOR_WHITE);

        // set up the widget
        getTextWidget().addMouseTrackListener(this);
        getTextWidget().addPaintListener(this);

        // create actions
        createActions();
        // add the global action handlers
        addActionHandlers();

        createMenu();
        createToolbar();
    }

    /**
     * @see org.eclipse.ui.IWorkbenchPart#setFocus()
     */
    public void setFocus() {
    }

    /**
     * show the console view based on the id set in find()
     */
    protected static void show() {
        IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
        try {
            page.showView(getConsoleId());
        } catch (NullPointerException ex) {
            // Eclipse Mars Bug:
            // https://bugs.eclipse.org/bugs/show_bug.cgi?id=473541
            // TODO Remove when fixed.
            PluginMessages.log(ex);
        } catch (PartInitException ex) {
            PluginMessages.log(ex);
        }
    }

    private StyleRange[] styleRanges;
    private StringBuffer buffer = new StringBuffer();
    private int buffed;

    /**
     * print output to the console
     *
     * @param text
     *            - the string to print
     * @param lineType
     *            - style attributes
     */
    public void print(String text, int lineType) {
        Color foreground = null;
        Color background = null;

        if (lineType != LINE_TYPE_NORMAL) {
            if ((LINE_TYPE_STATUS & lineType) == LINE_TYPE_STATUS
                    || (LINE_TYPE_HIGHLIGHT & lineType) == LINE_TYPE_HIGHLIGHT)
                show();

            if ((LINE_TYPE_ERROR & lineType) == LINE_TYPE_ERROR) {
                foreground = red;
            }
            if ((LINE_TYPE_STATUS & lineType) == LINE_TYPE_STATUS) {
                background = cyan;
            } else if ((LINE_TYPE_HIGHLIGHT & lineType) == LINE_TYPE_HIGHLIGHT) {
                background = magenta;
            }
        }

        StyledText st = getViewer().getTextWidget();

        synchronized (buffer) {
            if (lineType != LINE_TYPE_NORMAL) {
                int lineOffset = st.getOffsetAtLine(st.getLineCount() - 1) + buffed;

                if (st.getText().length() + buffed == 0)
                    styleRanges = null;

                StyleRange sr = new StyleRange(lineOffset, text.length(), foreground, background);
                if (styleRanges == null || styleRanges.length == 0)
                    styleRanges = new StyleRange[] { sr };
                else
                    styleRanges = (StyleRange[]) PluginUtil.addToArray(sr, styleRanges);
            }

            buffer.append(text);
            buffed += text.length();
        }

        // TODO: honor buffer size preference
        // int overflow = fullText.length() + text.length() - getBufferSize();
        // if (overflow > 0)
        // {
        // int trimToIdx = fullText.indexOf("\n", overflow);
        // if (trimToIdx > 0)
        // {
        // st.replaceTextRange(0, trimToIdx, "");
        // }
        // }

        printJob();
    }

    private UIJob queueJob;

    private UIJob getQueueJob() {
        if (queueJob == null) {
            queueJob = new UIJob("JavaProcessConsole") {
                public IStatus runInUIThread(IProgressMonitor monitor) {
                    StyledText st = getViewer().getTextWidget();
                    synchronized (buffer) {
                        st.append(buffer.toString());
                        buffer.setLength(0);
                        buffed = 0;

                        st.setStyleRanges(styleRanges);

                        // scroll to the bottom
                        if (!scrollLockAction.isChecked()) {
                            int textLength = st.getText().length();
                            if (textLength > 0) {
                                st.setCaretOffset(textLength);
                                st.showSelection();
                            }
                        }

                        // update the find replace action since the text has
                        // changed
                        IUpdate findReplace = (IUpdate) findReplaceAction;
                        if (findReplace != null)
                            findReplace.update();
                    }

                    return Status.OK_STATUS;
                }
            };

            queueJob.setSystem(true);
            queueJob.setPriority(Job.INTERACTIVE);
            // queueJob.setRule(console.getSchedulingRule());
        }

        return queueJob;
    }

    public void printJob() {
        if (buffed > 500)
            getQueueJob().schedule();
        else
            getQueueJob().schedule(25);
    }

    /**
     * clear the console
     */
    public void clear() {
        show();
        StyledText st = getViewer().getTextWidget();
        synchronized (buffer) {
            st.setText("");
            styleRanges = new StyleRange[0];
            buffer.setLength(0);
            buffed = 0;
        }
    }

    /**
     * add action handlers for the view
     */
    private void createActions() {
        // copy
        copyAction = new Action("Copy") {
            public void run() {
                getViewer().getTextWidget().copy();
            }
        };
        copyAction.setImageDescriptor(MdwPlugin.getImageDescriptor("icons/copy.gif"));
        copyAction.setToolTipText("Copy");

        // select all
        selectAllAction = new Action("Select All") {
            public void run() {
                getViewer().getTextWidget().selectAll();
                getViewer().setSelection(getViewer().getSelection());
            }
        };
        selectAllAction.setImageDescriptor(MdwPlugin.getImageDescriptor("icons/select_all.gif"));
        selectAllAction.setToolTipText("Select All");

        // search
        ResourceBundle bundle = ResourceBundle
                .getBundle("org.eclipse.debug.internal.ui.views.DebugUIViewsMessages");
        findReplaceAction = new FindReplaceAction(bundle, null, this);
        findReplaceAction.setImageDescriptor(MdwPlugin.getImageDescriptor("icons/search.gif"));
        findReplaceAction.setToolTipText("Search");

        // clear output
        clearOutputAction = new ClearOutputAction(getViewer()) {
            public void run() {
                clear();
            }
        };

        // scroll lock
        scrollLockAction = new Action("Scroll Lock") {
            public void run() {
                scrollLocked = !scrollLocked;
                scrollLockAction.setChecked(scrollLocked);
            }
        };
        scrollLockAction.setImageDescriptor(MdwPlugin.getImageDescriptor("icons/lock.gif"));
        scrollLockAction.setToolTipText("Scroll Lock");
        scrollLockAction.setChecked(false);
    }

    /**
     * add action handlers for the view
     */
    private void addActionHandlers() {
        // add selection listener for enabling copying
        getViewer().addSelectionChangedListener(new ISelectionChangedListener() {
            public void selectionChanged(SelectionChangedEvent event) {
                updateActionEnablement();
            }
        });

        IActionBars bars = getViewSite().getActionBars();
        bars.setGlobalActionHandler("copy", copyAction);
        bars.setGlobalActionHandler("selectAll", selectAllAction);
        bars.setGlobalActionHandler("find", findReplaceAction);
        bars.setGlobalActionHandler("scroll_lock", scrollLockAction);

        updateActionEnablement();
    }

    /**
     * determine whether to enable actions
     */
    private void updateActionEnablement() {
        String selText = getViewer().getTextWidget().getSelectionText();
        copyAction.setEnabled(selText.length() > 0);
    }

    /**
     * create menu
     */
    private void createMenu() {
        IMenuManager mgr = getViewSite().getActionBars().getMenuManager();
        mgr.add(copyAction);
        mgr.add(selectAllAction);
        mgr.add(clearOutputAction);
        mgr.add(scrollLockAction);
        mgr.add(findReplaceAction);
    }

    /**
     * create toolbar
     */
    private void createToolbar() {
        IToolBarManager mgr = getViewSite().getActionBars().getToolBarManager();
        mgr.add(copyAction);
        // mgr.add(selectAllAction);
        mgr.add(clearOutputAction);
        mgr.add(scrollLockAction);
        mgr.add(findReplaceAction);
    }

    /**
     * dispose of the text viewer and its resources
     */
    public void dispose() {
        Control control = getViewer().getTextWidget();
        if (control != null) {
            control.removeMouseTrackListener(this);
            control.removePaintListener(this);
        }
        if (handCursor != null) {
            handCursor.dispose();
        }
        if (textCursor != null) {
            textCursor.dispose();
        }
    }

    // methods for the IFindReplaceTarget interface
    public boolean canPerformFind() {
        return true;
    }

    public boolean isEditable() {
        return false;
    }

    public void replaceSelection(String text) {
    }

    public int findAndSelect(int widgetOffset, String findString, boolean searchForward, boolean caseSensitive,
            boolean wholeWord) {
        if (getViewer().getTextWidget() == null)
            return -1;

        try {
            int fromOffset = 0;
            if (widgetOffset == -1) {
                fromOffset = -1;
            } else {
                fromOffset = getViewer().getTextWidget().getCaretOffset();
                if (getViewer().getTextWidget().getSelectionCount() > 0)
                    fromOffset++;
                if (fromOffset >= getViewer().getDocument().getLength() && fromOffset > 0)
                    fromOffset--;
            }

            IRegion matchRegion = new FindReplaceDocumentAdapter(getViewer().getDocument()).find(fromOffset,
                    findString, searchForward, caseSensitive, wholeWord, false);
            if (matchRegion != null) {
                int widgetPos = matchRegion.getOffset();
                int length = matchRegion.getLength();
                getViewer().getTextWidget().setSelectionRange(widgetPos, length);
                getViewer().setSelection(getViewer().getSelection(), true);

                return getViewer().widgetOffset2ModelOffset(widgetPos);
            }
        } catch (BadLocationException ex) {
            PluginMessages.log(ex);
        }
        return -1;
    }

    public Point getSelection() {
        return getViewer().getTextWidget().getSelection();
    }

    public String getSelectionText() {
        return getViewer().getTextWidget().getSelectionText();
    }

    // methods for MouseListener interface
    public void mouseDoubleClick(MouseEvent e) {
    }

    public void mouseDown(MouseEvent e) {
    }

    public void mouseUp(MouseEvent e) {
        if (hyperLink != null) {
            String selection = getTextWidget().getSelectionText();
            if (selection.length() <= 0) {
                if (e.button == 1) {
                    hyperLink.linkActivated();
                }
            }
        }
    }

    // methods for MouseTrackListener interface
    public void mouseEnter(MouseEvent e) {
        getTextWidget().addMouseMoveListener(this);
    }

    public void mouseExit(MouseEvent e) {
        getTextWidget().removeMouseMoveListener(this);
        if (hyperLink != null) {
            linkExited(hyperLink);
        }
    }

    public void mouseHover(MouseEvent e) {
    }

    protected void linkEntered(JavaSourceHyperlink link) {
        Control control = getViewer().getTextWidget();
        control.setRedraw(false);
        if (hyperLink != null) {
            linkExited(hyperLink);
        }
        hyperLink = link;
        hyperLink.linkEntered();
        control.setCursor(getHandCursor());
        control.setRedraw(true);
        control.redraw();
        control.addMouseListener(this);
    }

    protected void linkExited(JavaSourceHyperlink link) {
        link.linkExited();
        hyperLink = null;
        Control control = getViewer().getTextWidget();
        control.setCursor(getTextCursor());
        control.redraw();
        control.removeMouseListener(this);
    }

    @SuppressWarnings("restriction")
    protected Cursor getHandCursor() {
        if (handCursor == null) {
            handCursor = new Cursor(org.eclipse.debug.internal.ui.DebugUIPlugin.getStandardDisplay(),
                    SWT.CURSOR_HAND);
        }
        return handCursor;
    }

    @SuppressWarnings("restriction")
    protected Cursor getTextCursor() {
        if (textCursor == null) {
            textCursor = new Cursor(org.eclipse.debug.internal.ui.DebugUIPlugin.getStandardDisplay(),
                    SWT.CURSOR_IBEAM);
        }
        return textCursor;
    }

    // method for the MouseMoveListener interface
    public void mouseMove(MouseEvent e) {
        mouseOffset = -1;
        try {
            Point p = new Point(e.x, e.y);
            mouseOffset = getTextWidget().getOffsetAtLocation(p);
        } catch (IllegalArgumentException ex) {
            // out of the document range
        }
        updateLinks(mouseOffset);
    }

    int mouseOffset;

    /**
     * the cursor has just moved to the given offset, the mouse has hovered over
     * the given offset, so update link rendering
     *
     * @param offset
     */
    protected void updateLinks(int offset) {
        if (offset >= 0) {
            JavaSourceHyperlink link = getHyperlink(offset);
            if (link != null) {
                if (link.equals(hyperLink)) {
                    return;
                } else {
                    linkEntered(link);
                    return;
                }
            }
        }
        if (hyperLink != null) {
            linkExited(hyperLink);
        }
    }

    /**
     * returns a JavaSourceHyperlink if the hover location is appropriate
     *
     * @param offset
     * @return the link or null if no link should appear
     */
    public JavaSourceHyperlink getHyperlink(int offset) {
        if (offset >= 0) {
            StyledText widget = getViewer().getTextWidget();
            int line = widget.getLineAtOffset(offset);
            String lineText = getLineText(line);
            JavaSourceHyperlink link = JavaSourceHyperlink.create(lineText, getJavaProject());
            return link;
        }
        return null;
    }

    /**
     * parse a String with delimiters to find the text for a given line
     *
     * @param line
     *            - line number
     * @return the string for the given line
     */
    private String getLineText(int line) {
        String text = getViewer().getTextWidget().getText();
        int count = 0;
        int start = 0;
        while (start != -1 && count < line) {
            start = text.indexOf('\n', start + 1);
            count++;
        }
        String lineText = text.substring(start + 1, text.indexOf('\n', start + 1));
        return lineText.endsWith("\r") ? lineText.substring(0, lineText.length() - 1) : lineText;
    }

    /**
     * paints the control
     *
     * @param e
     */
    public void paintControl(PaintEvent e) {
        if (hyperLink != null) {
            StyledText widget = getViewer().getTextWidget();
            int line = widget.getLineAtOffset(mouseOffset);
            try {
                IRegion lineRegion = getDocument().getLineInformation(line);
                int lineStart = lineRegion.getOffset();
                Color fgColor = e.gc.getForeground();
                e.gc.setForeground(red);
                int linkStart = lineStart + hyperLink.getLinkStart();
                int linkEnd = lineStart + hyperLink.getLinkEnd();
                Point p1 = getTextWidget().getLocationAtOffset(linkStart);
                Point p2 = getTextWidget().getLocationAtOffset(linkEnd);
                FontMetrics metrics = e.gc.getFontMetrics();
                int height = metrics.getHeight();
                e.gc.drawLine(p1.x, p1.y + height, p2.x, p2.y + height);
                e.gc.setForeground(fgColor);
            } catch (BadLocationException ex) {
            }
        }
    }
}