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 18 package org.apache.harmony.luni.tests.internal.net.www.protocol.https; 19 20 import java.io.File; 21 import java.io.FileInputStream; 22 import java.io.FileNotFoundException; 23 import java.io.IOException; 24 import java.io.InputStream; 25 import java.io.OutputStream; 26 import java.io.PrintStream; 27 import java.net.Authenticator; 28 import java.net.HttpURLConnection; 29 import java.net.InetSocketAddress; 30 import java.net.PasswordAuthentication; 31 import java.net.Proxy; 32 import java.net.ServerSocket; 33 import java.net.Socket; 34 import java.net.SocketTimeoutException; 35 import java.net.URL; 36 import java.security.KeyStore; 37 import java.security.cert.Certificate; 38 import java.util.Arrays; 39 40 import javax.net.ssl.HostnameVerifier; 41 import javax.net.ssl.HttpsURLConnection; 42 import javax.net.ssl.KeyManagerFactory; 43 import javax.net.ssl.SSLContext; 44 import javax.net.ssl.SSLServerSocket; 45 import javax.net.ssl.SSLSession; 46 import javax.net.ssl.SSLSocket; 47 import javax.net.ssl.SSLSocketFactory; 48 import javax.net.ssl.TrustManagerFactory; 49 50 import junit.framework.AssertionFailedError; 51 import junit.framework.TestCase; 52 import 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 */ 65 public 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 826 * if property was not set or file does not exist. 827 */ 828 private static String getKeyStoreFileName() throws Exception { 829 String ksFileName = "org/apache/harmony/luni/tests/key_store." 830 + KeyStore.getDefaultType().toLowerCase(); 831 URL url = ClassLoader.getSystemClassLoader().getResource(ksFileName); 832 assertNotNull("Expected KeyStore file: '" + ksFileName 833 + "' for default KeyStore of type '" 834 + KeyStore.getDefaultType() + "' does not exist.", url); 835 return new File(url.toURI()).getAbsolutePath(); 836 } 837 838 /** 839 * Builds and returns the context used for secure socket creation. 840 */ 841 private static SSLContext getContext() throws Exception { 842 String type = KeyStore.getDefaultType(); 843 SSLContext ctx; 844 845 String keyStore = getKeyStoreFileName(); 846 File keyStoreFile = new File(keyStore); 847 848 FileInputStream fis = new FileInputStream(keyStoreFile); 849 850 KeyStore ks = KeyStore.getInstance(type); 851 ks.load(fis, KS_PASSWORD.toCharArray()); 852 853 KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory 854 .getDefaultAlgorithm()); 855 kmf.init(ks, KS_PASSWORD.toCharArray()); 856 857 TrustManagerFactory tmf = TrustManagerFactory 858 .getInstance(TrustManagerFactory.getDefaultAlgorithm()); 859 tmf.init(ks); 860 861 ctx = SSLContext.getInstance("TLSv1"); 862 ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 863 864 return ctx; 865 } 866 867 /** 868 * Sets up the properties pointing to the key store and trust store and used 869 * as default values by JSSE staff. This is needed to test HTTPS behaviour 870 * in the case of default SSL Socket Factories. 871 */ 872 private static void setUpStoreProperties() throws Exception { 873 String type = KeyStore.getDefaultType(); 874 875 systemKeyStoreType = System.getProperty("javax.net.ssl.keyStoreType"); 876 systemKeyStore = System.getProperty("javax.net.ssl.keyStore"); 877 systemKeyStorePassword = System 878 .getProperty("javax.net.ssl.keyStorePassword"); 879 880 systemTrustStoreType = System 881 .getProperty("javax.net.ssl.trustStoreType"); 882 systemTrustStore = System.getProperty("javax.net.ssl.trustStore"); 883 systemTrustStorePassword = System 884 .getProperty("javax.net.ssl.trustStorePassword"); 885 886 System.setProperty("javax.net.ssl.keyStoreType", type); 887 System.setProperty("javax.net.ssl.keyStore", getKeyStoreFileName()); 888 System.setProperty("javax.net.ssl.keyStorePassword", KS_PASSWORD); 889 890 System.setProperty("javax.net.ssl.trustStoreType", type); 891 System.setProperty("javax.net.ssl.trustStore", getKeyStoreFileName()); 892 System.setProperty("javax.net.ssl.trustStorePassword", KS_PASSWORD); 893 } 894 895 /** 896 * Rolls back the values of system properties. 897 */ 898 private static void tearDownStoreProperties() { 899 if (systemKeyStoreType == null) { 900 System.clearProperty("javax.net.ssl.keyStoreType"); 901 } else { 902 System 903 .setProperty("javax.net.ssl.keyStoreType", 904 systemKeyStoreType); 905 } 906 if (systemKeyStore == null) { 907 System.clearProperty("javax.net.ssl.keyStore"); 908 } else { 909 System.setProperty("javax.net.ssl.keyStore", systemKeyStore); 910 } 911 if (systemKeyStorePassword == null) { 912 System.clearProperty("javax.net.ssl.keyStorePassword"); 913 } else { 914 System.setProperty("javax.net.ssl.keyStorePassword", 915 systemKeyStorePassword); 916 } 917 918 if (systemTrustStoreType == null) { 919 System.clearProperty("javax.net.ssl.trustStoreType"); 920 } else { 921 System.setProperty("javax.net.ssl.trustStoreType", 922 systemTrustStoreType); 923 } 924 if (systemTrustStore == null) { 925 System.clearProperty("javax.net.ssl.trustStore"); 926 } else { 927 System.setProperty("javax.net.ssl.trustStore", systemTrustStore); 928 } 929 if (systemTrustStorePassword == null) { 930 System.clearProperty("javax.net.ssl.trustStorePassword"); 931 } else { 932 System.setProperty("javax.net.ssl.trustStorePassword", 933 systemTrustStorePassword); 934 } 935 } 936 937 /** 938 * Performs interaction between client's HttpURLConnection and servers side 939 * (ServerSocket). 940 */ 941 public static Socket doInteraction( 942 final HttpURLConnection clientConnection, 943 final ServerSocket serverSocket) throws Throwable { 944 return doInteraction(clientConnection, serverSocket, OK_CODE, false, 945 false); 946 } 947 948 /** 949 * Performs interaction between client's HttpURLConnection and servers side 950 * (ServerSocket). Server will response with specified response code. 951 */ 952 public static Socket doInteraction( 953 final HttpURLConnection clientConnection, 954 final ServerSocket serverSocket, final int responseCode) 955 throws Throwable { 956 return doInteraction(clientConnection, serverSocket, responseCode, 957 false, false); 958 } 959 960 /** 961 * Performs interaction between client's HttpURLConnection and servers side 962 * (ServerSocket) over persistent connection. 963 */ 964 public static Socket doPersistentInteraction( 965 final HttpURLConnection clientConnection, 966 final ServerSocket serverSocket) throws Throwable { 967 return doInteraction(clientConnection, serverSocket, OK_CODE, false, 968 true); 969 } 970 971 /** 972 * Performs interaction between client's HttpURLConnection and servers side 973 * (ServerSocket) over persistent connection. Server will response with 974 * specified response code. 975 */ 976 public static Socket doPersistentInteraction( 977 final HttpURLConnection clientConnection, 978 final ServerSocket serverSocket, final int responseCode) 979 throws Throwable { 980 return doInteraction(clientConnection, serverSocket, responseCode, 981 false, true); 982 } 983 984 /** 985 * Performs interaction between client's HttpURLConnection and servers side 986 * (ServerSocket). Server will response with specified response code. 987 * 988 * @param doAuthentication 989 * specifies if the server needs client authentication. 990 */ 991 public static Socket doInteraction( 992 final HttpURLConnection clientConnection, 993 final ServerSocket serverSocket, final int responseCode, 994 final boolean doAuthentication, final boolean checkPersistence) 995 throws Throwable { 996 997 // set up the connection 998 clientConnection.setDoInput(true); 999 clientConnection.setConnectTimeout(TIMEOUT); 1000 clientConnection.setReadTimeout(TIMEOUT); 1001 1002 ServerWork server = new ServerWork(serverSocket, responseCode, 1003 doAuthentication, checkPersistence); 1004 1005 ClientConnectionWork client = new ClientConnectionWork(clientConnection); 1006 1007 server.start(); 1008 client.start(); 1009 1010 client.join(); 1011 if (client.thrown != null) { 1012 if (responseCode != OK_CODE) { // not OK response expected 1013 // it is probably expected exception, keep it as is 1014 throw client.thrown; 1015 } 1016 if ((client.thrown instanceof SocketTimeoutException) 1017 && (server.thrown != null)) { 1018 // server's exception is more informative in this case 1019 throw new Exception(server.thrown); 1020 } else { 1021 throw new Exception(client.thrown); 1022 } 1023 } 1024 1025 if (checkPersistence) { 1026 ClientConnectionWork client2 = new ClientConnectionWork( 1027 (HttpURLConnection) clientConnection.getURL() 1028 .openConnection()); 1029 client2.start(); 1030 client2.join(); 1031 if (client2.thrown != null) { 1032 if (responseCode != OK_CODE) { // not OK response expected 1033 // it is probably expected exception, keep it as is 1034 throw client2.thrown; 1035 } 1036 if ((client2.thrown instanceof SocketTimeoutException) 1037 && (server.thrown != null)) { 1038 // server's exception is more informative in this case 1039 throw new Exception(server.thrown); 1040 } else { 1041 throw new Exception(client2.thrown); 1042 } 1043 } 1044 } 1045 1046 server.join(); 1047 1048 if (server.thrown != null) { 1049 throw server.thrown; 1050 } 1051 return server.peerSocket; 1052 } 1053 1054 /** 1055 * The host name verifier used in test. 1056 */ 1057 static class TestHostnameVerifier implements HostnameVerifier { 1058 1059 boolean verified = false; 1060 1061 public boolean verify(String hostname, SSLSession session) { 1062 if (DO_LOG) { 1063 System.out.println("***> verification " + hostname + " " 1064 + session.getPeerHost()); 1065 } 1066 verified = true; 1067 return true; 1068 } 1069 } 1070 1071 /** 1072 * The base class for mock Client and Server. 1073 */ 1074 static class Work extends Thread { 1075 1076 /** 1077 * The header of OK HTTP response. 1078 */ 1079 static String responseHead = "HTTP/1.1 200 OK\n"; 1080 1081 /** 1082 * The content of the response. 1083 */ 1084 static String plainResponseContent = "<HTML>\n" 1085 + "<HEAD><TITLE>Plain Response Content</TITLE></HEAD>\n" 1086 + "</HTML>"; 1087 1088 /** 1089 * The tail of the response. 1090 */ 1091 static String plainResponseTail = "Content-type: text/html\n" 1092 + "Content-length: " + plainResponseContent.length() + "\n\n" 1093 + plainResponseContent; 1094 1095 /** 1096 * The response message to be sent in plain (HTTP) format. 1097 */ 1098 static String plainResponse = responseHead + plainResponseTail; 1099 1100 /** 1101 * The content of the response to be sent during HTTPS session. 1102 */ 1103 static String httpsResponseContent = "<HTML>\n" 1104 + "<HEAD><TITLE>HTTPS Response Content</TITLE></HEAD>\n" 1105 + "</HTML>"; 1106 1107 /** 1108 * The tail of the response to be sent during HTTPS session. 1109 */ 1110 static String httpsResponseTail = "Content-type: text/html\n" 1111 + "Content-length: " + httpsResponseContent.length() + "\n\n" 1112 + httpsResponseContent; 1113 1114 /** 1115 * The response requiring client's proxy authentication. 1116 */ 1117 static String respAuthenticationRequired = "HTTP/1.0 407 Proxy authentication required\n" 1118 + "Proxy-authenticate: Basic realm=\"localhost\"\n\n"; 1119 1120 /** 1121 * The data to be posted by client to the server. 1122 */ 1123 static String clientsData = "_.-^ Client's Data ^-._"; 1124 1125 /** 1126 * The exception thrown during peers interaction. 1127 */ 1128 protected Throwable thrown; 1129 1130 /** 1131 * The print stream used for debug log. If it is null debug info will 1132 * not be printed. 1133 */ 1134 private PrintStream out = new PrintStream(System.out); 1135 1136 /** 1137 * Prints log message. 1138 */ 1139 public synchronized void log(String message) { 1140 if (DO_LOG && (out != null)) { 1141 System.out.println("[" + getName() + "]: " + message); 1142 } 1143 } 1144 } 1145 1146 /** 1147 * The class used for server side works. 1148 */ 1149 static class ServerWork extends Work { 1150 1151 // the server socket used for connection 1152 private ServerSocket serverSocket; 1153 1154 // the socket connected with client peer 1155 private Socket peerSocket; 1156 1157 // indicates if the server acts as proxy server 1158 private boolean actAsProxy; 1159 1160 // indicates if the server needs proxy authentication 1161 private boolean needProxyAuthentication; 1162 1163 // do we check for connection persistence 1164 private boolean checkPersistence; 1165 1166 // response code to be send to the client peer 1167 private int responseCode; 1168 1169 /** 1170 * Creates the thread acting as a server side. 1171 */ 1172 public ServerWork(ServerSocket serverSocket) { 1173 // the server does not require proxy authentication 1174 // and sends OK_CODE (OK) response code 1175 this(serverSocket, OK_CODE, false, false); 1176 } 1177 1178 /** 1179 * Creates the thread acting as a server side. 1180 * 1181 * @param serverSocket 1182 * the server socket to be used during connection 1183 * @param responseCode 1184 * the response code to be sent to the client 1185 * @param needProxyAuthentication 1186 * indicates if the server needs proxy authentication 1187 */ 1188 public ServerWork(ServerSocket serverSocket, int responseCode, 1189 boolean needProxyAuthentication, boolean checkPersistence) { 1190 this.serverSocket = serverSocket; 1191 this.responseCode = responseCode; 1192 this.needProxyAuthentication = needProxyAuthentication; 1193 this.checkPersistence = checkPersistence; 1194 // will act as a proxy server if the specified server socket 1195 // is not a secure server socket 1196 if (serverSocket instanceof SSLServerSocket) { 1197 // demand client to send its certificate 1198 ((SSLServerSocket) serverSocket).setNeedClientAuth(true); 1199 // work as a HTTPS server, not as HTTP proxy 1200 this.actAsProxy = false; 1201 } else { 1202 this.actAsProxy = true; 1203 } 1204 this.actAsProxy = !(serverSocket instanceof SSLServerSocket); 1205 setName(this.actAsProxy ? "Proxy Server" : "Server"); 1206 } 1207 1208 /** 1209 * Closes the connection. 1210 */ 1211 public void closeSocket(Socket socket) { 1212 try { 1213 socket.getInputStream().close(); 1214 } catch (IOException e) { 1215 } 1216 try { 1217 socket.getOutputStream().close(); 1218 } catch (IOException e) { 1219 } 1220 try { 1221 socket.close(); 1222 } catch (IOException e) { 1223 } 1224 } 1225 1226 /** 1227 * Performs the actual server work. If some exception occurs during the 1228 * work it will be stored in the <code>thrown</code> field. 1229 */ 1230 public void run() { 1231 // the buffer used for reading the messages 1232 byte[] buff = new byte[2048]; 1233 // the number of bytes read into the buffer 1234 int num; 1235 try { 1236 // configure the server socket to avoid blocking 1237 serverSocket.setSoTimeout(TIMEOUT); 1238 // accept client connection 1239 peerSocket = serverSocket.accept(); 1240 // configure the client connection to avoid blocking 1241 peerSocket.setSoTimeout(TIMEOUT); 1242 log("Client connection ACCEPTED"); 1243 1244 InputStream is = peerSocket.getInputStream(); 1245 OutputStream os = peerSocket.getOutputStream(); 1246 1247 // how many times established connection will be used 1248 int number_of_uses = checkPersistence ? 2 : 1; 1249 for (int it = 0; it < number_of_uses; it++) { 1250 if (checkPersistence) { 1251 log("=========================================="); 1252 log("Use established connection for " + (it + 1) 1253 + " time"); 1254 } 1255 1256 num = is.read(buff); 1257 String message = new String(buff, 0, num, "UTF-8"); 1258 log("Got request:\n" + message); 1259 log("------------------"); 1260 1261 if (!actAsProxy) { 1262 // Act as Server (not Proxy) side 1263 if (message.startsWith("POST")) { 1264 // client connection sent some data 1265 log("try to read client data"); 1266 num = is.read(buff); 1267 message = new String(buff, 0, num, "UTF-8"); 1268 log("client's data: '" + message + "'"); 1269 // check the received data 1270 assertEquals(clientsData, message); 1271 } 1272 // just send the response 1273 os 1274 .write(("HTTP/1.1 " + responseCode + "\n" + httpsResponseTail) 1275 .getBytes("UTF-8")); 1276 log("Simple NON-Proxy work is DONE"); 1277 continue; 1278 } 1279 1280 // Do proxy work 1281 if (needProxyAuthentication) { 1282 log("Authentication required ..."); 1283 // send Authentication Request 1284 os.write(respAuthenticationRequired.getBytes("UTF-8")); 1285 // read response 1286 num = is.read(buff); 1287 if (num == -1) { 1288 // this connection was closed, 1289 // do clean up and create new one: 1290 closeSocket(peerSocket); 1291 peerSocket = serverSocket.accept(); 1292 peerSocket.setSoTimeout(TIMEOUT); 1293 log("New client connection ACCEPTED"); 1294 is = peerSocket.getInputStream(); 1295 os = peerSocket.getOutputStream(); 1296 num = is.read(buff); 1297 } 1298 message = new String(buff, 0, num, "UTF-8"); 1299 log("Got authenticated request:\n" + message); 1300 log("------------------"); 1301 // check provided authorization credentials 1302 assertTrue("Received message does not contain " 1303 + "authorization credentials", 1304 message.toLowerCase().indexOf( 1305 "proxy-authorization:") > 0); 1306 } 1307 1308 if (peerSocket instanceof SSLSocket) { 1309 // it will be so if we are have second iteration 1310 // over persistent connection 1311 os 1312 .write(("HTTP/1.1 " + OK_CODE + "\n" + httpsResponseTail) 1313 .getBytes("UTF-8")); 1314 log("Sent OK RESPONSE over SSL"); 1315 } else { 1316 // The content of this response will reach proxied 1317 // HTTPUC but will not reach proxied HTTPSUC 1318 // In case of HTTP connection it will be the final 1319 // message, in case of HTTPS connection this message 1320 // will just indicate that connection with remote 1321 // host has been done 1322 // (i.e. SSL tunnel has been established). 1323 os.write(plainResponse.getBytes("UTF-8")); 1324 log("Sent OK RESPONSE"); 1325 } 1326 1327 if (message.startsWith("CONNECT")) { // request for SSL 1328 // tunnel 1329 log("Perform SSL Handshake..."); 1330 // create sslSocket acting as a remote server peer 1331 SSLSocket sslSocket = (SSLSocket) getContext() 1332 .getSocketFactory() 1333 .createSocket(peerSocket, "localhost", 1334 peerSocket.getPort(), true); // do 1335 // autoclose 1336 sslSocket.setUseClientMode(false); 1337 // demand client authentication 1338 sslSocket.setNeedClientAuth(true); 1339 sslSocket.startHandshake(); 1340 peerSocket = sslSocket; 1341 is = peerSocket.getInputStream(); 1342 os = peerSocket.getOutputStream(); 1343 1344 // read the HTTP request sent by secure connection 1345 // (HTTPS request) 1346 num = is.read(buff); 1347 message = new String(buff, 0, num, "UTF-8"); 1348 log("[Remote Server] Request from SSL tunnel:\n" 1349 + message); 1350 log("------------------"); 1351 1352 if (message.startsWith("POST")) { 1353 // client connection sent some data 1354 log("[Remote Server] try to read client data"); 1355 num = is.read(buff); 1356 message = new String(buff, 0, num, "UTF-8"); 1357 log("[Remote Server] client's data: '" + message 1358 + "'"); 1359 // check the received data 1360 assertEquals(clientsData, message); 1361 } 1362 1363 log("[Remote Server] Sending the response by SSL tunnel.."); 1364 // send the response with specified response code 1365 os 1366 .write(("HTTP/1.1 " + responseCode + "\n" + httpsResponseTail) 1367 .getBytes("UTF-8")); 1368 } 1369 log("Work is DONE"); 1370 } 1371 ; 1372 } catch (Throwable e) { 1373 if (DO_LOG) { 1374 e.printStackTrace(); 1375 } 1376 thrown = e; 1377 } finally { 1378 closeSocket(peerSocket); 1379 try { 1380 serverSocket.close(); 1381 } catch (IOException e) { 1382 } 1383 } 1384 } 1385 } 1386 1387 /** 1388 * The class used for client side works. It could be used to test both 1389 * HttpURLConnection and HttpsURLConnection. 1390 */ 1391 static class ClientConnectionWork extends Work { 1392 1393 // connection to be used to contact the server side 1394 private HttpURLConnection connection; 1395 1396 /** 1397 * Creates the thread acting as a client side. 1398 * 1399 * @param connection 1400 * connection to be used to contact the server side 1401 */ 1402 public ClientConnectionWork(HttpURLConnection connection) { 1403 this.connection = connection; 1404 setName("Client Connection"); 1405 log("Created over connection: " + connection.getClass()); 1406 } 1407 1408 /** 1409 * Performs the actual client work. If some exception occurs during the 1410 * work it will be stored in the <code>thrown<code> field. 1411 */ 1412 public void run() { 1413 try { 1414 log("Opening the connection.."); 1415 connection.connect(); 1416 log("Connection has been ESTABLISHED, using proxy: " 1417 + connection.usingProxy()); 1418 if (connection.getDoOutput()) { 1419 // connection configured to post data, do so 1420 connection.getOutputStream().write(clientsData.getBytes("UTF-8")); 1421 } 1422 // read the content of HTTP(s) response 1423 InputStream is = connection.getInputStream(); 1424 log("Input Stream obtained: " + is.getClass()); 1425 byte[] buff = new byte[2048]; 1426 int num = 0; 1427 int byt = 0; 1428 while ((num < buff.length) && (is.available() > 0) 1429 && ((byt = is.read()) != -1)) { 1430 buff[num++] = (byte) byt; 1431 } 1432 String message = new String(buff, 0, num, "UTF-8"); 1433 log("Got content:\n" + message); 1434 log("------------------"); 1435 log("Response code: " + connection.getResponseCode()); 1436 1437 if (connection instanceof HttpsURLConnection) { 1438 assertEquals(httpsResponseContent, message); 1439 } else { 1440 assertEquals(plainResponseContent, message); 1441 } 1442 } catch (Throwable e) { 1443 if (DO_LOG) { 1444 e.printStackTrace(); 1445 } 1446 thrown = e; 1447 } 1448 } 1449 } 1450 1451 public static junit.framework.Test suite() { 1452 return new TestSuite(HttpsURLConnectionTest.class); 1453 } 1454 1455 } 1456