uk.ac.soton.itinnovation.sad.service.services.EccIntegrationService.java Source code

Java tutorial

Introduction

Here is the source code for uk.ac.soton.itinnovation.sad.service.services.EccIntegrationService.java

Source

/////////////////////////////////////////////////////////////////////////
//
//  University of Southampton IT Innovation Centre, 2013
//
// Copyright in this library belongs to the University of Southampton
// IT Innovation Centre of Gamma House, Enterprise Road,
// Chilworth Science Park, Southampton, SO16 7NS, UK.
//
// This software may not be used, sold, licensed, transferred, copied
// or reproduced in whole or in part in any manner or form or in or
// on any media by any person other than in accordance with the terms
// of the Licence Agreement supplied with the software, or otherwise
// without the prior written consent of the copyright owners.
//
// This software is distributed WITHOUT ANY WARRANTY, without even the
// implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE, except where stated in the Licence Agreement supplied with
// the software.
//
//   Created By :         Maxim Bashevoy
//   Created Date :         2013-08-23
//   Created for Project :           Experimedia
//
/////////////////////////////////////////////////////////////////////////
package uk.ac.soton.itinnovation.sad.service.services;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.ServerSocket;
import java.util.ArrayList;
import java.util.HashMap;
import javax.annotation.PostConstruct;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import uk.ac.soton.itinnovation.sad.service.adapters.ProcessWatcher;

@Service("eccIntegrationService")
public class EccIntegrationService {

    private final Logger logger = LoggerFactory.getLogger(getClass());

    private final String fileSeparator = System.getProperty("file.separator");
    private final HashMap<String, String> pluginNamesAndPorts = new HashMap<>();
    private ArrayList<Process> createdProcesses;

    @Autowired
    @Qualifier("configurationService")
    ConfigurationService configurationService;

    @Autowired
    @Qualifier("pluginsService")
    PluginsService pluginsService;

    public EccIntegrationService() {
    }

    @PostConstruct
    public void init() {
    }

