/*
 * Copyright (c) 2014, 2016, 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.
 *
 * 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.
 */
/*
 * @test
 * @bug 8035158 8145732
 * @run main/othervm B8035158
 */

import java.net.Proxy;
import java.net.ProxySelector;
import java.net.URI;
import java.util.*;
import java.util.concurrent.Callable;

public class B8035158 {

    public static void main(String[] args) {
        for (TestCase t : emptyNonProxiesHosts()) t.run();
        for (TestCase t : nonEmptyNonProxiesHosts()) t.run();
        for (TestCase t : misc()) t.run();
    }

    // Setting http.nonProxyHosts to an empty string has an effect of
    // not including default hosts to the list of exceptions
    // (i.e. if you want everything to be connected directly rather than
    // through proxy, you should set this property to an empty string)
    private static Collection<TestCase> emptyNonProxiesHosts() {
        List<TestCase> tests = new LinkedList<>();
        String[] loopbacks = {"localhost", "[::1]", "[::0]", "0.0.0.0",
                "127.0.0.0", "127.0.0.1", "127.0.1.0", "127.0.1.1",
                "127.1.0.0", "127.1.0.1", "127.1.1.0", "127.1.1.1"};
        Map<String, String> properties = new HashMap<>();
        properties.put("http.proxyHost", "http://proxy.example.com");
        properties.put("http.nonProxyHosts", "");
        for (String s : loopbacks) {
            tests.add(new TestCase(properties, "http://" + s, true));
        }
        return tests;
    }

    // No matter what is set into the http.nonProxyHosts (as far as it is not
    // an empty string) loopback address aliases must be always connected
    // directly
    private static Collection<TestCase> nonEmptyNonProxiesHosts() {
        List<TestCase> tests = new LinkedList<>();
        String[] nonProxyHosts = {
                "google.com",
                "localhost", "[::1]", "[::0]", "0.0.0.0",
                "127.0.0.0", "127.0.0.1", "127.0.1.0", "127.0.1.1",
                "127.1.0.0", "127.1.0.1", "127.1.1.0", "127.1.1.1"};
        String[] loopbacks = {"localhost", "[::1]", "[::0]", "0.0.0.0",
                "127.0.0.0", "127.0.0.1", "127.0.1.0", "127.0.1.1",
                "127.1.0.0", "127.1.0.1", "127.1.1.0", "127.1.1.1"};
        for (String h : nonProxyHosts) {
            for (String s : loopbacks) {
                Map<String, String> properties = new HashMap<>();
                properties.put("http.proxyHost", "http://proxy.example.com");
                properties.put("http.nonProxyHosts", h);
                tests.add(new TestCase(properties, "http://" + s, false));
            }
        }
        return tests;
    }

