CloudSlang/cloud-slang

View on GitHub
cloudslang-runtime/src/main/java/io/cloudslang/lang/runtime/env/RunEnvironment.java

Summary

Maintainability
C
1 day
Test Coverage
/*******************************************************************************
 * (c) Copyright 2016 Hewlett-Packard Development Company, L.P.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Apache License v2.0 which accompany this distribution.
 *
 * The Apache License is available at
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 *******************************************************************************/
package io.cloudslang.lang.runtime.env;

import com.google.common.base.Function;
import com.google.common.collect.Collections2;
import com.hp.oo.sdk.content.plugin.SerializableSessionObject;
import io.cloudslang.lang.entities.NavigationOptions;
import io.cloudslang.lang.entities.SystemProperty;
import io.cloudslang.lang.entities.bindings.Argument;
import io.cloudslang.lang.entities.bindings.prompt.Prompt;
import io.cloudslang.lang.entities.bindings.values.SensitiveValue;
import io.cloudslang.lang.entities.bindings.values.Value;
import io.cloudslang.score.api.StatefulSessionStack;
import org.apache.commons.lang3.Validate;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * User: stoneo
 * Date: 20/10/2014
 * Time: 10:28
 */
public class RunEnvironment implements Serializable {

    // Call arguments for the current step
    private Map<String, Value> callArguments;

    // Return values from the current step
    private ReturnValues returnValues;

    // The position of the next step
    private Long nextStepPosition;

    // Navigation options, e.g. ROI value for each navigation step
    private Map<String, List<NavigationOptions>> navigationOptions;

    // Stack holding the contexts of the parent scopes
    private ContextStack contextStack;

    // Stack of the parent flow's data (for the sub-flow use-case)
    private ParentFlowStack parentFlowStack;

    private ExecutionPath executionPath;

    private final Set<SystemProperty> systemProperties;

    // Map holding serializable data that is common for the entire run
    // This is data that should be shared between different actions with the ability to change the data
    private Map<String, SerializableSessionObject> serializableDataMap;

    private StatefulSessionStack statefulSessionStack;

    //prompt args for current step
    private Map<String, Prompt> promptArguments;

    //Map holding already prompted values
    private Map<String, Value> promptedValues;

    //flag for keeping track of the changed context
    private boolean contextModified;

    //list of the arguments that need to be rebound if context is modified
    private List<Argument> modifiedArguments;

    public RunEnvironment(Set<SystemProperty> systemProperties) {
        Validate.notNull(systemProperties, "system properties cannot be null");
        contextStack = new ContextStack();
        parentFlowStack = new ParentFlowStack();
        callArguments = new HashMap<>();
        executionPath = new ExecutionPath();
        serializableDataMap = new HashMap<>();
        statefulSessionStack = new StatefulSessionStack();
        this.systemProperties = systemProperties;
        promptArguments = new LinkedHashMap<>();
        promptedValues = new HashMap<>();
        contextModified = false;
    }

    public RunEnvironment() {
        this(new HashSet<SystemProperty>());
    }

    public ContextStack getStack() {
        return contextStack;
    }

    public ParentFlowStack getParentFlowStack() {
        return parentFlowStack;
    }

    public Map<String, Value> removeCallArguments() {
        Map<String, Value> callArgumentsValues = callArguments;
        callArguments = new HashMap<>();
        return callArgumentsValues;
    }

    public void putCallArguments(Map<String, Value> callArguments) {
        this.callArguments.putAll(callArguments);
    }

    public void putPromptArguments(Map<String, Prompt> prompts) {
        this.promptArguments.putAll(prompts);
    }

    public Map<String, Prompt> getPromptArguments() {
        return promptArguments;
    }

    public Map<String, Prompt> removePromptArguments() {
        Map<String, Prompt> promptArguments = this.promptArguments;
        this.promptArguments = new LinkedHashMap<>();
        return promptArguments;
    }

    public void keepPromptedValues(Map<String, Value> promptedValues) {
        this.promptedValues.putAll(promptedValues);
    }

    public Map<String, Value> removePromptedValues() {
        Map<String, Value> promptedValues = this.promptedValues;
        this.promptedValues = new HashMap<>();
        return promptedValues;
    }

    public Map<String, Value> getCallArguments() {
        return callArguments;
    }

    public ReturnValues removeReturnValues() {
        ReturnValues values = returnValues;
        returnValues = null;
        return values;
    }

    public void putReturnValues(ReturnValues returnValues) {
        this.returnValues = returnValues;
    }

    public Long removeNextStepPosition() {
        Long nextStep = nextStepPosition;
        nextStepPosition = null;
        return nextStep;
    }

    public void putNextStepPosition(Long nextStepPosition) {
        this.nextStepPosition = nextStepPosition;
    }

    public List<NavigationOptions> removeStepNavigationOptions(String key) {
        if (navigationOptions != null) {
            return navigationOptions.remove(key);
        }
        return null;
    }