    public boolean start() {

        logger.debug("Initialising ECC Integration service");
        createdProcesses = new ArrayList<>();

        boolean result = true;

        // If ECC intagration enabled
        if (!configurationService.getConfiguration().isEccEnabled()) {
            logger.debug("Nothing to do, ECC integration disabled");

        } else {

            // Discover plugins
            JSONObject pluginInfo;
            String pathToPlugins = pluginsService.getAbsolutePluginsPath();
            JSONObject currentSadConfig = JSONObject.fromObject(configurationService.getConfiguration());
            String configurationFilePath;
            try {
                File tmp = File.createTempFile("sadconfiguration", ".json");
                tmp.deleteOnExit();

                File coordinatorPath = new File(configurationService.getConfiguration().getCoordinatorPath());

                currentSadConfig.put("coordinatorPathAbs", coordinatorPath.getAbsolutePath());

                FileWriter fileWriter = new FileWriter(tmp);
                fileWriter.write(currentSadConfig.toString());
                fileWriter.close();
                configurationFilePath = tmp.getAbsolutePath();
                logger.debug("Stored current configuration for plugins\n" + currentSadConfig.toString(2) + "\nin: "
                        + configurationFilePath);
            } catch (IOException e) {
                logger.error("Failed to create temporary configuration file", e);
                return false;
            }
            ServerSocket s;

            Thread tempThread;
            int pluginCounter = 0;
            for (String pluginName : pluginsService.getPluginNames()) {

                pluginCounter++;

                logger.debug("Processing plugin " + pluginCounter + ": " + pluginName);
                pluginInfo = pluginsService.getPluginByName(pluginName);

                if (pluginInfo.isEmpty()) {
                    logger.error("Plugin not found: " + pluginName);
                    continue;
                }

                if (!pluginInfo.containsKey("paths")) {
                    logger.error(
                            "Plugin configuration must contain \'paths\'. Misconfigured plugin: " + pluginName);
                    continue;
                }

                if (!pluginInfo.containsKey("pluginFolder")) {
                    logger.error(
                            "Plugin configuration must be loaded with pluginsService that fills in the \'pluginFolder\' field. Misconfigured plugin: "
                                    + pluginName);
                    continue;
                }

                JSONObject pluginPaths = pluginInfo.getJSONObject("paths");

                if (!pluginPaths.containsKey("jar")) {
                    logger.error(
                            "Plugin configuration must contain \'paths/jar\'. Misconfigured plugin: " + pluginName);
                    continue;
                }
                if (!pluginPaths.containsKey("dependenciesFolder")) {
                    logger.error(
                            "Plugin configuration must contain \'paths/dependenciesFolder\'. Misconfigured plugin: "
                                    + pluginName);
                    continue;
                }
                if (!pluginInfo.containsKey("pluginFolder")) {
                    logger.error("Plugin configuration must contain \'pluginFolder\'. Misconfigured plugin: "
                            + pluginName);
                    continue;
                }

                //                portNumber++;
                String jarPath = pluginPaths.getString("jar");
                String dependenciesFolderPath = pluginPaths.getString("dependenciesFolder");
                String pluginFolder = pluginInfo.getString("pluginFolder");
                String port = null;
                try {
                    s = new ServerSocket(0);
                    port = Integer.toString(s.getLocalPort());
                    s.close();
                } catch (IOException ex) {
                    logger.error("Failed to assign a new free port", ex);
                    throw new RuntimeException(ex);
                }

                String uuid = configurationService.getConfiguration().getEcc().getClientsUuuidSeed()
                        + Integer.toHexString(pluginCounter);
                logger.debug("Using seeded UUID: " + uuid);

                logger.debug("Plugin jar path from configuration: " + jarPath + ", dependenciesFolderPath: "
                        + dependenciesFolderPath);
                logger.debug("Plugin folder configuration: " + pathToPlugins);
                logger.debug("Socket port: " + port);
                logger.debug("ECC client UUID: " + uuid);

                String[] command = new String[] { "java", "-cp",
                        pathToPlugins + fileSeparator + pluginFolder + fileSeparator + dependenciesFolderPath
                                + fileSeparator + "*",
                        "-jar", pathToPlugins + fileSeparator + pluginFolder + fileSeparator + jarPath, "ecc",
                        configurationFilePath, port, uuid };

                StringBuilder commandSb = new StringBuilder();
                for (String c : command) {
                    commandSb.append(c);
                    commandSb.append(" ");
                }
                String commandAsString = commandSb.toString();

                logger.debug("Launching ECC part of '" + pluginName + "' plugin with command: " + commandAsString
                        + " on port: " + port);

                pluginNamesAndPorts.put(pluginName, port);

                try {
                    Process p = Runtime.getRuntime().exec(command);
                    tempThread = new Thread(new ProcessWatcher(p));
                    tempThread.start();
                    createdProcesses.add(p);

                } catch (Throwable ex) {
                    logger.error("Failed to start ECC part of '" + pluginName + "' plugin", ex);
                    result = false;
                }
            }

        }

        return result;
    }

    public HashMap<String, String> getPluginNamesAndPorts() {
        return pluginNamesAndPorts;
    }

    public String getPortForPluginName(String pluginName) {
        if (pluginNamesAndPorts.containsKey(pluginName)) {
            return pluginNamesAndPorts.get(pluginName);
        } else {
            return null;
        }
    }

    public void stop() {
        logger.debug("Shutting down ECC client threads");
        try {
            int returnValue;
            for (Process p : createdProcesses) {
                p.destroy();
                logger.debug("Process shutdown signal sent, waiting for it to finish");
                returnValue = p.waitFor();
                logger.debug("Process return value: " + returnValue);
            }
        } catch (InterruptedException e) {
            logger.error("Failed to stop ECC client thread", e);
        }
    }

}