emenda.kwopenproject.Activator.java Source code

Java tutorial

Introduction

Here is the source code for emenda.kwopenproject.Activator.java

Source

package emenda.kwopenproject;

import java.io.BufferedReader;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;

import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceChangeEvent;
import org.eclipse.core.resources.IResourceChangeListener;
import org.eclipse.core.resources.IResourceDelta;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.MessageBox;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.osgi.framework.BundleContext;

import emenda.kwjlib.*;
import emenda.kwopenproject.preferences.PreferenceConstants;
import emenda.kwopenproject.remote.KlocworkCaller;

import org.json.*;

import java.util.Date;
import java.util.HashMap;
import java.util.Properties;
import java.lang.Long;

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

    // The plug-in ID
    public static final String PLUGIN_ID = "kwopenproject"; //$NON-NLS-1$

    // The shared instance
    private static Activator plugin;

    //Strings for use in property files
    final static String PROP_TEMP_FILEPATH = "kwtd4.filepath";
    final static String PROP_PROJECT_VERSION = "kwtd4.version";
    final static String PROP_PROJECT_CONFIGPATH = "kwtd4.server.configpath";
    final static String PROP_PROJECT_PROJECTNAME = "kwtd4.project";
    final static String PROP_PROJECT_BUILDUNIT = "kwtd4.buildunit";
    final static String PROP_PROJECT_MKSVERSION = "kwtd4.mksversion";
    final static String PROP_PROJECT_MKSHISTORYFILE = "kwtd4.mkshistoryfile";
    final static String PROP_PROJECT_SERVER = ".server";
    final static String PROP_PROJECT_BUILDSPEC = ".buildspec";
    final static String PROP_PROJECT_KWHOST = ".server.host";
    final static String PROP_PROJECT_KWPORT = ".server.port";
    //   final static String PROP_PROJECT_KWUSER = ".server.user";
    final static String PROP_PROJECT_LICHOST = ".license.host";
    final static String PROP_PROJECT_LICPORT = ".license.port";
    final static String PROP_PROJECT_SSL = ".ssl";
    final static String PROP_PROJECT_KWOPENPROJECT_PORT = ".kwopenproject.port";
    final static String PROP_KW_HOST = "klocwork.host";
    final static String PROP_KW_PORT = "klocwork.port";
    final static String PROP_KW_LICHOST = "license.host";
    final static String PROP_KW_LICPORT = "license.port";
    final static String PROP_KW_PROJECT = "klocwork.project";
    final static String PROP_KW_SSL = "klocwork.ssl";
    final static String KLOCWORK_PROPERTIES_FILE = "\\klocwork.properties";

    final static boolean PROMPT_USER = true;

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

    /*
     * (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;

        //After starting plug-in, load plug-in preferences and set up logging
        store = Activator.getDefault().getPreferenceStore();
        IWorkspace workspace = ResourcesPlugin.getWorkspace();
        logging = new Logging(workspace.getRoot().getLocation().toOSString()
                + store.getString(PreferenceConstants.P_WORKSPACELOG));
        //scan each project, then register listener
        logging.writeLog("Plug-in startup. Scanning projects...");
        if (scanProjects() == true)
            logging.writeLog("Plug-in startup. Scanning projects... Success");
        else
            logging.writeLog("Plug-in startup. Scanning projects... Failure");
        logging.writeLog("Registering listener with workspace...");
        if (registerListener())
            logging.writeLog("Registering listener with workspace... Success");
        else
            logging.writeLog("Registering listener with workspace... Failure");
        //      org.eclipse.swt.widgets.Shell parent = getWorkbench().getModalDialogShellProvider().getShell();
        //      MessageBox dialog = new MessageBox(parent, SWT.ICON_QUESTION | SWT.YES | SWT.NO);
        //      dialog.setText("Klocwork Project Activation");
        //      dialog.setMessage("Klocwork has noticed that you have opened a new project and will now attempt to load settings automatically. Do you wish to continue?");
        //      dialog.open();
    }

    /*
     * (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);
    }

    /**
     * Returns the shared instance
     *
     * @return the shared instance
     */
    public static Activator 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);
    }

    /*
     * Non-inherited variables and functions
     */

    private IResourceChangeListener listener;
    private HashMap<String, Long> lastModifiedMap;
    private final String versionNumber = "1.0";
    private Logging logging;
    private IPreferenceStore store;

    //Utility function to load properties
    public Properties loadProperties(String propertyPath) {
        logging.writeLog("Loading properties file: " + propertyPath + "...");
        //Initialise and load properties object from file
        Properties prop = new Properties();
        try {
            prop.load(new FileInputStream(propertyPath));
            prop.put(PROP_TEMP_FILEPATH, propertyPath);
        } catch (Exception e) {
            logging.writeLog("Exception while reading properties file: " + propertyPath + "\nException message: "
                    + e.getMessage());
            return null;
        }
        logging.writeLog("Loading properties file: " + propertyPath + "... Success");
        return prop;
    }

    //Utility function to store properties
    public boolean storeProperties(Properties prop) {
        if (prop != null) {
            //Remove temporary filepath value from file before storing
            String filepath = prop.getProperty(PROP_TEMP_FILEPATH);
            prop.remove(PROP_TEMP_FILEPATH);
            try {
                logging.writeLog("Storing properties file: " + filepath + "...");
                prop.store(new FileOutputStream(filepath), null);
                logging.writeLog("Storing properties file: " + filepath + "... SUCCESS");
            } catch (Exception e) {
                logging.writeLog("Exception while writing Klocwork Sync properties to file: "
                        + prop.getProperty(PROP_TEMP_FILEPATH) + "\nMessage: " + e.getMessage());
                return false;
            }
        }

        return true;
    }

    //Function to register the listener
    public boolean registerListener() {
        logging.writeLog("Registering listener...");
        //Declare the listener
        listener = new IResourceChangeListener() {
            public void resourceChanged(IResourceChangeEvent event) {
                handleEvent(event);
            }
        };

        //Register the listener with the workspace
        IWorkspace workspace = ResourcesPlugin.getWorkspace();
        workspace.addResourceChangeListener(listener);
        logging.writeLog("Successfully registed listener");
        return true;
    }

    //Function called by listener upon event
    //Check for a POST_CHANGE event then scan for a recently opened project
    private void handleEvent(IResourceChangeEvent event) {
        if (event.getType() == IResourceChangeEvent.POST_CHANGE) {
            logging.writeLog("Handling event of type POST_CHANGE...");
            IResourceDelta rootDelta = event.getDelta();
            //Scan the delta tree for a newly opened project with function getOpenedProject
            logging.writeLog("Fetching activated project (if any)...");
            IResourceDelta projectDelta = getActivatedProject(rootDelta);
            //Have we found a project?
            if (projectDelta != null) {
                logging.writeLog("Project found! Processing...");
                //Handle the project resource
                IResource projectResource = projectDelta.getResource();
                handleResource(projectResource);
                logging.writeLog("Project found! Processing... Complete");
            }
        }
    }

    //Function to retrieve the opened project (if there is one) from
    // the project list of the workspace (represented by rootDelta)
    private IResourceDelta getActivatedProject(IResourceDelta rootDelta) {
        logging.writeLog("Fetching project resource objects...");
        IResourceDelta children[] = rootDelta.getAffectedChildren();

        if (children == null) {
            logging.writeLog("No project resource objects could be retrieved. Bailing out.");
            return null;
        }

        logging.writeLog("Number of project resource objects found: " + children.length);

        for (int i = 0; i < children.length; i++) {
            logging.writeLog("Processing project resource object " + i + " of " + children.length);

            if (children[i] == null)
                continue;

            //No need to check "closed" projects
            IResource resource = children[i].getResource();
            logging.writeLog("Project name: " + resource.getName());
            if (resource.isAccessible() == true) {
                String filepath = resource.getLocation().toOSString()
                        + store.getString(PreferenceConstants.P_KWTD4PROPERTIES);
                File file = new File(filepath);
                if (file.exists() != true) {
                    logging.writeLog(
                            "No kwtd4 properties file found for this project! Continuing to next project...");
                    continue;
                }

                long lastModified = lastModifiedMap.get(resource.getName());
                logging.writeLog("Kwtd4 properties file found. Last modified: " + file.lastModified()
                        + ". Comparing this date to " + lastModified);
                if (file.lastModified() > lastModified) {
                    //The config file of this project has been modified since last scan,
                    //so this is the project to process
                    logging.writeLog(
                            "Properties file has been modified, this is the project which has been activated.");
                    lastModifiedMap.put(resource.getName(), file.lastModified());
                    return children[i];
                }
            }
            //         //Check if an "open project" event has occurred
            //         if((children[i].getFlags() & IResourceDelta.OPEN) != 0) {
            //            IResource resource = children[i].getResource();
            //            if(resource == null)
            //               continue;
            //            
            //             //IResourceDelta.OPEN flag is used for both opening and closing
            //             //project, so we must check it is accessible (i.e. open)
            //            if(resource.getType() == IResource.PROJECT &&      
            //               resource.isAccessible() == true) {
            //               //This is the project which has been opened!
            //               return children[i];
            //            }
            //         }
        }

        return null;
    }

    //Function to handle a project resource.
    // Attempts to set values in the Klocwork plug-in synchronisation tab
    // Fetches list of Klocwork projects from Klocwork server
    // If no matching project exists on server, makes calls to create one
    // Sets values in synchronisation tab accordingly
    private boolean handleResource(IResource projectResource) {

        String projectname;
        String uniqueName;
        String tempresult;

        String host;
        String port;
        String user;

        String workspacePath;
        String klocworkPropertiesFilePath;

        Properties klocworkProperties;
        Properties projectProperties;
        Properties kwtd4Properties;

        IPath projectPath;

        //      //Display messagebox, asking user if they wish to continue
        //      org.eclipse.swt.widgets.Shell parent = getWorkbench().getModalDialogShellProvider().getShell();
        //      MessageBox dialog = new MessageBox(parent, SWT.ICON_QUESTION | SWT.YES | SWT.NO);
        //      dialog.setText("Klocwork Project Activation");
        //      dialog.setMessage("Klocwork has noticed that you have opened a new project and will now attempt to load settings automatically. Do you wish to continue?");

        //Begin by fetching project path and loading properties file
        projectPath = projectResource.getLocation();
        workspacePath = projectResource.getWorkspace().getRoot().getLocation().toOSString();
        klocworkPropertiesFilePath = workspacePath + store.getString(PreferenceConstants.P_PROJECTSDIR) + "\\"
                + projectResource.getName() + store.getString(PreferenceConstants.P_KWLPPROPERTIES);
        klocworkProperties = loadProperties(klocworkPropertiesFilePath);
        projectProperties = loadProperties(
                projectPath.toOSString() + store.getString(PreferenceConstants.P_KWTD4PROPERTIES));
        kwtd4Properties = loadProperties(
                projectProperties.getProperty(PROP_PROJECT_CONFIGPATH) + KLOCWORK_PROPERTIES_FILE);

        //Logging
        logging.writeLog("Now processing project " + projectResource.getName() + ". Please see log file "
                + projectPath.toOSString() + store.getString(PreferenceConstants.P_PROJECTLOG)
                + " for more information.");
        Logging projectLog = new Logging(
                projectPath.toOSString() + store.getString(PreferenceConstants.P_PROJECTLOG));
        projectLog.writeLog("Processing project " + projectResource.getName());

        //Check version is correct
        if (!(projectProperties.get(PROP_PROJECT_VERSION).equals(versionNumber))) {
            projectLog.writeLog("Incorrect version number in properties file: "
                    + projectProperties.getProperty(PROP_TEMP_FILEPATH) + " \nProgram version: " + versionNumber
                    + ". Properties file version: " + projectProperties.get(PROP_PROJECT_VERSION));
        }

        //      //1. Retrieve plugin sync settings, if they are already set then return true,
        //      // we do not need to change them
        //      projectLog.writeLog("Fetching existing Klocwork project setting...");
        //      String kwsyncname = klocworkProperties.getProperty(PROP_KW_PROJECT);
        //      if(kwsyncname != null && kwsyncname.length() > 0) {
        //         projectLog.writeLog("Setting already exists, value is: " + kwsyncname);
        //         projectLog.writeLog("No further processing of project.");
        //         return true;
        //      }
        //      projectLog.writeLog("Setting does not exist/is incorrect, fetching project unique name from properties file: " + projectProperties.getProperty(PROP_TEMP_FILEPATH));

        //1. Fetch project & iteration unique name
        // Return false on failure
        projectLog.writeLog("Generating project unique name from values fetched from properties file: "
                + projectProperties.getProperty(PROP_TEMP_FILEPATH));
        uniqueName = Util.generateUniqueName(projectProperties.getProperty(PROP_PROJECT_PROJECTNAME),
                projectProperties.getProperty(PROP_PROJECT_BUILDUNIT),
                projectProperties.getProperty(PROP_PROJECT_MKSVERSION));
        if (uniqueName.length() < 1) {
            projectLog.writeLog(
                    "Generated project unique name is blank. Please correct settings in kwtd4settings.properties file: "
                            + projectProperties.getProperty(PROP_TEMP_FILEPATH));
            return false;
        }
        projectLog.writeLog("Generated project unique name is: " + uniqueName);
        //We can now read various values from kwtd4 project-specific properties
        host = kwtd4Properties.getProperty(uniqueName + PROP_PROJECT_KWHOST);
        port = kwtd4Properties.getProperty(uniqueName + PROP_PROJECT_KWPORT);
        user = System.getProperty("user.name");
        //      user = kwtd4Properties.getProperty(uniqueName + PROP_PROJECT_KWUSER);
        //Check that we have generated the correct unique name by attempting to retrieve the Klocwork server host value
        // for the project in question. If the retrieval fails then no settings for this project exist and it must be created.
        tempresult = kwtd4Properties.getProperty(uniqueName + PROP_PROJECT_KWHOST);
        if (tempresult != null && tempresult.length() > 0) {
            //2. Set values of Klocwork synchronisation tab using values from properties file
            klocworkProperties.put(PROP_KW_HOST, host);
            klocworkProperties.put(PROP_KW_PORT, port);
            klocworkProperties.put(PROP_KW_LICHOST, kwtd4Properties.getProperty(uniqueName + PROP_PROJECT_LICHOST));
            klocworkProperties.put(PROP_KW_LICPORT, kwtd4Properties.getProperty(uniqueName + PROP_PROJECT_LICPORT));
            klocworkProperties.put(PROP_KW_SSL, kwtd4Properties.getProperty(uniqueName + PROP_PROJECT_SSL));
        } else { //Copy settings from an earlier version
            tempresult = Util.getPreviousVersion(projectProperties.getProperty(PROP_PROJECT_PROJECTNAME),
                    projectProperties.getProperty(PROP_PROJECT_BUILDUNIT),
                    projectProperties.getProperty(PROP_PROJECT_MKSVERSION), kwtd4Properties);
            if (tempresult == null || tempresult.length() < 1) {
                //Now we have a problem, what do we do? <-- Could happen very easily
                projectLog.writeLog("Could not find an earlier version of " + uniqueName
                        + ". Unable to continue as Klocwork host and port are required.");
                projectLog.writeLog("Please correct this by entering the following information manually in file "
                        + kwtd4Properties.getProperty(PROP_TEMP_FILEPATH) + ":");
                projectLog.writeLog(" 1. " + uniqueName + PROP_PROJECT_KWHOST);
                projectLog.writeLog(" 2. " + uniqueName + PROP_PROJECT_KWPORT);
                projectLog.writeLog(" 3. " + uniqueName + PROP_PROJECT_LICHOST);
                projectLog.writeLog(" 4. " + uniqueName + PROP_PROJECT_LICPORT);
                return false;
            }

        }

        //3. Fetch list of projects from server
        // Try to find a project on server which matches the unique name
        // If a match is found, set this in the properties of the project
        projectname = "";
        projectLog.writeLog("Connecting to KW Review Web API to retrieve list of existing projects...");
        projectLog.writeLog("host: " + host + " port: " + port + " user: " + user);
        KWWebAPIService service = new KWWebAPIService(host, port, user);
        if (service.connect()) {
            KWJSONRecord projects[] = service.projects();
            if (projects == null) {
                projectLog.writeLog("No projects returned. Error message (if any): " + KWWebAPIService.getError());
            } else {
                //See if we have found a match
                for (int i = 0; i < projects.length; i++) {
                    if (projects[i].getValue("name").equalsIgnoreCase(uniqueName)) {
                        projectLog.writeLog("Match found, project " + projects[i].getValue("name"));
                        projectname = uniqueName;
                        break;
                    }
                }
            }
        } else {
            projectLog.writeLog("Connection failed. Error message returned: " + KWWebAPIService.getError());
        }

        //4. If all else fails, the project must be created on the KW server
        // This is achieved using Java RMI with a listener on the server
        // Once the project has been created, load the source from MKS
        // Then run an analysis and upload the results
        // Always duplicate the project to ensure history and settings are copied
        if (projectname.length() < 1) {
            projectLog.writeLog("Attempting to connect to KlocworkWorker server (RMI) service");
            KlocworkCaller caller = new KlocworkCaller();
            //Connect to RMI listener (KlocworkWorker) using caller (KlocworkCaller)
            if (caller.connectToServer(host,
                    Integer.parseInt(kwtd4Properties.getProperty(uniqueName + PROP_PROJECT_KWOPENPROJECT_PORT)))) {
                projectLog.writeLog("Connected to server successfully!");
            } else {
                projectLog.writeLog("ERROR: Connection failed.");
                projectLog.writeLog("Server error (if any): " + caller.getServerError());
                projectLog.writeLog("Caller error (if any): " + caller.getError());
                return false;
            }
            //Attempt to create project
            if (caller.createProject("http://" + host + ":" + port, uniqueName, "")) {
                projectLog.writeLog("Created project successfully!");
            } else {
                projectLog.writeLog("ERROR: Project creation failed.");
                projectLog.writeLog("Server error (if any): " + caller.getServerError());
                projectLog.writeLog("Caller error (if any): " + caller.getError());
                return false;
            }
            //TODO: Use TD4 to fetch source and perform build
            //TODO: Run analysis
            //TODO: Upload results
            projectname = "something";
        }

        klocworkProperties.put(PROP_KW_PROJECT, projectname);
        return storeProperties(klocworkProperties);
    }

    private boolean scanProjects() {
        //Initialise hashmap if not initialised
        logging.writeLog("Initialising hashmap...");
        if (lastModifiedMap == null) {
            lastModifiedMap = new HashMap<String, Long>();
        }
        //Get the workspace and iterate through projects
        IWorkspace workspace = ResourcesPlugin.getWorkspace();
        IProject projects[] = workspace.getRoot().getProjects();
        if (projects != null) {
            logging.writeLog("Number of projects found in scan: " + projects.length);
            for (int i = 0; i < projects.length; i++) {
                String filepath = projects[i].getLocation().toOSString()
                        + store.getString(PreferenceConstants.P_KWTD4PROPERTIES);
                File file = new File(filepath);
                //Store the last modified date of the config file in the hashmap
                if (file.exists()) {
                    lastModifiedMap.put(projects[i].getName(), file.lastModified());
                } else {
                    lastModifiedMap.put(projects[i].getName(), (long) 0);
                }
                logging.writeLog("Last modified date of file " + filepath + " stored in hashmap as "
                        + lastModifiedMap.get(projects[i].getName()));
            }
            return true;
        }
        logging.writeLog("No projects were returned when scanning. Empty workspace?");
        return false;
    }
}