diff -r db7aba84ef7e o.n.core/nbproject/project.xml --- a/o.n.core/nbproject/project.xml Thu Sep 15 11:05:11 2011 +0200 +++ b/o.n.core/nbproject/project.xml Thu Sep 15 16:23:34 2011 +0200 @@ -160,7 +160,7 @@ - 8.0 + 8.17 diff -r db7aba84ef7e o.n.core/src/org/netbeans/core/NbAuthenticator.java --- a/o.n.core/src/org/netbeans/core/NbAuthenticator.java Thu Sep 15 11:05:11 2011 +0200 +++ b/o.n.core/src/org/netbeans/core/NbAuthenticator.java Thu Sep 15 16:23:34 2011 +0200 @@ -44,6 +44,7 @@ package org.netbeans.core; import java.net.PasswordAuthentication; +import java.net.URL; import java.util.logging.Level; import java.util.logging.Logger; import java.util.prefs.Preferences; @@ -51,6 +52,7 @@ import org.openide.DialogDisplayer; import org.openide.util.NbBundle; import org.openide.util.NbPreferences; +import org.openide.util.NetworkSettings; /** Global password protected sites Authenticator for IDE * @@ -61,7 +63,6 @@ private static final long TIMEOUT = 3000; private static long lastTry = 0; - private NbAuthenticator() { Preferences proxySettingsNode = NbPreferences.root().node("/org/netbeans/core"); //NOI18N assert proxySettingsNode != null; @@ -73,6 +74,10 @@ } } + static void install4test() { + setDefault(new NbAuthenticator()); + } + @Override protected PasswordAuthentication getPasswordAuthentication() { Logger.getLogger(NbAuthenticator.class.getName()).log(Level.FINER, "Authenticator.getPasswordAuthentication() with prompt " + this.getRequestingPrompt()); //NOI18N @@ -85,6 +90,13 @@ if (getRequestingProtocol().startsWith("SOCKS")&&(ProxySettings.getAuthenticationUsername().length()>0)) { //NOI18N return new java.net.PasswordAuthentication(ProxySettings.getAuthenticationUsername(), ProxySettings.getAuthenticationPassword()); } + if (NetworkSettings.isAuthenticationDialogSuppressed()) { + return null; + } + PasswordAuthentication auth = getAuthenticationFromURL(); + if (auth != null) { + return auth; + } NbAuthenticatorPanel ui = new NbAuthenticatorPanel(getRequestingPrompt()); Object result = DialogDisplayer.getDefault().notify( new DialogDescriptor(ui, NbBundle.getMessage(NbAuthenticator.class, "CTL_Authentication"))); //NOI18N @@ -101,4 +113,17 @@ return null; } + private PasswordAuthentication getAuthenticationFromURL() { + URL u = this.getRequestingURL(); + if (u != null) { + String auth = u.getUserInfo(); + if (auth != null) { + int i = auth.indexOf(':'); + String user = (i == -1) ? auth : auth.substring(0, i); + String pwd = (i == -1) ? "" : auth.substring(i + 1); + return new PasswordAuthentication(user, pwd.toCharArray()); + } + } + return null; + } } diff -r db7aba84ef7e o.n.core/src/org/netbeans/core/ProxySettings.java --- a/o.n.core/src/org/netbeans/core/ProxySettings.java Thu Sep 15 11:05:11 2011 +0200 +++ b/o.n.core/src/org/netbeans/core/ProxySettings.java Thu Sep 15 16:23:34 2011 +0200 @@ -45,17 +45,27 @@ package org.netbeans.core; import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Proxy; +import java.net.ProxySelector; +import java.net.URI; import java.net.UnknownHostException; import java.util.HashSet; +import java.util.List; import java.util.Locale; import java.util.Set; import java.util.StringTokenizer; +import java.util.logging.Level; +import java.util.logging.Logger; import java.util.prefs.PreferenceChangeListener; import java.util.prefs.Preferences; import org.netbeans.api.keyring.Keyring; import org.openide.util.NbBundle; import org.openide.util.NbPreferences; +import org.openide.util.NetworkSettings; +import org.openide.util.Parameters; import org.openide.util.Utilities; +import org.openide.util.lookup.ServiceProvider; /** * @@ -95,6 +105,8 @@ /** Proxy PAC file manually set. */ public static final int MANUAL_SET_PAC = 4; + private static final Logger LOGGER = Logger.getLogger(ProxySettings.class.getName()); + private static Preferences getPreferences() { return NbPreferences.forModule (ProxySettings.class); } @@ -437,4 +449,71 @@ } } + private static InetSocketAddress analyzeProxy(URI uri) { + Parameters.notNull("uri", uri); + List proxies = ProxySelector.getDefault().select(uri); + assert proxies != null : "ProxySelector cannot return null for " + uri; + assert !proxies.isEmpty() : "ProxySelector cannot return empty list for " + uri; + Proxy p = proxies.get(0); + if (Proxy.Type.DIRECT == p.type()) { + // return null for DIRECT proxy + return null; + } else { + if (p.address() instanceof InetSocketAddress) { + // check is + //assert ! ((InetSocketAddress) p.address()).isUnresolved() : p.address() + " must be resolved address."; + return (InetSocketAddress) p.address(); + } else { + LOGGER.log(Level.INFO, p.address() + " is not instanceof InetSocketAddress but " + p.address().getClass()); + return null; + } + } + } + + @ServiceProvider(service = NetworkSettings.ProxyCredentialsProvider.class, position = 1000) + public static class NbProxyCredentialsProvider extends NetworkSettings.ProxyCredentialsProvider { + + @Override + public String getProxyHost(URI u) { + if (getPreferences() == null) { + return null; + } + InetSocketAddress sa = analyzeProxy(u); + return sa == null ? null : sa.getHostName(); + } + + @Override + public String getProxyPort(URI u) { + if (getPreferences() == null) { + return null; + } + InetSocketAddress sa = analyzeProxy(u); + return sa == null ? null : Integer.toString(sa.getPort()); + } + + @Override + protected String getProxyUserName(URI u) { + if (getPreferences() == null) { + return null; + } + return ProxySettings.getAuthenticationUsername(); + } + + @Override + protected char[] getProxyPassword(URI u) { + if (getPreferences() == null) { + return null; + } + return ProxySettings.getAuthenticationPassword(); + } + + @Override + protected boolean isProxyAuthentication(URI u) { + if (getPreferences() == null) { + return false; + } + return getPreferences().getBoolean(USE_PROXY_AUTHENTICATION, false); + } + + } } diff -r db7aba84ef7e o.n.core/test/unit/src/org/netbeans/core/NbAuthenticatorTest.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/o.n.core/test/unit/src/org/netbeans/core/NbAuthenticatorTest.java Thu Sep 15 16:23:34 2011 +0200 @@ -0,0 +1,84 @@ +/* + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. + * + * Copyright 2011 Oracle and/or its affiliates. All rights reserved. + * + * Oracle and Java are registered trademarks of Oracle and/or its affiliates. + * Other names may be trademarks of their respective owners. + * + * The contents of this file are subject to the terms of either the GNU + * General Public License Version 2 only ("GPL") or the Common + * Development and Distribution License("CDDL") (collectively, the + * "License"). You may not use this file except in compliance with the + * License. You can obtain a copy of the License at + * http://www.netbeans.org/cddl-gplv2.html + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the + * specific language governing permissions and limitations under the + * License. When distributing the software, include this License Header + * Notice in each file and include the License file at + * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the GPL Version 2 section of the License file that + * accompanied this code. If applicable, add the following below the + * License Header, with the fields enclosed by brackets [] replaced by + * your own identifying information: + * "Portions Copyrighted [year] [name of copyright owner]" + * + * If you wish your version of this file to be governed by only the CDDL + * or only the GPL Version 2, indicate your decision by adding + * "[Contributor] elects to include this software in this distribution + * under the [CDDL or GPL Version 2] license." If you do not indicate a + * single choice of license, a recipient has the option to distribute + * your version of this file under either the CDDL, the GPL Version 2 or + * to extend the choice of license to its licensees as provided above. + * However, if you add GPL Version 2 code and therefore, elected the GPL + * Version 2 license, then the option applies only if the new code is + * made subject to such option by the copyright holder. + * + * Contributor(s): + * + * Portions Copyrighted 2011 Sun Microsystems, Inc. + */ +package org.netbeans.core; + +import java.net.Authenticator; +import java.net.Inet4Address; +import java.net.PasswordAuthentication; +import java.net.URL; +import java.util.concurrent.Callable; +import org.netbeans.junit.NbTestCase; +import org.openide.util.NetworkSettings; + +/** + * + * @author Ondrej Vrabec + */ +public class NbAuthenticatorTest extends NbTestCase { + + public NbAuthenticatorTest(String name) { + super(name); + } + + public void testUserInfoInUrl () throws Exception { + NbAuthenticator.install4test(); + PasswordAuthentication auth = Authenticator.requestPasswordAuthentication("localhost", Inet4Address.getLocalHost(), 1234, "http", null, "http", + new URL("http://user:password@localhost/resource"), Authenticator.RequestorType.SERVER); + + assertNotNull(auth); + assertEquals("user", auth.getUserName()); + assertEquals("password", new String(auth.getPassword())); + } + + public void testSupressedAuthenticator () throws Exception { + NbAuthenticator.install4test(); + PasswordAuthentication auth = + NetworkSettings.suppressAuthenticationDialog(new Callable() { + @Override + public PasswordAuthentication call () throws Exception { + return Authenticator.requestPasswordAuthentication("localhost", Inet4Address.getLocalHost(), 1234, "http", null, "http", + new URL("http://user:password@localhost/resource"), Authenticator.RequestorType.SERVER); + } + }); + assertNull(auth); + } +} diff -r db7aba84ef7e openide.util/apichanges.xml --- a/openide.util/apichanges.xml Thu Sep 15 11:05:11 2011 +0200 +++ b/openide.util/apichanges.xml Thu Sep 15 16:23:34 2011 +0200 @@ -51,6 +51,48 @@ Actions API + + + SPI NetworkSettings.ProxyCredentialsProvider added + + + + + +

+ Most of the proxy and network credentials are currently read + from a default NetBeans storage. This may not be ideal + for other Platform aplications storing the settings in a different + way or computing them dynamically. + A SPI + NetworkSettings.ProxyCredentialsProvider allows NetBeans Platform + users to provide proxy and network credentials separately. + See http://wiki.netbeans.org/Authenticator +

+
+ + +
+ + + NetworkSettings.suppressAuthenticationDialog added + + + + + +

+ Some plugins needs a way to suppress + Authenticator without asking + user a question about the credentials. + Invoke + suppressAuthenticationDialog with a block of code where authentication dialog will be suppressed. + See http://wiki.netbeans.org/Authenticator +

+
+ + +
NetworkSettings added diff -r db7aba84ef7e openide.util/manifest.mf --- a/openide.util/manifest.mf Thu Sep 15 11:05:11 2011 +0200 +++ b/openide.util/manifest.mf Thu Sep 15 16:23:34 2011 +0200 @@ -1,5 +1,5 @@ Manifest-Version: 1.0 OpenIDE-Module: org.openide.util OpenIDE-Module-Localizing-Bundle: org/openide/util/Bundle.properties -OpenIDE-Module-Specification-Version: 8.16 +OpenIDE-Module-Specification-Version: 8.17 diff -r db7aba84ef7e openide.util/src/org/openide/util/NetworkSettings.java --- a/openide.util/src/org/openide/util/NetworkSettings.java Thu Sep 15 11:05:11 2011 +0200 +++ b/openide.util/src/org/openide/util/NetworkSettings.java Thu Sep 15 16:23:34 2011 +0200 @@ -41,14 +41,9 @@ */ package org.openide.util; -import java.net.InetSocketAddress; -import java.net.Proxy; -import java.net.ProxySelector; import java.net.URI; -import java.util.List; -import java.util.logging.Level; +import java.util.concurrent.Callable; import java.util.logging.Logger; -import java.util.prefs.Preferences; /** Useful static methods for getting Network Proxy required for make network * connection for specified resource. @@ -58,24 +53,23 @@ */ public final class NetworkSettings { - private static final String PROXY_AUTHENTICATION_USERNAME = "proxyAuthenticationUsername"; private static final String PROXY_AUTHENTICATION_PASSWORD = "proxyAuthenticationPassword"; - private static final String USE_PROXY_AUTHENTICATION = "useProxyAuthentication"; private static final Logger LOGGER = Logger.getLogger(NetworkSettings.class.getName()); + private static ThreadLocal authenticationDialogSuppressed = new ThreadLocal(); /** Returns the hostname part of network proxy address * based on given URI to access the resource at. * Returns null for direct connection. * * @param u The URI that a connection is required to - * @return the hostname part of the Proxy address + * @return the hostname part of the Proxy address or null */ public static String getProxyHost(URI u) { - if (getPreferences() == null) { - return null; + ProxyCredentialsProvider provider = Lookup.getDefault().lookup(ProxyCredentialsProvider.class); + if (provider == null) { + LOGGER.warning("No ProxyCredentialsProvider found in lookup " + Lookup.getDefault() + " thus no proxy information will provide!"); } - InetSocketAddress sa = analyzeProxy(u); - return sa == null ? null : sa.getHostName(); + return provider == null ? null : provider.getProxyHost(u); } /** Returns the port part of network proxy address @@ -83,71 +77,131 @@ * Returns null for direct connection. * * @param u The URI that a connection is required to - * @return the port part of the Proxy address + * @return the port part of the Proxy address or null */ public static String getProxyPort(URI u) { - if (getPreferences() == null) { - return null; + ProxyCredentialsProvider provider = Lookup.getDefault().lookup(ProxyCredentialsProvider.class); + if (provider == null) { + LOGGER.warning("No ProxyCredentialsProvider found in lookup " + Lookup.getDefault() + " thus no proxy information will provide!"); } - InetSocketAddress sa = analyzeProxy(u); - return sa == null ? null : Integer.toString(sa.getPort()); + return provider == null ? null : provider.getProxyPort(u); } /** Returns the username for Proxy Authentication. * Returns null if no authentication required. * * @param u The URI that a connection is required to - * @return username for Proxy Authentication + * @return username for Proxy Authentication or null */ public static String getAuthenticationUsername(URI u) { - if (getPreferences() == null) { - return null; + ProxyCredentialsProvider provider = Lookup.getDefault().lookup(ProxyCredentialsProvider.class); + if (provider == null) { + LOGGER.warning("No ProxyCredentialsProvider found in lookup " + Lookup.getDefault() + " thus no proxy information will provide!"); } - if (getPreferences().getBoolean(USE_PROXY_AUTHENTICATION, false)) { - return getPreferences().get(PROXY_AUTHENTICATION_USERNAME, ""); + if (provider != null && provider.isProxyAuthentication(u)) { + return provider.getProxyUserName(u); } return null; } - + /** Returns the key for reading password for Proxy Authentication. - * Use {@link Keyring} for reading the password from the ring. + * Use {@link org.netbeans.api.Keyring} for reading the password from the ring. * Returns null if no authentication required. * * @param u The URI that a connection is required to - * @return the key for reading password for Proxy Authentication from the ring + * @return the key for reading password for Proxy Authentication from the ring or null */ public static String getKeyForAuthenticationPassword(URI u) { - if (getPreferences() == null) { - return null; + ProxyCredentialsProvider provider = Lookup.getDefault().lookup(ProxyCredentialsProvider.class); + if (provider == null) { + LOGGER.warning("No ProxyCredentialsProvider found in lookup " + Lookup.getDefault() + " thus no proxy information will provide!"); } - if (getPreferences().getBoolean(USE_PROXY_AUTHENTICATION, false)) { + if (provider != null && provider.isProxyAuthentication(u)) { return PROXY_AUTHENTICATION_PASSWORD; } return null; } - private static Preferences getPreferences() { - return NbPreferences.root().node("org/netbeans/core"); // NOI18N - } - - private static InetSocketAddress analyzeProxy(URI uri) { - Parameters.notNull("uri", uri); - List proxies = ProxySelector.getDefault().select(uri); - assert proxies != null : "ProxySelector cannot return null for " + uri; - assert ! proxies.isEmpty() : "ProxySelector cannot return empty list for " + uri; - Proxy p = proxies.get(0); - if (Proxy.Type.DIRECT == p.type()) { - // return null for DIRECT proxy - return null; - } else { - if (p.address() instanceof InetSocketAddress) { - // check is - //assert ! ((InetSocketAddress) p.address()).isUnresolved() : p.address() + " must be resolved address."; - return (InetSocketAddress) p.address(); - } else { - LOGGER.log(Level.INFO, p.address() + " is not instanceof InetSocketAddress but " + p.address().getClass()); - return null; - } + /** Suppress asking user a question about the authentication credentials while + * running blockOfCode. It's a contract with NetBeans implementation + * of Authenticator. + * In case a system is using other Authenticator implementation, it must call {@link #isAuthenticationDialogSuppressed} method. + * + * @param blockOfCode {@link Callable} containing code which will be executed while authentication is suppressed + * @return a result of calling of blockOfCode and may throw an exception. + * @throws Exception + * @see #isAuthenticationDialogSuppressed + * @since 8.17 + */ + public static R suppressAuthenticationDialog(Callable blockOfCode) throws Exception { + try { + authenticationDialogSuppressed.set(Boolean.TRUE); + return blockOfCode.call(); + } finally { + authenticationDialogSuppressed.remove(); } } + + /** A utility method for implementations of Authenticator + * to suppress asking users a authentication question while running code posted + * in {@link #authenticationDialogSuppressed}. + * + * @return true while running code posted in {@link #authenticationDialogSuppressed} method. + * @since 8.17 + * @see #authenticationDialogSuppressed + */ + public static boolean isAuthenticationDialogSuppressed() { + return Boolean.TRUE.equals(authenticationDialogSuppressed.get()); + } + + /** A SPI abstract class {@link NetworkSettings.ProxyCredentialsProvider} allows + * NetBeans Platform users to provide own proxy and network credentials separately. + * + * @see http://wiki.netbeans.org/Authenticator + * @author Jiri Rechtacek, Ondrej Vrabec + * @since 8.17 + */ + public static abstract class ProxyCredentialsProvider { + + /** Returns the username for Proxy Authentication. + * Returns null if no authentication required. + * + * @param u The URI that a connection is required to + * @return username for Proxy Authentication + */ + protected abstract String getProxyUserName(URI u); + + /** Returns the password for Proxy Authentication. + * Returns null if no authentication required. + * + * @param u The URI that a connection is required to + * @return password for Proxy Authentication + */ + protected abstract char[] getProxyPassword(URI u); + + /** Returns true if Proxy Authentication is required. + * + * @param u The URI that a connection is required to + * @return true if authentication required. + */ + protected abstract boolean isProxyAuthentication(URI u); + + /** Returns the hostname part of network proxy address + * based on given URI to access the resource at. + * Returns null for direct connection. + * + * @param u The URI that a connection is required to + * @return the hostname part of the Proxy address or null + */ + protected abstract String getProxyHost(URI u); + + /** Returns the port part of network proxy address + * based on given URI to access the resource at. + * Returns null for direct connection. + * + * @param u The URI that a connection is required to + * @return the port part of the Proxy address or null + */ + protected abstract String getProxyPort(URI u); + } } diff -r db7aba84ef7e openide.util/test/unit/src/org/openide/util/NetworkSettingsTest.java --- a/openide.util/test/unit/src/org/openide/util/NetworkSettingsTest.java Thu Sep 15 11:05:11 2011 +0200 +++ b/openide.util/test/unit/src/org/openide/util/NetworkSettingsTest.java Thu Sep 15 16:23:34 2011 +0200 @@ -39,25 +39,33 @@ * * Portions Copyrighted 2011 Sun Microsystems, Inc. */ - package org.openide.util; +import java.io.IOException; +import java.net.Authenticator; +import java.net.Inet4Address; import java.net.InetSocketAddress; -import java.net.URISyntaxException; -import java.util.Collections; -import java.io.IOException; +import java.net.PasswordAuthentication; import java.net.Proxy; import java.net.ProxySelector; import java.net.SocketAddress; import java.net.URI; +import java.net.URISyntaxException; +import java.net.UnknownHostException; +import java.util.Collections; import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.CountDownLatch; import junit.framework.TestCase; +import org.netbeans.junit.MockServices; +import org.openide.util.NetworkSettings.ProxyCredentialsProvider; /** * - * @author Jiri Rechtacek + * @author Jiri Rechtacek, Ondrej Vrabec */ public class NetworkSettingsTest extends TestCase { + private static ProxySelector defaultPS; public NetworkSettingsTest(String name) { @@ -91,6 +99,7 @@ } }; ProxySelector.setDefault(ps); + MockServices.setServices(MyProxyCredentialsProvider.class); } @Override @@ -105,7 +114,7 @@ } public void testGetProxyForRemote() throws URISyntaxException { - URI u = new URI("http://remove.org"); + URI u = new URI("http://remote.org"); assertEquals("Check NetworkSettings.getProxyHost() for " + u, "corpcache.cache", NetworkSettings.getProxyHost(u)); assertEquals("Check NetworkSettings.getProxyPort() for " + u, "1234", NetworkSettings.getProxyPort(u)); } @@ -116,4 +125,147 @@ assertNull("NetworkSettings.getProxyPort() returns null for " + u, NetworkSettings.getProxyPort(u)); } -} \ No newline at end of file + public void testIsAuthenticationDialogNotSuppressed() throws Exception { + final boolean[] suppressed = new boolean[1]; + Authenticator.setDefault(new Authenticator() { + + @Override + protected PasswordAuthentication getPasswordAuthentication() { + suppressed[0] = NetworkSettings.isAuthenticationDialogSuppressed(); + return super.getPasswordAuthentication(); + } + }); + + Authenticator.requestPasswordAuthentication("localhost", Inet4Address.getLocalHost(), 1234, "http", null, "http"); + assertFalse(suppressed[0]); + } + + public void testIsAuthenticationDialogSuppressed() throws Exception { + final boolean[] suppressed = new boolean[1]; + Authenticator.setDefault(new Authenticator() { + + @Override + protected PasswordAuthentication getPasswordAuthentication() { + suppressed[0] = NetworkSettings.isAuthenticationDialogSuppressed(); + return super.getPasswordAuthentication(); + } + }); + + Callable callable = new Callable() { + + @Override + public Void call() throws Exception { + Authenticator.requestPasswordAuthentication("localhost", Inet4Address.getLocalHost(), 1234, "http", null, "http"); + return null; + } + }; + NetworkSettings.suppressAuthenticationDialog(callable); + assertTrue(suppressed[0]); + } + + @SuppressWarnings("SleepWhileInLoop") + public void testIsAuthenticationDialogSuppressedExclusive() throws InterruptedException, UnknownHostException { + final boolean[] suppressed = new boolean[1]; + Authenticator.setDefault(new Authenticator() { + + @Override + protected PasswordAuthentication getPasswordAuthentication() { + suppressed[0] = NetworkSettings.isAuthenticationDialogSuppressed(); + return super.getPasswordAuthentication(); + } + }); + + final CountDownLatch doneSignal1 = new CountDownLatch(1); + final CountDownLatch doneSignal2 = new CountDownLatch(1); + Thread t = new Thread(new Runnable() { + @Override + public void run() { + Callable callable = new Callable() { + + @Override + public Void call() throws Exception { + doneSignal1.countDown(); + doneSignal2.await(); + Authenticator.requestPasswordAuthentication("localhost", Inet4Address.getLocalHost(), 1234, "http", null, "http"); + return null; + } + }; + try { + NetworkSettings.suppressAuthenticationDialog(callable); + } catch (Exception ex) { + Exceptions.printStackTrace(ex); + } + } + }); + t.start(); + doneSignal1.await(); + Authenticator.requestPasswordAuthentication("localhost", Inet4Address.getLocalHost(), 1234, "http", null, "http"); + assertFalse(suppressed[0]); + doneSignal2.countDown(); + t.join(); + assertTrue(suppressed[0]); + } + + public void testNoProxyCredentialsProviderFound() throws URISyntaxException { + MockServices.setServices(); + URI localURI = new URI("http://localhost"); + assertNull("NetworkSettings.getProxyHost() returns null for " + localURI, NetworkSettings.getProxyHost(localURI)); + assertNull("NetworkSettings.getProxyPort() returns null for " + localURI, NetworkSettings.getProxyPort(localURI)); + URI remoteURI = new URI("http://remove.org"); + assertNull("NetworkSettings.getProxyHost() returns null for " + remoteURI, NetworkSettings.getProxyHost(localURI)); + assertNull("NetworkSettings.getProxyHost() returns null for " + remoteURI, NetworkSettings.getProxyHost(localURI)); + URI intraURI = new URI("http://inner.private.web"); + assertNull("NetworkSettings.getProxyHost() returns null for " + intraURI, NetworkSettings.getProxyHost(intraURI)); + assertNull("NetworkSettings.getProxyPort() returns null for " + intraURI, NetworkSettings.getProxyPort(intraURI)); + } + + public static class MyProxyCredentialsProvider extends ProxyCredentialsProvider { + + @Override + protected String getProxyUserName(URI u) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + protected char[] getProxyPassword(URI u) { + throw new UnsupportedOperationException("Not supported yet."); + } + + @Override + protected boolean isProxyAuthentication(URI u) { + return false; + } + + @Override + protected String getProxyHost(URI u) { + InetSocketAddress sa = analyzeProxy(u); + return sa == null ? null : sa.getHostName(); + } + + @Override + protected String getProxyPort(URI u) { + InetSocketAddress sa = analyzeProxy(u); + return sa == null ? null : Integer.toString(sa.getPort()); + } + } + + private static InetSocketAddress analyzeProxy(URI uri) { + Parameters.notNull("uri", uri); + List proxies = ProxySelector.getDefault().select(uri); + assert proxies != null : "ProxySelector cannot return null for " + uri; + assert !proxies.isEmpty() : "ProxySelector cannot return empty list for " + uri; + Proxy p = proxies.get(0); + if (Proxy.Type.DIRECT == p.type()) { + // return null for DIRECT proxy + return null; + } else { + if (p.address() instanceof InetSocketAddress) { + // check is + //assert ! ((InetSocketAddress) p.address()).isUnresolved() : p.address() + " must be resolved address."; + return (InetSocketAddress) p.address(); + } else { + return null; + } + } + } +}