All Downloads are FREE. Search and download functionalities are using the official Maven repository.

step.parameter.ParameterManager Maven / Gradle / Ivy

/*******************************************************************************
 * Copyright (C) 2020, exense GmbH
 *  
 * This file is part of STEP
 *  
 * STEP is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *  
 * STEP is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *  
 * You should have received a copy of the GNU Affero General Public License
 * along with STEP.  If not, see .
 ******************************************************************************/
package step.parameter;

import java.util.*;
import java.util.stream.Collectors;

import javax.script.Bindings;
import javax.script.ScriptException;
import javax.script.SimpleBindings;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ch.exense.commons.app.Configuration;
import step.commons.activation.Activator;
import step.core.accessors.Accessor;
import step.core.dynamicbeans.DynamicBeanResolver;
import step.core.dynamicbeans.DynamicValue;
import step.core.encryption.EncryptionManager;
import step.core.encryption.EncryptionManagerException;
import step.core.objectenricher.ObjectPredicate;
import step.core.plugins.exceptions.PluginCriticalException;

public class ParameterManager {
	
	public static final String RESET_VALUE = "####change me####";
	public static final String PROTECTED_VALUE = "******";

	private static Logger logger = LoggerFactory.getLogger(ParameterManager.class);
	
	private Accessor parameterAccessor;
	private EncryptionManager encryptionManager;

	private String defaultScriptEngine;
	private final DynamicBeanResolver dynamicBeanResolver;

	public ParameterManager(Accessor parameterAccessor, EncryptionManager encryptionManager, Configuration configuration, DynamicBeanResolver dynamicBeanResolver) {
		this(parameterAccessor, encryptionManager, configuration.getProperty("tec.activator.scriptEngine", Activator.DEFAULT_SCRIPT_ENGINE), dynamicBeanResolver);
	}

	public ParameterManager(Accessor parameterAccessor, EncryptionManager encryptionManager, String defaultScriptEngine, DynamicBeanResolver dynamicBeanResolver) {
		this.parameterAccessor = parameterAccessor;
		this.encryptionManager = encryptionManager;
		this.defaultScriptEngine = defaultScriptEngine;
		this.dynamicBeanResolver = dynamicBeanResolver;
	}

	public static ParameterManager copy(ParameterManager from, Accessor parameterAccessor){
		return new ParameterManager(parameterAccessor, from.encryptionManager, from.defaultScriptEngine, from.dynamicBeanResolver);
	}

	public Parameter save(Parameter newParameter, Parameter sourceParameter, String modificationUser) {
		if (isProtected(newParameter) && newParameter.getValue() != null && newParameter.getValue().isDynamic()) {
			throw new ParameterManagerException("Protected parameters do not support values with dynamic expression.");
		}

		ParameterScope scope = newParameter.getScope();
		if(scope != null && scope.equals(ParameterScope.GLOBAL) && newParameter.getScopeEntity() != null) {
			throw new ParameterManagerException("Scope entity cannot be set for parameters with GLOBAL scope.");
		}

		if(sourceParameter != null && isProtected(sourceParameter)) {
			// protected value should not be changed
			newParameter.setProtectedValue(true);
			// if the protected mask is set as value, reuse source value (i.e. value hasn't been changed)
			DynamicValue newParameterValue = newParameter.getValue();
			if(newParameterValue != null && !newParameterValue.isDynamic() && newParameterValue.get().equals(PROTECTED_VALUE)) {
				newParameter.setValue(sourceParameter.getValue());
			}
		}

		try {
			newParameter = this.encryptParameterValueIfEncryptionManagerAvailable(newParameter);
		} catch (EncryptionManagerException e) {
			throw new ParameterManagerException("Error while encrypting parameter value", e);
		}

		Date lastModificationDate = new Date();
		newParameter.setLastModificationDate(lastModificationDate);
		newParameter.setLastModificationUser(modificationUser);

		return parameterAccessor.save(newParameter);
	}

