com.contrastsecurity.ide.eclipse.ui.internal.model.EventsTab.java Source code

Java tutorial

Introduction

Here is the source code for com.contrastsecurity.ide.eclipse.ui.internal.model.EventsTab.java

Source

/*******************************************************************************
 * Copyright (c) 2017 Contrast Security.
 * All rights reserved. 
 * 
 * This program and the accompanying materials are made available under 
 * the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 3 of the License.
 * 
 * The terms of the GNU GPL version 3 which accompanies this distribution
 * and is available at https://www.gnu.org/licenses/gpl-3.0.en.html
 * 
 * Contributors:
 *     Contrast Security - initial API and implementation
 *******************************************************************************/
package com.contrastsecurity.ide.eclipse.ui.internal.model;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
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.IType;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.search.IJavaSearchConstants;
import org.eclipse.jdt.core.search.SearchEngine;
import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.layout.TreeColumnLayout;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.jface.viewers.TreeViewerColumn;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.progress.UIJob;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.eclipse.ui.texteditor.ITextEditor;

import com.contrastsecurity.ide.eclipse.core.extended.EventItem;
import com.contrastsecurity.ide.eclipse.core.extended.EventResource;
import com.contrastsecurity.ide.eclipse.core.extended.EventSummaryResource;
import com.contrastsecurity.ide.eclipse.ui.ContrastUIActivator;

public class EventsTab extends AbstractTab {

    private EventSummaryResource eventSummary;
    private TreeViewer viewer;

    public EventsTab(Composite parent, int style) {
        super(parent, style);
        TreeColumnLayout layout = new TreeColumnLayout();
        getControl().setLayout(layout);
        viewer = new TreeViewer(getControl(), SWT.FULL_SELECTION | SWT.V_SCROLL | SWT.H_SCROLL);
        GridData gd = new GridData(SWT.FILL, SWT.FILL, true, true);
        viewer.getTree().setLayoutData(gd);

        TreeViewerColumn typeColumn = new TreeViewerColumn(viewer, SWT.NONE);
        layout.setColumnData(typeColumn.getColumn(), new ColumnWeightData(400));

        viewer.setLabelProvider(new EventLabelProvider(viewer));
        viewer.setContentProvider(new EventContentProvider());
        viewer.getTree().addMouseListener(new MouseListener() {

            @Override
            public void mouseUp(MouseEvent e) {
            }

            @Override
            public void mouseDown(MouseEvent e) {
            }

            @Override
            public void mouseDoubleClick(MouseEvent e) {
                ISelection sel = viewer.getSelection();
                if (sel instanceof IStructuredSelection) {
                    Object selected = ((IStructuredSelection) sel).getFirstElement();
                    if (selected instanceof EventItem) {
                        EventItem eventItem = (EventItem) selected;
                        if (eventItem.isStacktrace()) {
                            final String str = eventItem.getValue();
                            final String typeName;
                            final int lineNumber;
                            try {
                                typeName = getTypeName(str);
                                lineNumber = getLineNumber(str);
                            } catch (CoreException e1) {
                                ErrorDialog.openError(ContrastUIActivator.getActiveWorkbenchShell(), "Error",
                                        "Stacktrace Error", e1.getStatus());
                                return;
                            }
                            Job search = new Job("Searching for code in workspace...") {
                                @Override
                                protected IStatus run(IProgressMonitor monitor) {
                                    Set<IType> result = null;
                                    try {
                                        if (str.contains(".java")) {
                                            result = findTypeInWorkspace(typeName);
                                            searchCompleted(result, typeName, lineNumber, null);
                                        } else {
                                            List<IFile> resultFile = findFileInWorkspace(typeName);
                                            searchCompleted(resultFile, typeName, lineNumber, null);
                                        }
                                    } catch (CoreException e) {
                                        searchCompleted(null, typeName, lineNumber, e.getStatus());
                                    }
                                    return Status.OK_STATUS;
                                }

                            };
                            search.schedule();
                        }
                    }
                }
            }
        });
    }

    private IType getTypeFromActiveProject(Set<IType> inputSet) {

        IProject iProject = getIProjectFromActiveEditor();
        if (iProject != null) {
            for (IType file : inputSet) {
                if (file.getResource().getProject().equals(iProject)) {
                    return file;
                }
            }
        }
        return null;
    }

