com.wakatime.eclipse.plugin.WakaTime.java Source code

Java tutorial

Introduction

Here is the source code for com.wakatime.eclipse.plugin.WakaTime.java

Source

/* ==========================================================
File:        WakaTime.java
Description: Automatic time tracking for Eclipse.
Maintainer:  WakaTime <support@wakatime.com>
License:     BSD, see LICENSE for more details.
Website:     https://wakatime.com/
===========================================================*/

package com.wakatime.eclipse.plugin;

import java.io.BufferedReader;
import java.io.File;
import java.io.InputStreamReader;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;

import org.eclipse.core.commands.IExecutionListener;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.widgets.Control;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IStartup;
import org.eclipse.ui.IURIEditorInput;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.commands.ICommandService;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.eclipse.ui.texteditor.AbstractTextEditor;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;

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

    // The plug-in ID
    public static final String PLUGIN_ID = "com.wakatime.eclipse.plugin";

    // The shared instance
    private static WakaTime plugin;
    private static ILog logInstance;
    private static boolean DEBUG = false;

    // Listeners
    private static CustomEditorListener editorListener;
    private static IExecutionListener executionListener;

    // Constants
    public static final long FREQUENCY = 2; // frequency of heartbeats in minutes
    public static final String CONFIG = ".wakatime.cfg";
    public static final String VERSION = Platform.getBundle(PLUGIN_ID).getVersion().toString();
    public static final String ECLIPSE_VERSION = Platform.getBundle("org.eclipse.platform").getVersion().toString();

    public String lastFile;
    public long lastTime = 0;

    /**
     * The constructor
     */
    public WakaTime() {
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
     */
    public void start(BundleContext context) throws Exception {
        logInstance = getLog();
        WakaTime.log("Initializing WakaTime plugin (https://wakatime.com) v" + VERSION);

        super.start(context);
        plugin = this;

        editorListener = new CustomEditorListener();
    }

    @Override
    public void earlyStartup() {
        final IWorkbench workbench = PlatformUI.getWorkbench();

        // listen for save file events
        ICommandService commandService = (ICommandService) workbench.getService(ICommandService.class);
        executionListener = new CustomExecutionListener();
        commandService.addExecutionListener(executionListener);

        workbench.getDisplay().asyncExec(new Runnable() {
            public void run() {
                IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
                if (window == null)
                    return;

                // prompt for apiKey if not set
                MenuHandler handler = new MenuHandler();
                DEBUG = handler.getDebug();
                String apiKey = handler.getApiKey();
                if (apiKey == "") {
                    handler.promptForApiKey(window);
                }

                Dependencies deps = new Dependencies();

                if (!deps.isPythonInstalled()) {
                    deps.installPython();
                    if (!deps.isPythonInstalled()) {
                        MessageDialog dialog = new MessageDialog(window.getShell(), "Warning!", null,
                                "WakaTime needs Python installed. Please install Python from python.org/downloads, then restart Eclipse.",
                                MessageDialog.WARNING, new String[] { IDialogConstants.OK_LABEL }, 0);
                        dialog.open();
                    }
                }
                if (!deps.isCLIInstalled()) {
                    deps.installCLI();
                }

                if (window.getPartService() == null)
                    return;

                // listen for caret movement
                if (window.getPartService().getActivePartReference() != null
                        && window.getPartService().getActivePartReference().getPage() != null
                        && window.getPartService().getActivePartReference().getPage().getActiveEditor() != null) {
                    IEditorPart part = window.getPartService().getActivePartReference().getPage().getActiveEditor();
                    if (!(part instanceof AbstractTextEditor))
                        return;
                    ((StyledText) part.getAdapter(Control.class)).addCaretListener(new CustomCaretListener());
                }

                // listen for change of active file
                window.getPartService().addPartListener(editorListener);

                if (window.getPartService().getActivePart() == null)
                    return;
                if (window.getPartService().getActivePart().getSite() == null)
                    return;
                if (window.getPartService().getActivePart().getSite().getPage() == null)
                    return;
                if (window.getPartService().getActivePart().getSite().getPage().getActiveEditor() == null)
                    return;
                if (window.getPartService().getActivePart().getSite().getPage().getActiveEditor()
                        .getEditorInput() == null)
                    return;

                // log file if one is opened by default
                IEditorInput input = window.getPartService().getActivePart().getSite().getPage().getActiveEditor()
                        .getEditorInput();
                if (input instanceof IURIEditorInput) {
                    URI uri = ((IURIEditorInput) input).getURI();
                    if (uri != null && uri.getPath() != null) {
                        String currentFile = uri.getPath();
                        long currentTime = System.currentTimeMillis() / 1000;
                        if (!currentFile.equals(WakaTime.getDefault().lastFile)
                                || WakaTime.getDefault().lastTime + WakaTime.FREQUENCY * 60 < currentTime) {
                            WakaTime.logFile(currentFile, WakaTime.getActiveProject(), false);
                            WakaTime.getDefault().lastFile = currentFile;
                            WakaTime.getDefault().lastTime = currentTime;
                        }
                    }
                }

                WakaTime.log("Finished initializing WakaTime plugin (https://wakatime.com) v" + VERSION);
            }
        });
    }

    /*
     * (non-Javadoc)
     * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
     */
    public void stop(BundleContext context) throws Exception {
        plugin = null;
        super.stop(context);

        IWorkbenchWindow window = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
        if (window != null && window.getPartService() != null)
            window.getPartService().removePartListener(editorListener);
    }

    public static void logFile(String file, String project, boolean isWrite) {
        ArrayList<String> cmds = new ArrayList<String>();
        cmds.add("python");
        cmds.add(WakaTime.getWakaTimeCLI());
        cmds.add("--file");
        cmds.add(WakaTime.fixFilePath(file));
        cmds.add("--plugin");
        cmds.add("eclipse/" + ECLIPSE_VERSION + " eclipse-wakatime/" + VERSION);
        if (project != null) {
            cmds.add("--project");
            cmds.add(project);
        }
        if (isWrite)
            cmds.add("--write");
        if (DEBUG)
            WakaTime.log(cmds.toString());
        try {
            Process proc = Runtime.getRuntime().exec(cmds.toArray(new String[cmds.size()]));
            if (DEBUG) {
                BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
                BufferedReader stdError = new BufferedReader(new InputStreamReader(proc.getErrorStream()));
                proc.waitFor();
                String s;
                while ((s = stdInput.readLine()) != null) {
                    WakaTime.log(s);
                }
                while ((s = stdError.readLine()) != null) {
                    WakaTime.log(s);
                }
                WakaTime.log("Command finished with return value: " + proc.exitValue());
            }
        } catch (Exception e) {
            WakaTime.error("Error", e);
        }
    }

    public static String getActiveProject() {
        IWorkbench workbench = PlatformUI.getWorkbench();
        IWorkbenchWindow window = workbench.getActiveWorkbenchWindow();
        if (window == null)
            return null;
        if (window.getPartService() == null)
            return null;
        if (window.getPartService().getActivePart() == null)
            return null;
        if (window.getPartService().getActivePart().getSite() == null)
            return null;
        if (window.getPartService().getActivePart().getSite().getPage() == null)
            return null;
        if (window.getPartService().getActivePart().getSite().getPage().getActiveEditor() == null)
            return null;
        if (window.getPartService().getActivePart().getSite().getPage().getActiveEditor().getEditorInput() == null)
            return null;

        IEditorInput input = window.getPartService().getActivePart().getSite().getPage().getActiveEditor()
                .getEditorInput();

        IProject project = null;

        if (input instanceof FileEditorInput) {
            project = ((FileEditorInput) input).getFile().getProject();
        }

        if (project == null)
            return null;

        return project.getName();
    }

    public static String fixFilePath(String file) {
        return file.replaceFirst("^[\\\\/]([A-Z]:[\\\\/])", "$1");
    }

    public static String getWakaTimeCLI() {
        Bundle bundle = Platform.getBundle("com.wakatime.eclipse.plugin");
        URL url = bundle.getEntry("/");
        URL rootURL = null;
        try {
            rootURL = FileLocator.toFileURL(url);
        } catch (Exception e) {
            WakaTime.error("Error", e);
        }
        if (rootURL == null)
            return null;
        File rootDir = new File(rootURL.getPath());
        File script = new File(rootDir,
                "dependencies" + File.separator + "wakatime-master" + File.separator + "wakatime-cli.py");
        return script.getAbsolutePath();
    }

    public static void log(String msg) {
        WakaTime.logMessage(msg, Status.INFO, null);
    }

    public static void error(String msg) {
        WakaTime.logMessage(msg, Status.ERROR, null);
    }

    public static void error(String msg, Exception e) {
        WakaTime.logMessage(msg, Status.ERROR, e);
    }

    public static void logMessage(String msg, int level, Exception e) {
        if (logInstance != null)
            logInstance.log(new Status(level, PLUGIN_ID, Status.OK, msg, e));
    }

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

    /**
     * Returns an image descriptor for the image file at the given
     * plug-in relative path
     *
     * @param path the path
     * @return the image descriptor
     */
    public static ImageDescriptor getImageDescriptor(String path) {
        return imageDescriptorFromPlugin(PLUGIN_ID, path);
    }
}