/*
 * Copyright 2004-2007 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

/**
 * @test
 * @bug 5026745
 * @run main/othervm/timeout=500 Test
 * @summary Cannot flush output stream when writing to an HttpUrlConnection
 */

import java.io.*;
import java.net.*;
import com.sun.net.httpserver.*;

public class Test implements HttpHandler {

    static int count = 0;

    static final String str1 = "Helloworld1234567890abcdefghijklmnopqrstuvwxyz"+
                                "1234567890abcdefkjsdlkjflkjsldkfjlsdkjflkj"+
                                "1434567890abcdefkjsdlkjflkjsldkfjlsdkjflkj";

    static final String str2 = "Helloworld1234567890abcdefghijklmnopqrstuvwxyz"+
                                "1234567890";

    public void handle(HttpExchange exchange) {
        String reqbody;
        try {
            switch (count) {
            case 0: /* test1 -- keeps conn alive */
            case 1: /* test2 -- closes conn */
                printRequestURI(exchange);
                reqbody = read(exchange.getRequestBody());
                if (!reqbody.equals(str1)) {
                    exchange.sendResponseHeaders(500, 0);
                    break;
                }

                Headers headers = exchange.getRequestHeaders();
                String chunk =  headers.getFirst("Transfer-encoding");

                if (!"chunked".equals (chunk)) {
                    exchange.sendResponseHeaders(501, 0);
                    break;
                }

                exchange.sendResponseHeaders(200, reqbody.length());
                write(exchange.getResponseBody(), reqbody);

                if (count == 1) {
                    Headers resHeaders = exchange.getResponseHeaders() ;
                    resHeaders.set("Connection", "close");
                }
                break;
            case 2: /* test 3 */
                printRequestURI(exchange);
                reqbody = read(exchange.getRequestBody());

                if (!reqbody.equals(str2)) {
                    exchange.sendResponseHeaders(500, 0);
                    break;
                }
                headers = exchange.getRequestHeaders();
                int clen = Integer.parseInt( headers.getFirst("Content-length"));

                if (clen != str2.length()) {
                    exchange.sendResponseHeaders(501, 0);
                    break;
                }
                Headers resHeaders = exchange.getResponseHeaders() ;
                resHeaders.set("Connection", "close");

                exchange.sendResponseHeaders(200, reqbody.length());
                write(exchange.getResponseBody(), reqbody);
                break;
            case 3: /* test 4 */
            case 4: /* test 5 */
                printRequestURI(exchange);
                break;
            case 5: /* test 6 */
                printRequestURI(exchange);
                resHeaders = exchange.getResponseHeaders() ;
                resHeaders.set("Location", "http://foo.bar/");
                resHeaders.set("Connection", "close");
                exchange.sendResponseHeaders(307, 0);
                break;
            case 6: /* test 7 */
            case 7: /* test 8 */
                printRequestURI(exchange);
                reqbody = read(exchange.getRequestBody());
                if (reqbody != null && !"".equals(reqbody)) {
                    exchange.sendResponseHeaders(501, 0);
                    break;
                }
                resHeaders = exchange.getResponseHeaders() ;
                resHeaders.set("Connection", "close");
                exchange.sendResponseHeaders(200, 0);
                break;
            case 8: /* test 9 */
                printRequestURI(exchange);
                reqbody = read(exchange.getRequestBody());
                if (!reqbody.equals(str1)) {
                    exchange.sendResponseHeaders(500, 0);
                    break;
                }

                headers = exchange.getRequestHeaders();
                chunk =  headers.getFirst("Transfer-encoding");
                if (!"chunked".equals(chunk)) {
                    exchange.sendResponseHeaders(501, 0);
                    break;
                }

                exchange.sendResponseHeaders(200, reqbody.length());
                write(exchange.getResponseBody(), reqbody);
                break;
            case 9: /* test10 */
                printRequestURI(exchange);
                InputStream is = exchange.getRequestBody();
                String s = read (is, str1.length());

                boolean error = false;
                for (int i=10; i< 200 * 1024; i++) {
                    byte c = (byte)is.read();

                    if (c != (byte)i) {
                        error = true;
                        System.out.println ("error at position " + i);
                    }
                }
                if (!s.equals(str1) ) {
                    System.out.println ("received string : " + s);
                    exchange.sendResponseHeaders(500, 0);
                } else if (error) {
                    System.out.println ("error");
                    exchange.sendResponseHeaders(500, 0);
                } else {
                    exchange.sendResponseHeaders(200, 0);
                }
                break;
            }
            exchange.close();
            count ++;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    static void printRequestURI(HttpExchange exchange) {
        URI uri = exchange.getRequestURI();
        System.out.println("HttpServer: handle " + uri);
    }


    static String read (InputStream is, int len) {
        try {
            byte[] ba = new byte [len];
            int c;
            int l = 0;
            while ((c= is.read(ba, l, ba.length-l)) != -1 && l<len)  {
                l += c;
            }
            return new String (ba, 0, l, "ISO8859-1");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    static String read(InputStream is) {
        try {
            byte[] ba = new byte [8096];
            int off = 0, c;
            while ((c= is.read(ba, off, ba.length)) != -1)  {
                off += c;
            }
            return new String(ba, 0, off, "ISO8859-1");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    static void write(OutputStream os, String str) {
        try {
            byte[] ba = str.getBytes("ISO8859-1");
            os.write(ba);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static void readAndCompare(InputStream is, String cmp) throws IOException {
        int c;
        byte buf[] = new byte [1024];
        int off = 0;
        int len = 1024;
        while ((c=is.read(buf, off, len)) != -1) {
            off += c;
            len -= c;
        }
        String s1 = new String(buf, 0, off, "ISO8859_1");
        if (!cmp.equals(s1)) {
            throw new IOException("strings not same");
        }
    }

    /* basic chunked test (runs twice) */

    static void test1 (String u) throws Exception {
        URL url = new URL (u);
        System.out.println ("client opening connection to: " + u);
        HttpURLConnection urlc = (HttpURLConnection)url.openConnection ();
        urlc.setChunkedStreamingMode (20);
        urlc.setDoOutput(true);
        urlc.setRequestMethod ("POST");
        OutputStream os = urlc.getOutputStream ();
        os.write (str1.getBytes());
        os.close();
        InputStream is = urlc.getInputStream();
        readAndCompare (is, str1);
        is.close();
    }

    /* basic fixed length test */

    static void test3 (String u) throws Exception {
        URL url = new URL (u);
        System.out.println ("client opening connection to: " + u);
        HttpURLConnection urlc = (HttpURLConnection)url.openConnection ();
        urlc.setFixedLengthStreamingMode (str2.length());
        urlc.setDoOutput(true);
        urlc.setRequestMethod ("POST");
        OutputStream os = urlc.getOutputStream ();
        os.write (str2.getBytes());
        os.close();
        InputStream is = urlc.getInputStream();
        readAndCompare (is, str2);
        is.close();
    }

    /* write too few bytes */

    static void test4 (String u) throws Exception {
        URL url = new URL (u);
        System.out.println ("client opening connection to: " + u);
        HttpURLConnection urlc = (HttpURLConnection)url.openConnection ();
        urlc.setFixedLengthStreamingMode (str2.length()+1);
        urlc.setDoOutput(true);
        urlc.setRequestMethod ("POST");
        OutputStream os = urlc.getOutputStream ();
        os.write (str2.getBytes());
        try {
            os.close();
            throw new Exception ("should have thrown IOException");
        } catch (IOException e) {}
    }

    /* write too many bytes */

    static void test5 (String u) throws Exception {
        URL url = new URL (u);
        System.out.println ("client opening connection to: " + u);
        HttpURLConnection urlc = (HttpURLConnection)url.openConnection ();
        urlc.setFixedLengthStreamingMode (str2.length()-1);
        urlc.setDoOutput(true);
        urlc.setRequestMethod ("POST");
        OutputStream os = urlc.getOutputStream ();
        try {
            os.write (str2.getBytes());
            throw new Exception ("should have thrown IOException");
        } catch (IOException e) {}
    }

    /* check for HttpRetryException on redirection */

    static void test6 (String u) throws Exception {
        URL url = new URL (u);
        System.out.println ("client opening connection to: " + u);
        HttpURLConnection urlc = (HttpURLConnection)url.openConnection ();
        urlc.setChunkedStreamingMode (20);
        urlc.setDoOutput(true);
        urlc.setRequestMethod ("POST");
        OutputStream os = urlc.getOutputStream ();
        os.write (str1.getBytes());
        os.close();
        try {
            InputStream is = urlc.getInputStream();
            throw new Exception ("should have gotten HttpRetryException");
        } catch (HttpRetryException e) {
            if (e.responseCode() != 307) {
                throw new Exception ("Wrong response code " + e.responseCode());
            }
            if (!e.getLocation().equals ("http://foo.bar/")) {
                throw new Exception ("Wrong location " + e.getLocation());
            }
        }
    }

    /* next two tests send zero length posts */

    static void test7 (String u) throws Exception {
        URL url = new URL (u);
        System.out.println ("client opening connection to: " + u);
        HttpURLConnection urlc = (HttpURLConnection)url.openConnection ();
        urlc.setChunkedStreamingMode (20);
        urlc.setDoOutput(true);
        urlc.setRequestMethod ("POST");
        OutputStream os = urlc.getOutputStream ();
        os.close();
        int ret = urlc.getResponseCode();
        if (ret != 200) {
            throw new Exception ("Expected 200: got " + ret);
        }
    }

    static void test8 (String u) throws Exception {
        URL url = new URL (u);
        System.out.println ("client opening connection to: " + u);
        HttpURLConnection urlc = (HttpURLConnection)url.openConnection ();
        urlc.setFixedLengthStreamingMode (0);
        urlc.setDoOutput(true);
        urlc.setRequestMethod ("POST");
        OutputStream os = urlc.getOutputStream ();
        os.close();
        int ret = urlc.getResponseCode();
        if (ret != 200) {
            throw new Exception ("Expected 200: got " + ret);
        }
    }

    /* calling setChunkedStreamingMode with -1 should entail using
       the default chunk size */
   static void test9 (String u) throws Exception {
        URL url = new URL (u);
        System.out.println ("client opening connection to: " + u);
        HttpURLConnection urlc = (HttpURLConnection)url.openConnection ();
        urlc.setChunkedStreamingMode (-1);
        urlc.setDoOutput(true);
        urlc.setRequestMethod ("POST");
        OutputStream os = urlc.getOutputStream ();
        os.write (str1.getBytes());
        os.close();
        InputStream is = urlc.getInputStream();
        readAndCompare (is, str1);
        is.close();
    }

   static void test10 (String u) throws Exception {
        URL url = new URL (u);
        System.out.println ("client opening connection to: " + u);
        HttpURLConnection urlc = (HttpURLConnection)url.openConnection ();
        urlc.setChunkedStreamingMode (4 * 1024);
        urlc.setDoOutput(true);
        urlc.setRequestMethod ("POST");
        OutputStream os = urlc.getOutputStream ();
        byte[] buf = new byte [200 * 1024];
        for (int i=0; i< 200 * 1024; i++) {
            buf[i] = (byte) i;
        }
        /* write a small bit first, and then the large buffer */
        os.write (str1.getBytes());
        os.write (buf, 10, buf.length - 10); /* skip 10 bytes to test offset */
        os.close();
        InputStream is = urlc.getInputStream();
        is.close();
        int ret = urlc.getResponseCode();
        if (ret != 200) {
            throw new Exception ("Expected 200: got " + ret);
        }
    }

    static com.sun.net.httpserver.HttpServer httpserver;

    public static void main (String[] args) throws Exception {
        try {
            httpserver = com.sun.net.httpserver.HttpServer.create(new InetSocketAddress(0), 0);
            HttpContext ctx = httpserver.createContext("/test/", new Test() );
            httpserver.start();

            int port = httpserver.getAddress().getPort();

            System.out.println ("Server started: listening on port: " + port);
            test1("http://localhost:"+ port + "/test/test1");
            test1("http://localhost:"+ port + "/test/test2");
            test3("http://localhost:"+ port + "/test/test3");
            test4("http://localhost:"+ port + "/test/test4");
            test5("http://localhost:"+ port + "/test/test5");
            test6("http://localhost:"+ port + "/test/test6");
            test7("http://localhost:"+ port + "/test/test7");
            test8("http://localhost:"+ port + "/test/test8");
            test9("http://localhost:"+ port + "/test/test9");
            test10("http://localhost:"+ port + "/test/test10");
        } finally {
            if (httpserver != null)
                httpserver.stop(0);
        }
    }

}