    private IProject getIProjectFromActiveEditor() {
        IEditorPart ieditorpart = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage()
                .getActiveEditor();
        if (ieditorpart != null) {
            IEditorInput input = ieditorpart.getEditorInput();
            if (input instanceof IFileEditorInput) {
                IResource iResource = ((IFileEditorInput) input).getFile();
                return iResource.getProject();
            }
        }
        return null;
    }

    private void searchCompleted(Object result, final String typeName, final int lineNumber, final IStatus status) {
        UIJob job = new UIJob("Search complete") {
            @Override
            public IStatus runInUIThread(IProgressMonitor monitor) {
                if (!validateSearchResult(result)) {
                    if (status == null) {
                        MessageDialog.openInformation(ContrastUIActivator.getActiveWorkbenchShell(), "Information",
                                "Source not found for " + typeName);
                    } else {
                        ContrastUIActivator.statusDialog("Source not found", status);
                    }
                } else {
                    processSearchResult(result, typeName, lineNumber);
                }
                return Status.OK_STATUS;
            }
        };
        job.setSystem(true);
        job.schedule();
    }

    @SuppressWarnings("unchecked")
    private void processSearchResult(Object result, String typeName, int lineNumber) {
        if (result instanceof Set<?>) {
            IEditorPart editorPart = null;

            IType iType = getTypeFromActiveProject((Set<IType>) result);

            for (IType file : (Set<IType>) result) {
                try {
                    if (!file.equals(iType)) {
                        editorPart = EditorUtility.openInEditor(file, true);
                    }
                } catch (PartInitException e1) {
                    ContrastUIActivator.statusDialog("Error", e1.getStatus());
                    return;
                }
                if (editorPart != null)
                    openEditor(editorPart, lineNumber, typeName);
            }

            if (iType != null) {
                try {
                    editorPart = EditorUtility.openInEditor(iType, true);
                } catch (PartInitException e1) {
                    ContrastUIActivator.statusDialog("Error", e1.getStatus());
                    return;
                }
                if (editorPart != null)
                    openEditor(editorPart, lineNumber, typeName);
            }

        } else {
            List<IFile> matches = (List<IFile>) result;
            for (IFile file : matches) {
                IEditorPart editorPart;
                try {
                    editorPart = EditorUtility.openInEditor(file, true);
                } catch (PartInitException e1) {
                    ContrastUIActivator.statusDialog("Error", e1.getStatus());
                    return;
                }
                if (editorPart != null)
                    openEditor(editorPart, lineNumber, typeName);
            }
        }
    }

    private void openEditor(IEditorPart editorPart, final int lineNumber, final String typeName) {
        if (editorPart != null) {
            try {
                if (editorPart instanceof ITextEditor && lineNumber >= 0) {
                    ITextEditor textEditor = (ITextEditor) editorPart;
                    IDocumentProvider provider = textEditor.getDocumentProvider();
                    IEditorInput editorInput = editorPart.getEditorInput();
                    provider.connect(editorInput);
                    IDocument document = provider.getDocument(editorInput);
                    try {
                        IRegion line = document.getLineInformation(lineNumber == 0 ? 0 : lineNumber - 1);
                        textEditor.selectAndReveal(line.getOffset(), line.getLength());
                    } catch (BadLocationException e) {
                        MessageDialog.openInformation(ContrastUIActivator.getActiveWorkbenchShell(),
                                "Invalid line number",
                                (lineNumber + 1) + " is not valid line number in " + typeName);
                    }
                    provider.disconnect(editorInput);
                }
            } catch (CoreException e) {
                ContrastUIActivator.statusDialog(e.getStatus().getMessage(), e.getStatus());
            }
        }
    }

    private boolean validateSearchResult(Object result) {
        if (result instanceof Set<?>)
            return (result != null && ((Set<?>) result).size() > 0);
        else
            return (result != null && ((List<?>) result).size() > 0);
    }

