AbortResponse headers case insensitive header names

Signed-off-by: jansupol <jan.supol@oracle.com>
diff --git a/core-client/src/test/java/org/glassfish/jersey/client/AbortTest.java b/core-client/src/test/java/org/glassfish/jersey/client/AbortTest.java
index 1bac330..974cbe9 100644
--- a/core-client/src/test/java/org/glassfish/jersey/client/AbortTest.java
+++ b/core-client/src/test/java/org/glassfish/jersey/client/AbortTest.java
@@ -53,6 +53,7 @@
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Locale;
 import java.util.Map;
 import java.util.concurrent.CompletionStage;
 import java.util.concurrent.atomic.AtomicReference;
@@ -225,6 +226,43 @@
         }
     }
 
+    @Test
+    public void testResponseContextCaseInsensitiveKeys() {
+        try (Response response = ClientBuilder.newClient()
+                .register(new ClientRequestFilter() {
+                    @Override
+                    public void filter(ClientRequestContext requestContext) throws IOException {
+                        requestContext.abortWith(Response.ok()
+                                .header("header1", "value")
+                                .header("header1", "value1 , value2")
+                                .header("header1", "Value3,white space ")
+                                .header("header2", "Value4;;Value5")
+                                .build());
+                    }
+                })
+                .register(new ClientResponseFilter() {
+                    @Override
+                    public void filter(ClientRequestContext requestContext, ClientResponseContext context) {
+                        Assertions.assertTrue(context.getHeaderString("header1").contains("value"));
+                        Assertions.assertTrue(context.getHeaderString("HEADER1").contains("value2"));
+                        //White space in value not trimmed
+                        Assertions.assertFalse(context.getHeaderString("header1").contains("whitespace"));
+                        //Multiple character separator
+                        Assertions.assertTrue(context.getHeaderString("header2").contains("Value5"));
+
+                        Assertions.assertTrue(context.getHeaders().containsKey("HEADer1"));
+                        Assertions.assertFalse(context.getHeaders().get("HEADer1").isEmpty());
+                        Assertions.assertFalse(context.getHeaders().remove("HeAdEr1").isEmpty());
+                        Assertions.assertFalse(context.getHeaders().containsKey("header1"));
+                    }
+                })
+                .target("http://localhost:8080")
+                .request()
+                .get()) {
+            Assertions.assertEquals(200, response.getStatus());
+        }
+    }
+
     private static class StringHeader extends AtomicReference<String> {
 
     }
diff --git a/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/Views.java b/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/Views.java
index 75b1987..d1480d2 100644
--- a/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/Views.java
+++ b/core-common/src/main/java/org/glassfish/jersey/internal/util/collection/Views.java
@@ -230,6 +230,76 @@
             final List<Object> old = originalMap.put(key, (List<Object>) (List<?>) value);
             return valuesTransformer.apply(old);
         }
+
+        @Override
+        public boolean containsKey(Object key) {
+            Iterator<Entry<String, List<String>>> i = entrySet().iterator();
+            if (key == null) {
+                while (i.hasNext()) {
+                    Entry<String, List<String>> e = i.next();
+                    if (e.getKey() == null) {
+                        return true;
+                    }
+                }
+            } else {
+                while (i.hasNext()) {
+                    Entry<String, List<String>> e = i.next();
+                    if (((String) key).equalsIgnoreCase(e.getKey())) {
+                        return true;
+                    }
+                }
+            }
+            return false;
+        }
+
+        @Override
+        public List<String> get(Object key) {
+            Iterator<Entry<String, List<String>>> i = entrySet().iterator();
+            if (key == null) {
+                while (i.hasNext()) {
+                    Entry<String, List<String>> e = i.next();
+                    if (e.getKey() == null) {
+                        return e.getValue();
+                    }
+                }
+            } else {
+                while (i.hasNext()) {
+                    Entry<String, List<String>> e = i.next();
+                    if (((String) key).equalsIgnoreCase(e.getKey())) {
+                        return e.getValue();
+                    }
+                }
+            }
+            return null;
+        }
+
+        @Override
+        public List<String> remove(Object key) {
+            Iterator<Entry<String, List<String>>> i = entrySet().iterator();
+            Entry<String, List<String>> correctEntry = null;
+            if (key == null) {
+                while (correctEntry == null && i.hasNext()) {
+                    Entry<String, List<String>> e = i.next();
+                    if (e.getKey() == null) {
+                        correctEntry = e;
+                    }
+                }
+            } else {
+                while (correctEntry == null && i.hasNext()) {
+                    Entry<String, List<String>> e = i.next();
+                    if (((String) key).equalsIgnoreCase(e.getKey())) {
+                        correctEntry = e;
+                    }
+                }
+            }
+
+            List<String> oldValue = null;
+            if (correctEntry != null) {
+                oldValue = correctEntry.getValue();
+                i.remove();
+            }
+            return oldValue;
+        }
     }
 
     /**