ca.uvic.chisel.javasketch.SketchPlugin.java Source code

Java tutorial

Introduction

Here is the source code for ca.uvic.chisel.javasketch.SketchPlugin.java

Source

/*******************************************************************************
 * Copyright (c) 2009 the CHISEL group and contributors.
 * 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:
 *     Del Myers - initial API and implementation
 *******************************************************************************/
package ca.uvic.chisel.javasketch;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Properties;

import org.eclipse.core.resources.WorkspaceJob;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IDebugEventSetListener;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.resource.ColorRegistry;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;

import ca.uvic.chisel.javasketch.data.model.ITrace;
import ca.uvic.chisel.javasketch.data.model.ITraceEvent;
import ca.uvic.chisel.javasketch.data.model.ITraceEventListener;
import ca.uvic.chisel.javasketch.data.model.ITraceModel;
import ca.uvic.chisel.javasketch.internal.DBProgramSketch;
import ca.uvic.chisel.javasketch.internal.SketchEvents;
import ca.uvic.chisel.javasketch.internal.interest.DegreeOfInterest;
import ca.uvic.chisel.javasketch.launching.ITraceClient;
import ca.uvic.chisel.javasketch.launching.internal.JavaAgentTraceClient;
import ca.uvic.chisel.javasketch.ui.ISketchColorConstants;
import ca.uvic.chisel.javasketch.ui.ISketchImageConstants;
import ca.uvic.chisel.javasketch.ui.internal.SketchUI;

/**
 * The activator class controls the plug-in life cycle
 */
public class SketchPlugin extends AbstractUIPlugin {

    // The plug-in ID
    public static final String PLUGIN_ID = "ca.uvic.chisel.javasketch";

    // The shared instance
    private static SketchPlugin plugin;

    // Listener for debug events.
    private DebugListener debugListener;

    private SketchEvents events;

    private DegreeOfInterest doi;

    private ColorRegistry colorRegistry;

    private Map<String, IProgramSketch> cachedSketches;

    private ITraceEventListener staticJavaModelListener;

    private class StaticJavaModelListener implements ITraceEventListener {

        private long eventTime = 0;

        /* (non-Javadoc)
         * @see ca.uvic.chisel.javasketch.data.model.ITraceEventListener#handleEvents(ca.uvic.chisel.javasketch.data.model.ITraceEvent[])
         */
        @Override
        public void handleEvents(ITraceEvent[] events) {

            for (ITraceEvent event : events) {
                switch (event.getType()) {
                case MethodEventType:
                case TypeEventType:
                    long currentTime = System.currentTimeMillis();
                    if (currentTime - eventTime >= 3000) {
                        SketchUI.INSTANCE.refreshJavaUI();
                        eventTime = currentTime;
                    }
                }
            }
        }

    }

    private class DebugListener implements IDebugEventSetListener {

        @Override
        public void handleDebugEvents(DebugEvent[] events) {
            SketchPlugin.this.handleDebugEvents(events);
        }

    }

    /**
     * The constructor
     */
    public SketchPlugin() {
        staticJavaModelListener = new StaticJavaModelListener();
        doi = new DegreeOfInterest();
        cachedSketches = new HashMap<String, IProgramSketch>();
        this.debugListener = new DebugListener();
    }

