/** * 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; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashSet; import java.util.logging.Level; import com.rapidminer.RapidMiner; import com.rapidminer.gui.properties.ProxyParameterSaver; import com.rapidminer.tools.SystemInfoUtilities.OperatingSystem; /** * This class applies the proxy settings on the JVM environment * * @author Jonas Wilms-Pfau * @since 7.3.0 * */ public class ProxySettings { /** * Non Proxy Settings * <p> * Set some random proxy but ignore every URL -> Proxy is bypassed * </p> */ // Could be every non empty String private final static String NON_PROXY_HOST = "127.0.0.1"; // Could be every valid Port private final static String NON_PROXY_PORT = "80"; // Must be * to ignore all proxy settings private final static String NON_PROXY_RULE = "*"; /** Default value for Linux and Windows */ private static final String DEFAULT = ""; public static final String PROXY_PREFIX = "rapidminer.proxy."; public static final String SYSTEM_PREFIX = ""; private static final String HTTP_NON_PROXY_RULE = "http.nonProxyHosts"; private static final String FTP_NON_PROXY_RULE = "ftp.nonProxyHosts"; private static final String SOCKS_NON_PROXY_RULE = "socksNonProxyHosts"; /* RapidMiner proxy settings */ private final static String PROXY_HOSTS[] = { RapidMiner.PROPERTY_RAPIDMINER_HTTP_PROXY_HOST, RapidMiner.PROPERTY_RAPIDMINER_HTTPS_PROXY_HOST, RapidMiner.PROPERTY_RAPIDMINER_FTP_PROXY_HOST, RapidMiner.PROPERTY_RAPIDMINER_SOCKS_PROXY_HOST }; private final static String PROXY_PORTS[] = { RapidMiner.PROPERTY_RAPIDMINER_HTTP_PROXY_PORT, RapidMiner.PROPERTY_RAPIDMINER_HTTPS_PROXY_PORT, RapidMiner.PROPERTY_RAPIDMINER_FTP_PROXY_PORT, RapidMiner.PROPERTY_RAPIDMINER_SOCKS_PROXY_PORT }; /* Real system settings */ private final static String PROXY_RULES[] = { HTTP_NON_PROXY_RULE, FTP_NON_PROXY_RULE, SOCKS_NON_PROXY_RULE }; /** * To support OSX we have to store the System settings before the RapidMiner cfg file is loaded */ public static void storeSystemSettings() { if (SystemInfoUtilities.getOperatingSystem() == OperatingSystem.OSX) { Arrays.asList(toNative(PROXY_HOSTS)).stream().forEach(SystemSettings::store); Arrays.asList(toNative(PROXY_PORTS)).stream().forEach(SystemSettings::store); Arrays.asList(PROXY_RULES).stream().forEach(SystemSettings::store); } else { Arrays.asList(toNative(PROXY_HOSTS)).stream().forEach(SystemSettings::storeDefault); Arrays.asList(toNative(PROXY_PORTS)).stream().forEach(SystemSettings::storeDefault); Arrays.asList(PROXY_RULES).stream().forEach(SystemSettings::storeDefault); } } /** * This Method * <ul> * <li>Migrates the old proxy settings if needed</li> * <li>Applies the current proxy Settings</li> * <li>Registers a ChangeListener to change the proxy settings on save</li> * </ul> * */ public static void init() { ProxySettings.storeSystemSettings(); ProxyIntegrator.updateOldInstallation(); ParameterService.registerParameterChangeListener(new ProxyParameterSaver()); } /** * Applies the RapidMiner proxy settings on the corresponding JVM System properties */ public static void apply() { switch (ParameterService.getParameterValue(RapidMiner.PROPERTY_RAPIDMINER_PROXY_MODE)) { case RapidMiner.RAPIDMINER_PROXY_MODE_SYSTEM: // System Proxy SystemSettings.apply(); break; case RapidMiner.RAPIDMINER_PROXY_MODE_DIRECT: // No Proxy setSystemValue(NON_PROXY_HOST, toNative(PROXY_HOSTS)); setSystemValue(NON_PROXY_PORT, toNative(PROXY_PORTS)); setSystemValue(NON_PROXY_RULE, PROXY_RULES); break; case RapidMiner.RAPIDMINER_PROXY_MODE_MANUAL: // User Settings copyParameterToSystem(PROXY_HOSTS, toNative(PROXY_HOSTS)); copyParameterToSystem(PROXY_PORTS, toNative(PROXY_PORTS)); String exclusionRule = ParameterService.getParameterValue(RapidMiner.PROPERTY_RAPIDMINER_PROXY_EXCLUDE); setSystemValue(exclusionRule, PROXY_RULES); // Apply Socks Version int socksVersionOffset = Arrays.asList(RapidMiner.RAPIDMINER_SOCKS_VERSIONS) .indexOf(ParameterService.getParameterValue(RapidMiner.PROPERTY_RAPIDMINER_SOCKS_VERSION)); int initialSocksVersion = 4; ParameterService.setParameterValue(toNative(RapidMiner.PROPERTY_RAPIDMINER_SOCKS_VERSION), String.valueOf(initialSocksVersion + socksVersionOffset)); break; } GlobalAuthenticator.refreshProxyAuthenticators(); } /** * Set one value to all System Keys * * @param value * @param systemKey */ private static void setSystemValue(String value, String[] systemKeys) { for (String parameterKey : systemKeys) { setSystemProperty(parameterKey, value); } } private static void setSystemProperty(String key, String value) { if (value != null && key != null) { System.setProperty(key, value); } } /** * Copies the ParameterService values from the source keys to target System property keys * <p> * Warning: both arrays must have the same length. * </p> * * @param sourceKeys * ParameterService keys * @param targetKeys * System keys */ private static void copyParameterToSystem(String[] sourceKeys, String[] targetKeys) { for (int i = 0; i < sourceKeys.length; i++) { String sourceValue = ParameterService.getParameterValue(sourceKeys[i]); setSystemProperty(targetKeys[i], sourceValue); } } /** * Converts the given keys to native System keys * * @param keys * @return */ private static String[] toNative(String keys[]) { return Arrays.asList(keys).stream().map(ProxySettings::toNative).toArray(String[]::new); } /** * Converts the given key to a native System key * * @param key * @return */ private static String toNative(String key) { return key.replace(PROXY_PREFIX, SYSTEM_PREFIX); } /** * This class migrates the old proxy settings into the new structure. * <p> * Use ProxyService.init() to check for updates * </p> * * @author Jonas Wilms-Pfau * */ private static class ProxyIntegrator { private static final String OLD_KEY = "http.proxyUsername"; private static final String NEW_KEY = RapidMiner.PROPERTY_RAPIDMINER_SOCKS_VERSION; /** * Update an old installation * <p> * Copies the old native properties into the new RapidMiner properties * </p> * */ private static void updateOldInstallation() { if (ParameterService.getParameterValue(OLD_KEY) != null && ParameterService.getParameterValue(NEW_KEY) == null) { LogService.getRoot().log(Level.INFO, "com.rapidminer.tools.ProxyService.migrate"); // Copy from old System properties to new RapidMiner properties copyParameterValues(toNative(PROXY_HOSTS), PROXY_HOSTS); copyParameterValues(toNative(PROXY_PORTS), PROXY_PORTS); // merge exclusionRules together HashSet<String> rules = new LinkedHashSet<>(); for (String ruleKey : PROXY_RULES) { String rule = System.getProperty(ruleKey); if (rule != null && !"".equals(rule)) { rules.addAll(Arrays.asList(rule.split("\\|"))); } } String exclusionRule = String.join("|", rules); setParameterValue(RapidMiner.PROPERTY_RAPIDMINER_PROXY_EXCLUDE, exclusionRule); setSystemValue(exclusionRule, PROXY_RULES); } } /** * Copies the parameter values from source to target * <p> * Warning: both arrays must have the same length. * </p> * * @param sourceKey * ParameterService keys * @param targetKey * ParameterService keys */ private static void copyParameterValues(String[] sourceKeys, String[] targetKeys) { for (int i = 0; i < sourceKeys.length; i++) { String sourceValue = ParameterService.getParameterValue(sourceKeys[i]); setParameterValue(targetKeys[i], sourceValue); } } /** * Set a value to the given ParameterService key * * @param key * @param value */ private static void setParameterValue(String key, String value) { if (value != null && value != "") { ParameterService.setParameterValue(key, value); } } } /** * Helper Class to support Mac OS X */ private static class SystemSettings { private static HashMap<String, String> settings = new HashMap<String, String>(); /** * Stores the current System property or the default value for the given key * * @param key */ private static void store(String key) { settings.putIfAbsent(key, System.getProperty(key, DEFAULT)); } /** * Stores the default value for the given key * * @param key */ private static void storeDefault(String key) { settings.putIfAbsent(key, DEFAULT); } /** * Applies all stored settings to the system */ private static void apply() { settings.forEach(System::setProperty); } } }