    // unsorted tests
    private static Collection<TestCase> misc() {
        List<TestCase> t = new LinkedList<>();
        t.add(new TestCase("oracle.com", "http://137.254.16.101", true));
        t.add(new TestCase("google.com", "http://74.125.200.101", true));

        t.add(new TestCase("google.com|google.ie", "http://google.co.uk",
                true));
        t.add(new TestCase("google.com|google.ie", "http://google.com",
                false));
        t.add(new TestCase("google.com|google.ie", "http://google.ie",
                false));
        t.add(new TestCase("google.com|google.com|google.ie",
                "http://google.ie", false));

        t.add(new TestCase("google.com|bing.com|yahoo.com",
                "http://127.0.0.1", false));
        t.add(new TestCase("google.com|bing.com|yahoo.com",
                "http://google.com", false));
        t.add(new TestCase("google.com|bing.com|yahoo.com",
                "http://bing.com", false));
        t.add(new TestCase("google.com|bing.com|yahoo.com",
                "http://yahoo.com", false));

        t.add(new TestCase("google.com|bing.com", "http://google.com", false));
        t.add(new TestCase("google.com|bing.com", "http://bing.com", false));
        t.add(new TestCase("google.com|bing.com", "http://yahoo.com",
                true));
        t.add(new TestCase("google.com|bing.co*", "http://google.com", false));
        t.add(new TestCase("google.com|bing.co*", "http://bing.com", false));
        t.add(new TestCase("google.com|bing.co*", "http://yahoo.com",
                true));
        t.add(new TestCase("google.com|*ing.com", "http://google.com", false));
        t.add(new TestCase("google.com|*ing.com", "http://bing.com", false));
        t.add(new TestCase("google.com|*ing.com", "http://yahoo.com",
                true));
        t.add(new TestCase("google.co*|bing.com", "http://google.com", false));
        t.add(new TestCase("google.co*|bing.com", "http://bing.com", false));
        t.add(new TestCase("google.co*|bing.com", "http://yahoo.com",
                true));
        t.add(new TestCase("google.co*|bing.co*", "http://google.com", false));
        t.add(new TestCase("google.co*|bing.co*", "http://bing.com", false));
        t.add(new TestCase("google.co*|bing.co*", "http://yahoo.com",
                true));
        t.add(new TestCase("google.co*|*ing.com", "http://google.com", false));
        t.add(new TestCase("google.co*|*ing.com", "http://bing.com", false));
        t.add(new TestCase("google.co*|*ing.com", "http://yahoo.com",
                true));
        t.add(new TestCase("*oogle.com|bing.com", "http://google.com", false));
        t.add(new TestCase("*oogle.com|bing.com", "http://bing.com", false));
        t.add(new TestCase("*oogle.com|bing.com", "http://yahoo.com",
                true));
        t.add(new TestCase("*oogle.com|bing.co*", "http://google.com", false));
        t.add(new TestCase("*oogle.com|bing.co*", "http://bing.com", false));
        t.add(new TestCase("*oogle.com|bing.co*", "http://yahoo.com",
                true));
        t.add(new TestCase("*oogle.com|*ing.com", "http://google.com", false));
        t.add(new TestCase("*oogle.com|*ing.com", "http://bing.com", false));
        t.add(new TestCase("*oogle.com|*ing.com", "http://yahoo.com",
                true));

        t.add(new TestCase("google.com|bing.com|yahoo.com", "http://google.com", false));
        t.add(new TestCase("google.com|bing.com|yahoo.com", "http://bing.com", false));
        t.add(new TestCase("google.com|bing.com|yahoo.com", "http://yahoo.com", false));
        t.add(new TestCase("google.com|bing.com|yahoo.com",
                "http://duckduckgo.com", true));

        t.add(new TestCase("p-proxy.com", "http://p-proxy.com", false));
        t.add(new TestCase("google.co*|google.ie", "http://google.co.uk",
                false));

        t.add(new TestCase("*oracle.com", "http://my.oracle.com", false));
        t.add(new TestCase("google.com|bing.com|yahoo.com", "http://127.0.0.1", false));
        t.add(new TestCase("google.com|bing.com|yahoo.com", "http://yahoo.com", false));

        // example from
        // http://docs.oracle.com/javase/7/docs/technotes/guides/net/proxies.html
        t.add(new TestCase("localhost|host.example.com", "http://localhost",
                false));
        t.add(new TestCase("localhost|host.example.com",
                "http://host.example.com", false));
        t.add(new TestCase("localhost|host.example.com",
                "http://google.com", true));
        return t;
    }


    private static <T> T withSystemPropertiesSet(
            Map<String, String> localProperties,
            Callable<? extends T> code) {
        Map<String, String> backup = new HashMap<>();
        try {
            backupAndSetProperties(localProperties, backup);
            return code.call();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            restoreProperties(backup);
        }
    }

    private static void backupAndSetProperties(
            Map<String, String> localProperties,
            Map<String, String> oldProperties) {
        for (Map.Entry<String, String> e : localProperties.entrySet()) {
            String oldValue = System.setProperty(e.getKey(), e.getValue());
            oldProperties.put(e.getKey(), oldValue);
        }
    }

    private static void restoreProperties(Map<String, String> oldProperties) {
        for (Map.Entry<String, String> e : oldProperties.entrySet()) {
            String oldValue = e.getValue();
            String key = e.getKey();
            if (oldValue == null)
                System.getProperties().remove(key);
            else
                System.setProperty(key, oldValue);
        }
    }

    private static class TestCase {

        final Map<String, String> localProperties;
        final String urlhost;
        final boolean expectedProxying;

        TestCase(String nonProxyHosts, String urlhost,
                 boolean expectedProxying) {
            this(nonProxyHosts, "proxy.example.com", urlhost,
                    expectedProxying);
        }

        TestCase(String nonProxyHosts, String proxyHost, String urlhost,
                 boolean expectedProxying) {
            this(new HashMap<String, String>() {
                {
                    put("http.nonProxyHosts", nonProxyHosts);
                    put("http.proxyHost", proxyHost);
                }
            }, urlhost, expectedProxying);
        }

        TestCase(Map<String, String> localProperties, String urlhost,
                 boolean expectedProxying) {
            this.localProperties = localProperties;
            this.urlhost = urlhost;
            this.expectedProxying = expectedProxying;
        }

        void run() {
            System.out.printf("urlhost=%s properties=%s: proxied? %s%n",
                    urlhost, localProperties, expectedProxying);

            List<Proxy> proxies = withSystemPropertiesSet(localProperties,
                    () -> ProxySelector.getDefault().select(
                            URI.create(urlhost))
            );

            verify(proxies);
        }

        void verify(List<? extends Proxy> proxies) {

            boolean actualProxying = !(proxies.size() == 1 &&
                    proxies.get(0).type() == Proxy.Type.DIRECT);

            if (actualProxying != expectedProxying)
                throw new AssertionError(String.format(
                        "Expected %s connection for %s (given " +
                                "properties=%s). Here's the list of proxies " +
                                "returned: %s",
                        expectedProxying ? "proxied" : "direct", urlhost,
                        localProperties, proxies
                ));
        }
    }
}
