org.imsglobal.lti.toolProvider.ToolConsumer.java Source code

Java tutorial

Introduction

Here is the source code for org.imsglobal.lti.toolProvider.ToolConsumer.java

Source

package org.imsglobal.lti.toolProvider;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.imsglobal.lti.LTIMessage;
import org.imsglobal.lti.LTIUtil;
import org.imsglobal.lti.profile.ServiceDefinition;
import org.imsglobal.lti.signature.oauth1.OAuthUtil;
import org.imsglobal.lti.toolProvider.dataConnector.DataConnector;
import org.imsglobal.lti.toolProvider.dataConnector.DataConnectorFactory;
import org.imsglobal.lti.toolProvider.mediaType.ConsumerProfile;
import org.imsglobal.lti.toolProvider.service.ToolSettings;
import org.joda.time.DateTime;
import org.json.simple.JSONObject;

import net.oauth.OAuth;
import net.oauth.OAuthAccessor;
import net.oauth.OAuthConsumer;
import net.oauth.OAuthException;
import net.oauth.OAuthMessage;
import net.oauth.signature.OAuthSignatureMethod;

/**
 * Class to represent a tool consumer
 *
 * @author  Stephen P Vickers <svickers@imsglobal.org>
 * @copyright  IMS Global Learning Consortium Inc
 * @date  2016
 * @version 3.0.2
 * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
 * translated to Java by David Block (dave@northcreek.ca)
 */
public class ToolConsumer implements LTISource {

    /**
     * Local name of tool consumer.
     *
     * @var string name
     */
    private String name = null;
    /**
     * Shared secret.
     *
     * @var string secret
     */
    private String secret = null;
    /**
     * LTI version (as reported by last tool consumer connection).
     *
     * @var string ltiVersion
     */
    private String ltiVersion = null;
    /**
     * Name of tool consumer (as reported by last tool consumer connection).
     *
     * @var string consumerName
     */
    private String consumerName = null;
    /**
     * Tool consumer version (as reported by last tool consumer connection).
     *
     * @var string consumerVersion
     */
    private String consumerVersion = null;
    /**
     * Tool consumer GUID (as reported by first tool consumer connection).
     *
     * @var string consumerGuid
     */
    private String consumerGuid = null;
    /**
     * Optional CSS path (as reported by last tool consumer connection).
     *
     * @var string cssPath
     */
    private String cssPath = null;
    /**
     * Whether the tool consumer instance is protected by matching the consumer_guid value in incoming requests.
     *
     * @var boolean protected
     */
    private boolean thisprotected = false;
    /**
     * Whether the tool consumer instance is enabled to accept incoming connection requests.
     *
     * @var boolean enabled
     */
    private boolean enabled = false;
    /**
     * Date/time from which the the tool consumer instance is enabled to accept incoming connection requests.
     *
     * @var int enableFrom
     */
    private DateTime enableFrom = null;
    /**
     * Date/time until which the tool consumer instance is enabled to accept incoming connection requests.
     *
     * @var int enableUntil
     */
    private DateTime enableUntil = null;
    /**
     * Date of last connection from this tool consumer.
     *
     * @var int lastAccess
     */
    private DateTime lastAccess = null;
    /**
     * Default scope to use when generating an Id value for a user.
     *
     * @var int idScope
     */
    public int idScope = ToolProvider.ID_SCOPE_ID_ONLY;
    /**
     * Default email address (or email domain) to use when no email address is provided for a user.
     *
     * @var string defaultEmail
     */
    private String defaultEmail;
    /**
     * Setting values (LTI parameters, custom parameters and local parameters).
     *
     * @var array settings
     */
    private Map<String, List<String>> settings = new HashMap<String, List<String>>();
    /**
     * Date/time when the object was created.
     *
     * @var int created
     */
    private DateTime created = null;
    /**
     * Date/time when the object was last updated.
     *
     * @var int updated
     */
    private DateTime updated = null;

    /**
     * Consumer ID value.
     *
     * @var int id
     */
    private int id;
    /**
     * Consumer key value.
     *
     * @var string key
     */
    private String key;
    /**
     * Whether the settings value have changed since last saved.
     *
     * @var boolean settingsChanged
     */
    private boolean settingsChanged = false;
    /**
     * Data connector object or string.
     *
     * @var DataConnector dataConnector
     */
    private DataConnector dataConnector = null;

