/** * Copyright (C) 2001-2017 by RapidMiner and the contributors * * Complete list of developers available at our web site: * * http://rapidminer.com * * This program 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. * * This program 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 this program. * If not, see http://www.gnu.org/licenses/. */ package com.rapidminer.tools.config; import java.io.IOException; import java.security.Key; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.logging.Level; import com.rapidminer.parameter.ParameterType; import com.rapidminer.repository.internal.remote.RemoteRepository; import com.rapidminer.tools.LogService; import com.rapidminer.tools.cipher.KeyGeneratorTool; import com.rapidminer.tools.config.actions.ConfigurableAction; /** * Abstract standard implementation of the {@link Configurable} class. * <p> * Contains additional methods which are not part of the {@link Configurable} interface for * compatiblity reasons, e.g {@link #getActions()} and {@link #getTestAction()}. * </p> * * @author Simon Fischer, Dominik Halfkann, Marco Boeck * */ public abstract class AbstractConfigurable implements Configurable { private int id = -1; private String name = "name undefined"; private Map<String, String> parameters = new HashMap<>(); private RemoteRepository source; @Override public int getId() { return id; } @Override public void setId(int id) { this.id = id; } /** * Returns the parameter value for the given key. The value has gone through the * {@link ParameterType#transformNewValue(String)} method. * * @param key * @return */ @Override public String getParameter(String key) { // we only have a map of key - value Strings here, but we need to apply special handling, // e.g. for ParameterTypePassword // iterate over ParameterTypes in Configurator, find the one matching the key and return the // value returned from the transformNewValue method AbstractConfigurator<? extends Configurable> configurator = ConfigurationManager.getInstance() .getAbstractConfigurator(getTypeId()); List<ParameterType> parameterTypes = configurator.getParameterTypes(configurator.getParameterHandler(this)); for (ParameterType type : parameterTypes) { if (type.getKey().equals(key)) { return type.transformNewValue(parameters.get(key)); } } return parameters.get(key); } /** * Returns the xml representation of this parameter value. * * @param key * @return */ public String getParameterAsXMLString(String key) { return parameters.get(key); } /** * Returns the xml representation of this parameter value. If the {@link ParameterType} uses * encryption, will decrypt the value with the given old key and encrypt it again with the * specified new key. * * @param key * key of the parameter * @param decryptKey * used to decrypt the parameter values * @param encryptKey * used to encrypt the parameter values again * @return */ public String getParameterAndChangeEncryption(String key, Key decryptKey, Key encryptKey) { String value = parameters.get(key); // we only have a map of key - value Strings here, but we need to apply special handling, // e.g. for ParameterTypePassword // iterate over ParameterTypes in Configurator, find the one matching the key and return the // decrypted and encrypted again value AbstractConfigurator<? extends Configurable> configurator = ConfigurationManager.getInstance() .getAbstractConfigurator(getTypeId()); for (ParameterType type : configurator.getParameterTypes(configurator.getParameterHandler(this))) { if (type.getKey().equals(key)) { // store current key (will most likely be identical to the decrypt key) Key currentKey = null; try { currentKey = KeyGeneratorTool.getUserKey(); } catch (IOException e) { // should not happen, if it does we simply cannot restore the original key LogService.getRoot().log(Level.WARNING, "com.rapidminer.tools.config.AbstractConfigurable.cannot_backup_key"); } // configurables are stored encrypted, so set the decryption key KeyGeneratorTool.setUserKey(decryptKey); // decrypt it with decryption key value = type.transformNewValue(parameters.get(key)); // set encryption key KeyGeneratorTool.setUserKey(encryptKey); // encrypt it again with encryption key value = type.toString(value); // restore key which was used before this call if (currentKey != null) { KeyGeneratorTool.setUserKey(currentKey); } break; } } return value; } @Override public void setParameter(String key, String value) { parameters.put(key, value); } @Override public void configure(Map<String, String> parameters) { this.parameters.clear(); this.parameters.putAll(parameters); } @Override public Map<String, String> getParameters() { return parameters; } @Override public String getName() { return this.name; } @Override public void setName(String name) { this.name = name; } @Override public void setSource(RemoteRepository source) { this.source = source; } @Override public RemoteRepository getSource() { return source; } @Override public String getShortInfo() { return null; } @Override public boolean hasSameValues(Configurable comparedConfigurable) { if (!name.equals(comparedConfigurable.getName())) { return false; } if (this.parameters.size() != comparedConfigurable.getParameters().size()) { return false; } for (Map.Entry<String, String> parameterEntry : this.parameters.entrySet()) { if (!parameterEntry.getValue().toString() .equals(comparedConfigurable.getParameter(parameterEntry.getKey()).toString())) { // If the string comparison of the 2 objects with equals() returns false return false; } } return true; } /** * @deprecated Use {@link AbstractConfigurable#isEmptyOrDefault(AbstractConfigurator)} instead. */ @Deprecated @Override public boolean isEmptyOrDefault(Configurator<? extends Configurable> configurator) { return isEmptyOrDefault((AbstractConfigurator<? extends Configurable>) configurator); } /** * Checks if the Configurable is empty (has no values/only empty values/default values) * * @param configurator * The configurator to resolve the default values from **/ public boolean isEmptyOrDefault(AbstractConfigurator<? extends Configurable> configurator) { if (this.getName() != null && !this.getName().equals("")) { return false; } else if (this.getParameters() != null && this.getParameters().size() > 0) { for (String key : this.getParameters().keySet()) { // find default value String defaultValue = ""; List<ParameterType> parameterTypes = configurator.getParameterTypes(configurator.getParameterHandler(this)); for (ParameterType type : parameterTypes) { if (type.getKey().equals(key)) { defaultValue = type.getDefaultValueAsString(); } } if (this.getParameters().get(key) != null && !this.getParameters().get(key).equals("") && !this.getParameters().get(key).equals(defaultValue)) { return false; } } return true; } return true; } /** * Returns a list of {@link ConfigurableAction}s. They can be used to perform various tasks * associated with this configuration type, e.g. clearing a cache. * <p> * If no actions are required for this configuration type, returns <code>null</code>. * </p> * These actions can be defined per {@link Configurable} instance, so two {@link Configurable}s * of the same {@link Configurator} type can have different actions. </p> * <p> * Also the actions can be changed dynamically, as they are retrieved each time they are * required. * </p> * * @return */ public Collection<ConfigurableAction> getActions() { return null; } /** * Returns a {@link TestConfigurableAction} which tests the settings for the * {@link Configurable}, e.g. a connection. * <p> * If no test action is required, returns <code>null</code>. * </p> * These actions can be defined per {@link Configurable} instance, so two {@link Configurable}s * of the same {@link Configurator} type can have different actions. </p> * <p> * Also the actions can be changed dynamically, as they are retrieved each time they are * required. * </p> * * @return */ public TestConfigurableAction getTestAction() { return null; } }