Repository: tomee Updated Branches: refs/heads/master d7e062cc5 -> f91f2833e
TOMEE-1922 multiple values support for openejb-http Project: http://git-wip-us.apache.org/repos/asf/tomee/repo Commit: http://git-wip-us.apache.org/repos/asf/tomee/commit/f91f2833 Tree: http://git-wip-us.apache.org/repos/asf/tomee/tree/f91f2833 Diff: http://git-wip-us.apache.org/repos/asf/tomee/diff/f91f2833 Branch: refs/heads/master Commit: f91f2833e88f7f916c5e05671cc0225101187e45 Parents: d7e062c Author: Romain manni-Bucau <rmannibu...@gmail.com> Authored: Wed Sep 7 09:58:28 2016 +0200 Committer: Romain manni-Bucau <rmannibu...@gmail.com> Committed: Wed Sep 7 09:58:28 2016 +0200 ---------------------------------------------------------------------- .../apache/openejb/server/cxf/rs/LinkTest.java | 75 ++++++++++++++++++++ .../openejb/server/httpd/HttpRequestImpl.java | 40 ++++++----- .../openejb/server/httpd/HttpResponseImpl.java | 42 +++++++---- .../openejb/server/httpd/OpenEJBHttpServer.java | 16 ++++- 4 files changed, 140 insertions(+), 33 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/tomee/blob/f91f2833/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/LinkTest.java ---------------------------------------------------------------------- diff --git a/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/LinkTest.java b/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/LinkTest.java new file mode 100644 index 0000000..f34f32f --- /dev/null +++ b/server/openejb-cxf-rs/src/test/java/org/apache/openejb/server/cxf/rs/LinkTest.java @@ -0,0 +1,75 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.openejb.server.cxf.rs; + +import org.apache.openejb.junit.ApplicationComposer; +import org.apache.openejb.testing.Classes; +import org.apache.openejb.testing.EnableServices; +import org.apache.openejb.testing.RandomPort; +import org.junit.Test; +import org.junit.runner.RunWith; + +import javax.enterprise.context.ApplicationScoped; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.core.Link; +import javax.ws.rs.core.Response; +import java.io.IOException; +import java.net.URL; +import java.util.Collection; +import java.util.Set; + +import static javax.ws.rs.core.MediaType.WILDCARD_TYPE; +import static org.junit.Assert.assertEquals; + +@EnableServices("jaxrs") +@Classes(cdi = true, innerClassesAsBean = true) +@RunWith(ApplicationComposer.class) +public class LinkTest { + @RandomPort("http") + private URL base; + + @Test + public void get() throws IOException { + final Response response = ClientBuilder.newClient() + .target(base.toExternalForm()).path("openejb/link") + .property("org.apache.cxf.http.header.split", true) + .request(WILDCARD_TYPE).get(); + assertEquals(2, Collection.class.cast(response.getHeaders().get("a")).size()); + + final Set<Link> actual = response.getLinks(); + assertEquals(2, actual.size()); + + final Set<Link> expected = new LinkEndpoint().doLink().getLinks(); + assertEquals(expected, actual); + } + + @Path("link") + @ApplicationScoped + public static class LinkEndpoint { + @GET + public Response doLink() { + return Response.ok() + .header("a", "1") + .header("a", "2") + .link("http://test1", "self") + .link("http://test2", "rel") + .build(); + } + } +} http://git-wip-us.apache.org/repos/asf/tomee/blob/f91f2833/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/HttpRequestImpl.java ---------------------------------------------------------------------- diff --git a/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/HttpRequestImpl.java b/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/HttpRequestImpl.java index 42951cf..3ae0608 100644 --- a/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/HttpRequestImpl.java +++ b/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/HttpRequestImpl.java @@ -46,6 +46,7 @@ import java.security.Principal; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.Enumeration; import java.util.HashMap; import java.util.LinkedList; @@ -109,7 +110,7 @@ public class HttpRequestImpl implements HttpRequest { /** * the headers for this page */ - private final Map<String, String> headers = new HashMap<>(); + private final Map<String, List<String>> headers = new HashMap<>(); /** * the form parameters for this page @@ -178,7 +179,8 @@ public class HttpRequestImpl implements HttpRequest { * @return The value of the header */ public String getHeader(String name) { - return headers.get(name); + List<String> strings = headers.get(name); + return strings == null || strings.isEmpty() ? null : strings.get(0); } @Override @@ -188,12 +190,14 @@ public class HttpRequestImpl implements HttpRequest { @Override public Enumeration<String> getHeaders(String s) { - return new ArrayEnumeration(Arrays.asList(headers.get(s))); + final List<String> list = headers.get(s); + return new ArrayEnumeration(list == null ? Collections.emptyList() : list); } @Override - public int getIntHeader(String s) { - return Integer.parseInt(s); + public int getIntHeader(final String s) { + final String header = getHeader(s); + return header == null ? -1 : Integer.parseInt(header); } /** @@ -404,7 +408,7 @@ public class HttpRequestImpl implements HttpRequest { parameters.putAll(queryParams); if (headers.containsKey("Cookie")) { - final String cookie = headers.get("Cookie"); + final String cookie = getHeader("Cookie"); if (cookie != null) { final String[] cookies = cookie.split(";"); for (String c : cookies) { @@ -429,7 +433,7 @@ public class HttpRequestImpl implements HttpRequest { final StringBuilder builder = new StringBuilder(); builder.append("******************* REQUEST ******************\n"); builder.append(method).append(" ").append(uri).append("\n"); - for (Map.Entry<String, String> entry : headers.entrySet()) { + for (Map.Entry<String, List<String>> entry : headers.entrySet()) { builder.append(entry).append("\n"); } builder.append("\n"); @@ -609,21 +613,21 @@ public class HttpRequestImpl implements HttpRequest { } /* [1] parse the name */ - int colonIndex = hf.indexOf((int) ':'); - String name = hf.substring(0, colonIndex); - if (name == null) - break; + final int colonIndex = hf.indexOf((int) ':'); + final String name = hf.substring(0, colonIndex); /* [2] Parse the Value */ - String value = hf.substring(colonIndex + 1, hf.length()); - if (value == null) - break; - value = value.trim(); - headers.put(name, value); + final String value = hf.substring(colonIndex + 1, hf.length()).trim(); + List<String> values = headers.get(name); + if (values == null) { + values = new ArrayList<>(); + headers.put(name, values); + } + values.add(value); } // Update the URI to be what the client sees the the server as. - String host = headers.get("Host"); + final String host = getHeader("Host"); if (host != null) { String hostName; int port = uri.getPort(); @@ -712,7 +716,7 @@ public class HttpRequestImpl implements HttpRequest { formParams.put(name, value); } - } else if (hasBody && CHUNKED.equals(headers.get(TRANSFER_ENCODING))) { + } else if (hasBody && CHUNKED.equals(getHeader(TRANSFER_ENCODING))) { try { ByteArrayOutputStream out = new ByteArrayOutputStream(4096); for (String line = in.readLine(); line != null; line = in.readLine()) { http://git-wip-us.apache.org/repos/asf/tomee/blob/f91f2833/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/HttpResponseImpl.java ---------------------------------------------------------------------- diff --git a/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/HttpResponseImpl.java b/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/HttpResponseImpl.java index 2229a42..c1a7af5 100644 --- a/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/HttpResponseImpl.java +++ b/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/HttpResponseImpl.java @@ -33,13 +33,16 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.net.URLConnection; +import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; +import java.util.List; import java.util.Locale; import java.util.Map; import java.util.StringTokenizer; +import static java.util.Collections.singletonList; + /** * This class takes care of HTTP Responses. It sends data back to the browser. */ @@ -60,7 +63,7 @@ public class HttpResponseImpl implements HttpResponse { /** * Response headers */ - private final Map<String, String> headers = new HashMap<String, String>(); + private final Map<String, List<String>> headers = new HashMap<>(); /** * the writer for the response @@ -110,12 +113,12 @@ public class HttpResponseImpl implements HttpResponse { * @param value the value of the header */ public void setHeader(final String name, final String value) { - headers.put(name, value); + headers.put(name, new ArrayList<>(singletonList(value))); } @Override public void setIntHeader(final String s, final int i) { - headers.put(s, Integer.toString(i)); + setHeader(s, Integer.toString(i)); } @Override @@ -131,17 +134,22 @@ public class HttpResponseImpl implements HttpResponse { @Override public void addCookie(final Cookie cookie) { - headers.put(cookie.getName(), cookie.getValue()); + setHeader(cookie.getName(), cookie.getValue()); } @Override public void addDateHeader(final String s, final long l) { - headers.put(s, Long.toString(l)); + setHeader(s, Long.toString(l)); } @Override public void addHeader(final String s, final String s1) { - headers.put(s, s1); + Collection<String> list = headers.get(s); + if (list == null) { + setHeader(s, s1); + } else { + list.add(s1); + } } @Override @@ -181,7 +189,8 @@ public class HttpResponseImpl implements HttpResponse { * @return the value of the header */ public String getHeader(final String name) { - return headers.get(name); + final Collection<String> strings = headers.get(name); + return strings == null ? null : strings.iterator().next(); } @Override @@ -191,7 +200,7 @@ public class HttpResponseImpl implements HttpResponse { @Override public Collection<String> getHeaders(final String s) { - return Collections.singletonList(headers.get(s)); + return headers.get(s); } @Override @@ -484,7 +493,7 @@ public class HttpResponseImpl implements HttpResponse { return; } - headers.put(HttpRequest.HEADER_SET_COOKIE, SessionManager.EJBSESSIONID + '=' + session.getId() + "; Path=/"); + setHeader(HttpRequest.HEADER_SET_COOKIE, SessionManager.EJBSESSIONID + '=' + session.getId() + "; Path=/"); } /** @@ -515,10 +524,19 @@ public class HttpResponseImpl implements HttpResponse { * @throws java.io.IOException if an exception is thrown */ private void writeHeaders(final DataOutput out) throws IOException { - for (final Map.Entry<String, String> entry : headers.entrySet()) { + for (final Map.Entry<String, List<String>> entry : headers.entrySet()) { out.writeBytes("" + entry.getKey()); out.writeBytes(CSP); - out.writeBytes("" + entry.getValue()); + if (entry.getValue().size() == 1) { + out.writeBytes("" + entry.getValue().get(0)); + } else if (entry.getValue().size() > 1) { + final StringBuilder builder = new StringBuilder(); + for (final String e : entry.getValue()) { + builder.append(e).append(','); + } + builder.setLength(builder.length() - 1); + out.write(builder.toString().getBytes(encoding)); + } out.writeBytes(CRLF); } } http://git-wip-us.apache.org/repos/asf/tomee/blob/f91f2833/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/OpenEJBHttpServer.java ---------------------------------------------------------------------- diff --git a/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/OpenEJBHttpServer.java b/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/OpenEJBHttpServer.java index 6f480c5..2fa3d6d 100644 --- a/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/OpenEJBHttpServer.java +++ b/server/openejb-http/src/main/java/org/apache/openejb/server/httpd/OpenEJBHttpServer.java @@ -43,6 +43,8 @@ import java.io.StringWriter; import java.net.Socket; import java.net.SocketException; import java.net.URI; +import java.util.Collection; +import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; @@ -83,9 +85,17 @@ public class OpenEJBHttpServer implements HttpServer { listener == null ? getHttpListenerRegistry() : listener, ParentClassLoaderFinder.Helper.get()); } - public static boolean isTextXml(final Map<String, String> headers) { - final String contentType = headers.get("Content-Type"); - return contentType != null && contentType.contains("text/xml"); + public static boolean isTextXml(final Map<String, List<String>> headers) { + final Collection<String> contentType = headers.get("Content-Type"); + if (contentType == null) { + return false; + } + for (final String current : contentType) { + if (current.contains("text/xml")) { + return true; + } + } + return false; } @Override