/*
 * 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
                ));
        }
    }
}
