1/* 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18package org.apache.harmony.luni.tests.internal.net.www.protocol.https; 19 20import java.io.File; 21import java.io.FileInputStream; 22import java.io.FileNotFoundException; 23import java.io.IOException; 24import java.io.InputStream; 25import java.io.OutputStream; 26import java.io.PrintStream; 27import java.net.Authenticator; 28import java.net.HttpURLConnection; 29import java.net.InetSocketAddress; 30import java.net.PasswordAuthentication; 31import java.net.Proxy; 32import java.net.ServerSocket; 33import java.net.Socket; 34import java.net.SocketTimeoutException; 35import java.net.URL; 36import java.security.KeyStore; 37import java.security.cert.Certificate; 38import java.util.Arrays; 39 40import javax.net.ssl.HostnameVerifier; 41import javax.net.ssl.HttpsURLConnection; 42import javax.net.ssl.KeyManagerFactory; 43import javax.net.ssl.SSLContext; 44import javax.net.ssl.SSLServerSocket; 45import javax.net.ssl.SSLSession; 46import javax.net.ssl.SSLSocket; 47import javax.net.ssl.SSLSocketFactory; 48import javax.net.ssl.TrustManagerFactory; 49 50import junit.framework.AssertionFailedError; 51import junit.framework.TestCase; 52import junit.framework.TestSuite; 53 54/** 55 * Implementation independent test for HttpsURLConnection. The test needs 56 * certstore file placed in system classpath and named as "key_store." + the 57 * type of the default KeyStore installed in the system in lower case. <br> 58 * For example: if default KeyStore type in the system is BKS (i.e. 59 * java.security file sets up the property keystore.type=BKS), thus classpath 60 * should point to the directory with "key_store.bks" file. <br> 61 * This certstore file should contain self-signed certificate generated by 62 * keytool utility in a usual way. <br> 63 * The password to the certstore should be "password" (without quotes). 64 */ 65public class HttpsURLConnectionTest extends TestCase { 66 67 // the password to the store 68 private static final String KS_PASSWORD = "password"; 69 70 // turn on/off logging 71 private static final boolean DO_LOG = false; 72 73 // read/connection timeout value 74 private static final int TIMEOUT = 5000; 75 76 // OK response code 77 private static final int OK_CODE = 200; 78 79 // Not Found response code 80 private static final int NOT_FOUND_CODE = 404; 81 82 // Proxy authentication required response code 83 private static final int AUTHENTICATION_REQUIRED_CODE = 407; 84 85 // fields keeping the system values of corresponding properties 86 private static String systemKeyStoreType; 87 88 private static String systemKeyStore; 89 90 private static String systemKeyStorePassword; 91 92 private static String systemTrustStoreType; 93 94 private static String systemTrustStore; 95 96 private static String systemTrustStorePassword; 97 98 /** 99 * Checks that HttpsURLConnection's default SSLSocketFactory is operable. 100 */ 101 public void testGetDefaultSSLSocketFactory() throws Exception { 102 // set up the properties defining the default values needed by SSL stuff 103 setUpStoreProperties(); 104 105 try { 106 SSLSocketFactory defaultSSLSF = HttpsURLConnection 107 .getDefaultSSLSocketFactory(); 108 ServerSocket ss = new ServerSocket(0); 109 Socket s = defaultSSLSF 110 .createSocket("localhost", ss.getLocalPort()); 111 ss.accept(); 112 s.close(); 113 ss.close(); 114 } finally { 115 // roll the properties back to system values 116 tearDownStoreProperties(); 117 } 118 } 119 120 /** 121 * Checks if HTTPS connection performs initial SSL handshake with the server 122 * working over SSL, sends encrypted HTTP request, and receives expected 123 * HTTP response. After HTTPS session if finished test checks connection 124 * state parameters established by HttpsURLConnection. 125 */ 126 public void testHttpsConnection() throws Throwable { 127 // set up the properties defining the default values needed by SSL stuff 128 setUpStoreProperties(); 129 130 try { 131 // create the SSL server socket acting as a server 132 SSLContext ctx = getContext(); 133 ServerSocket ss = ctx.getServerSocketFactory() 134 .createServerSocket(0); 135 136 // create the HostnameVerifier to check hostname verification 137 TestHostnameVerifier hnv = new TestHostnameVerifier(); 138 HttpsURLConnection.setDefaultHostnameVerifier(hnv); 139 140 // create url connection to be tested 141 URL url = new URL("https://localhost:" + ss.getLocalPort()); 142 HttpsURLConnection connection = (HttpsURLConnection) url 143 .openConnection(); 144 145 // perform the interaction between the peers 146 SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss); 147 148 // check the connection state 149 checkConnectionStateParameters(connection, peerSocket); 150 151 // should silently exit 152 connection.connect(); 153 } finally { 154 // roll the properties back to system values 155 tearDownStoreProperties(); 156 } 157 } 158 159 /** 160 * Checks if HTTPS connection performs initial SSL handshake with the server 161 * working over SSL, sends encrypted HTTP request, and receives expected 162 * HTTP response. After that it checks that the established connection is 163 * persistent. After HTTPS session if finished test checks connection state 164 * parameters established by HttpsURLConnection. 165 */ 166 public void testHttpsPersistentConnection() throws Throwable { 167 // set up the properties defining the default values needed by SSL stuff 168 setUpStoreProperties(); 169 170 try { 171 // create the SSL server socket acting as a server 172 SSLContext ctx = getContext(); 173 ServerSocket ss = ctx.getServerSocketFactory() 174 .createServerSocket(0); 175 176 // create the HostnameVerifier to check hostname verification 177 TestHostnameVerifier hnv = new TestHostnameVerifier(); 178 HttpsURLConnection.setDefaultHostnameVerifier(hnv); 179 180 // create url connection to be tested 181 URL url = new URL("https://localhost:" + ss.getLocalPort()); 182 HttpsURLConnection connection = (HttpsURLConnection) url 183 .openConnection(); 184 185 // perform the interaction between the peers 186 SSLSocket peerSocket = (SSLSocket) doPersistentInteraction( 187 connection, ss); 188 189 // check the connection state 190 checkConnectionStateParameters(connection, peerSocket); 191 192 // should silently exit 193 connection.connect(); 194 } finally { 195 // roll the properties back to system values 196 tearDownStoreProperties(); 197 } 198 } 199 200 /** 201 * Tests the behaviour of HTTPS connection in case of unavailability of 202 * requested resource. 203 */ 204 public void testHttpsConnection_Not_Found_Response() throws Throwable { 205 // set up the properties defining the default values needed by SSL stuff 206 setUpStoreProperties(); 207 208 try { 209 // create the SSL server socket acting as a server 210 SSLContext ctx = getContext(); 211 ServerSocket ss = ctx.getServerSocketFactory() 212 .createServerSocket(0); 213 214 // create the HostnameVerifier to check hostname verification 215 TestHostnameVerifier hnv = new TestHostnameVerifier(); 216 HttpsURLConnection.setDefaultHostnameVerifier(hnv); 217 218 // create url connection to be tested 219 URL url = new URL("https://localhost:" + ss.getLocalPort()); 220 HttpsURLConnection connection = (HttpsURLConnection) url 221 .openConnection(); 222 223 try { 224 doInteraction(connection, ss, NOT_FOUND_CODE); 225 fail("Expected exception was not thrown."); 226 } catch (FileNotFoundException e) { 227 if (DO_LOG) { 228 System.out.println("Expected exception was thrown: " 229 + e.getMessage()); 230 } 231 } 232 233 // should silently exit 234 connection.connect(); 235 } finally { 236 // roll the properties back to system values 237 tearDownStoreProperties(); 238 } 239 } 240 241 /** 242 * Tests possibility to set up the default SSLSocketFactory to be used by 243 * HttpsURLConnection. 244 */ 245 public void testSetDefaultSSLSocketFactory() throws Throwable { 246 // create the SSLServerSocket which will be used by server side 247 SSLContext ctx = getContext(); 248 SSLServerSocket ss = (SSLServerSocket) ctx.getServerSocketFactory() 249 .createServerSocket(0); 250 251 SSLSocketFactory socketFactory = (SSLSocketFactory) ctx 252 .getSocketFactory(); 253 // set up the factory as default 254 HttpsURLConnection.setDefaultSSLSocketFactory(socketFactory); 255 // check the result 256 assertSame("Default SSLSocketFactory differs from expected", 257 socketFactory, HttpsURLConnection.getDefaultSSLSocketFactory()); 258 259 // create the HostnameVerifier to check hostname verification 260 TestHostnameVerifier hnv = new TestHostnameVerifier(); 261 HttpsURLConnection.setDefaultHostnameVerifier(hnv); 262 263 // create HttpsURLConnection to be tested 264 URL url = new URL("https://localhost:" + ss.getLocalPort()); 265 HttpsURLConnection connection = (HttpsURLConnection) url 266 .openConnection(); 267 268 TestHostnameVerifier hnv_late = new TestHostnameVerifier(); 269 // late initialization: should not be used for created connection 270 HttpsURLConnection.setDefaultHostnameVerifier(hnv_late); 271 272 // perform the interaction between the peers 273 SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss); 274 // check the connection state 275 checkConnectionStateParameters(connection, peerSocket); 276 // check the verification process 277 assertTrue("Hostname verification was not done", hnv.verified); 278 assertFalse( 279 "Hostname verification should not be done by this verifier", 280 hnv_late.verified); 281 // check the used SSLSocketFactory 282 assertSame("Default SSLSocketFactory should be used", 283 HttpsURLConnection.getDefaultSSLSocketFactory(), connection 284 .getSSLSocketFactory()); 285 286 // should silently exit 287 connection.connect(); 288 } 289 290 /** 291 * Tests possibility to set up the SSLSocketFactory to be used by 292 * HttpsURLConnection. 293 */ 294 public void testSetSSLSocketFactory() throws Throwable { 295 // create the SSLServerSocket which will be used by server side 296 SSLContext ctx = getContext(); 297 SSLServerSocket ss = (SSLServerSocket) ctx.getServerSocketFactory() 298 .createServerSocket(0); 299 300 // create the HostnameVerifier to check hostname verification 301 TestHostnameVerifier hnv = new TestHostnameVerifier(); 302 HttpsURLConnection.setDefaultHostnameVerifier(hnv); 303 304 // create HttpsURLConnection to be tested 305 URL url = new URL("https://localhost:" + ss.getLocalPort()); 306 HttpsURLConnection connection = (HttpsURLConnection) url 307 .openConnection(); 308 309 SSLSocketFactory socketFactory = (SSLSocketFactory) ctx 310 .getSocketFactory(); 311 connection.setSSLSocketFactory(socketFactory); 312 313 TestHostnameVerifier hnv_late = new TestHostnameVerifier(); 314 // late initialization: should not be used for created connection 315 HttpsURLConnection.setDefaultHostnameVerifier(hnv_late); 316 317 // perform the interaction between the peers 318 SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss); 319 // check the connection state 320 checkConnectionStateParameters(connection, peerSocket); 321 // check the verification process 322 assertTrue("Hostname verification was not done", hnv.verified); 323 assertFalse( 324 "Hostname verification should not be done by this verifier", 325 hnv_late.verified); 326 // check the used SSLSocketFactory 327 assertNotSame("Default SSLSocketFactory should not be used", 328 HttpsURLConnection.getDefaultSSLSocketFactory(), connection 329 .getSSLSocketFactory()); 330 assertSame("Result differs from expected", socketFactory, connection 331 .getSSLSocketFactory()); 332 333 // should silently exit 334 connection.connect(); 335 } 336 337 /** 338 * Tests the behaviour of HttpsURLConnection in case of retrieving of the 339 * connection state parameters before connection has been made. 340 */ 341 public void testUnconnectedStateParameters() throws Throwable { 342 // create HttpsURLConnection to be tested 343 URL url = new URL("https://localhost:55555"); 344 HttpsURLConnection connection = (HttpsURLConnection) url 345 .openConnection(); 346 347 try { 348 connection.getCipherSuite(); 349 fail("Expected IllegalStateException was not thrown"); 350 } catch (IllegalStateException e) { 351 } 352 try { 353 connection.getPeerPrincipal(); 354 fail("Expected IllegalStateException was not thrown"); 355 } catch (IllegalStateException e) { 356 } 357 try { 358 connection.getLocalPrincipal(); 359 fail("Expected IllegalStateException was not thrown"); 360 } catch (IllegalStateException e) { 361 } 362 363 try { 364 connection.getServerCertificates(); 365 fail("Expected IllegalStateException was not thrown"); 366 } catch (IllegalStateException e) { 367 } 368 try { 369 connection.getLocalCertificates(); 370 fail("Expected IllegalStateException was not thrown"); 371 } catch (IllegalStateException e) { 372 } 373 } 374 375 /** 376 * Tests if setHostnameVerifier() method replaces default verifier. 377 */ 378 public void testSetHostnameVerifier() throws Throwable { 379 // setting up the properties pointing to the key/trust stores 380 setUpStoreProperties(); 381 382 try { 383 // create the SSLServerSocket which will be used by server side 384 SSLServerSocket ss = (SSLServerSocket) getContext() 385 .getServerSocketFactory().createServerSocket(0); 386 387 // create the HostnameVerifier to check that Hostname verification 388 // is done 389 TestHostnameVerifier hnv = new TestHostnameVerifier(); 390 HttpsURLConnection.setDefaultHostnameVerifier(hnv); 391 392 // create HttpsURLConnection to be tested 393 URL url = new URL("https://localhost:" + ss.getLocalPort()); 394 HttpsURLConnection connection = (HttpsURLConnection) url 395 .openConnection(); 396 397 TestHostnameVerifier hnv_late = new TestHostnameVerifier(); 398 // replace default verifier 399 connection.setHostnameVerifier(hnv_late); 400 401 // perform the interaction between the peers and check the results 402 SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss); 403 assertTrue("Hostname verification was not done", hnv_late.verified); 404 assertFalse( 405 "Hostname verification should not be done by this verifier", 406 hnv.verified); 407 checkConnectionStateParameters(connection, peerSocket); 408 409 // should silently exit 410 connection.connect(); 411 } finally { 412 // roll the properties back to system values 413 tearDownStoreProperties(); 414 } 415 } 416 417 /** 418 * Tests the behaviour in case of sending the data to the server. 419 */ 420 public void test_doOutput() throws Throwable { 421 // setting up the properties pointing to the key/trust stores 422 setUpStoreProperties(); 423 424 try { 425 // create the SSLServerSocket which will be used by server side 426 SSLServerSocket ss = (SSLServerSocket) getContext() 427 .getServerSocketFactory().createServerSocket(0); 428 429 // create the HostnameVerifier to check that Hostname verification 430 // is done 431 TestHostnameVerifier hnv = new TestHostnameVerifier(); 432 HttpsURLConnection.setDefaultHostnameVerifier(hnv); 433 434 // create HttpsURLConnection to be tested 435 URL url = new URL("https://localhost:" + ss.getLocalPort()); 436 HttpsURLConnection connection = (HttpsURLConnection) url 437 .openConnection(); 438 connection.setDoOutput(true); 439 440 // perform the interaction between the peers and check the results 441 SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss); 442 checkConnectionStateParameters(connection, peerSocket); 443 444 // should silently exit 445 connection.connect(); 446 } finally { 447 // roll the properties back to system values 448 tearDownStoreProperties(); 449 } 450 } 451 452 /** 453 * Tests the behaviour in case of sending the data to the server over 454 * persistent connection. 455 */ 456 public void testPersistence_doOutput() throws Throwable { 457 // setting up the properties pointing to the key/trust stores 458 setUpStoreProperties(); 459 460 try { 461 // create the SSLServerSocket which will be used by server side 462 SSLServerSocket ss = (SSLServerSocket) getContext() 463 .getServerSocketFactory().createServerSocket(0); 464 465 // create the HostnameVerifier to check that Hostname verification 466 // is done 467 TestHostnameVerifier hnv = new TestHostnameVerifier(); 468 HttpsURLConnection.setDefaultHostnameVerifier(hnv); 469 470 // create HttpsURLConnection to be tested 471 URL url = new URL("https://localhost:" + ss.getLocalPort()); 472 HttpsURLConnection connection = (HttpsURLConnection) url 473 .openConnection(); 474 connection.setDoOutput(true); 475 476 // perform the interaction between the peers and check the results 477 SSLSocket peerSocket = (SSLSocket) doPersistentInteraction( 478 connection, ss); 479 checkConnectionStateParameters(connection, peerSocket); 480 481 // should silently exit 482 connection.connect(); 483 } finally { 484 // roll the properties back to system values 485 tearDownStoreProperties(); 486 } 487 } 488 489 /** 490 * Tests HTTPS connection process made through the proxy server. 491 */ 492 public void testProxyConnection() throws Throwable { 493 // setting up the properties pointing to the key/trust stores 494 setUpStoreProperties(); 495 496 try { 497 // create the SSLServerSocket which will be used by server side 498 ServerSocket ss = new ServerSocket(0); 499 500 // create the HostnameVerifier to check that Hostname verification 501 // is done 502 TestHostnameVerifier hnv = new TestHostnameVerifier(); 503 HttpsURLConnection.setDefaultHostnameVerifier(hnv); 504 505 // create HttpsURLConnection to be tested 506 URL url = new URL("https://requested.host:55556/requested.data"); 507 HttpsURLConnection connection = (HttpsURLConnection) url 508 .openConnection(new Proxy(Proxy.Type.HTTP, 509 new InetSocketAddress("localhost", ss 510 .getLocalPort()))); 511 512 // perform the interaction between the peers and check the results 513 SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss); 514 checkConnectionStateParameters(connection, peerSocket); 515 516 // should silently exit 517 connection.connect(); 518 } finally { 519 // roll the properties back to system values 520 tearDownStoreProperties(); 521 } 522 } 523 524 /** 525 * Tests HTTPS connection process made through the proxy server. Checks that 526 * persistent connection to the host exists and can be used no in spite of 527 * explicit Proxy specifying. 528 */ 529 public void testPersistentProxyConnection() throws Throwable { 530 // setting up the properties pointing to the key/trust stores 531 setUpStoreProperties(); 532 533 try { 534 // create the SSLServerSocket which will be used by server side 535 ServerSocket ss = new ServerSocket(0); 536 537 // create the HostnameVerifier to check that Hostname verification 538 // is done 539 TestHostnameVerifier hnv = new TestHostnameVerifier(); 540 HttpsURLConnection.setDefaultHostnameVerifier(hnv); 541 542 // create HttpsURLConnection to be tested 543 URL url = new URL("https://requested.host:55556/requested.data"); 544 HttpsURLConnection connection = (HttpsURLConnection) url 545 .openConnection(new Proxy(Proxy.Type.HTTP, 546 new InetSocketAddress("localhost", ss 547 .getLocalPort()))); 548 549 // perform the interaction between the peers and check the results 550 SSLSocket peerSocket = (SSLSocket) doPersistentInteraction( 551 connection, ss); 552 checkConnectionStateParameters(connection, peerSocket); 553 554 // should silently exit 555 connection.connect(); 556 } finally { 557 // roll the properties back to system values 558 tearDownStoreProperties(); 559 } 560 } 561 562 /** 563 * Tests HTTPS connection process made through the proxy server. Proxy 564 * server needs authentication. 565 */ 566 public void testProxyAuthConnection() throws Throwable { 567 // setting up the properties pointing to the key/trust stores 568 setUpStoreProperties(); 569 570 try { 571 // create the SSLServerSocket which will be used by server side 572 ServerSocket ss = new ServerSocket(0); 573 574 // create the HostnameVerifier to check that Hostname verification 575 // is done 576 TestHostnameVerifier hnv = new TestHostnameVerifier(); 577 HttpsURLConnection.setDefaultHostnameVerifier(hnv); 578 579 Authenticator.setDefault(new Authenticator() { 580 581 protected PasswordAuthentication getPasswordAuthentication() { 582 return new PasswordAuthentication("user", "password" 583 .toCharArray()); 584 } 585 }); 586 587 // create HttpsURLConnection to be tested 588 URL url = new URL("https://requested.host:55555/requested.data"); 589 HttpsURLConnection connection = (HttpsURLConnection) url 590 .openConnection(new Proxy(Proxy.Type.HTTP, 591 new InetSocketAddress("localhost", ss 592 .getLocalPort()))); 593 594 // perform the interaction between the peers and check the results 595 SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss); 596 checkConnectionStateParameters(connection, peerSocket); 597 598 // should silently exit 599 connection.connect(); 600 } finally { 601 // roll the properties back to system values 602 tearDownStoreProperties(); 603 } 604 } 605 606 /** 607 * Tests HTTPS connection process made through the proxy server. 2 HTTPS 608 * connections are opened for one URL. For the first time the connection is 609 * opened through one proxy, for the second time through another. 610 */ 611 public void testConsequentProxyConnection() throws Throwable { 612 // setting up the properties pointing to the key/trust stores 613 setUpStoreProperties(); 614 615 try { 616 // create the SSLServerSocket which will be used by server side 617 ServerSocket ss = new ServerSocket(0); 618 619 // create the HostnameVerifier to check that Hostname verification 620 // is done 621 TestHostnameVerifier hnv = new TestHostnameVerifier(); 622 HttpsURLConnection.setDefaultHostnameVerifier(hnv); 623 624 // create HttpsURLConnection to be tested 625 URL url = new URL("https://requested.host:55555/requested.data"); 626 HttpsURLConnection connection = (HttpsURLConnection) url 627 .openConnection(new Proxy(Proxy.Type.HTTP, 628 new InetSocketAddress("localhost", ss 629 .getLocalPort()))); 630 631 // perform the interaction between the peers and check the results 632 SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss); 633 checkConnectionStateParameters(connection, peerSocket); 634 635 // create another SSLServerSocket which will be used by server side 636 ss = new ServerSocket(0); 637 638 connection = (HttpsURLConnection) url.openConnection(new Proxy( 639 Proxy.Type.HTTP, new InetSocketAddress("localhost", ss 640 .getLocalPort()))); 641 642 // perform the interaction between the peers and check the results 643 peerSocket = (SSLSocket) doInteraction(connection, ss); 644 checkConnectionStateParameters(connection, peerSocket); 645 } finally { 646 // roll the properties back to system values 647 tearDownStoreProperties(); 648 } 649 } 650 651 /** 652 * Tests HTTPS connection process made through the proxy server. Proxy 653 * server needs authentication. Client sends data to the server. 654 */ 655 public void testProxyAuthConnection_doOutput() throws Throwable { 656 // setting up the properties pointing to the key/trust stores 657 setUpStoreProperties(); 658 659 try { 660 // create the SSLServerSocket which will be used by server side 661 ServerSocket ss = new ServerSocket(0); 662 663 // create the HostnameVerifier to check that Hostname verification 664 // is done 665 TestHostnameVerifier hnv = new TestHostnameVerifier(); 666 HttpsURLConnection.setDefaultHostnameVerifier(hnv); 667 668 Authenticator.setDefault(new Authenticator() { 669 670 protected PasswordAuthentication getPasswordAuthentication() { 671 return new PasswordAuthentication("user", "password" 672 .toCharArray()); 673 } 674 }); 675 676 // create HttpsURLConnection to be tested 677 URL url = new URL("https://requested.host:55554/requested.data"); 678 HttpsURLConnection connection = (HttpsURLConnection) url 679 .openConnection(new Proxy(Proxy.Type.HTTP, 680 new InetSocketAddress("localhost", ss 681 .getLocalPort()))); 682 connection.setDoOutput(true); 683 684 // perform the interaction between the peers and check the results 685 SSLSocket peerSocket = (SSLSocket) doInteraction(connection, ss, 686 OK_CODE); 687 checkConnectionStateParameters(connection, peerSocket); 688 } finally { 689 // roll the properties back to system values 690 tearDownStoreProperties(); 691 } 692 } 693 694 /** 695 * Tests HTTPS connection process made through the proxy server. Proxy 696 * server needs authentication but client fails to authenticate 697 * (Authenticator was not set up in the system). 698 */ 699 public void testProxyAuthConnectionFailed() throws Throwable { 700 // setting up the properties pointing to the key/trust stores 701 setUpStoreProperties(); 702 703 try { 704 // create the SSLServerSocket which will be used by server side 705 ServerSocket ss = new ServerSocket(0); 706 707 // create the HostnameVerifier to check that Hostname verification 708 // is done 709 TestHostnameVerifier hnv = new TestHostnameVerifier(); 710 HttpsURLConnection.setDefaultHostnameVerifier(hnv); 711 712 // create HttpsURLConnection to be tested 713 URL url = new URL("https://requested.host:55555/requested.data"); 714 HttpURLConnection connection = (HttpURLConnection) url 715 .openConnection(new Proxy(Proxy.Type.HTTP, 716 new InetSocketAddress("localhost", ss 717 .getLocalPort()))); 718 719 // perform the interaction between the peers and check the results 720 try { 721 doInteraction(connection, ss, AUTHENTICATION_REQUIRED_CODE); 722 } catch (IOException e) { 723 // SSL Tunnelling failed 724 if (DO_LOG) { 725 System.out.println("Got expected IOException: " 726 + e.getMessage()); 727 } 728 } 729 } finally { 730 // roll the properties back to system values 731 tearDownStoreProperties(); 732 } 733 } 734 735 /** 736 * Tests the behaviour of HTTPS connection in case of unavailability of 737 * requested resource. 738 */ 739 public void testProxyConnection_Not_Found_Response() throws Throwable { 740 // setting up the properties pointing to the key/trust stores 741 setUpStoreProperties(); 742 743 try { 744 // create the SSLServerSocket which will be used by server side 745 ServerSocket ss = new ServerSocket(0); 746 747 // create the HostnameVerifier to check that Hostname verification 748 // is done 749 TestHostnameVerifier hnv = new TestHostnameVerifier(); 750 HttpsURLConnection.setDefaultHostnameVerifier(hnv); 751 752 // create HttpsURLConnection to be tested 753 URL url = new URL("https://localhost:" + ss.getLocalPort()); 754 HttpURLConnection connection = (HttpURLConnection) url 755 .openConnection(new Proxy(Proxy.Type.HTTP, 756 new InetSocketAddress("localhost", ss 757 .getLocalPort()))); 758 759 try { 760 doInteraction(connection, ss, NOT_FOUND_CODE); // NOT FOUND 761 fail("Expected exception was not thrown."); 762 } catch (FileNotFoundException e) { 763 if (DO_LOG) { 764 System.out.println("Expected exception was thrown: " 765 + e.getMessage()); 766 } 767 } 768 } finally { 769 // roll the properties back to system values 770 tearDownStoreProperties(); 771 } 772 } 773 774 // --------------------------------------------------------------------- 775 // ------------------------ Staff Methods ------------------------------ 776 // --------------------------------------------------------------------- 777 778 /** 779 * Log the name of the test case to be executed. 780 */ 781 public void setUp() throws Exception { 782 if (DO_LOG) { 783 System.out.println(); 784 System.out.println("------------------------"); 785 System.out.println("------ " + getName()); 786 System.out.println("------------------------"); 787 } 788 } 789 790 /** 791 * Checks the HttpsURLConnection getter's values and compares them with 792 * actual corresponding values of remote peer. 793 */ 794 public static void checkConnectionStateParameters( 795 HttpsURLConnection clientConnection, SSLSocket serverPeer) 796 throws Exception { 797 SSLSession session = serverPeer.getSession(); 798 799 assertEquals(session.getCipherSuite(), clientConnection 800 .getCipherSuite()); 801 802 assertEquals(session.getLocalPrincipal(), clientConnection 803 .getPeerPrincipal()); 804 805 assertEquals(session.getPeerPrincipal(), clientConnection 806 .getLocalPrincipal()); 807 808 Certificate[] serverCertificates = clientConnection 809 .getServerCertificates(); 810 Certificate[] localCertificates = session.getLocalCertificates(); 811 assertTrue("Server certificates differ from expected", Arrays.equals( 812 serverCertificates, localCertificates)); 813 814 localCertificates = clientConnection.getLocalCertificates(); 815 serverCertificates = session.getPeerCertificates(); 816 assertTrue("Local certificates differ from expected", Arrays.equals( 817 serverCertificates, localCertificates)); 818 } 819 820 /** 821 * Returns the file name of the key/trust store. The key store file (named 822 * as "key_store." + extension equals to the default KeyStore type installed 823 * in the system in lower case) is searched in classpath. 824 * 825 * @throws AssertionFailedError if property was not set or file does not exist. 826 */ 827 private static String getKeyStoreFileName() throws Exception { 828 String ksFileName = "org/apache/harmony/luni/tests/key_store." 829 + KeyStore.getDefaultType().toLowerCase(); 830 URL url = ClassLoader.getSystemClassLoader().getResource(ksFileName); 831 assertNotNull("Expected KeyStore file: '" + ksFileName 832 + "' for default KeyStore of type '" 833 + KeyStore.getDefaultType() + "' does not exist.", url); 834 return new File(url.toURI()).getAbsolutePath(); 835 } 836 837 /** 838 * Builds and returns the context used for secure socket creation. 839 */ 840 private static SSLContext getContext() throws Exception { 841 String type = KeyStore.getDefaultType(); 842 SSLContext ctx; 843 844 String keyStore = getKeyStoreFileName(); 845 File keyStoreFile = new File(keyStore); 846 847 FileInputStream fis = new FileInputStream(keyStoreFile); 848 849 KeyStore ks = KeyStore.getInstance(type); 850 ks.load(fis, KS_PASSWORD.toCharArray()); 851 852 KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory 853 .getDefaultAlgorithm()); 854 kmf.init(ks, KS_PASSWORD.toCharArray()); 855 856 TrustManagerFactory tmf = TrustManagerFactory 857 .getInstance(TrustManagerFactory.getDefaultAlgorithm()); 858 tmf.init(ks); 859 860 ctx = SSLContext.getInstance("TLSv1"); 861 ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 862 863 return ctx; 864 } 865 866 /** 867 * Sets up the properties pointing to the key store and trust store and used 868 * as default values by JSSE staff. This is needed to test HTTPS behaviour 869 * in the case of default SSL Socket Factories. 870 */ 871 private static void setUpStoreProperties() throws Exception { 872 String type = KeyStore.getDefaultType(); 873 874 systemKeyStoreType = System.getProperty("javax.net.ssl.keyStoreType"); 875 systemKeyStore = System.getProperty("javax.net.ssl.keyStore"); 876 systemKeyStorePassword = System 877 .getProperty("javax.net.ssl.keyStorePassword"); 878 879 systemTrustStoreType = System 880 .getProperty("javax.net.ssl.trustStoreType"); 881 systemTrustStore = System.getProperty("javax.net.ssl.trustStore"); 882 systemTrustStorePassword = System 883 .getProperty("javax.net.ssl.trustStorePassword"); 884 885 System.setProperty("javax.net.ssl.keyStoreType", type); 886 System.setProperty("javax.net.ssl.keyStore", getKeyStoreFileName()); 887 System.setProperty("javax.net.ssl.keyStorePassword", KS_PASSWORD); 888 889 System.setProperty("javax.net.ssl.trustStoreType", type); 890 System.setProperty("javax.net.ssl.trustStore", getKeyStoreFileName()); 891 System.setProperty("javax.net.ssl.trustStorePassword", KS_PASSWORD); 892 } 893 894 /** 895 * Rolls back the values of system properties. 896 */ 897 private static void tearDownStoreProperties() { 898 if (systemKeyStoreType == null) { 899 System.clearProperty("javax.net.ssl.keyStoreType"); 900 } else { 901 System 902 .setProperty("javax.net.ssl.keyStoreType", 903 systemKeyStoreType); 904 } 905 if (systemKeyStore == null) { 906 System.clearProperty("javax.net.ssl.keyStore"); 907 } else { 908 System.setProperty("javax.net.ssl.keyStore", systemKeyStore); 909 } 910 if (systemKeyStorePassword == null) { 911 System.clearProperty("javax.net.ssl.keyStorePassword"); 912 } else { 913 System.setProperty("javax.net.ssl.keyStorePassword", 914 systemKeyStorePassword); 915 } 916 917 if (systemTrustStoreType == null) { 918 System.clearProperty("javax.net.ssl.trustStoreType"); 919 } else { 920 System.setProperty("javax.net.ssl.trustStoreType", 921 systemTrustStoreType); 922 } 923 if (systemTrustStore == null) { 924 System.clearProperty("javax.net.ssl.trustStore"); 925 } else { 926 System.setProperty("javax.net.ssl.trustStore", systemTrustStore); 927 } 928 if (systemTrustStorePassword == null) { 929 System.clearProperty("javax.net.ssl.trustStorePassword"); 930 } else { 931 System.setProperty("javax.net.ssl.trustStorePassword", 932 systemTrustStorePassword); 933 } 934 } 935 936 /** 937 * Performs interaction between client's HttpURLConnection and servers side 938 * (ServerSocket). 939 */ 940 public static Socket doInteraction( 941 final HttpURLConnection clientConnection, 942 final ServerSocket serverSocket) throws Throwable { 943 return doInteraction(clientConnection, serverSocket, OK_CODE, false, 944 false); 945 } 946 947 /** 948 * Performs interaction between client's HttpURLConnection and servers side 949 * (ServerSocket). Server will response with specified response code. 950 */ 951 public static Socket doInteraction( 952 final HttpURLConnection clientConnection, 953 final ServerSocket serverSocket, final int responseCode) 954 throws Throwable { 955 return doInteraction(clientConnection, serverSocket, responseCode, 956 false, false); 957 } 958 959 /** 960 * Performs interaction between client's HttpURLConnection and servers side 961 * (ServerSocket) over persistent connection. 962 */ 963 public static Socket doPersistentInteraction( 964 final HttpURLConnection clientConnection, 965 final ServerSocket serverSocket) throws Throwable { 966 return doInteraction(clientConnection, serverSocket, OK_CODE, false, 967 true); 968 } 969 970 /** 971 * Performs interaction between client's HttpURLConnection and servers side 972 * (ServerSocket) over persistent connection. Server will response with 973 * specified response code. 974 */ 975 public static Socket doPersistentInteraction( 976 final HttpURLConnection clientConnection, 977 final ServerSocket serverSocket, final int responseCode) 978 throws Throwable { 979 return doInteraction(clientConnection, serverSocket, responseCode, 980 false, true); 981 } 982 983 /** 984 * Performs interaction between client's HttpURLConnection and servers side 985 * (ServerSocket). Server will response with specified response code. 986 * 987 * @param doAuthentication specifies if the server needs client authentication. 988 */ 989 public static Socket doInteraction( 990 final HttpURLConnection clientConnection, 991 final ServerSocket serverSocket, final int responseCode, 992 final boolean doAuthentication, final boolean checkPersistence) 993 throws Throwable { 994 995 // set up the connection 996 clientConnection.setDoInput(true); 997 clientConnection.setConnectTimeout(TIMEOUT); 998 clientConnection.setReadTimeout(TIMEOUT); 999 1000 ServerWork server = new ServerWork(serverSocket, responseCode, 1001 doAuthentication, checkPersistence); 1002 1003 ClientConnectionWork client = new ClientConnectionWork(clientConnection); 1004 1005 server.start(); 1006 client.start(); 1007 1008 client.join(); 1009 if (client.thrown != null) { 1010 if (responseCode != OK_CODE) { // not OK response expected 1011 // it is probably expected exception, keep it as is 1012 throw client.thrown; 1013 } 1014 if ((client.thrown instanceof SocketTimeoutException) 1015 && (server.thrown != null)) { 1016 // server's exception is more informative in this case 1017 throw new Exception(server.thrown); 1018 } else { 1019 throw new Exception(client.thrown); 1020 } 1021 } 1022 1023 if (checkPersistence) { 1024 ClientConnectionWork client2 = new ClientConnectionWork( 1025 (HttpURLConnection) clientConnection.getURL() 1026 .openConnection()); 1027 client2.start(); 1028 client2.join(); 1029 if (client2.thrown != null) { 1030 if (responseCode != OK_CODE) { // not OK response expected 1031 // it is probably expected exception, keep it as is 1032 throw client2.thrown; 1033 } 1034 if ((client2.thrown instanceof SocketTimeoutException) 1035 && (server.thrown != null)) { 1036 // server's exception is more informative in this case 1037 throw new Exception(server.thrown); 1038 } else { 1039 throw new Exception(client2.thrown); 1040 } 1041 } 1042 } 1043 1044 server.join(); 1045 1046 if (server.thrown != null) { 1047 throw server.thrown; 1048 } 1049 return server.peerSocket; 1050 } 1051 1052 /** 1053 * The host name verifier used in test. 1054 */ 1055 static class TestHostnameVerifier implements HostnameVerifier { 1056 1057 boolean verified = false; 1058 1059 public boolean verify(String hostname, SSLSession session) { 1060 if (DO_LOG) { 1061 System.out.println("***> verification " + hostname + " " 1062 + session.getPeerHost()); 1063 } 1064 verified = true; 1065 return true; 1066 } 1067 } 1068 1069 /** 1070 * The base class for mock Client and Server. 1071 */ 1072 static class Work extends Thread { 1073 1074 /** 1075 * The header of OK HTTP response. 1076 */ 1077 static String responseHead = "HTTP/1.1 200 OK\n"; 1078 1079 /** 1080 * The content of the response. 1081 */ 1082 static String plainResponseContent = "<HTML>\n" 1083 + "<HEAD><TITLE>Plain Response Content</TITLE></HEAD>\n" 1084 + "</HTML>"; 1085 1086 /** 1087 * The tail of the response. 1088 */ 1089 static String plainResponseTail = "Content-type: text/html\n" 1090 + "Content-length: " + plainResponseContent.length() + "\n\n" 1091 + plainResponseContent; 1092 1093 /** 1094 * The response message to be sent in plain (HTTP) format. 1095 */ 1096 static String plainResponse = responseHead + plainResponseTail; 1097 1098 /** 1099 * The content of the response to be sent during HTTPS session. 1100 */ 1101 static String httpsResponseContent = "<HTML>\n" 1102 + "<HEAD><TITLE>HTTPS Response Content</TITLE></HEAD>\n" 1103 + "</HTML>"; 1104 1105 /** 1106 * The tail of the response to be sent during HTTPS session. 1107 */ 1108 static String httpsResponseTail = "Content-type: text/html\n" 1109 + "Content-length: " + httpsResponseContent.length() + "\n\n" 1110 + httpsResponseContent; 1111 1112 /** 1113 * The response requiring client's proxy authentication. 1114 */ 1115 static String respAuthenticationRequired = "HTTP/1.0 407 Proxy authentication required\n" 1116 + "Proxy-authenticate: Basic realm=\"localhost\"\n\n"; 1117 1118 /** 1119 * The data to be posted by client to the server. 1120 */ 1121 static String clientsData = "_.-^ Client's Data ^-._"; 1122 1123 /** 1124 * The exception thrown during peers interaction. 1125 */ 1126 protected Throwable thrown; 1127 1128 /** 1129 * The print stream used for debug log. If it is null debug info will 1130 * not be printed. 1131 */ 1132 private PrintStream out = new PrintStream(System.out); 1133 1134 /** 1135 * Prints log message. 1136 */ 1137 public synchronized void log(String message) { 1138 if (DO_LOG && (out != null)) { 1139 System.out.println("[" + getName() + "]: " + message); 1140 } 1141 } 1142 } 1143 1144 /** 1145 * The class used for server side works. 1146 */ 1147 static class ServerWork extends Work { 1148 1149 // the server socket used for connection 1150 private ServerSocket serverSocket; 1151 1152 // the socket connected with client peer 1153 private Socket peerSocket; 1154 1155 // indicates if the server acts as proxy server 1156 private boolean actAsProxy; 1157 1158 // indicates if the server needs proxy authentication 1159 private boolean needProxyAuthentication; 1160 1161 // do we check for connection persistence 1162 private boolean checkPersistence; 1163 1164 // response code to be send to the client peer 1165 private int responseCode; 1166 1167 /** 1168 * Creates the thread acting as a server side. 1169 */ 1170 public ServerWork(ServerSocket serverSocket) { 1171 // the server does not require proxy authentication 1172 // and sends OK_CODE (OK) response code 1173 this(serverSocket, OK_CODE, false, false); 1174 } 1175 1176 /** 1177 * Creates the thread acting as a server side. 1178 * 1179 * @param serverSocket the server socket to be used during connection 1180 * @param responseCode the response code to be sent to the client 1181 * @param needProxyAuthentication indicates if the server needs proxy authentication 1182 */ 1183 public ServerWork(ServerSocket serverSocket, int responseCode, 1184 boolean needProxyAuthentication, boolean checkPersistence) { 1185 this.serverSocket = serverSocket; 1186 this.responseCode = responseCode; 1187 this.needProxyAuthentication = needProxyAuthentication; 1188 this.checkPersistence = checkPersistence; 1189 // will act as a proxy server if the specified server socket 1190 // is not a secure server socket 1191 if (serverSocket instanceof SSLServerSocket) { 1192 // demand client to send its certificate 1193 ((SSLServerSocket) serverSocket).setNeedClientAuth(true); 1194 // work as a HTTPS server, not as HTTP proxy 1195 this.actAsProxy = false; 1196 } else { 1197 this.actAsProxy = true; 1198 } 1199 this.actAsProxy = !(serverSocket instanceof SSLServerSocket); 1200 setName(this.actAsProxy ? "Proxy Server" : "Server"); 1201 } 1202 1203 /** 1204 * Closes the connection. 1205 */ 1206 public void closeSocket(Socket socket) { 1207 try { 1208 socket.getInputStream().close(); 1209 } catch (IOException e) { 1210 } 1211 try { 1212 socket.getOutputStream().close(); 1213 } catch (IOException e) { 1214 } 1215 try { 1216 socket.close(); 1217 } catch (IOException e) { 1218 } 1219 } 1220 1221 /** 1222 * Performs the actual server work. If some exception occurs during the 1223 * work it will be stored in the <code>thrown</code> field. 1224 */ 1225 public void run() { 1226 // the buffer used for reading the messages 1227 byte[] buff = new byte[2048]; 1228 // the number of bytes read into the buffer 1229 int num; 1230 try { 1231 // configure the server socket to avoid blocking 1232 serverSocket.setSoTimeout(TIMEOUT); 1233 // accept client connection 1234 peerSocket = serverSocket.accept(); 1235 // configure the client connection to avoid blocking 1236 peerSocket.setSoTimeout(TIMEOUT); 1237 log("Client connection ACCEPTED"); 1238 1239 InputStream is = peerSocket.getInputStream(); 1240 OutputStream os = peerSocket.getOutputStream(); 1241 1242 // how many times established connection will be used 1243 int number_of_uses = checkPersistence ? 2 : 1; 1244 for (int it = 0; it < number_of_uses; it++) { 1245 if (checkPersistence) { 1246 log("=========================================="); 1247 log("Use established connection for " + (it + 1) 1248 + " time"); 1249 } 1250 1251 num = is.read(buff); 1252 String message = new String(buff, 0, num, "UTF-8"); 1253 log("Got request:\n" + message); 1254 log("------------------"); 1255 1256 if (!actAsProxy) { 1257 // Act as Server (not Proxy) side 1258 if (message.startsWith("POST")) { 1259 // client connection sent some data 1260 log("try to read client data"); 1261 num = is.read(buff); 1262 message = new String(buff, 0, num, "UTF-8"); 1263 log("client's data: '" + message + "'"); 1264 // check the received data 1265 assertEquals(clientsData, message); 1266 } 1267 // just send the response 1268 os 1269 .write(("HTTP/1.1 " + responseCode + "\n" + httpsResponseTail) 1270 .getBytes("UTF-8")); 1271 log("Simple NON-Proxy work is DONE"); 1272 continue; 1273 } 1274 1275 // Do proxy work 1276 if (needProxyAuthentication) { 1277 log("Authentication required ..."); 1278 // send Authentication Request 1279 os.write(respAuthenticationRequired.getBytes("UTF-8")); 1280 // read response 1281 num = is.read(buff); 1282 if (num == -1) { 1283 // this connection was closed, 1284 // do clean up and create new one: 1285 closeSocket(peerSocket); 1286 peerSocket = serverSocket.accept(); 1287 peerSocket.setSoTimeout(TIMEOUT); 1288 log("New client connection ACCEPTED"); 1289 is = peerSocket.getInputStream(); 1290 os = peerSocket.getOutputStream(); 1291 num = is.read(buff); 1292 } 1293 message = new String(buff, 0, num, "UTF-8"); 1294 log("Got authenticated request:\n" + message); 1295 log("------------------"); 1296 // check provided authorization credentials 1297 assertTrue("Received message does not contain " 1298 + "authorization credentials", 1299 message.toLowerCase().indexOf( 1300 "proxy-authorization:") > 0); 1301 } 1302 1303 if (peerSocket instanceof SSLSocket) { 1304 // it will be so if we are have second iteration 1305 // over persistent connection 1306 os 1307 .write(("HTTP/1.1 " + OK_CODE + "\n" + httpsResponseTail) 1308 .getBytes("UTF-8")); 1309 log("Sent OK RESPONSE over SSL"); 1310 } else { 1311 // The content of this response will reach proxied 1312 // HTTPUC but will not reach proxied HTTPSUC 1313 // In case of HTTP connection it will be the final 1314 // message, in case of HTTPS connection this message 1315 // will just indicate that connection with remote 1316 // host has been done 1317 // (i.e. SSL tunnel has been established). 1318 os.write(plainResponse.getBytes("UTF-8")); 1319 log("Sent OK RESPONSE"); 1320 } 1321 1322 if (message.startsWith("CONNECT")) { // request for SSL 1323 // tunnel 1324 log("Perform SSL Handshake..."); 1325 // create sslSocket acting as a remote server peer 1326 SSLSocket sslSocket = (SSLSocket) getContext() 1327 .getSocketFactory() 1328 .createSocket(peerSocket, "localhost", 1329 peerSocket.getPort(), true); // do 1330 // autoclose 1331 sslSocket.setUseClientMode(false); 1332 // demand client authentication 1333 sslSocket.setNeedClientAuth(true); 1334 sslSocket.startHandshake(); 1335 peerSocket = sslSocket; 1336 is = peerSocket.getInputStream(); 1337 os = peerSocket.getOutputStream(); 1338 1339 // read the HTTP request sent by secure connection 1340 // (HTTPS request) 1341 num = is.read(buff); 1342 message = new String(buff, 0, num, "UTF-8"); 1343 log("[Remote Server] Request from SSL tunnel:\n" 1344 + message); 1345 log("------------------"); 1346 1347 if (message.startsWith("POST")) { 1348 // client connection sent some data 1349 log("[Remote Server] try to read client data"); 1350 num = is.read(buff); 1351 message = new String(buff, 0, num, "UTF-8"); 1352 log("[Remote Server] client's data: '" + message 1353 + "'"); 1354 // check the received data 1355 assertEquals(clientsData, message); 1356 } 1357 1358 log("[Remote Server] Sending the response by SSL tunnel.."); 1359 // send the response with specified response code 1360 os 1361 .write(("HTTP/1.1 " + responseCode + "\n" + httpsResponseTail) 1362 .getBytes("UTF-8")); 1363 } 1364 log("Work is DONE"); 1365 } 1366 ; 1367 } catch (Throwable e) { 1368 if (DO_LOG) { 1369 e.printStackTrace(); 1370 } 1371 thrown = e; 1372 } finally { 1373 closeSocket(peerSocket); 1374 try { 1375 serverSocket.close(); 1376 } catch (IOException e) { 1377 } 1378 } 1379 } 1380 } 1381 1382 /** 1383 * The class used for client side works. It could be used to test both 1384 * HttpURLConnection and HttpsURLConnection. 1385 */ 1386 static class ClientConnectionWork extends Work { 1387 1388 // connection to be used to contact the server side 1389 private HttpURLConnection connection; 1390 1391 /** 1392 * Creates the thread acting as a client side. 1393 * 1394 * @param connection connection to be used to contact the server side 1395 */ 1396 public ClientConnectionWork(HttpURLConnection connection) { 1397 this.connection = connection; 1398 setName("Client Connection"); 1399 log("Created over connection: " + connection.getClass()); 1400 } 1401 1402 /** 1403 * Performs the actual client work. If some exception occurs during the 1404 * work it will be stored in the <code>thrown<code> field. 1405 */ 1406 public void run() { 1407 try { 1408 log("Opening the connection.."); 1409 connection.connect(); 1410 log("Connection has been ESTABLISHED, using proxy: " 1411 + connection.usingProxy()); 1412 if (connection.getDoOutput()) { 1413 // connection configured to post data, do so 1414 connection.getOutputStream().write(clientsData.getBytes("UTF-8")); 1415 } 1416 // read the content of HTTP(s) response 1417 InputStream is = connection.getInputStream(); 1418 log("Input Stream obtained: " + is.getClass()); 1419 byte[] buff = new byte[2048]; 1420 int num = 0; 1421 int byt = 0; 1422 while ((num < buff.length) && (is.available() > 0) 1423 && ((byt = is.read()) != -1)) { 1424 buff[num++] = (byte) byt; 1425 } 1426 String message = new String(buff, 0, num, "UTF-8"); 1427 log("Got content:\n" + message); 1428 log("------------------"); 1429 log("Response code: " + connection.getResponseCode()); 1430 1431 if (connection instanceof HttpsURLConnection) { 1432 assertEquals(httpsResponseContent, message); 1433 } else { 1434 assertEquals(plainResponseContent, message); 1435 } 1436 } catch (Throwable e) { 1437 if (DO_LOG) { 1438 e.printStackTrace(); 1439 } 1440 thrown = e; 1441 } 1442 } 1443 } 1444 1445 public static junit.framework.Test suite() { 1446 return new TestSuite(HttpsURLConnectionTest.class); 1447 } 1448 1449} 1450