    protected void handleDebugEvents(DebugEvent[] events) {
        for (DebugEvent event : events) {
            if (event.getSource() instanceof ITraceClient) {
                SketchUI.INSTANCE.refreshCommands();
            }
        }
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
     */
    public void start(BundleContext context) throws Exception {
        super.start(context);
        plugin = this;
        DebugPlugin.getDefault().addDebugEventListener(debugListener);
        events = new SketchEvents();
        getPreferenceStore().addPropertyChangeListener(SketchUI.INSTANCE);
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
     */
    public void stop(BundleContext context) throws Exception {
        plugin = null;
        DebugPlugin.getDefault().removeDebugEventListener(debugListener);
        synchronized (cachedSketches) {
            for (IProgramSketch sketch : cachedSketches.values()) {
                if (sketch.isConnected()) {
                    sketch.getPortal().close();
                }
            }
        }
        super.stop(context);
    }

    /**
     * Returns the shared instance
     *
     * @return the shared instance
     */
    public static SketchPlugin getDefault() {
        return plugin;
    }

    /**
     * Returns the associated trace client for the given process, or NULL if one doesn't 
     * exist.
     * @param process
     * @return
     */
    public ITraceClient getAssociatedClient(IProcess process) {
        if (process != null) {
            if (process instanceof ITraceClient) {
                return (ITraceClient) process;
            }
            for (IProcess p : process.getLaunch().getProcesses()) {
                if (p instanceof ITraceClient) {
                    return (ITraceClient) p;
                }
            }
        }
        return null;
    }

    /**
     * Returns all of the traces stored for this workspace. The returned traces
     * are not cached, but there should be no transient information in the
     * returned sketches that cannot be computed.
     * @return all of the traces stored for this workspace.
     */
    public IProgramSketch[] getStoredSketches() {
        //all of the traces are stored in the plugin state location.
        synchronized (cachedSketches) {
            File stateLocation = getStateLocation().toFile();
            File[] launchDirectories = stateLocation.listFiles();
            for (File launchDirectory : launchDirectories) {
                if (launchDirectory.isDirectory()) {
                    //process all of the directories inside this one
                    for (File traceDirectory : launchDirectory.listFiles()) {
                        if (traceDirectory.isDirectory()) {
                            //check to see if it has the correct data stored
                            File propertiesFile = new File(traceDirectory,
                                    JavaAgentTraceClient.PROCESS_PROPERTIES_FILE);
                            if (propertiesFile.exists()) {
                                try {
                                    Properties props = new Properties();
                                    FileInputStream fis = new FileInputStream(propertiesFile);
                                    props.load(fis);
                                    fis.close();
                                    String id = props.getProperty(JavaAgentTraceClient.ID_PROPERTY);
                                    if (!cachedSketches.containsKey(id)) {
                                        FileReader reader = new FileReader(
                                                new File(traceDirectory, "launch.configuration"));
                                        char[] buf = new char[1024];
                                        int read = -1;
                                        StringWriter writer = new StringWriter();
                                        while ((read = reader.read(buf)) != -1) {
                                            writer.write(buf, 0, read);
                                        }
                                        reader.close();
                                        writer.close();
                                        ILaunchConfiguration cf = DebugPlugin.getDefault().getLaunchManager()
                                                .getLaunchConfiguration(writer.toString());
                                        if (cf != null) {
                                            cachedSketches.put(id, new DBProgramSketch(traceDirectory));
                                        }

                                    }
                                } catch (IOException e) {
                                    Status s = new Status(Status.WARNING, PLUGIN_ID,
                                            "An error occurred reading sketch at location " + traceDirectory
                                                    + ". It will be deleted.",
                                            e);
                                    getLog().log(s);
                                    delete(traceDirectory);
                                } catch (CoreException e) {
                                    Status s = new Status(Status.WARNING, PLUGIN_ID,
                                            "An error occurred reading sketch at location " + traceDirectory
                                                    + ". It will be deleted.",
                                            e);
                                    getLog().log(s);
                                    delete(traceDirectory);
                                }
                            } else {
                                Status s = new Status(Status.WARNING, PLUGIN_ID,
                                        "An error occurred reading sketch at location " + traceDirectory
                                                + ". It will be deleted.");
                                getLog().log(s);
                                delete(traceDirectory);
                            }
                        }
                    }
                }
            }
            Collection<IProgramSketch> sketches = cachedSketches.values();
            return sketches.toArray(new IProgramSketch[sketches.size()]);
        }

    }

    private void delete(File file) {
        IPath storageLocation = getStateLocation();
        IPath filePath = new Path(file.getAbsolutePath());
        if (!storageLocation.isPrefixOf(filePath))
            return;
        if (file.isDirectory()) {
            File[] children = file.listFiles();
            for (File child : children) {
                delete(child);
            }
        }
        file.delete();
    }

    public void addSketchEventListener(ISketchEventListener listener) {
        events.addListener(listener);
    }

    /**
     * @param traceNavigatorContentProvider
     */
    public void removeSketchEventListener(ISketchEventListener listener) {
        events.removeListener(listener);
    }

    /**
     * Returns the stored sketches for the given launch configuration.
     * @param configuration the configuration to check.
     * @return
     */
    public IProgramSketch[] getStoredSketches(String launchConfigurationName) {
        ArrayList<IProgramSketch> traces = new ArrayList<IProgramSketch>();
        for (IProgramSketch sketch : getStoredSketches()) {
            String sketchName = sketch.getTracedLaunchConfiguration().getName();
            if (sketchName.equals(launchConfigurationName)) {
                traces.add(sketch);
            }
        }
        return traces.toArray(new IProgramSketch[traces.size()]);
    }

    public void log(Exception e) {
        if (e instanceof CoreException) {
            getLog().log((((CoreException) e).getStatus()));
        } else {
            getLog().log(createStatus(e));
        }
    }

    public IStatus createStatus(Exception e) {
        String message = e.getMessage();
        if (message == null) {
            message = "";
        }
        return new Status(IStatus.ERROR, PLUGIN_ID, message, e);
    }

    /* (non-Javadoc)
     * @see org.eclipse.ui.plugin.AbstractUIPlugin#initializeImageRegistry(org.eclipse.jface.resource.ImageRegistry)
     */
    @Override
    protected void initializeImageRegistry(ImageRegistry reg) {
        reg.put(ISketchImageConstants.ICON_TRACE_EDITOR,
                imageDescriptorFromPlugin(PLUGIN_ID, "images/obj16/trace_editor.png"));
        reg.put(ISketchImageConstants.ICON_TRACE_ACTIVE,
                imageDescriptorFromPlugin(PLUGIN_ID, "images/etool16/trace-active.gif"));
        reg.put(ISketchImageConstants.ICON_TRACE_INACTIVE,
                imageDescriptorFromPlugin(PLUGIN_ID, "images/etool16/trace-inactive.gif"));

        reg.put(ISketchImageConstants.ICON_PROCESS_TRACE,
                imageDescriptorFromPlugin(PLUGIN_ID, "images/obj16/trace_proc.png"));
        reg.put(ISketchImageConstants.ICON_THREAD_TRACE,
                imageDescriptorFromPlugin(PLUGIN_ID, "images/obj16/trace_thread.png"));
        reg.put(ISketchImageConstants.ICON_CALENDAR,
                imageDescriptorFromPlugin(PLUGIN_ID, "images/obj16/calendar.png"));
        reg.put(ISketchImageConstants.ICON_ACTIVATION,
                imageDescriptorFromPlugin(PLUGIN_ID, "images/obj16/activation.png"));
        reg.put(ISketchImageConstants.ICON_ANNOTATION,
                imageDescriptorFromPlugin(PLUGIN_ID, "images/obj16/annotation.png"));
        reg.put(ISketchImageConstants.ICON_ANNOTATIONS,
                imageDescriptorFromPlugin(PLUGIN_ID, "images/obj16/annotations.png"));
        reg.put(ISketchImageConstants.ICON_TRACE, imageDescriptorFromPlugin(PLUGIN_ID, "images/trace_view.png"));
        reg.put(ISketchImageConstants.OVERLAY_ANALYSE,
                imageDescriptorFromPlugin(PLUGIN_ID, "images/dec8/ovr_gear.png"));
        reg.put(ISketchImageConstants.OVERLAY_PLAY,
                imageDescriptorFromPlugin(PLUGIN_ID, "images/dec8/ovr_play.png"));
        reg.put(ISketchImageConstants.OVERLAY_STOP,
                imageDescriptorFromPlugin(PLUGIN_ID, "images/dec8/ovr_stop.png"));
        reg.put(ISketchImageConstants.ICON_ELEMENT_FILTERED,
                imageDescriptorFromPlugin("images/etool16/closedeye.png"));
        reg.put(ISketchImageConstants.ICON_ELEMENT_VISIBLE,
                imageDescriptorFromPlugin("images/etool16/openeye.png"));
        reg.put(ISketchImageConstants.ICON_ELEMENT_VISIBLE + "1-3",
                imageDescriptorFromPlugin("images/etool16/1-3eye.png"));
        reg.put(ISketchImageConstants.ICON_ELEMENT_VISIBLE + "2-3",
                imageDescriptorFromPlugin("images/etool16/2-3eye.png"));
        reg.put(ISketchImageConstants.ICON_LOGO, imageDescriptorFromPlugin("images/logo16.png"));

        super.initializeImageRegistry(reg);
    }

    public ColorRegistry getColorRegistry() {
        if (this.colorRegistry == null) {
            colorRegistry = new ColorRegistry(PlatformUI.getWorkbench().getDisplay());
            colorRegistry.put(ISketchColorConstants.RED_KEY, new RGB(200, 0, 0));
            colorRegistry.put(ISketchColorConstants.GREEN_KEY, new RGB(0, 150, 0));
            colorRegistry.put(ISketchColorConstants.BLUE_KEY, new RGB(0, 0, 200));
            colorRegistry.put(ISketchColorConstants.LIGHT_RED_KEY, new RGB(255, 225, 225));
            colorRegistry.put(ISketchColorConstants.LIGHT_GREEN_KEY, new RGB(225, 255, 225));
            colorRegistry.put(ISketchColorConstants.LIGHT_BLUE_KEY, new RGB(225, 225, 255));
            colorRegistry.put(ISketchColorConstants.ERROR_BG_KEY, new RGB(255, 250, 250));
            colorRegistry.put(ISketchColorConstants.CONDITION_BG_KEY, new RGB(250, 255, 250));
            colorRegistry.put(ISketchColorConstants.LOOP_BG_KEY, new RGB(250, 250, 255));
            colorRegistry.put(ISketchColorConstants.AMBER_KEY, new RGB(255, 160, 32));
            colorRegistry.put(ISketchColorConstants.LIGHT_AMBER_KEY, new RGB(255, 225, 180));
            colorRegistry.put(ISketchColorConstants.LIGHT_PURPLE_KEY, new RGB(255, 225, 255));
            colorRegistry.put(ISketchColorConstants.PURPLE_KEY, new RGB(255, 180, 255));
            colorRegistry.put(ISketchColorConstants.GRAY_KEY, new RGB(150, 150, 150));
            colorRegistry.put(ISketchColorConstants.BLACK_KEY, new RGB(0, 0, 0));

        }
        return colorRegistry;
    }

    /**
     * Deletes a sketch from the system.
     * @param sketch the sketch
     */
    public void deleteSketch(IProgramSketch sketch) {
        deleteSketch(sketch, true);
    }

    public void deleteSketch(final IProgramSketch sketch, boolean fork) {
        final Runnable work = new Runnable() {
            /* (non-Javadoc)
             * @see java.lang.Runnable#run()
             */
            @Override
            public void run() {
                if (sketch instanceof DBProgramSketch) {
                    DBProgramSketch s = (DBProgramSketch) sketch;
                    if (s != null) {
                        if (s.equals(getActiveSketch())) {
                            setActiveSketch(null);
                        }
                        getDOI().setSketchHidden(sketch, false, new NullProgressMonitor());
                        boolean deleted = s.delete();
                        if (deleted) {
                            synchronized (cachedSketches) {
                                Iterator<IProgramSketch> sketches = cachedSketches.values().iterator();
                                while (sketches.hasNext()) {
                                    IProgramSketch next = sketches.next();
                                    if (next.equals(sketch)) {
                                        sketches.remove();
                                    }
                                }
                            }
                            events.fireEvent(new SketchEvent(sketch, SketchEvent.SketchEventType.SketchDeleted));

                        }
                        if (sketch.equals(doi.getActiveSketch())) {
                            setActiveSketch(null);
                        }
                    }
                }
            }
        };
        if (fork) {
            WorkspaceJob job = new WorkspaceJob("Deleting " + sketch.getLabel()) {
                @Override
                public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
                    work.run();
                    return Status.OK_STATUS;
                }
            };
            job.schedule();
        } else {
            work.run();
        }
    }

    /**
     * @param traceElement
     * @return
     */
    public IProgramSketch getSketch(ITraceModel traceElement) {
        if (traceElement == null)
            return null;
        ITrace trace = traceElement.getTrace();
        String launchID = trace.getLaunchID();
        IProgramSketch[] sketches = getStoredSketches();
        for (IProgramSketch sketch : sketches) {
            String sketchLaunch = sketch.getID();
            if (sketchLaunch.equals(launchID)) {
                return sketch;
            }
        }
        return null;
    }

    /**
     * Sets the active sketch to the given sketch. May be null.
     * @param sketch the new active sketch. May be null.
     */
    public synchronized void setActiveSketch(final IProgramSketch sketch) {
        IProgramSketch activeSketch = doi.getActiveSketch();
        if (doi.getActiveSketch() != null) {
            if (activeSketch.getTraceData() != null) {
                activeSketch.getTraceData().removeListener(staticJavaModelListener);
            }
        }
        try {
            IRunnableWithProgress runnable = new IRunnableWithProgress() {

                @Override
                public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
                    doi.setActiveSketch(sketch, monitor);
                    if (sketch != null) {
                        sketch.getTraceData().addListener(staticJavaModelListener);
                    }
                    SketchUI.INSTANCE.refreshJavaUI();

                }
            };
            if (Display.getCurrent() != null) {
                getWorkbench().getProgressService().busyCursorWhile(runnable);
            } else {
                runnable.run(new NullProgressMonitor());
            }

        } catch (InterruptedException e) {
        } catch (Exception e) {
            log(e);
            doi.setActiveSketch(null, new NullProgressMonitor());
            SketchUI.INSTANCE.refreshJavaUI();
        }
    }

    /**
     * Returns the active sketch in the framework. May be null.
     * @return
     */
    public synchronized IProgramSketch getActiveSketch() {
        return doi.getActiveSketch();
    }

    public static ImageDescriptor imageDescriptorFromPlugin(String location) {
        return imageDescriptorFromPlugin(PLUGIN_ID, location);
    }

    /**
     * @param lastTrace
     * @return
     */
    public IProgramSketch getSketch(String identifier) {
        if (identifier == null)
            return null;
        for (IProgramSketch sketch : getStoredSketches()) {
            if (sketch.getID().equals(identifier)) {
                return sketch;
            }
        }
        return null;
    }

    /**
     * @return
     */
    public IDegreeOfInterest getDOI() {
        return doi;
    }

}