    private String getTypeName(String stacktrace) throws CoreException {
        int start = stacktrace.lastIndexOf('(');
        int end = stacktrace.indexOf(':');
        if (start >= 0 && end > start) {
            String typeName = stacktrace.substring(start + 1, end);
            typeName = JavaCore.removeJavaLikeExtension(typeName);
            String qualifier = stacktrace.substring(0, start);
            start = qualifier.lastIndexOf('.');
            if (start >= 0) {
                start = new String((String) qualifier.subSequence(0, start)).lastIndexOf('.');
                if (start == -1) {
                    start = 0;
                }
            }
            if (start >= 0) {
                qualifier = qualifier.substring(0, start);
            }
            if (qualifier.length() > 0) {
                typeName = qualifier + "." + typeName;
            }
            return typeName;
        }
        IStatus status = new Status(IStatus.ERROR, ContrastUIActivator.PLUGIN_ID, 0,
                "Unable to parse type name from stacktrace", null);
        throw new CoreException(status);
    }

    private int getLineNumber(String stacktrace) throws CoreException {
        int index = stacktrace.lastIndexOf(':');
        if (index >= 0) {
            String numText = stacktrace.substring(index + 1);
            index = numText.indexOf(')');
            if (index >= 0) {
                numText = numText.substring(0, index);
            }
            try {
                return Integer.parseInt(numText);
            } catch (NumberFormatException e) {
                IStatus status = new Status(IStatus.ERROR, ContrastUIActivator.PLUGIN_ID, 0,
                        "Unable to parse line number from stacktrace", e);
                throw new CoreException(status);
            }
        }
        IStatus status = new Status(IStatus.ERROR, ContrastUIActivator.PLUGIN_ID, 0,
                "Unable to parse line number from stacktrace", null);
        throw new CoreException(status);
    }

    private static Set<IType> findTypeInWorkspace(String typeName) throws CoreException {
        int dot = typeName.lastIndexOf('.');
        char[][] qualifications;
        String simpleName;
        if (dot != -1) {
            qualifications = new char[][] { typeName.substring(0, dot).toCharArray() };
            simpleName = typeName.substring(dot + 1);
        } else {
            qualifications = null;
            simpleName = typeName;
        }
        char[][] typeNames = new char[][] { simpleName.toCharArray() };

        ContrastTypeNameMatchRequestor contrastTypeNameMatchRequestor = new ContrastTypeNameMatchRequestor();

        new SearchEngine().searchAllTypeNames(qualifications, typeNames, SearchEngine.createWorkspaceScope(),
                contrastTypeNameMatchRequestor, IJavaSearchConstants.WAIT_UNTIL_READY_TO_SEARCH, null);

        return contrastTypeNameMatchRequestor.getTypeNameMatches();
    }

    /**
     * Searches for file with a given name.
     * 
     * @param filename
     *            The file name with extension included.
     * @return IFile object or null if the file is not found.
     * @throws CoreException
     *             If the request fails.
     */
    private static List<IFile> findFileInWorkspace(String filename) throws CoreException {
        IWorkspaceRoot root = ResourcesPlugin.getWorkspace().getRoot();

        String[] name = StringUtils.split(filename, "(");
        List<IFile> matches = new ArrayList<>();

        for (IProject project : root.getProjects())
            findFile(name[name.length - 1], project, matches);

        return matches;
    }

    /**
     * Recursively searches for a file with a given name.
     * 
     * @param filename
     *            The file name with extension.
     * @param resource
     *            The resource to evaluate with the file name. Allowed types:
     *            IProject, IFolder and IFile.
     * @return An IFile object or null if the file is not found.
     * @throws CoreException
     *             If the request fails.
     */
    private static List<IFile> findFile(final String filename, IResource resource, List<IFile> matches)
            throws CoreException {
        if (resource instanceof IFile) {
            IFile file = (IFile) resource;
            if (StringUtils.equals(filename, file.getName()))
                matches.add(file);

            return matches;
        } else if (resource instanceof IFolder && !((IFolder) resource).getName().equals("target")) {
            IFolder folder = (IFolder) resource;

            for (IResource res : folder.members())
                findFile(filename, res, matches);
        } else if (resource instanceof IProject && ((IProject) resource).isOpen()) {
            IProject project = (IProject) resource;

            for (IResource res : project.members())
                findFile(filename, res, matches);
        }

        return matches;
    }

    public void setEventSummary(EventSummaryResource eventSummary) {
        this.eventSummary = eventSummary;
        if (eventSummary != null) {
            viewer.setInput(eventSummary.getEvents().toArray(new EventResource[0]));
        } else {
            viewer.setInput(new EventResource[0]);
        }
        getControl().getParent().layout(true, true);
        getControl().redraw();
    }

    public EventSummaryResource getEventSummary() {
        return eventSummary;
    }

}