0N/A/*
2362N/A * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation.
0N/A *
2362N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
0N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
0N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
2362N/A */
2362N/A
0N/A/**
0N/A * @test
0N/A * @bug 4769350
0N/A * @library ../../../sun/net/www/httptest/
0N/A * @build HttpCallback HttpServer ClosedChannelList HttpTransaction AbstractCallback
0N/A * @run main/othervm B4769350 server
0N/A * @run main/othervm B4769350 proxy
0N/A * @summary proxy authentication username and password caching only works in serial case
0N/A * Run in othervm since the test sets system properties that are read by the
0N/A * networking stack and cached when the HTTP handler is invoked, and previous
0N/A * tests may already have invoked the HTTP handler.
0N/A */
0N/A
0N/Aimport java.io.*;
0N/Aimport java.net.*;
0N/A
0N/Apublic class B4769350 {
0N/A
0N/A static int count = 0;
0N/A static boolean error = false;
0N/A
0N/A static void read (InputStream is) throws IOException {
0N/A int c;
0N/A while ((c=is.read()) != -1) {
0N/A //System.out.write (c);
0N/A }
0N/A }
0N/A
0N/A static class Client extends Thread {
0N/A String authority, path;
0N/A boolean allowerror;
0N/A
0N/A Client (String authority, String path, boolean allowerror) {
0N/A super("Thread-" + path);
0N/A this.authority = authority;
0N/A this.path = path;
0N/A this.allowerror = allowerror;
0N/A }
0N/A
0N/A public void run () {
0N/A try {
0N/A URI u = new URI ("http", authority, path, null, null);
0N/A URL url = u.toURL();
0N/A URLConnection urlc = url.openConnection ();
0N/A InputStream is = urlc.getInputStream ();
0N/A read (is);
0N/A is.close();
0N/A } catch (URISyntaxException e) {
0N/A System.out.println (e);
0N/A error = true;
0N/A } catch (IOException e) {
0N/A if (!allowerror) {
0N/A System.out.println (Thread.currentThread().getName() + " " + e);
0N/A e.printStackTrace();
0N/A error = true;
0N/A }
0N/A }
0N/A }
0N/A }
0N/A
0N/A static class CallBack extends AbstractCallback {
0N/A
0N/A void errorReply (HttpTransaction req, String reply) throws IOException {
0N/A req.addResponseHeader ("Connection", "close");
0N/A req.addResponseHeader ("WWW-Authenticate", reply);
0N/A req.sendResponse (401, "Unauthorized");
0N/A req.orderlyClose();
0N/A }
0N/A
0N/A void proxyReply (HttpTransaction req, String reply) throws IOException {
0N/A req.addResponseHeader ("Proxy-Authenticate", reply);
0N/A req.sendResponse (407, "Proxy Authentication Required");
0N/A }
0N/A
0N/A void okReply (HttpTransaction req) throws IOException {
0N/A req.addResponseHeader ("Connection", "close");
0N/A req.setResponseEntityBody ("Hello .");
0N/A req.sendResponse (200, "Ok");
0N/A req.orderlyClose();
0N/A }
0N/A
0N/A public void request (HttpTransaction req, int count) {
0N/A try {
0N/A URI uri = req.getRequestURI();
0N/A String path = uri.getPath();
0N/A if (path.endsWith ("/t1a")) {
0N/A doT1a (req, count);
0N/A } else if (path.endsWith ("/t1b")) {
0N/A doT1b (req, count);
0N/A } else if (path.endsWith ("/t1c")) {
0N/A doT1c (req, count);
0N/A } else if (path.endsWith ("/t1d")) {
0N/A doT1d (req, count);
0N/A } else if (path.endsWith ("/t2a")) {
0N/A doT2a (req, count);
0N/A } else if (path.endsWith ("/t2b")) {
0N/A doT2b (req, count);
0N/A } else if (path.endsWith ("/t3a")) {
0N/A doT3a (req, count);
0N/A } else if (path.endsWith ("/t3b")) {
0N/A doT3bc (req, count);
0N/A } else if (path.endsWith ("/t3c")) {
0N/A doT3bc (req, count);
0N/A } else {
0N/A System.out.println ("unexpected request URI");
0N/A }
0N/A } catch (IOException e) {
0N/A e.printStackTrace();
0N/A }
0N/A }
0N/A
0N/A /* T1 tests the client by sending 4 requests to 2 different realms
0N/A * in parallel. The client should recognise two pairs of dependent requests
0N/A * and execute the first of each pair in parallel. When they both succeed
0N/A * the second requests should be executed without calling the authenticator.
0N/A * The test succeeds if the authenticator was only called twice.
0N/A */
0N/A void doT1a (HttpTransaction req, int count) throws IOException {
0N/A switch (count) {
0N/A case 0:
0N/A errorReply (req, "Basic realm=\"realm1\"");
0N/A HttpServer.rendezvous ("one", 2);
0N/A break;
0N/A case 1:
0N/A HttpServer.waitForCondition ("cond2");
0N/A okReply (req);
0N/A break;
0N/A default:
0N/A System.out.println ("Unexpected request");
0N/A }
0N/A }
0N/A
0N/A
0N/A void doT1b (HttpTransaction req, int count) throws IOException {
0N/A switch (count) {
0N/A case 0:
0N/A errorReply (req, "Basic realm=\"realm2\"");
0N/A HttpServer.rendezvous ("one", 2);
0N/A HttpServer.setCondition ("cond1");
0N/A break;
0N/A case 1:
0N/A HttpServer.waitForCondition ("cond2");
0N/A okReply (req);
0N/A break;
0N/A default:
0N/A System.out.println ("Unexpected request");
0N/A }
0N/A }
0N/A
0N/A void doT1c (HttpTransaction req, int count) throws IOException {
0N/A switch (count) {
0N/A case 0:
0N/A errorReply (req, "Basic realm=\"realm1\"");
0N/A HttpServer.rendezvous ("two", 2);
0N/A break;
0N/A case 1:
0N/A okReply (req);
0N/A break;
0N/A default:
0N/A System.out.println ("Unexpected request");
0N/A }
0N/A }
0N/A
0N/A void doT1d (HttpTransaction req, int count) throws IOException {
0N/A switch (count) {
0N/A case 0:
0N/A errorReply (req, "Basic realm=\"realm2\"");
0N/A HttpServer.rendezvous ("two", 2);
0N/A HttpServer.setCondition ("cond2");
0N/A break;
0N/A case 1:
0N/A okReply (req);
0N/A break;
0N/A default:
0N/A System.out.println ("Unexpected request");
0N/A }
0N/A }
0N/A
0N/A
0N/A /* T2 tests to check that if initial authentication fails, the second will
0N/A * succeed, and the authenticator is called twice
0N/A */
0N/A
0N/A void doT2a (HttpTransaction req, int count) throws IOException {
0N/A /* This will be called several times */
0N/A if (count == 1) {
0N/A HttpServer.setCondition ("T2cond1");
0N/A }
0N/A errorReply (req, "Basic realm=\"realm3\"");
0N/A }
0N/A
0N/A void doT2b (HttpTransaction req, int count) throws IOException {
0N/A switch (count) {
0N/A case 0:
0N/A errorReply (req, "Basic realm=\"realm3\"");
0N/A break;
0N/A case 1:
0N/A okReply (req);
0N/A break;
0N/A default:
0N/A System.out.println ("Unexpected request");
0N/A }
0N/A }
0N/A
0N/A /* T3 tests proxy and server authentication. three threads request same
0N/A * resource at same time. Authenticator should be called once for server
0N/A * and once for proxy
0N/A */
0N/A void doT3a (HttpTransaction req, int count) throws IOException {
0N/A switch (count) {
0N/A case 0:
0N/A proxyReply (req, "Basic realm=\"proxy\"");
0N/A HttpServer.setCondition ("T3cond1");
0N/A break;
0N/A case 1:
0N/A errorReply (req, "Basic realm=\"realm4\"");
0N/A break;
0N/A case 2:
0N/A okReply (req);
0N/A break;
0N/A default:
0N/A System.out.println ("Unexpected request");
0N/A }
0N/A }
0N/A
0N/A void doT3bc (HttpTransaction req, int count) throws IOException {
0N/A switch (count) {
0N/A case 0:
0N/A proxyReply (req, "Basic realm=\"proxy\"");
0N/A break;
0N/A case 1:
0N/A okReply (req);
0N/A break;
0N/A default:
0N/A System.out.println ("Unexpected request");
0N/A }
0N/A }
0N/A };
0N/A
0N/A static HttpServer server;
0N/A static MyAuthenticator auth = new MyAuthenticator ();
0N/A
0N/A static int redirects = 4;
0N/A
0N/A static Client c1,c2,c3,c4,c5,c6,c7,c8,c9;
0N/A
0N/A static void doServerTests (String authority) throws Exception {
0N/A System.out.println ("Doing Server tests");
0N/A System.out.println ("T1");
0N/A c1 = new Client (authority, "/test/realm1/t1a", false);
0N/A c2 = new Client (authority, "/test/realm2/t1b", false);
0N/A c3 = new Client (authority, "/test/realm1/t1c", false);
0N/A c4 = new Client (authority, "/test/realm2/t1d", false);
0N/A
0N/A c1.start(); c2.start();
0N/A HttpServer.waitForCondition ("cond1");
0N/A c3.start(); c4.start();
0N/A c1.join(); c2.join(); c3.join(); c4.join();
0N/A
0N/A int f = auth.getCount();
0N/A if (f != 2) {
0N/A except ("Authenticator was called "+f+" times. Should be 2");
0N/A }
0N/A if (error) {
0N/A except ("error occurred");
0N/A }
0N/A
0N/A auth.resetCount();
0N/A System.out.println ("T2");
0N/A
0N/A c5 = new Client (authority, "/test/realm3/t2a", true);
0N/A c6 = new Client (authority, "/test/realm3/t2b", false);
0N/A c5.start ();
0N/A HttpServer.waitForCondition ("T2cond1");
0N/A c6.start ();
0N/A c5.join(); c6.join();
0N/A
0N/A f = auth.getCount();
0N/A if (f != redirects+1) {
0N/A except ("Authenticator was called "+f+" times. Should be: " + redirects+1);
0N/A }
0N/A if (error) {
0N/A except ("error occurred");
0N/A }
0N/A }
0N/A
0N/A static void doProxyTests (String authority) throws Exception {
0N/A System.out.println ("Doing Proxy tests");
0N/A c7 = new Client (authority, "/test/realm4/t3a", false);
0N/A c8 = new Client (authority, "/test/realm4/t3b", false);
0N/A c9 = new Client (authority, "/test/realm4/t3c", false);
0N/A c7.start ();
0N/A HttpServer.waitForCondition ("T3cond1");
0N/A c8.start ();
0N/A c9.start ();
0N/A c7.join(); c8.join(); c9.join();
0N/A
0N/A int f = auth.getCount();
0N/A if (f != 2) {
0N/A except ("Authenticator was called "+f+" times. Should be: " + 2);
0N/A }
0N/A if (error) {
0N/A except ("error occurred");
0N/A }
0N/A }
0N/A
0N/A public static void main (String[] args) throws Exception {
0N/A System.setProperty ("http.maxRedirects", Integer.toString (redirects));
0N/A System.setProperty ("http.auth.serializeRequests", "true");
0N/A Authenticator.setDefault (auth);
0N/A boolean proxy = args[0].equals ("proxy");
0N/A try {
0N/A server = new HttpServer (new CallBack(), 10, 1, 0);
0N/A System.out.println ("Server: listening on port: " + server.getLocalPort());
0N/A if (proxy) {
0N/A System.setProperty ("http.proxyHost", "localhost");
0N/A System.setProperty ("http.proxyPort",Integer.toString(server.getLocalPort()));
0N/A doProxyTests ("www.foo.com");
0N/A } else {
0N/A doServerTests ("localhost:"+server.getLocalPort());
0N/A }
0N/A server.terminate();
0N/A
0N/A } catch (Exception e) {
0N/A if (server != null) {
0N/A server.terminate();
0N/A }
0N/A throw e;
0N/A }
0N/A }
0N/A
0N/A static void pause (int millis) {
0N/A try {
0N/A Thread.sleep (millis);
0N/A } catch (InterruptedException e) {}
0N/A }
0N/A
0N/A public static void except (String s) {
0N/A server.terminate();
0N/A throw new RuntimeException (s);
0N/A }
0N/A
0N/A static class MyAuthenticator extends Authenticator {
0N/A MyAuthenticator () {
0N/A super ();
0N/A }
0N/A
0N/A int count = 0;
0N/A
0N/A public PasswordAuthentication getPasswordAuthentication () {
0N/A //System.out.println ("Authenticator called: " + getRequestingPrompt());
0N/A //try {
0N/A //Thread.sleep (1000);
0N/A //} catch (InterruptedException e) {}
0N/A PasswordAuthentication pw;
0N/A pw = new PasswordAuthentication ("user", "pass1".toCharArray());
0N/A count ++;
0N/A return pw;
0N/A }
0N/A
0N/A public void resetCount () {
0N/A count = 0;
0N/A }
0N/A
0N/A public int getCount () {
0N/A return (count);
0N/A }
0N/A }
0N/A}
0N/A