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