	public Map getAllParameterValues(Map contextBindings, ObjectPredicate objectPredicate) {
		return getAllParameters(contextBindings, objectPredicate).entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, e -> e.getValue().value.get()));
	}
	
	public Map getAllParameters(Map contextBindings, ObjectPredicate objectPredicate) {
		Map result = new HashMap<>();
		Bindings bindings = contextBindings!=null?new SimpleBindings(contextBindings):null;

		Map> parameterMap = new HashMap>();
		parameterAccessor.getAll().forEachRemaining(p->{
			if(objectPredicate==null || objectPredicate.test(p)) {
				List parameters = parameterMap.get(p.key);
				if(parameters==null) {
					parameters = new ArrayList<>();
					parameterMap.put(p.key, parameters);
				}
				parameters.add(p);
				try {
					Activator.compileActivationExpression(p, defaultScriptEngine);
				} catch (ScriptException e) {
					logger.error("Error while compiling activation expression of parameter "+p, e);
				}
			}
		});
		
		
		for(String key:parameterMap.keySet()) {
			List parameters = parameterMap.get(key);
			Parameter bestMatch = Activator.findBestMatch(bindings, parameters, defaultScriptEngine);
			if(bestMatch!=null) {
				result.put(key, bestMatch);
			}
		}
		resolveAllParameters(result, contextBindings);
		return result;
	}

	private void resolveAllParameters(Map allParameters, Map contextBindings) {
		List unresolvedParamKeys = new ArrayList<>(allParameters.keySet());
		List resolvedParamKeys = new ArrayList<>();
		HashMap bindings = new HashMap<>(contextBindings);
		int unresolvedCountBeforeIteration;
		do {
			unresolvedCountBeforeIteration = unresolvedParamKeys.size();
			unresolvedParamKeys.forEach(k -> {
				Parameter parameter = allParameters.get(k);
				Boolean protectedValue = parameter.getProtectedValue();
				boolean isProtected = parameter.getProtectedValue() != null && parameter.getProtectedValue();
				DynamicValue parameterValue = parameter.getValue();
				if (!isProtected && parameterValue != null) {
					try {
						if (parameterValue.isDynamic()) {
							dynamicBeanResolver.evaluate(parameter, bindings);
						}
						String resolvedValue = parameter.value.get(); //throw an error if evaluation failed
						bindings.put(k, resolvedValue);
						resolvedParamKeys.add(k);
					} catch (Exception e) {
						if (logger.isDebugEnabled()) {
							logger.debug("Could not (yet) resolve parameter dynamic value " + parameter);
						}
					}
				} else {
					//value is not set or parameter is protected, resolution is skipped
					resolvedParamKeys.add(k);
					if (logger.isDebugEnabled()) {
						logger.debug("Following parameters won't be resolved (null or protected value) " + parameter);
					}
				}
			});
			unresolvedParamKeys.removeAll(resolvedParamKeys);
		} while (!unresolvedParamKeys.isEmpty() && unresolvedParamKeys.size() < unresolvedCountBeforeIteration);
		if (!unresolvedParamKeys.isEmpty()) {
			throw new PluginCriticalException("Error while resolving parameters, following parameters could not be resolved: " + unresolvedParamKeys);
		}
	}
	
	public void encryptAllParameters() {
		parameterAccessor.getAll().forEachRemaining(p->{
			if(isProtected(p)) {
				logger.info("Encrypting parameter "+p);
				try {
					Parameter encryptedParameter = encryptParameterValueIfEncryptionManagerAvailable(p);
					parameterAccessor.save(encryptedParameter);
				} catch (EncryptionManagerException e) {
					logger.error("Error while encrypting parameter "+p.getKey());
				}
			}
		});
	}
	
	public void resetAllProtectedParameters() {
		parameterAccessor.getAll().forEachRemaining(p->{
			if(isProtected(p)) {
				logger.info("Resetting parameter "+p);
				p.setValue(new DynamicValue<>(RESET_VALUE));
				p.setEncryptedValue(null);
				parameterAccessor.save(p);
			}
		});
	}

	private boolean isProtected(Parameter p) {
		return p.getProtectedValue() != null && p.getProtectedValue();
	}
	
	public Parameter encryptParameterValueIfEncryptionManagerAvailable(Parameter parameter) throws EncryptionManagerException {
		if(encryptionManager != null) {
			if(isProtected(parameter)) {
				DynamicValue value = parameter.getValue();
				if(value != null && value.get() != null) {
					parameter.setValue(null);
					String encryptedValue = encryptionManager.encrypt(value.get());
					parameter.setEncryptedValue(encryptedValue);
				}
			}
		}
		return parameter;
	}

	public String getDefaultScriptEngine() {
		return defaultScriptEngine;
	}

	public Accessor getParameterAccessor() {
		return parameterAccessor;
	}

	public EncryptionManager getEncryptionManager() {
		return encryptionManager;
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy