/* * Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code 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 General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.tools.visualvm.modules.appui.options; import java.io.IOException; import java.net.HttpURLConnection; import java.net.InetSocketAddress; import java.net.MalformedURLException; import java.net.Proxy; import java.net.URL; import java.util.StringTokenizer; import java.util.logging.Level; import java.util.logging.Logger; import java.util.prefs.Preferences; import org.openide.util.NbBundle; import org.openide.util.NbPreferences; import org.openide.util.RequestProcessor; /** * * @author Jiri Sedlacek * @author Tomas Hurka */ class NetworkOptionsModel { enum TestingStatus { OK, FAILED, WAITING, NOT_TESTED } private static final Logger LOGGER = Logger.getLogger(NetworkOptionsModel.class.getName()); private static final String NON_PROXY_HOSTS_DELIMITER = "|"; //NOI18N private static final RequestProcessor rp = new RequestProcessor(NetworkOptionsModel.class); private static Preferences getProxyPreferences() { return ProxySettings.getPreferences(); } boolean getUsageStatistics() { String key = System.getProperty("nb.show.statistics.ui"); // NOI18N if (key != null) { return getProxyPreferences().getBoolean(key, Boolean.FALSE); } else { return false; } } void setUsageStatistics(boolean use) { String key = System.getProperty("nb.show.statistics.ui"); //NOI18N if ((key != null) && (use != getUsageStatistics())) { getProxyPreferences().putBoolean(key, use); } } int getProxyType() { return getProxyPreferences().getInt(ProxySettings.PROXY_TYPE, ProxySettings.AUTO_DETECT_PROXY); } void setProxyType(int proxyType) { if (proxyType != getProxyType()) { if (ProxySettings.AUTO_DETECT_PROXY == proxyType) { getProxyPreferences().putInt(ProxySettings.PROXY_TYPE, usePAC() ? ProxySettings.AUTO_DETECT_PAC : ProxySettings.AUTO_DETECT_PROXY); } else { getProxyPreferences().putInt(ProxySettings.PROXY_TYPE, proxyType); } } } String getHttpProxyHost() { return ProxySettings.getHttpHost(); } void setHttpProxyHost(String proxyHost) { if (!proxyHost.equals(getHttpProxyHost())) { getProxyPreferences().put(ProxySettings.PROXY_HTTP_HOST, proxyHost); } } String getHttpProxyPort() { return ProxySettings.getHttpPort(); } void setHttpProxyPort(String proxyPort) { if (!proxyPort.equals(getHttpProxyPort())) { getProxyPreferences().put(ProxySettings.PROXY_HTTP_PORT, validatePort(proxyPort) ? proxyPort : ""); } } String getHttpsProxyHost() { return ProxySettings.getHttpsHost(); } void setHttpsProxyHost(String proxyHost) { if (!proxyHost.equals(getHttpsProxyHost())) { getProxyPreferences().put(ProxySettings.PROXY_HTTPS_HOST, proxyHost); } } String getHttpsProxyPort() { return ProxySettings.getHttpsPort(); } void setHttpsProxyPort(String proxyPort) { if (!proxyPort.equals(getHttpsProxyPort())) { getProxyPreferences().put(ProxySettings.PROXY_HTTPS_PORT, validatePort(proxyPort) ? proxyPort : ""); } } String getSocksHost() { return ProxySettings.getSocksHost(); } void setSocksHost(String socksHost) { if (!socksHost.equals(getSocksHost())) { getProxyPreferences().put(ProxySettings.PROXY_SOCKS_HOST, socksHost); } } String getSocksPort() { return ProxySettings.getSocksPort(); } void setSocksPort(String socksPort) { if (!socksPort.equals(getSocksPort())) { getProxyPreferences().put(ProxySettings.PROXY_SOCKS_PORT, validatePort(socksPort) ? socksPort : ""); } } String getOriginalHttpsHost() { return getProxyPreferences().get(ProxySettings.PROXY_HTTPS_HOST, ""); } String getOriginalHttpsPort() { return getProxyPreferences().get(ProxySettings.PROXY_HTTPS_PORT, ""); } String getOriginalSocksHost() { return getProxyPreferences().get(ProxySettings.PROXY_SOCKS_HOST, ""); } String getOriginalSocksPort() { return getProxyPreferences().get(ProxySettings.PROXY_SOCKS_PORT, ""); } String getNonProxyHosts() { return code2view(ProxySettings.getNonProxyHosts()); } void setNonProxyHosts(String nonProxy) { if (!nonProxy.equals(getNonProxyHosts())) { getProxyPreferences().put(ProxySettings.NOT_PROXY_HOSTS, view2code(nonProxy)); } } boolean useProxyAuthentication() { return ProxySettings.useAuthentication(); } void setUseProxyAuthentication(boolean use) { if (use != useProxyAuthentication()) { getProxyPreferences().putBoolean(ProxySettings.USE_PROXY_AUTHENTICATION, use); } } boolean useProxyAllProtocols() { return ProxySettings.useProxyAllProtocols(); } void setUseProxyAllProtocols(boolean use) { if (use != useProxyAllProtocols()) { getProxyPreferences().putBoolean(ProxySettings.USE_PROXY_ALL_PROTOCOLS, use); } } String getProxyAuthenticationUsername() { return ProxySettings.getAuthenticationUsername(); } void setAuthenticationUsername(String username) { getProxyPreferences().put(ProxySettings.PROXY_AUTHENTICATION_USERNAME, username); } char[] getProxyAuthenticationPassword() { return ProxySettings.getAuthenticationPassword(); } void setAuthenticationPassword(char[] password) { ProxySettings.setAuthenticationPassword(password); } static boolean usePAC() { String pacUrl = getProxyPreferences().get(ProxySettings.SYSTEM_PAC, ""); // NOI18N return pacUrl != null && pacUrl.length() > 0; } static void testConnection(final NetworkOptionsPanel panel, final int proxyType, final String proxyHost, final String proxyPortString, final String nonProxyHosts) { rp.post(new Runnable() { @Override public void run() { testProxy(panel, proxyType, proxyHost, proxyPortString, nonProxyHosts); } }); } // private helper methods .................................................. private static void testProxy(NetworkOptionsPanel panel, int proxyType, String proxyHost, String proxyPortString, String nonProxyHosts) { panel.updateTestConnectionStatus(TestingStatus.WAITING, null); TestingStatus status = TestingStatus.FAILED; String message = null; String testingUrlHost; URL testingUrl; Proxy testingProxy; try { testingUrl = new URL(ProxySettings.HTTP_CONNECTION_TEST_URL); testingUrlHost = testingUrl.getHost(); } catch (MalformedURLException ex) { LOGGER.log(Level.SEVERE, "Cannot create url from string.", ex); // NOI18N panel.updateTestConnectionStatus(status, message); return; } switch (proxyType) { case ProxySettings.DIRECT_CONNECTION: testingProxy = Proxy.NO_PROXY; break; case ProxySettings.AUTO_DETECT_PROXY: case ProxySettings.AUTO_DETECT_PAC: nonProxyHosts = ProxySettings.getSystemNonProxyHosts(); if (isNonProxy(testingUrlHost, nonProxyHosts)) { testingProxy = Proxy.NO_PROXY; } else { String host = ProxySettings.getTestSystemHttpHost(); int port = 0; try { port = Integer.valueOf(ProxySettings.getTestSystemHttpPort()); } catch (NumberFormatException ex) { LOGGER.log(Level.INFO, "Cannot parse port number", ex); //NOI18N } testingProxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(host, port)); } break; case ProxySettings.MANUAL_SET_PROXY: nonProxyHosts = view2code(nonProxyHosts); if (isNonProxy(testingUrl.getHost(), nonProxyHosts)) { testingProxy = Proxy.NO_PROXY; } else { try { int proxyPort = Integer.valueOf(proxyPortString); testingProxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(proxyHost, proxyPort)); } catch (NumberFormatException ex) { // shouldn't fall into this code LOGGER.log(Level.INFO, "Cannot parse port number", ex); // NOI18N status = TestingStatus.FAILED; message = NbBundle.getMessage(NetworkOptionsModel.class, "NetworkOptionsModel_PortError"); // NOI18N panel.updateTestConnectionStatus(status, message); return; } } break; case ProxySettings.MANUAL_SET_PAC: // Never should get here, user cannot set up PAC manualy from IDE default: testingProxy = Proxy.NO_PROXY; } try { status = testHttpConnection(testingUrl, testingProxy) ? TestingStatus.OK : TestingStatus.FAILED; } catch (IOException ex) { LOGGER.log(Level.INFO, "Cannot connect via http protocol.", ex); //NOI18N message = ex.getLocalizedMessage(); } panel.updateTestConnectionStatus(status, message); } private static boolean testHttpConnection(URL url, Proxy proxy) throws IOException { boolean result = false; HttpURLConnection httpConnection = (HttpURLConnection) url.openConnection(proxy); // Timeout shorten to 5s httpConnection.setConnectTimeout(5000); httpConnection.connect(); if (httpConnection.getResponseCode() == HttpURLConnection.HTTP_OK || httpConnection.getResponseCode() == HttpURLConnection.HTTP_MOVED_TEMP) { result = true; } httpConnection.disconnect(); return result; } // Simplified to use only with supposed netbeans.org host private static boolean isNonProxy(String host, String nonProxyHosts) { boolean isNonProxy = false; if (host != null && nonProxyHosts != null) { StringTokenizer st = new StringTokenizer(nonProxyHosts, NON_PROXY_HOSTS_DELIMITER, false); while (st.hasMoreTokens()) { if (st.nextToken().equals(host)) { isNonProxy = true; break; } } } return isNonProxy; } private static boolean validatePort(String port) { if (port.trim().length() == 0) { return true; } boolean ok = false; try { Integer.parseInt(port); ok = true; } catch (NumberFormatException nfe) { assert false : nfe; } return ok; } private static String code2view(String code) { return code == null ? code : code.replace("|", ", "); // NOI18N } private static String view2code(String view) { return view == null ? view : view.replace(", ", "|"); // NOI18N } }