    private List<String> capability_offered = new ArrayList<String>();

    private Map<String, List<String>> toolProxyMap;

    private ConsumerProfile profile = new ConsumerProfile();

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getSecret() {
        return secret;
    }

    public void setSecret(String secret) {
        this.secret = secret;
    }

    public String getLtiVersion() {
        return ltiVersion;
    }

    public void setLtiVersion(String ltiVersion) {
        this.ltiVersion = ltiVersion;
    }

    public String getConsumerName() {
        return consumerName;
    }

    public void setConsumerName(String consumerName) {
        this.consumerName = consumerName;
    }

    public String getConsumerVersion() {
        return consumerVersion;
    }

    public void setConsumerVersion(String consumerVersion) {
        this.consumerVersion = consumerVersion;
    }

    public String getConsumerGuid() {
        return consumerGuid;
    }

    public void setConsumerGuid(String consumerGuid) {
        this.consumerGuid = consumerGuid;
    }

    public String getCssPath() {
        return cssPath;
    }

    public void setCssPath(String cssPath) {
        this.cssPath = cssPath;
    }

    public boolean isThisprotected() {
        return thisprotected;
    }

    public void setThisprotected(boolean thisprotected) {
        this.thisprotected = thisprotected;
    }

    public boolean isEnabled() {
        return enabled;
    }

    public void setEnabled(boolean enabled) {
        this.enabled = enabled;
    }

    public DateTime getEnableFrom() {
        return enableFrom;
    }

    public void setEnableFrom(DateTime enableFrom) {
        this.enableFrom = enableFrom;
    }

    public DateTime getEnableUntil() {
        return enableUntil;
    }

    public void setEnableUntil(DateTime enableUntil) {
        this.enableUntil = enableUntil;
    }

    public DateTime getLastAccess() {
        return lastAccess;
    }

    public void setLastAccess(DateTime lastAccess) {
        this.lastAccess = lastAccess;
    }

    public int getIdScope() {
        return idScope;
    }

    public void setIdScope(int idScope) {
        this.idScope = idScope;
    }

    public String getDefaultEmail() {
        return defaultEmail;
    }

    public void setDefaultEmail(String defaultEmail) {
        this.defaultEmail = defaultEmail;
    }

    public DateTime getCreated() {
        return created;
    }

    public void setCreated(DateTime created) {
        this.created = created;
    }

    public DateTime getUpdated() {
        return updated;
    }

    public void setUpdated(DateTime updated) {
        this.updated = updated;
    }

    public String getId() {
        return String.valueOf(id);
    }

    public void setId(int id) {
        this.id = id;
    }

    public boolean isSettingsChanged() {
        return settingsChanged;
    }

