1
0
mirror of https://github.com/arduino/Arduino.git synced 2025-01-18 07:52:14 +01:00

Introducing CustomProxySelector

This commit is contained in:
Federico Fissore 2015-08-07 15:26:17 +02:00
parent d884a2d14f
commit 708da3bd86
7 changed files with 267 additions and 39 deletions

View File

@ -29,6 +29,7 @@
package cc.arduino.view.preferences;
import cc.arduino.Constants;
import processing.app.Base;
import processing.app.BaseNoGui;
import processing.app.I18n;
@ -46,20 +47,6 @@ import static processing.app.I18n.tr;
public class Preferences extends javax.swing.JDialog {
public static final String PROXY_TYPE_NONE = "none";
public static final String PROXY_TYPE_AUTO = "auto";
public static final String PROXY_TYPE_MANUAL = "manual";
public static final String PROXY_MANUAL_TYPE_HTTP = "HTTP";
public static final String PROXY_MANUAL_TYPE_SOCKS = "SOCKS";
public static final String PREF_PROXY_MANUAL_TYPE = "proxy.manual.type";
public static final String PREF_PROXY_TYPE = "proxy.type";
public static final String PREF_PROXY_PAC_URL = "proxy.pac.url";
public static final String PREF_PROXY_MANUAL_HOSTNAME = "proxy.manual.hostname";
public static final String PREF_PROXY_MANUAL_PORT = "proxy.manual.port";
public static final String PREF_PROXY_MANUAL_USERNAME = "proxy.manual.username";
public static final String PREF_PROXY_MANUAL_PASSWORD = "proxy.manual.password";
private final Language[] languages;
private final Language[] missingLanguages;
private final WarningItem[] warningItems;
@ -460,11 +447,11 @@ public class Preferences extends javax.swing.JDialog {
proxyTypeButtonGroup.add(noProxy);
noProxy.setText(tr("No proxy"));
noProxy.setActionCommand(PROXY_TYPE_NONE);
noProxy.setActionCommand(Constants.PROXY_TYPE_NONE);
proxyTypeButtonGroup.add(autoProxy);
autoProxy.setText(tr("Auto-detect proxy settings"));
autoProxy.setActionCommand(PROXY_TYPE_AUTO);
autoProxy.setActionCommand(Constants.PROXY_TYPE_AUTO);
autoProxy.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
autoProxyItemStateChanged(evt);
@ -473,7 +460,7 @@ public class Preferences extends javax.swing.JDialog {
proxyTypeButtonGroup.add(manualProxy);
manualProxy.setText(tr("Manual proxy configuration"));
manualProxy.setActionCommand(PROXY_TYPE_MANUAL);
manualProxy.setActionCommand(Constants.PROXY_TYPE_MANUAL);
manualProxy.addItemListener(new java.awt.event.ItemListener() {
public void itemStateChanged(java.awt.event.ItemEvent evt) {
manualProxyItemStateChanged(evt);
@ -489,11 +476,11 @@ public class Preferences extends javax.swing.JDialog {
manualProxyTypeButtonGroup.add(manualProxyHTTP);
manualProxyHTTP.setText("HTTP");
manualProxyHTTP.setActionCommand(PROXY_MANUAL_TYPE_HTTP);
manualProxyHTTP.setActionCommand(Constants.PROXY_MANUAL_TYPE_HTTP);
manualProxyTypeButtonGroup.add(manualProxySOCKS);
manualProxySOCKS.setText("SOCKS");
manualProxySOCKS.setActionCommand(PROXY_MANUAL_TYPE_SOCKS);
manualProxySOCKS.setActionCommand(Constants.PROXY_MANUAL_TYPE_SOCKS);
manualProxyHostNameLabel.setText(tr("Host name:"));
@ -803,13 +790,13 @@ public class Preferences extends javax.swing.JDialog {
PreferencesData.set("boardsmanager.additional.urls", additionalBoardsManagerField.getText().replace("\r\n", "\n").replace("\r", "\n").replace("\n", ","));
PreferencesData.set(PREF_PROXY_TYPE, proxyTypeButtonGroup.getSelection().getActionCommand());
PreferencesData.set(PREF_PROXY_PAC_URL, autoProxyUsePAC.isSelected() ? autoProxyPACURL.getText() : "");
PreferencesData.set(PREF_PROXY_MANUAL_TYPE, manualProxyTypeButtonGroup.getSelection().getActionCommand());
PreferencesData.set(PREF_PROXY_MANUAL_HOSTNAME, manualProxyHostName.getText());
PreferencesData.set(PREF_PROXY_MANUAL_PORT, manualProxyPort.getText());
PreferencesData.set(PREF_PROXY_MANUAL_USERNAME, manualProxyUsername.getText());
PreferencesData.set(PREF_PROXY_MANUAL_PASSWORD, String.valueOf(manualProxyPassword.getPassword()));
PreferencesData.set(Constants.PREF_PROXY_TYPE, proxyTypeButtonGroup.getSelection().getActionCommand());
PreferencesData.set(Constants.PREF_PROXY_PAC_URL, autoProxyUsePAC.isSelected() ? autoProxyPACURL.getText() : "");
PreferencesData.set(Constants.PREF_PROXY_MANUAL_TYPE, manualProxyTypeButtonGroup.getSelection().getActionCommand());
PreferencesData.set(Constants.PREF_PROXY_MANUAL_HOSTNAME, manualProxyHostName.getText());
PreferencesData.set(Constants.PREF_PROXY_MANUAL_PORT, manualProxyPort.getText());
PreferencesData.set(Constants.PREF_PROXY_MANUAL_USERNAME, manualProxyUsername.getText());
PreferencesData.set(Constants.PREF_PROXY_MANUAL_PASSWORD, String.valueOf(manualProxyPassword.getPassword()));
}
private void showPrerefencesData() {
@ -852,29 +839,29 @@ public class Preferences extends javax.swing.JDialog {
additionalBoardsManagerField.setText(PreferencesData.get("boardsmanager.additional.urls"));
disableAllProxyFields();
String proxyType = PreferencesData.get(PREF_PROXY_TYPE, PROXY_TYPE_AUTO);
String proxyType = PreferencesData.get(Constants.PREF_PROXY_TYPE, Constants.PROXY_TYPE_AUTO);
if (PROXY_TYPE_NONE.equals(proxyType)) {
if (Constants.PROXY_TYPE_NONE.equals(proxyType)) {
noProxy.setSelected(true);
} else if (PROXY_TYPE_AUTO.equals(proxyType)) {
} else if (Constants.PROXY_TYPE_AUTO.equals(proxyType)) {
autoProxy.setSelected(true);
autoProxyFieldsSetEnabled(true);
if (!PreferencesData.get(PREF_PROXY_PAC_URL, "").isEmpty()) {
if (!PreferencesData.get(Constants.PREF_PROXY_PAC_URL, "").isEmpty()) {
autoProxyUsePAC.setSelected(true);
autoProxyPACURL.setText(PreferencesData.get(PREF_PROXY_PAC_URL));
autoProxyPACURL.setText(PreferencesData.get(Constants.PREF_PROXY_PAC_URL));
}
} else {
manualProxy.setSelected(true);
manualProxyFieldsSetEnabled(true);
manualProxyHostName.setText(PreferencesData.get(PREF_PROXY_MANUAL_HOSTNAME));
manualProxyPort.setText(PreferencesData.get(PREF_PROXY_MANUAL_PORT));
manualProxyUsername.setText(PreferencesData.get(PREF_PROXY_MANUAL_USERNAME));
manualProxyPassword.setText(PreferencesData.get(PREF_PROXY_MANUAL_PASSWORD));
manualProxyHostName.setText(PreferencesData.get(Constants.PREF_PROXY_MANUAL_HOSTNAME));
manualProxyPort.setText(PreferencesData.get(Constants.PREF_PROXY_MANUAL_PORT));
manualProxyUsername.setText(PreferencesData.get(Constants.PREF_PROXY_MANUAL_USERNAME));
manualProxyPassword.setText(PreferencesData.get(Constants.PREF_PROXY_MANUAL_PASSWORD));
}
String selectedManualProxyType = PreferencesData.get(PREF_PROXY_MANUAL_TYPE, PROXY_MANUAL_TYPE_HTTP);
manualProxyHTTP.setSelected(PROXY_MANUAL_TYPE_HTTP.equals(selectedManualProxyType));
manualProxySOCKS.setSelected(PROXY_MANUAL_TYPE_SOCKS.equals(selectedManualProxyType));
String selectedManualProxyType = PreferencesData.get(Constants.PREF_PROXY_MANUAL_TYPE, Constants.PROXY_MANUAL_TYPE_HTTP);
manualProxyHTTP.setSelected(Constants.PROXY_MANUAL_TYPE_HTTP.equals(selectedManualProxyType));
manualProxySOCKS.setSelected(Constants.PROXY_MANUAL_TYPE_SOCKS.equals(selectedManualProxyType));
}
private void manualProxyFieldsSetEnabled(boolean enabled) {

View File

@ -0,0 +1,104 @@
package cc.arduino.net;
import cc.arduino.Constants;
import org.junit.Before;
import org.junit.Test;
import java.net.*;
import java.util.HashMap;
import java.util.Map;
import static org.junit.Assert.assertEquals;
public class CustomProxySelectorTest {
private Map<String, String> preferences;
private URI uri;
@Before
public void setUp() throws Exception {
System.setProperty("java.net.useSystemProxies", "true");
uri = new URL("https://www.arduino.cc").toURI();
preferences = new HashMap<>();
}
@Test
public void testNoProxy() throws Exception {
preferences.put(Constants.PREF_PROXY_TYPE, Constants.PROXY_TYPE_NONE);
CustomProxySelector proxySelector = new CustomProxySelector(preferences);
Proxy proxy = proxySelector.getProxyFor(uri);
assertEquals(Proxy.NO_PROXY, proxy);
}
@Test
public void testSystemProxy() throws Exception {
preferences.put(Constants.PREF_PROXY_TYPE, Constants.PROXY_TYPE_AUTO);
CustomProxySelector proxySelector = new CustomProxySelector(preferences);
Proxy proxy = proxySelector.getProxyFor(uri);
assertEquals(ProxySelector.getDefault().select(uri).get(0), proxy);
}
@Test
public void testProxyPACHTTP() throws Exception {
preferences.put(Constants.PREF_PROXY_TYPE, Constants.PROXY_TYPE_AUTO);
preferences.put(Constants.PREF_PROXY_PAC_URL, CustomProxySelectorTest.class.getResource("proxy_http.pac").toExternalForm());
CustomProxySelector proxySelector = new CustomProxySelector(preferences);
Proxy proxy = proxySelector.getProxyFor(uri);
assertEquals(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("proxy.example.com", 8080)), proxy);
}
@Test
public void testProxyPACSOCKS() throws Exception {
preferences.put(Constants.PREF_PROXY_TYPE, Constants.PROXY_TYPE_AUTO);
preferences.put(Constants.PREF_PROXY_PAC_URL, CustomProxySelectorTest.class.getResource("proxy_socks.pac").toExternalForm());
CustomProxySelector proxySelector = new CustomProxySelector(preferences);
Proxy proxy = proxySelector.getProxyFor(uri);
assertEquals(new Proxy(Proxy.Type.SOCKS, new InetSocketAddress("proxy.example.com", 8080)), proxy);
}
@Test
public void testProxyPACDirect() throws Exception {
preferences.put(Constants.PREF_PROXY_TYPE, Constants.PROXY_TYPE_AUTO);
preferences.put(Constants.PREF_PROXY_PAC_URL, CustomProxySelectorTest.class.getResource("proxy_direct.pac").toExternalForm());
CustomProxySelector proxySelector = new CustomProxySelector(preferences);
Proxy proxy = proxySelector.getProxyFor(uri);
assertEquals(Proxy.NO_PROXY, proxy);
}
@Test
public void testManualProxy() throws Exception {
preferences.put(Constants.PREF_PROXY_TYPE, Constants.PROXY_TYPE_MANUAL);
preferences.put(Constants.PREF_PROXY_MANUAL_TYPE, Constants.PROXY_MANUAL_TYPE_HTTP);
preferences.put(Constants.PREF_PROXY_MANUAL_HOSTNAME, "localhost");
preferences.put(Constants.PREF_PROXY_MANUAL_PORT, "8080");
CustomProxySelector proxySelector = new CustomProxySelector(preferences);
Proxy proxy = proxySelector.getProxyFor(uri);
assertEquals(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("localhost", 8080)), proxy);
}
@Test
public void testManualProxyWithLogin() throws Exception {
preferences.put(Constants.PREF_PROXY_TYPE, Constants.PROXY_TYPE_MANUAL);
preferences.put(Constants.PREF_PROXY_MANUAL_TYPE, Constants.PROXY_MANUAL_TYPE_HTTP);
preferences.put(Constants.PREF_PROXY_MANUAL_HOSTNAME, "localhost");
preferences.put(Constants.PREF_PROXY_MANUAL_PORT, "8080");
preferences.put(Constants.PREF_PROXY_MANUAL_USERNAME, "username");
preferences.put(Constants.PREF_PROXY_MANUAL_PASSWORD, "pwd");
CustomProxySelector proxySelector = new CustomProxySelector(preferences);
Proxy proxy = proxySelector.getProxyFor(uri);
assertEquals(new Proxy(Proxy.Type.HTTP, new InetSocketAddress("localhost", 8080)), proxy);
PasswordAuthentication authentication = Authenticator.requestPasswordAuthentication(null, 8080, uri.toURL().getProtocol(), "ciao", "");
assertEquals(authentication.getUserName(), "username");
assertEquals(String.valueOf(authentication.getPassword()), "pwd");
}
}

View File

@ -0,0 +1,4 @@
function FindProxyForURL(url, host)
{
return "DIRECT";
}

View File

@ -0,0 +1,4 @@
function FindProxyForURL(url, host)
{
return "PROXY proxy.example.com:8080; DIRECT";
}

View File

@ -0,0 +1,4 @@
function FindProxyForURL(url, host)
{
return "SOCKS proxy.example.com:8080; DIRECT";
}

View File

@ -40,13 +40,26 @@ public class Constants {
public static final String DEFAULT_INDEX_FILE_NAME = "package_index.json";
public static final List<String> PROTECTED_PACKAGE_NAMES = Arrays.asList("arduino", "Intel");
public static final String PACKAGE_INDEX_URL;
public static final String LIBRARY_DEVELOPMENT_FLAG_FILE = ".development";
public static final long BOARDS_LIBS_UPDATABLE_CHECK_START_PERIOD = 60000;
public static final int NOTIFICATION_POPUP_AUTOCLOSE_DELAY = 10000;
public static final String PROXY_TYPE_NONE = "none";
public static final String PROXY_TYPE_AUTO = "auto";
public static final String PROXY_TYPE_MANUAL = "manual";
public static final String PROXY_MANUAL_TYPE_HTTP = "HTTP";
public static final String PROXY_MANUAL_TYPE_SOCKS = "SOCKS";
public static final String PREF_PROXY_MANUAL_TYPE = "proxy.manual.type";
public static final String PREF_PROXY_TYPE = "proxy.type";
public static final String PREF_PROXY_PAC_URL = "proxy.pac.url";
public static final String PREF_PROXY_MANUAL_HOSTNAME = "proxy.manual.hostname";
public static final String PREF_PROXY_MANUAL_PORT = "proxy.manual.port";
public static final String PREF_PROXY_MANUAL_USERNAME = "proxy.manual.username";
public static final String PREF_PROXY_MANUAL_PASSWORD = "proxy.manual.password";
public static final String PACKAGE_INDEX_URL;
public static final String LIBRARY_INDEX_URL;
public static final String LIBRARY_INDEX_URL_GZ;

View File

@ -0,0 +1,112 @@
package cc.arduino.net;
import cc.arduino.Constants;
import org.apache.commons.compress.utils.IOUtils;
import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import java.io.IOException;
import java.net.*;
import java.nio.charset.Charset;
import java.util.Map;
public class CustomProxySelector {
private final Map<String, String> preferences;
public CustomProxySelector(Map<String, String> preferences) {
this.preferences = preferences;
clearPreviousAuthenticator();
}
public Proxy getProxyFor(URI uri) throws IOException, ScriptException, NoSuchMethodException {
if (Constants.PROXY_TYPE_NONE.equals(preferences.get(Constants.PREF_PROXY_TYPE))) {
return Proxy.NO_PROXY;
}
if (Constants.PROXY_TYPE_AUTO.equals(preferences.get(Constants.PREF_PROXY_TYPE))) {
String pac = preferences.get(Constants.PREF_PROXY_PAC_URL);
if (pac == null || pac.isEmpty()) {
return ProxySelector.getDefault().select(uri).get(0);
}
return pacProxy(pac, uri);
}
if (preferences.get(Constants.PREF_PROXY_TYPE).equals(Constants.PROXY_TYPE_MANUAL)) {
return manualProxy();
}
throw new IllegalStateException("Unable to understand proxy settings");
}
private Proxy pacProxy(String pac, URI uri) throws IOException, ScriptException, NoSuchMethodException {
URLConnection urlConnection = new URL(pac).openConnection();
urlConnection.connect();
if (urlConnection instanceof HttpURLConnection) {
int responseCode = ((HttpURLConnection) urlConnection).getResponseCode();
if (responseCode != 200) {
throw new IOException("Unable to fetch PAC file at " + pac + ". Response code is " + responseCode);
}
}
String pacScript = new String(IOUtils.toByteArray(urlConnection.getInputStream()), Charset.forName("ASCII"));
ScriptEngine nashorn = new ScriptEngineManager().getEngineByName("nashorn");
nashorn.eval(pacScript);
String proxyConfigs = callFindProxyForURL(uri, nashorn);
return makeProxyFrom(proxyConfigs);
}
private Proxy makeProxyFrom(String proxyConfigs) {
String proxyConfig = proxyConfigs.split(";")[0];
if (proxyConfig.startsWith("DIRECT")) {
return Proxy.NO_PROXY;
}
Proxy.Type type;
if (proxyConfig.startsWith("PROXY")) {
type = Proxy.Type.HTTP;
proxyConfig = proxyConfig.replace("PROXY ", "");
} else {
type = Proxy.Type.SOCKS;
proxyConfig = proxyConfig.replace("SOCKS ", "");
}
String[] hostPort = proxyConfig.split(":");
return new Proxy(type, new InetSocketAddress(hostPort[0], Integer.valueOf(hostPort[1])));
}
private String callFindProxyForURL(URI uri, ScriptEngine nashorn) throws ScriptException, NoSuchMethodException {
Invocable script = (Invocable) nashorn;
return (String) script.invokeFunction("FindProxyForURL", toUrl(uri).toExternalForm());
}
private URL toUrl(URI uri) {
try {
return uri.toURL();
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
}
private Proxy manualProxy() {
setAuthenticator();
Proxy.Type type = Proxy.Type.valueOf(preferences.get(Constants.PREF_PROXY_MANUAL_TYPE));
return new Proxy(type, new InetSocketAddress(preferences.get(Constants.PREF_PROXY_MANUAL_HOSTNAME), Integer.valueOf(preferences.get(Constants.PREF_PROXY_MANUAL_PORT))));
}
private void clearPreviousAuthenticator() {
Authenticator.setDefault(null);
}
private void setAuthenticator() {
Authenticator.setDefault(
new Authenticator() {
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(
preferences.get(Constants.PREF_PROXY_MANUAL_USERNAME), preferences.get(Constants.PREF_PROXY_MANUAL_PASSWORD).toCharArray());
}
}
);
}
}