1 /*
   2  * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  15  * You should have received a copy of the GNU General Public License version
  16  * 2 along with this work; if not, write to the Free Software Foundation,
  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 /**
  25  * @test
  26  * @bug 7128648
  27  * @summary HttpURLConnection.getHeaderFields should return an unmodifiable Map
  28  */
  29 
  30 import java.io.IOException;
  31 import java.net.InetAddress;
  32 import java.net.InetSocketAddress;
  33 import java.net.URI;
  34 import java.net.HttpURLConnection;
  35 import java.util.Collection;
  36 import java.util.ArrayList;
  37 import java.util.List;
  38 import java.util.Map;
  39 import com.sun.net.httpserver.HttpExchange;
  40 import com.sun.net.httpserver.HttpHandler;
  41 import com.sun.net.httpserver.HttpServer;
  42 import com.sun.net.httpserver.Headers;
  43 
  44 public class UnmodifiableMaps {
  45 
  46     void test(String[] args) throws Exception {
  47         HttpServer server = startHttpServer();
  48         try {
  49             InetSocketAddress address = server.getAddress();
  50             URI uri = new URI("http://" + InetAddress.getLocalHost().getHostAddress()
  51                               + ":" + address.getPort() + "/foo");
  52             doClient(uri);
  53         } finally {
  54             server.stop(0);
  55         }
  56     }
  57 
  58     void doClient(URI uri) throws Exception {
  59         HttpURLConnection uc = (HttpURLConnection) uri.toURL().openConnection();
  60 
  61         // Test1: getRequestProperties is unmodifiable
  62         System.out.println("Check getRequestProperties");
  63         checkUnmodifiable(uc.getRequestProperties());
  64         uc.addRequestProperty("X", "V");
  65         uc.addRequestProperty("X1", "V1");
  66         checkUnmodifiable(uc.getRequestProperties());
  67 
  68         int resp = uc.getResponseCode();
  69         check(resp == 200,
  70               "Unexpected response code. Expected 200, got " + resp);
  71 
  72         // Test2: getHeaderFields is unmodifiable
  73         System.out.println("Check getHeaderFields");
  74         checkUnmodifiable(uc.getHeaderFields());
  75         // If the implementation does caching, check again.
  76         checkUnmodifiable(uc.getHeaderFields());
  77     }
  78 
  79     // HTTP Server
  80     HttpServer startHttpServer() throws IOException {
  81         HttpServer httpServer = HttpServer.create(new InetSocketAddress(0), 0);
  82         httpServer.createContext("/foo", new SimpleHandler());
  83         httpServer.start();
  84         return httpServer;
  85     }
  86 
  87     class SimpleHandler implements HttpHandler {
  88         @Override
  89         public void handle(HttpExchange t) throws IOException {
  90             Headers respHeaders = t.getResponseHeaders();
  91             // ensure some response headers, over the usual ones
  92             respHeaders.add("RespHdr1", "Value1");
  93             respHeaders.add("RespHdr2", "Value2");
  94             respHeaders.add("RespHdr3", "Value3");
  95             t.sendResponseHeaders(200, -1);
  96             t.close();
  97         }
  98     }
  99 
 100     void checkUnmodifiable(Map<String,List<String>> map) {
 101         checkUnmodifiableMap(map);
 102 
 103         // Now check the individual values
 104         Collection<List<String>> values = map.values();
 105         for (List<String> value : values) {
 106             checkUnmodifiableList(value);
 107         }
 108     }
 109 
 110     void checkUnmodifiableMap(final Map<String,List<String>> map) {
 111         expectThrow( new Runnable() {
 112             public void run() { map.clear(); }});
 113         expectThrow( new Runnable() {
 114             public void run() { map.put("X", new ArrayList<String>()); }});
 115         expectThrow( new Runnable() {
 116             public void run() { map.remove("X"); }});
 117     }
 118 
 119     void checkUnmodifiableList(final List<String> list) {
 120         expectThrow( new Runnable() {
 121             public void run() { list.clear(); }});
 122         expectThrow( new Runnable() {
 123             public void run() { list.add("X"); }});
 124         expectThrow( new Runnable() {
 125             public void run() { list.remove("X"); }});
 126     }
 127 
 128     void expectThrow(Runnable r) {
 129         try { r.run(); fail("Excepted UOE to be thrown."); Thread.dumpStack(); }
 130         catch (UnsupportedOperationException e) { pass(); }
 131     }
 132 
 133     volatile int passed = 0, failed = 0;
 134     void pass() {passed++;}
 135     void fail() {failed++;}
 136     void fail(String msg) {System.err.println(msg); fail();}
 137     void unexpected(Throwable t) {failed++; t.printStackTrace();}
 138     void check(boolean cond, String failMessage) {if (cond) pass(); else fail(failMessage);}
 139     public static void main(String[] args) throws Throwable {
 140         Class<?> k = new Object(){}.getClass().getEnclosingClass();
 141         try {k.getMethod("instanceMain",String[].class)
 142                 .invoke( k.newInstance(), (Object) args);}
 143         catch (Throwable e) {throw e.getCause();}}
 144     public void instanceMain(String[] args) throws Throwable {
 145         try {test(args);} catch (Throwable t) {unexpected(t);}
 146         System.out.printf("%nPassed = %d, failed = %d%n%n", passed, failed);
 147         if (failed > 0) throw new AssertionError("Some tests failed");}
 148 }
 149