    public void setSettingsChanged(boolean settingsChanged) {
        this.settingsChanged = settingsChanged;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public String getKey() {
        return key;
    }

    public void setProfile(ConsumerProfile profile) {
        this.profile = profile;
    }

    public void setDataConnector(DataConnector dataConnector) {
        this.dataConnector = dataConnector;
    }

    /**
     * Class constructor.
     *
     * @param string  key             Consumer key
     * @param DataConnector   dataConnector   A data connector object
     * @param boolean autoEnable      true if the tool consumers is to be enabled automatically (optional, default is false)
     */
    public ToolConsumer() {
        this(null, null, false);
    }

    public ToolConsumer(String key) {
        this(key, null, false);
    }

    public ToolConsumer(String key, DataConnector dataConnector) {
        this(key, dataConnector, false);
    }

    public ToolConsumer(String key, DataConnector dataConnector, boolean autoEnable) {

        initialize();
        if ((dataConnector == null)) {
            dataConnector = DataConnectorFactory.getDataConnector();
        }
        setDataConnector(dataConnector);
        if (key != null) {
            load(key, autoEnable);
        } else {
            setSecret(DataConnector.getRandomString(32));
        }

    }

    /**
     * Initialise the tool consumer.
     */
    public void initialize() {

        setIdScope(ToolProvider.ID_SCOPE_ID_ONLY);

    }

    /**
     * Initialise the tool consumer.
     *
     * Pseudonym for initialize().
     */
    public void initialise() {

        initialize();

    }

    /**
     * Save the tool consumer to the database.
     *
     * @return boolean True if the object was successfully saved
     */
    public boolean save() {

        boolean ok = dataConnector.saveToolConsumer(this);
        if (ok) {
            setSettingsChanged(false);
        }

        return ok;

    }

    /**
     * Delete the tool consumer from the database.
     *
     * @return boolean True if the object was successfully deleted
     */
    public boolean delete() {

        return dataConnector.deleteToolConsumer(this);

    }

    /**
     * Get the tool consumer record ID.
     *
     * @return int Consumer record ID value
     */
    public int getRecordId() {

        return Integer.valueOf(getId());

    }

    /**
     * Sets the tool consumer record ID.
     *
     * @param int id  Consumer record ID value
     */
    public void setRecordId(int id) {

        setId(id);

    }

    /**
     * Get the tool consumer key.
     *
     * @return string Consumer key value
     */

    /**
     * Set the tool consumer key.
     *
     * @param string key  Consumer key value
     */

    /**
     * Get the data connector.
     *
     * @return mixed Data connector object or string
     */

    /**
     * Is the consumer key available to accept launch requests?
     *
     * @return boolean True if the consumer key is enabled and within any date constraints
     */
    public boolean getIsAvailable() {

        boolean ok = isEnabled();

        DateTime now = DateTime.now();
        if (ok && getEnableFrom() != null) {
            ok = getEnableFrom().isBefore(now) || getEnableFrom().equals(now);
        }
        if (ok && getEnableUntil() != null) {
            ok = getEnableUntil().isBefore(now) || getEnableUntil().equals(now);
        }

        return ok;

    }

    /**
     * Get a setting value.
     *
     * @param string name    Name of setting
     * @param string default Value to return if the setting does not exist (optional, default is an empty string)
     *
     * @return string Setting value
     */
    public String getSetting(String name) {
        return getSetting(name, "");
    }

    public String getSetting(String name, String thedefault) {
        String value = thedefault;
        Map<String, List<String>> theSettings = getSettings();
        if (theSettings.containsKey(name)) {
            value = theSettings.get(name).get(0);
        }
        return value;

    }

    /**
     * Set a setting value.
     *
     * @param string name  Name of setting
     * @param string value Value to set, use an empty value to delete a setting (optional, default is null)
     */

    public void setSetting(String name) {
        setSetting(name, "");
    }

    public void setSetting(String name, String value) {
        Map<String, List<String>> theSettings = getSettings();
        String old_value = getSetting(name);
        if (value == null || value == "") {
            theSettings.remove(name);
            setSettings(theSettings);
        } else if (value != old_value) {
            List<String> theList = new ArrayList<String>();
            theList.add(value);
            theSettings.put(name, theList);
            setSettings(theSettings);
        }

    }

    /**
     * Get an array of all setting values.
     *
     * @return array Associative array of setting values
     */
    public Map<String, List<String>> getSettings() {

        return settings;

    }

    /**
     * Set an array of all setting values.
     *
     * @param array settings  Associative array of setting values
     */
    public void setSettings(Map<String, List<String>> settings) {

        this.settings = settings;
        setSettingsChanged(true);

    }

    /**
     * Save setting values.
     *
     * @return boolean True if the settings were successfully saved
     */
    public boolean saveSettings() {
        boolean ok = true;
        if (isSettingsChanged()) {
            ok = save();
        }

        return ok;

    }

    /**
     * Check if the Tool Settings service is supported.
     *
     * @return boolean True if this tool consumer supports the Tool Settings service
     */
    public boolean hasToolSettingsService() {

        String url = getSetting("custom_system_setting_url");
        boolean notEmpty = true;
        if (url == null | url.equals("")) {
            notEmpty = false;
        }
        return notEmpty;

    }

    /**
     * Get Tool Settings.
     *
     * @param boolean  simple     True if all the simple media type is to be used (optional, default is true)
     *
     * @return mixed The array of settings if successful, otherwise false
     */

    public Map<String, List<String>> getToolSettings() {
        return getToolSettings(true);
    }

    public Map<String, List<String>> getToolSettings(boolean simple) {

        String url = getSetting("custom_system_setting_url");
        ToolSettings service = new ToolSettings(this, url, simple);
        return service.get();

    }

    /**
     * Perform a Tool Settings service request.
     *
     * @param array    settings   An associative array of settings (optional, default is none)
     *
     * @return boolean True if action was successful, otherwise false
     */

    public boolean setToolSettings() {
        return setToolSettings(null);
    }

    public boolean setToolSettings(Map<String, List<String>> settings) {

        String url = getSetting("custom_system_setting_url");
        ToolSettings service = new ToolSettings(this, url);
        LTIMessage response = service.set(settings);
        return response.isOk();

    }

    protected static List<Entry<String, String>> convert(Map<String, List<String>> params) {
        List<Map.Entry<String, String>> theList = new ArrayList<Map.Entry<String, String>>();
        Set<String> sortedList = new TreeSet<String>();
        sortedList.addAll(params.keySet());
        for (String k : sortedList) {
            List<String> entries = params.get(k);
            Set<String> sortedEntries = new TreeSet<String>();
            sortedEntries.addAll(entries);
            for (String s : sortedEntries) {
                theList.add(new OAuth.Parameter(k, s));
            }
        }
        return theList;
    }

    private static Map<String, List<String>> convertBack(List<Entry<String, String>> oparams) {
        Map<String, List<String>> params = new HashMap<String, List<String>>();
        for (Entry<String, String> e : oparams) {
            LTIUtil.setParameter(params, e.getKey(), e.getValue());
        }
        return params;
    }

    /**
     * Add the OAuth signature to an LTI message.
     *
     * @param String  url         URL for message request
     * @param String  type        LTI message type
     * @param String  version     LTI version
     * @param Map   params      Message parameters
     *
     * @return array Array of signed message parameters
     */
    public Map<String, List<String>> signParameters(String urlString, String type, String version, String method,
            Map<String, List<String>> params) {
        List<Entry<String, String>> oparams = new ArrayList<Entry<String, String>>();
        Map<String, List<String>> queryParams = new HashMap<String, List<String>>();
        if (urlString != null) {
            // Check for query parameters which need to be included in the signature
            try {
                URL url = new URL(urlString);
                String query = url.getQuery();
                if (StringUtils.isNotEmpty(query)) {
                    queryParams = OAuthUtil.parse_parameters(url.getQuery());
                }
                params.putAll(queryParams);

                // Add standard parameters

                LTIUtil.setParameter(params, "lti_version", version);
                LTIUtil.setParameter(params, "lti_message_type", type);
                LTIUtil.setParameter(params, "oauth_callback", "about:blank");

                oparams = convert(params);

                if (StringUtils.isEmpty(method)) {
                    method = "POST";
                }

                // Add OAuth signature
                OAuthMessage message = doSignature(urlString, oparams, getKey(), getSecret(), method);
                oparams = message.getParameters(); //replace with signed parameters
                // Remove parameters being passed on the query string
                oparams = removeQueryParams(oparams, queryParams);
            } catch (MalformedURLException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            } catch (IOException e1) {
                e1.printStackTrace();
            } catch (OAuthException e1) {
                e1.printStackTrace();
            } catch (URISyntaxException e1) {
                e1.printStackTrace();
            }
        }

        return convertBack(oparams);

    }

    /**
     * Add the OAuth signature to an array of message parameters or to a header string.
     *
     * @return mixed Array of signed message parameters or header string
     */
    public static Map<String, List<String>> addSignature(String endpoint, String consumerKey, String consumerSecret,
            Map<String, List<String>> data, String method, String type) {
        List<Entry<String, String>> oparams = new ArrayList<Entry<String, String>>();
        Map<String, List<String>> params = new HashMap<String, List<String>>();
        if (data != null) {
            params = data;
        }
        if (StringUtils.isEmpty(method)) {
            method = "POST";
        }
        // Check for query parameters which need to be included in the signature
        try {
            URL url = new URL(endpoint);
            Map<String, List<String>> queryParams = OAuthUtil.parse_parameters(url.getQuery());
            params.putAll(queryParams);

            oparams = convert(params);

            // Add OAuth signature
            OAuthMessage message = doSignature(endpoint, oparams, consumerKey, consumerSecret, method);
            oparams = message.getParameters();

            // Remove parameters being passed on the query string
            oparams = removeQueryParams(oparams, queryParams);

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (IOException e1) {
            e1.printStackTrace();
        } catch (OAuthException e1) {
            e1.printStackTrace();
        } catch (URISyntaxException e1) {
            e1.printStackTrace();
        }

        return convertBack(oparams);

    }

    public static String addSignature(String endpoint, String consumerKey, String consumerSecret, String data,
            String method, String type) {
        List<Entry<String, String>> oparams = new ArrayList<Entry<String, String>>();
        Map<String, List<String>> params = new HashMap<String, List<String>>();
        URL url;
        Map<String, List<String>> queryParams = new HashMap<String, List<String>>();
        List<Entry<String, String>> headers = new ArrayList<Entry<String, String>>();
        try {
            url = new URL(endpoint);
            queryParams = OAuthUtil.parse_parameters(url.getQuery());
            params.putAll(queryParams);

            // Calculate body hash
            MessageDigest md = MessageDigest.getInstance("SHA1");
            byte[] sha1 = md.digest(data.getBytes());
            String hash = Base64.encodeBase64String(sha1);
            List<String> hashList = new ArrayList<String>();
            hashList.add(hash);
            params.put("oauth_body_hash", hashList);

            oparams = convert(params);

            // Add OAuth signature
            OAuthMessage message = doSignature(endpoint, oparams, consumerKey, consumerSecret, method);

            // Remove parameters being passed on the query string
            oparams = removeQueryParams(message.getParameters(), queryParams);

            headers = message.getHeaders();
            if (StringUtils.isEmpty(data)) {
                if (type != null) {
                    headers = addHeader(headers, "Accept", type);
                }
            } else if (StringUtils.isNotEmpty(type)) {
                headers = addHeader(headers, "Content-Type", type);
                headers = addHeader(headers, "Content-Length", String.valueOf(data.length()));
            }
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (OAuthException e) {
            e.printStackTrace();
        } catch (URISyntaxException e) {
            e.printStackTrace();
        }

        return convertHeader(headers);
    }

    private static List<Entry<String, String>> addHeader(List<Entry<String, String>> headers, String key,
            String value) {
        HashMap<String, String> temp = new HashMap<String, String>();
        temp.put(key, value);
        for (Entry<String, String> e : temp.entrySet()) {
            headers.add(e);
        }
        return headers;
    }

    private static String convertHeader(List<Entry<String, String>> headers) {
        StringBuilder sb = new StringBuilder();
        for (Entry<String, String> e : headers) {
            sb.append("\n").append(e.getKey()).append(": {").append(e.getValue()).append("}");
        }
        return sb.toString();
    }

    private static OAuthMessage doSignature(String urlString, List<Entry<String, String>> oparams, String key,
            String secret, String method) throws IOException, OAuthException, URISyntaxException {

        OAuthConsumer oAuthConsumer = new OAuthConsumer("about:blank", key, secret, null);
        OAuthAccessor oAuthAccessor = new OAuthAccessor(oAuthConsumer);
        OAuthMessage message = new OAuthMessage(method, urlString, oparams);
        message.sign(oAuthAccessor);
        return message;
    }

    private static List<Entry<String, String>> removeQueryParams(List<Entry<String, String>> oparams,
            Map<String, List<String>> queryParams) {
        List<Entry<String, String>> oparams2 = new ArrayList<Entry<String, String>>();
        for (Entry<String, String> e : oparams) {
            boolean copy = true;
            if (queryParams.containsKey(e.getKey())) {
                if (queryParams.get(e.getKey()).equals(e.getValue())) {
                    copy = false;
                }
            }
            if (copy) {
                oparams2.add(e);
            }
        }
        return oparams2;
    }

    /**
     * Perform a service request
     *
     * @param object service  Service object to be executed
     * @param string method   HTTP action
     * @param string format   Media type
     * @param mixed  data     Array of parameters or body string
     *
     * @return HTTPMessage HTTP object containing request and response details
     */
    public LTIMessage doServiceRequest(ServiceDefinition service, String method, String format,
            Map<String, List<String>> parameters) {

        Map<String, List<String>> params = ToolConsumer.addSignature(service.getEndpoint().toExternalForm(),
                this.getKey(), this.getSecret(), parameters, method, format);

        // Connect to tool consumer
        LTIMessage http = new LTIMessage(service.getEndpoint().toExternalForm(), method, null, null, params);
        // Parse JSON response
        http.send();
        String response = http.getResponse();
        JSONObject json = http.getResponseJson();
        if (http.isOk()) {
            return http;
        } else {
            return null;
        }

    }

    /**
    * Perform a service request
    *
    * @param object service  Service object to be executed
    * @param string method   HTTP action
    * @param string format   Media type
    * @param mixed  data     Array of parameters or body string
    *
    * @return HTTPMessage HTTP object containing request and response details
    */
    public LTIMessage doServiceRequest(ServiceDefinition service, String method, String format, String data) {

        String header = ToolConsumer.addSignature(service.getEndpoint().toExternalForm(), this.getKey(),
                this.getSecret(), data, method, format);

        // Connect to tool consumer
        LTIMessage http = new LTIMessage(service.getEndpoint().toExternalForm(), method, data, header, null);
        // Parse JSON response
        http.send();
        String response = http.getResponse();
        JSONObject json = http.getResponseJson();
        if (http.isOk()) {
            return http;
        } else {
            return null;
        }

    }

    /**
     * Load the tool consumer from the database by its record ID.
     *
     * @param int          id                The consumer key record ID
     * @param DataConnector   dataConnector    Database connection object
     *
     * @return object ToolConsumer       The tool consumer object
     */
    public static ToolConsumer fromRecordId(int id, DataConnector dataConnector) {

        ToolConsumer toolConsumer = new ToolConsumer(null, dataConnector);

        toolConsumer.initialize();
        toolConsumer.setRecordId(id);
        if (!dataConnector.loadToolConsumer(toolConsumer)) {
            toolConsumer.initialize();
        }

        return toolConsumer;

    }

    /**
     * Load the tool consumer from the database.
     *
     * @param string  key        The consumer key value
     * @param boolean autoEnable True if the consumer should be enabled (optional, default if false)
     *
     * @return boolean True if the consumer was successfully loaded
     */

    private boolean load(String key) {
        return load(key, false);
    }

    private boolean load(String key, boolean autoEnable) {
        setKey(key);
        dataConnector = DataConnectorFactory.getDataConnector();
        boolean ok = dataConnector.loadToolConsumer(this);
        ok = this.dataConnector.loadToolConsumer(this);
        if (!ok) {
            setEnabled(autoEnable);
        }

        return ok;

    }

    public ToolConsumer getConsumer() {
        return this;
    }

    public DataConnector getDataConnector() {
        return DataConnectorFactory.getDataConnector();
    }

    public Map<String, User> getUserResultSourcedIDs(boolean flag, int scope) {
        return getDataConnector().getUserResultSourcedIDsToolConsumer(this, flag, scope);
    }

    public void setCapabilitiesOffered(List<String> capabilities) {
        this.capability_offered = capabilities;
    }

    public List<String> getCapabilitiesOffered() {
        return capability_offered;
    }

    public ConsumerProfile getProfile() {
        //this is the ToolConsumerProfile that comes from JSON-LD
        return profile;
    }

    public Map<String, List<String>> getToolProxyMap() {
        return toolProxyMap;
    }

    public void setToolProxyMap(Map<String, List<String>> toolProxyMap) {
        this.toolProxyMap = toolProxyMap;
    }

    public void setToolProxy(String string) {
        // TODO Auto-generated method stub
        // TODO parse string into map, I guess
    }

    public String getToolProxy() {
        // TODO Auto-generated method stub
        // TODO Serialize ToolProxyMap to a string
        return null;
    }

}