    public void putStepNavigationOptions(String key, List<NavigationOptions> stepNavigationOptions) {
        if (navigationOptions == null) {
            navigationOptions = new HashMap<>();
        }
        this.navigationOptions.put(key, stepNavigationOptions);
    }

    public ExecutionPath getExecutionPath() {
        return this.executionPath;
    }

    public Set<SystemProperty> getSystemProperties() {
        return systemProperties;
    }

    public Map<String, SerializableSessionObject> getSerializableDataMap() {
        return serializableDataMap;
    }

    public void resetStacks() {
        contextStack = new ContextStack();
        parentFlowStack = new ParentFlowStack();
    }

    public boolean containsSensitiveData() {
        return containsSensitiveCallArgument() ||
                containsSensitiveReturnValues() ||
                containsSensitiveSystemProperties() ||
                containsSensitiveContexts();
    }

    private boolean containsSensitiveData(Collection<Value> data) {
        if (data != null) {
            for (Value value : data) {
                if (value.isSensitive()) {
                    return true;
                }
            }
        }
        return false;
    }

    public void decryptSensitiveData() {
        for (Value value : prepareValuesForEncryptDecrypt()) {
            if (value.get() instanceof HashMap) {
                HashMap<String, Value> map = (HashMap<String, Value>) value.get();
                for (Serializable valueInMap : map.values()) {
                    if (valueInMap instanceof Value && ((Value) valueInMap).isSensitive()) {
                        ((SensitiveValue) valueInMap).decrypt();
                    }
                }
            } else if (value.isSensitive()) {
                ((SensitiveValue) value).decrypt();
            }
        }
    }

    public void encryptSensitiveData() {
        for (Value value : prepareValuesForEncryptDecrypt()) {
            if (value.get() instanceof HashMap) {
                HashMap<String, Value> map = (HashMap<String, Value>) value.get();
                for (Serializable valueInMap : map.values()) {
                    if (valueInMap instanceof Value && ((Value) valueInMap).isSensitive()) {
                        ((SensitiveValue) valueInMap).encrypt();
                    }
                }
            } else if (value.isSensitive()) {
                ((SensitiveValue) value).encrypt();
            }
        }
    }

    private boolean containsSensitiveCallArgument() {
        return callArguments != null && containsSensitiveData(callArguments.values());
    }

    private boolean containsSensitiveReturnValues() {
        return (returnValues != null) && (returnValues.getOutputs() != null) &&
                containsSensitiveData(returnValues.getOutputs().values());
    }

    private boolean containsSensitiveSystemProperties() {
        return (systemProperties != null) &&
                containsSensitiveData(Collections2.transform(systemProperties, new Function<SystemProperty, Value>() {
                    @Override
                    public Value apply(SystemProperty systemProperty) {
                        return systemProperty.getValue();
                    }
                }));
    }

    private boolean containsSensitiveContexts() {
        boolean hasSensitive = false;
        ContextStack tempStack = new ContextStack();
        Context context;
        while (!hasSensitive && (context = contextStack.popContext()) != null) {
            hasSensitive = containsSensitiveData(context.getImmutableViewOfLanguageVariables().values());
            hasSensitive = hasSensitive || containsSensitiveData(context.getImmutableViewOfVariables().values());
            tempStack.pushContext(context);
        }
        while ((context = tempStack.popContext()) != null) {
            contextStack.pushContext(context);
        }

        return hasSensitive;
    }

    private List<Value> prepareValuesForEncryptDecrypt() {
        List<Value> valuesToCheck = new LinkedList<>();
        if (callArguments != null) {
            valuesToCheck.addAll(callArguments.values());
        }
        if ((returnValues != null) && (returnValues.getOutputs() != null)) {
            valuesToCheck.addAll(returnValues.getOutputs().values());
        }
        if (systemProperties != null) {
            valuesToCheck.addAll(Collections2.transform(systemProperties, new Function<SystemProperty, Value>() {
                @Override
                public Value apply(SystemProperty systemProperty) {
                    return systemProperty.getValue();
                }
            }));
        }
        ContextStack tempStack = new ContextStack();
        Context context;
        while ((context = contextStack.popContext()) != null) {
            valuesToCheck.addAll(context.getImmutableViewOfLanguageVariables().values());
            valuesToCheck.addAll(context.getImmutableViewOfVariables().values());
            tempStack.pushContext(context);
        }
        while ((context = tempStack.popContext()) != null) {
            contextStack.pushContext(context);
        }

        return valuesToCheck;
    }

    public StatefulSessionStack getStatefulSessionsStack() {
        return statefulSessionStack;
    }

    public void setStatefulSessionsStack(StatefulSessionStack statefulSessionsStack) {
        this.statefulSessionStack = statefulSessionsStack;
    }

    public boolean isContextModified() {
        return contextModified;
    }

    public void setContextModified(boolean contextModified) {
        this.contextModified = contextModified;
    }

    public List<Argument> getModifiedArguments() {
        return modifiedArguments;
    }

    public void setModifiedArguments(List<Argument> modifiedArguments) {
        this.modifiedArguments = modifiedArguments;
    }
}