merge of the current 2.x into the 3.0
diff --git a/containers/jdk-http/pom.xml b/containers/jdk-http/pom.xml
index 659b4dc..f81c101 100644
--- a/containers/jdk-http/pom.xml
+++ b/containers/jdk-http/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2010, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -34,12 +34,6 @@
<dependencies>
<dependency>
- <groupId>commons-io</groupId>
- <artifactId>commons-io</artifactId>
- <scope>test</scope>
- <version>${commons.io.version}</version>
- </dependency>
- <dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
<scope>test</scope>
diff --git a/containers/jdk-http/src/test/java/org/glassfish/jersey/jdkhttp/JdkHttpsServerTest.java b/containers/jdk-http/src/test/java/org/glassfish/jersey/jdkhttp/JdkHttpsServerTest.java
index 01e9e34..d8a2798 100644
--- a/containers/jdk-http/src/test/java/org/glassfish/jersey/jdkhttp/JdkHttpsServerTest.java
+++ b/containers/jdk-http/src/test/java/org/glassfish/jersey/jdkhttp/JdkHttpsServerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -30,9 +30,9 @@
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLHandshakeException;
-import org.apache.commons.io.IOUtils;
import org.glassfish.jersey.SslConfigurator;
import org.glassfish.jersey.internal.util.JdkVersion;
+import org.glassfish.jersey.message.internal.ReaderWriter;
import org.glassfish.jersey.server.ResourceConfig;
import org.junit.jupiter.api.AfterEach;
@@ -195,9 +195,9 @@
final SslConfigurator sslConfigClient = SslConfigurator.newInstance()
- .trustStoreBytes(IOUtils.toByteArray(trustStore))
+ .trustStoreBytes(ReaderWriter.readFromAsBytes(trustStore))
.trustStorePassword(TRUSTSTORE_CLIENT_PWD)
- .keyStoreBytes(IOUtils.toByteArray(keyStore))
+ .keyStoreBytes(ReaderWriter.readFromAsBytes(keyStore))
.keyPassword(KEYSTORE_CLIENT_PWD);
return sslConfigClient.createSSLContext();
@@ -208,9 +208,9 @@
final InputStream keyStore = JdkHttpsServerTest.class.getResourceAsStream(KEYSTORE_SERVER_FILE);
final SslConfigurator sslConfigServer = SslConfigurator.newInstance()
- .keyStoreBytes(IOUtils.toByteArray(keyStore))
+ .keyStoreBytes(ReaderWriter.readFromAsBytes(keyStore))
.keyPassword(KEYSTORE_SERVER_PWD)
- .trustStoreBytes(IOUtils.toByteArray(trustStore))
+ .trustStoreBytes(ReaderWriter.readFromAsBytes(trustStore))
.trustStorePassword(TRUSTSTORE_SERVER_PWD);
return sslConfigServer.createSSLContext();
diff --git a/core-client/src/main/java/org/glassfish/jersey/client/ClientResponse.java b/core-client/src/main/java/org/glassfish/jersey/client/ClientResponse.java
index 35fcef5..698fb39 100644
--- a/core-client/src/main/java/org/glassfish/jersey/client/ClientResponse.java
+++ b/core-client/src/main/java/org/glassfish/jersey/client/ClientResponse.java
@@ -63,8 +63,12 @@
* @param response JAX-RS response to be used to initialize the response context.
*/
public ClientResponse(final ClientRequest requestContext, final Response response) {
- this(response.getStatusInfo(), requestContext);
- this.headers(OutboundJaxrsResponse.from(response, requestContext.getConfiguration()).getContext().getStringHeaders());
+ super(requestContext.getConfiguration(),
+ OutboundJaxrsResponse.from(response, requestContext.getConfiguration()).getContext().getStringHeaders(),
+ false
+ );
+ this.requestContext = requestContext;
+ init(response.getStatusInfo(), requestContext, requestContext.getUri());
final Object entity = response.getEntity();
if (entity != null) {
@@ -122,10 +126,13 @@
*/
public ClientResponse(Response.StatusType status, ClientRequest requestContext, URI resolvedRequestUri) {
super(requestContext.getConfiguration());
+ this.requestContext = requestContext;
+ init(status, requestContext, resolvedRequestUri);
+ }
+
+ private void init(Response.StatusType status, ClientRequest requestContext, URI resolvedRequestUri) {
this.status = status;
this.resolvedUri = resolvedRequestUri;
- this.requestContext = requestContext;
-
setWorkers(requestContext.getWorkers());
}
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 caffa4d..ae487bf 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
@@ -16,19 +16,30 @@
package org.glassfish.jersey.client;
+import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
+import jakarta.ws.rs.Priorities;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.WebApplicationException;
import jakarta.ws.rs.client.Client;
import jakarta.ws.rs.client.ClientBuilder;
import jakarta.ws.rs.client.ClientRequestContext;
import jakarta.ws.rs.client.ClientRequestFilter;
+import jakarta.ws.rs.client.ClientResponseContext;
+import jakarta.ws.rs.client.ClientResponseFilter;
+import jakarta.ws.rs.core.Application;
import jakarta.ws.rs.core.GenericEntity;
+import jakarta.ws.rs.core.Link;
import jakarta.ws.rs.core.MediaType;
import jakarta.ws.rs.core.MultivaluedMap;
import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.UriBuilder;
+import jakarta.ws.rs.core.Variant;
import jakarta.ws.rs.ext.MessageBodyWriter;
+import jakarta.ws.rs.ext.ReaderInterceptor;
+import jakarta.ws.rs.ext.ReaderInterceptorContext;
+import jakarta.ws.rs.ext.RuntimeDelegate;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.annotation.Annotation;
@@ -37,18 +48,25 @@
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
import java.util.List;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicReference;
-//import static java.nio.charset.StandardCharsets;
import static org.junit.jupiter.api.Assertions.assertEquals;
public class AbortTest {
private static final String TEXT_CSV = "text/csv";
+ private static final String TEXT_HEADER = "text/header";
private static final String EXPECTED_CSV = "hello;goodbye\nsalutations;farewell";
private static final List<List<String>> CSV_LIST = Arrays.asList(
Arrays.asList("hello", "goodbye"),
Arrays.asList("salutations", "farewell")
);
+ private final String entity = "HI";
+ private final String header = "CUSTOM_HEADER";
+
@Test
void testAbortWithGenericEntity() {
@@ -77,7 +95,6 @@
@Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
- System.out.println(genericType.getTypeName());
return List.class.isAssignableFrom(type) && genericType instanceof ParameterizedType
&& ((ParameterizedType) genericType).getActualTypeArguments()[0] instanceof ParameterizedType
&& String.class.equals(((ParameterizedType) ((ParameterizedType) genericType).getActualTypeArguments()[0])
@@ -99,4 +116,172 @@
}
}
+ @Test
+ void testAbortWithMBWWritingHeaders() {
+ try (Response response = ClientBuilder.newClient().register(new ClientRequestFilter() {
+ @Override
+ public void filter(ClientRequestContext requestContext) throws IOException {
+ requestContext.abortWith(Response.ok(entity, TEXT_HEADER).build());
+ }
+ }).register(new MessageBodyWriter<String>() {
+
+ @Override
+ public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+ return mediaType.toString().equals(TEXT_HEADER);
+ }
+
+ @Override
+ public void writeTo(String s, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+ MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException,
+ WebApplicationException {
+ httpHeaders.add(header, entity);
+ entityStream.write(s.getBytes());
+ }
+ }, Priorities.USER - 1).target("http://localhost:8080").request().get()) {
+ Assertions.assertEquals(entity, response.readEntity(String.class));
+ Assertions.assertEquals(entity, response.getHeaderString(header));
+ }
+ }
+
+ @Test
+ void testInterceptorHeaderAdd() {
+ final String header2 = "CUSTOM_HEADER_2";
+
+ try (Response response = ClientBuilder.newClient().register(new ClientRequestFilter() {
+ @Override
+ public void filter(ClientRequestContext requestContext) throws IOException {
+ requestContext.abortWith(Response.ok().entity(entity).build());
+ }
+ }).register(new ReaderInterceptor() {
+ @Override
+ public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ MultivaluedMap<String, String> headers = context.getHeaders();
+ headers.put(header, Collections.singletonList(entity));
+ headers.add(header2, entity);
+ return context.proceed();
+ }
+ })
+ .target("http://localhost:8080").request().get()) {
+ Assertions.assertEquals(entity, response.readEntity(String.class));
+ Assertions.assertEquals(entity, response.getHeaderString(header));
+ Assertions.assertEquals(entity, response.getHeaderString(header2));
+ }
+ }
+
+ @Test
+ void testInterceptorHeaderIterate() {
+ final AtomicReference<String> originalHeader = new AtomicReference<>();
+
+ try (Response response = ClientBuilder.newClient().register(new ClientRequestFilter() {
+ @Override
+ public void filter(ClientRequestContext requestContext) throws IOException {
+ requestContext.abortWith(Response.ok().header(header, header).entity(entity).build());
+ }
+ }).register(new ReaderInterceptor() {
+ @Override
+ public Object aroundReadFrom(ReaderInterceptorContext context) throws IOException, WebApplicationException {
+ MultivaluedMap<String, String> headers = context.getHeaders();
+ Iterator<Map.Entry<String, List<String>>> it = headers.entrySet().iterator();
+ while (it.hasNext()) {
+ Map.Entry<String, List<String>> next = it.next();
+ if (header.equals(next.getKey())) {
+ originalHeader.set(next.setValue(Collections.singletonList(entity)).get(0));
+ }
+ }
+ return context.proceed();
+ }
+ })
+ .target("http://localhost:8080").request().get()) {
+ Assertions.assertEquals(entity, response.readEntity(String.class));
+ Assertions.assertEquals(entity, response.getHeaderString(header));
+ Assertions.assertEquals(header, originalHeader.get());
+ }
+ }
+
+ @Test
+ void testNullHeader() {
+ final AtomicReference<String> originalHeader = new AtomicReference<>();
+ RuntimeDelegate.setInstance(new StringHeaderRuntimeDelegate(RuntimeDelegate.getInstance()));
+ try (Response response = ClientBuilder.newClient().register(new ClientRequestFilter() {
+ @Override
+ public void filter(ClientRequestContext requestContext) throws IOException {
+ requestContext.abortWith(Response.ok()
+ .header(header, new StringHeader())
+ .entity(entity).build());
+ }
+ }).register(new ClientResponseFilter() {
+ @Override
+ public void filter(ClientRequestContext requestContext, ClientResponseContext responseContext)
+ throws IOException {
+ originalHeader.set(responseContext.getHeaderString(header));
+ }
+ })
+ .target("http://localhost:8080").request().get()) {
+ Assertions.assertEquals(entity, response.readEntity(String.class));
+ Assertions.assertEquals("", originalHeader.get());
+ }
+ }
+
+ private static class StringHeader extends AtomicReference<String> {
+
+ }
+
+ private static class StringHeaderDelegate implements RuntimeDelegate.HeaderDelegate<StringHeader> {
+ @Override
+ public StringHeader fromString(String value) {
+ StringHeader stringHeader = new StringHeader();
+ stringHeader.set(value);
+ return stringHeader;
+ }
+
+ @Override
+ public String toString(StringHeader value) {
+ //on purpose
+ return null;
+ }
+ }
+
+ private static class StringHeaderRuntimeDelegate extends RuntimeDelegate {
+ private final RuntimeDelegate original;
+
+ private StringHeaderRuntimeDelegate(RuntimeDelegate original) {
+ this.original = original;
+ }
+
+ @Override
+ public UriBuilder createUriBuilder() {
+ return original.createUriBuilder();
+ }
+
+ @Override
+ public Response.ResponseBuilder createResponseBuilder() {
+ return original.createResponseBuilder();
+ }
+
+ @Override
+ public Variant.VariantListBuilder createVariantListBuilder() {
+ return original.createVariantListBuilder();
+ }
+
+ @Override
+ public <T> T createEndpoint(Application application, Class<T> endpointType)
+ throws IllegalArgumentException, UnsupportedOperationException {
+ return original.createEndpoint(application, endpointType);
+ }
+
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> HeaderDelegate<T> createHeaderDelegate(Class<T> type) throws IllegalArgumentException {
+ if (StringHeader.class.equals(type)) {
+ return (HeaderDelegate<T>) new StringHeaderDelegate();
+ }
+ return original.createHeaderDelegate(type);
+ }
+
+ @Override
+ public Link.Builder createLinkBuilder() {
+ return original.createLinkBuilder();
+ }
+ }
+
}
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 4765056..75b1987 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
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2016, 2024 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -129,60 +129,107 @@
* @return transformed map view.
*/
public static <K, V, O> Map<K, V> mapView(Map<K, O> originalMap, Function<O, V> valuesTransformer) {
- return new AbstractMap<K, V>() {
- @Override
- public Set<Entry<K, V>> entrySet() {
- return new AbstractSet<Entry<K, V>>() {
+ return new KVOMap<K, V, O>(originalMap, valuesTransformer);
+ }
+ private static class KVOMap<K, V, O> extends AbstractMap<K, V> {
+ protected final Map<K, O> originalMap;
+ protected final Function<O, V> valuesTransformer;
- Set<Entry<K, O>> originalSet = originalMap.entrySet();
- Iterator<Entry<K, O>> original = originalSet.iterator();
+ private KVOMap(Map<K, O> originalMap, Function<O, V> valuesTransformer) {
+ this.originalMap = originalMap;
+ this.valuesTransformer = valuesTransformer;
+ }
- @Override
- public Iterator<Entry<K, V>> iterator() {
- return new Iterator<Entry<K, V>>() {
- @Override
- public boolean hasNext() {
- return original.hasNext();
- }
+ @Override
+ public Set<Entry<K, V>> entrySet() {
+ return new AbstractSet<Entry<K, V>>() {
- @Override
- public Entry<K, V> next() {
+ Set<Entry<K, O>> originalSet = originalMap.entrySet();
+ Iterator<Entry<K, O>> original = originalSet.iterator();
- Entry<K, O> next = original.next();
+ @Override
+ public Iterator<Entry<K, V>> iterator() {
+ return new Iterator<Entry<K, V>>() {
+ @Override
+ public boolean hasNext() {
+ return original.hasNext();
+ }
- return new Entry<K, V>() {
- @Override
- public K getKey() {
- return next.getKey();
- }
+ @Override
+ public Entry<K, V> next() {
- @Override
- public V getValue() {
- return valuesTransformer.apply(next.getValue());
- }
+ Entry<K, O> next = original.next();
- @Override
- public V setValue(V value) {
- throw new UnsupportedOperationException("Not supported.");
- }
- };
- }
+ return new Entry<K, V>() {
+ @Override
+ public K getKey() {
+ return next.getKey();
+ }
- @Override
- public void remove() {
- original.remove();
- }
- };
- }
+ @Override
+ public V getValue() {
+ return valuesTransformer.apply(next.getValue());
+ }
- @Override
- public int size() {
- return originalSet.size();
- }
- };
- }
- };
+ @Override
+ public V setValue(V value) {
+ return KVOMap.this.setValue(next, value);
+ }
+ };
+ }
+
+ @Override
+ public void remove() {
+ original.remove();
+ }
+ };
+ }
+
+ @Override
+ public int size() {
+ return originalSet.size();
+ }
+ };
+ }
+
+ protected V setValue(Map.Entry<K, O> entry, V value) {
+ throw new UnsupportedOperationException("Not supported.");
+ }
+ }
+
+ /**
+ * Create a {@link Map} view, which transforms the values of provided original map.
+ * <p>
+ *
+ * @param originalMap provided map.
+ * @param valuesTransformer values transformer.
+ * @return transformed map view.
+ */
+ public static Map<String, List<String>> mapObjectToStringView(Map<String, List<Object>> originalMap,
+ Function<List<Object>, List<String>> valuesTransformer) {
+ return new ObjectToStringMap(originalMap, valuesTransformer);
+ }
+
+ private static class ObjectToStringMap extends KVOMap<String, List<String>, List<Object>> {
+
+ private ObjectToStringMap(Map<String, List<Object>> originalMap, Function<List<Object>, List<String>> valuesTransformer) {
+ super(originalMap, valuesTransformer);
+ }
+
+ @Override
+ protected List<String> setValue(Entry<String, List<Object>> entry, List<String> value) {
+ @SuppressWarnings("unchecked")
+ final List<Object> old = entry.setValue((List<Object>) (List<?>) value);
+ return valuesTransformer.apply(old);
+ }
+
+ @Override
+ public List<String> put(String key, List<String> value) {
+ @SuppressWarnings("unchecked")
+ final List<Object> old = originalMap.put(key, (List<Object>) (List<?>) value);
+ return valuesTransformer.apply(old);
+ }
}
/**
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/CookiesParser.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/CookiesParser.java
index f8bec0a..51bb99e 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/CookiesParser.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/CookiesParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2020 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -86,20 +86,29 @@
}
/**
- * Check if a cookie with identical name had been parsed.
- * If yes, the one with the longest string will be kept
+ * Check if a cookie with similar names had been parsed.
+ * If yes, the one with the longest path will be kept
+ * For similar paths the newest is stored
* @param cookies : Map of cookies
* @param cookie : Cookie to be checked
*/
private static void checkSimilarCookieName(Map<String, Cookie> cookies, MutableCookie cookie) {
- if (cookie != null) {
- if (cookies.containsKey(cookie.name)){
- if (cookie.value.length() > cookies.get(cookie.name).getValue().length()){
- cookies.put(cookie.name, cookie.getImmutableCookie());
- }
- } else {
- cookies.put(cookie.name, cookie.getImmutableCookie());
- }
+ if (cookie == null) {
+ return;
+ }
+
+ boolean alreadyPresent = cookies.containsKey(cookie.name);
+ boolean recordCookie = !alreadyPresent;
+
+ if (alreadyPresent) {
+ final String newPath = cookie.path == null ? "" : cookie.path;
+ final String existingPath = cookies.get(cookie.name).getPath() == null ? ""
+ : cookies.get(cookie.name).getPath();
+ recordCookie = (newPath.length() >= existingPath.length());
+ }
+
+ if (recordCookie) {
+ cookies.put(cookie.name, cookie.getImmutableCookie());
}
}
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/HeaderUtils.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/HeaderUtils.java
index aeea686..c60386b 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/HeaderUtils.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/HeaderUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -210,7 +210,7 @@
}
return new AbstractMultivaluedMap<String, String>(
- Views.mapView(headers, input -> HeaderUtils.asStringList(input, rd))
+ Views.mapObjectToStringView(headers, input -> HeaderUtils.asStringList(input, rd))
) {
};
}
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/InboundMessageContext.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/InboundMessageContext.java
index 29cb6e0..46446a4 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/InboundMessageContext.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/InboundMessageContext.java
@@ -157,8 +157,22 @@
* as required by JAX-RS specification on the server side.
*/
public InboundMessageContext(Configuration configuration, boolean translateNce) {
+ this(configuration, HeaderUtils.createInbound(), translateNce);
+ }
+
+ /**
+ * Create new inbound message context.
+ *
+ * @param configuration the related client/server side {@link Configuration}. If {@code null},
+ * the default behaviour is expected.
+ * @param httpHeaders the http headers map.
+ * @param translateNce if {@code true}, the {@link javax.ws.rs.core.NoContentException} thrown by a
+ * selected message body reader will be translated into a {@link javax.ws.rs.BadRequestException}
+ * as required by JAX-RS specification on the server side.
+ */
+ public InboundMessageContext(Configuration configuration, MultivaluedMap<String, String> httpHeaders, boolean translateNce) {
super(configuration);
- this.headers = new GuardianStringKeyMultivaluedMap<>(HeaderUtils.createInbound());
+ this.headers = new GuardianStringKeyMultivaluedMap<>(httpHeaders);
this.entityContent = new EntityContent();
this.translateNce = translateNce;
this.configuration = configuration;
@@ -302,7 +316,11 @@
}
final Iterator<String> valuesIterator = values.iterator();
- StringBuilder buffer = new StringBuilder(valuesIterator.next());
+ String next = valuesIterator.next();
+ if (next == null) {
+ next = "";
+ }
+ StringBuilder buffer = new StringBuilder(next);
while (valuesIterator.hasNext()) {
buffer.append(',').append(valuesIterator.next());
}
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/ReaderWriter.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/ReaderWriter.java
index 018c9f0..38b5013 100644
--- a/core-common/src/main/java/org/glassfish/jersey/message/internal/ReaderWriter.java
+++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/ReaderWriter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -160,11 +160,23 @@
}
return sb.toString();
}
+
/**
- * The maximum size of array to allocate.
+ * Read/convert stream to the byte array.
+ *
+ * @param in stream to be converted to the byte array
+ * @return the byte array
+ * @throws IOException if there is an error reading from the stream
+ * @since 2.47
+ */
+ public static byte[] readFromAsBytes(InputStream in) throws IOException {
+ return readAllBytes(in);
+ }
+ /**
+ * The maximum size of an array to allocate.
* Some VMs reserve some header words in an array.
* Attempts to allocate larger arrays may result in
- * OutOfMemoryError: Requested array size exceeds VM limit
+ * OutOfMemoryError: Requested array size exceeds the VM limit
*/
private static final int MAX_BUFFER_SIZE = Integer.MAX_VALUE - 8;
diff --git a/pom.xml b/pom.xml
index eb7f65a..7aa01a2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2205,7 +2205,6 @@
<aspectj.weaver.version>1.9.22.1</aspectj.weaver.version>
<!-- <bnd.plugin.version>2.3.6</bnd.plugin.version>-->
<bouncycastle.version>1.70</bouncycastle.version>
- <commons.io.version>2.19.0</commons.io.version>
<commons.codec.version>1.16.1</commons.codec.version>
<!-- <commons-lang3.version>3.3.2</commons-lang3.version>-->
<commons.logging.version>1.3.5</commons.logging.version>
diff --git a/test-framework/maven/container-runner-maven-plugin/pom.xml b/test-framework/maven/container-runner-maven-plugin/pom.xml
index 21bbfd3..b84c7b3 100644
--- a/test-framework/maven/container-runner-maven-plugin/pom.xml
+++ b/test-framework/maven/container-runner-maven-plugin/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -168,10 +168,10 @@
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-archiver</artifactId>
</exclusion>
- <exclusion>
+ <!--<exclusion>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
- </exclusion>
+ </exclusion>-->
<exclusion>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
diff --git a/test-framework/maven/custom-enforcer-rules/pom.xml b/test-framework/maven/custom-enforcer-rules/pom.xml
index 5f702fc..e7ccf4e 100644
--- a/test-framework/maven/custom-enforcer-rules/pom.xml
+++ b/test-framework/maven/custom-enforcer-rules/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2015, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -49,14 +49,14 @@
<artifactId>plexus-utils</artifactId>
</exclusion>
<exclusion>
- <groupId>commons-io</groupId>
- <artifactId>commons-io</artifactId>
- </exclusion>
- <exclusion>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
</exclusion>
<exclusion>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ </exclusion>
+ <exclusion>
<groupId>org.apache.maven</groupId>
<artifactId>maven-core</artifactId>
</exclusion>
@@ -68,12 +68,6 @@
</dependency>
<dependency>
- <groupId>commons-io</groupId>
- <artifactId>commons-io</artifactId>
- <version>${commons.io.version}</version>
- </dependency>
-
- <dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>compile</scope>
diff --git a/test-framework/maven/custom-enforcer-rules/src/main/java/org/glassfish/jersey/test/maven/rule/FilePatternDoesNotExistRule.java b/test-framework/maven/custom-enforcer-rules/src/main/java/org/glassfish/jersey/test/maven/rule/FilePatternDoesNotExistRule.java
index f9c8fde..ee275ba 100644
--- a/test-framework/maven/custom-enforcer-rules/src/main/java/org/glassfish/jersey/test/maven/rule/FilePatternDoesNotExistRule.java
+++ b/test-framework/maven/custom-enforcer-rules/src/main/java/org/glassfish/jersey/test/maven/rule/FilePatternDoesNotExistRule.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2023 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -17,17 +17,19 @@
package org.glassfish.jersey.test.maven.rule;
import java.io.File;
-import java.io.FileFilter;
+import java.io.IOException;
+import java.nio.file.DirectoryStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.Arrays;
import java.util.Set;
import java.util.TreeSet;
-import org.apache.commons.io.filefilter.WildcardFileFilter;
import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
import org.apache.maven.enforcer.rules.AbstractStandardEnforcerRule;
/**
- * Maven enforcer rule to enforce that given set of files does not exist.<br/>
+ * Maven enforcer rule to enforce that a given set of files does not exist.<br/>
* This rule is similar to apache {@code requireFilesDontExist} with a support for wildcards.
*
* @author Stepan Vavra
@@ -55,8 +57,13 @@
}
final Set<File> matchedFiles = new TreeSet<>();
- for (File matchedFile : dir.listFiles((FileFilter) new WildcardFileFilter(fileItselfPattern))) {
- matchedFiles.add(matchedFile);
+ try {
+ final DirectoryStream<Path> directoryStream
+ = Files.newDirectoryStream(dir.toPath(), fileItselfPattern);
+ directoryStream.forEach(path -> matchedFiles.add(path.toFile()));
+ directoryStream.close();
+ } catch (IOException e) {
+ throw new EnforcerRuleException(e);
}
if (!matchedFiles.isEmpty()) {
diff --git a/tests/e2e-client/pom.xml b/tests/e2e-client/pom.xml
index b01f938..22104d4 100644
--- a/tests/e2e-client/pom.xml
+++ b/tests/e2e-client/pom.xml
@@ -225,11 +225,7 @@
<version>${junit-platform-suite.version}</version>
<scope>test</scope>
</dependency>
- <dependency>
- <groupId>commons-io</groupId>
- <artifactId>commons-io</artifactId>
- <version>${commons.io.version}</version>
- </dependency>
+
</dependencies>
<profiles>
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/AbstractConnectorServerTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/AbstractConnectorServerTest.java
index a458eb9..6564024 100644
--- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/AbstractConnectorServerTest.java
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/AbstractConnectorServerTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -18,7 +18,6 @@
import java.io.IOException;
import java.io.InputStream;
-import java.util.Arrays;
import java.util.stream.Stream;
import javax.net.ssl.SSLContext;
@@ -32,11 +31,10 @@
import org.glassfish.jersey.internal.util.JdkVersion;
import org.glassfish.jersey.jetty.connector.JettyConnectorProvider;
+import org.glassfish.jersey.message.internal.ReaderWriter;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
-import org.apache.commons.io.IOUtils;
-
/**
* SSL connector hostname verification tests.
*
@@ -96,9 +94,9 @@
final InputStream trustStore = SslConnectorConfigurationTest.class.getResourceAsStream(clientTrustStore());
final InputStream keyStore = SslConnectorConfigurationTest.class.getResourceAsStream(CLIENT_KEY_STORE);
return SslConfigurator.newInstance()
- .trustStoreBytes(IOUtils.toByteArray(trustStore))
+ .trustStoreBytes(ReaderWriter.readFromAsBytes(trustStore))
.trustStorePassword("asdfgh")
- .keyStoreBytes(IOUtils.toByteArray(keyStore))
+ .keyStoreBytes(ReaderWriter.readFromAsBytes(keyStore))
.keyPassword("asdfgh")
.createSSLContext();
}
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/Server.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/Server.java
index 20795c3..b66ff73 100644
--- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/Server.java
+++ b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/connector/ssl/Server.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -23,9 +23,9 @@
import jakarta.ws.rs.core.UriBuilder;
-import org.apache.commons.io.IOUtils;
import org.glassfish.jersey.logging.LoggingFeature;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;
+import org.glassfish.jersey.message.internal.ReaderWriter;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.grizzly.http.server.HttpServer;
@@ -86,9 +86,9 @@
SSLContextConfigurator sslContext = new SSLContextConfigurator();
// set up security context
- sslContext.setKeyStoreBytes(IOUtils.toByteArray(keyStore)); // contains server key pair
+ sslContext.setKeyStoreBytes(ReaderWriter.readFromAsBytes(keyStore)); // contains server key pair
sslContext.setKeyStorePass("asdfgh");
- sslContext.setTrustStoreBytes(IOUtils.toByteArray(trustStore)); // contains client certificate
+ sslContext.setTrustStoreBytes(ReaderWriter.readFromAsBytes(trustStore)); // contains client certificate
sslContext.setTrustStorePass("asdfgh");
ResourceConfig rc = new ResourceConfig();
diff --git a/tests/e2e-server/pom.xml b/tests/e2e-server/pom.xml
index e0d7298..73c9d23 100644
--- a/tests/e2e-server/pom.xml
+++ b/tests/e2e-server/pom.xml
@@ -217,12 +217,6 @@
</dependency>
<dependency>
- <groupId>commons-io</groupId>
- <artifactId>commons-io</artifactId>
- <version>${commons.io.version}</version>
- </dependency>
-
- <dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest</artifactId>
<scope>test</scope>
diff --git a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/SimilarInputStreamTest.java b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/SimilarInputStreamTest.java
index cedad3a..58e180c 100644
--- a/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/SimilarInputStreamTest.java
+++ b/tests/e2e-server/src/test/java/org/glassfish/jersey/tests/e2e/server/SimilarInputStreamTest.java
@@ -16,7 +16,6 @@
package org.glassfish.jersey.tests.e2e.server;
-import org.apache.commons.io.IOUtils;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.ServletContextHandler;
@@ -25,6 +24,7 @@
import org.glassfish.jersey.internal.InternalProperties;
import org.glassfish.jersey.jackson.JacksonFeature;
import org.glassfish.jersey.jetty.JettyHttpContainerFactory;
+import org.glassfish.jersey.message.internal.ReaderWriter;
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.servlet.ServletContainer;
import org.glassfish.jersey.test.JerseyTest;
@@ -203,7 +203,7 @@
private void cacheInputStream() throws IOException {
// Cache the inputstream in order to read it multiple times.
- cachedBytes = IOUtils.toByteArray(super.getInputStream());
+ cachedBytes = ReaderWriter.readFromAsBytes(super.getInputStream());
}
diff --git a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/CookieImplTest.java b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/CookieImplTest.java
index 1068272..5438e71 100644
--- a/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/CookieImplTest.java
+++ b/tests/e2e/src/test/java/org/glassfish/jersey/tests/api/CookieImplTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, 2022 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2014, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -151,27 +151,46 @@
@Test
public void testMultipleCookiesWithSameName(){
- String cookieHeader = "kobe=longeststring; kobe=shortstring";
+ String cookieHeader = "kobe=oldeststring; kobe=neweststring";
Map<String, Cookie> cookies = HttpHeaderReader.readCookies(cookieHeader);
assertEquals(cookies.size(), 1);
Cookie c = cookies.get("kobe");
assertEquals(c.getVersion(), 0);
assertEquals("kobe", c.getName());
- assertEquals("longeststring", c.getValue());
+ assertEquals("neweststring", c.getValue());
- cookieHeader = "bryant=longeststring; bryant=shortstring; fred=shortstring ;fred=longeststring;$Path=/path";
+ cookieHeader = "bryant=longeststring; bryant=neweststring; fred=oldeststring ;fred=neweststring;$Path=/path";
cookies = HttpHeaderReader.readCookies(cookieHeader);
assertEquals(cookies.size(), 2);
c = cookies.get("bryant");
assertEquals(c.getVersion(), 0);
assertEquals("bryant", c.getName());
- assertEquals("longeststring", c.getValue());
+ assertEquals("neweststring", c.getValue());
c = cookies.get("fred");
assertEquals(c.getVersion(), 0);
assertEquals("fred", c.getName());
- assertEquals("longeststring", c.getValue());
+ assertEquals("neweststring", c.getValue());
assertEquals("/path", c.getPath());
+ cookieHeader = "cookiewithpath=longeststring;$Path=/path; cookiewithpath=string1;$Path=/path;"
+ + " cookiewithpath=string2;$Path=/path ;cookiewithpath=string3;$Path=/path";
+ cookies = HttpHeaderReader.readCookies(cookieHeader);
+ assertEquals(cookies.size(), 1);
+ c = cookies.get("cookiewithpath");
+ assertEquals(c.getVersion(), 0);
+ assertEquals("cookiewithpath", c.getName());
+ assertEquals("string3", c.getValue());
+
+ cookieHeader = "cookiewithpath=longeststring;$Path=/path/added/path; cookiewithpath=string1;$Path=/path;"
+ + " cookiewithpath=string2;$Path=/path ;cookiewithpath=string3;$Path=/path";
+ cookies = HttpHeaderReader.readCookies(cookieHeader);
+ assertEquals(cookies.size(), 1);
+ c = cookies.get("cookiewithpath");
+ assertEquals(c.getVersion(), 0);
+ assertEquals("cookiewithpath", c.getName());
+ assertEquals("longeststring", c.getValue());
+ assertEquals("/path/added/path", c.getPath());
+
}
@Test
diff --git a/tools/jersey-release-notes-maven-plugin/pom.xml b/tools/jersey-release-notes-maven-plugin/pom.xml
index 1522089..dfd342b 100644
--- a/tools/jersey-release-notes-maven-plugin/pom.xml
+++ b/tools/jersey-release-notes-maven-plugin/pom.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
- Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved.
This program and the accompanying materials are made available under the
terms of the Eclipse Public License v. 2.0, which is available at
@@ -56,7 +56,7 @@
<dependency>
<groupId>org.apache.maven.plugin-tools</groupId>
<artifactId>maven-plugin-annotations</artifactId>
- <version>3.6.0</version>
+ <version>3.15.1</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -74,7 +74,8 @@
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
- <version>2.17.0</version>
+ <version>${commons.io.version}</version>
+ <scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.maven</groupId>
@@ -83,9 +84,15 @@
<scope>test</scope>
</dependency>
<dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <version>4.13.2</version>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-api</artifactId>
+ <version>${junit.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter</artifactId>
+ <version>${junit.version}</version>
<scope>test</scope>
</dependency>
@@ -96,7 +103,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-plugin-plugin</artifactId>
- <version>3.6.0</version>
+ <version>3.15.1</version>
<configuration>
<skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
</configuration>
@@ -113,7 +120,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
- <version>3.1</version>
+ <version>3.14.0</version>
<inherited>true</inherited>
<configuration>
<source>${java.version}</source>
@@ -127,6 +134,8 @@
<properties>
<java.version>1.8</java.version>
- <maven.version>3.8.1</maven.version>
+ <maven.version>3.9.9</maven.version>
+ <commons.io.version>2.19.0</commons.io.version>
+ <junit.version>5.12.2</junit.version>
</properties>
</project>
diff --git a/tools/jersey-release-notes-maven-plugin/src/test/java/org/glassfish/jersey/tools/plugins/releasenotes/GenerateReleaseNotesMojoTest.java b/tools/jersey-release-notes-maven-plugin/src/test/java/org/glassfish/jersey/tools/plugins/releasenotes/GenerateReleaseNotesMojoTest.java
index 93287ee..1826730 100644
--- a/tools/jersey-release-notes-maven-plugin/src/test/java/org/glassfish/jersey/tools/plugins/releasenotes/GenerateReleaseNotesMojoTest.java
+++ b/tools/jersey-release-notes-maven-plugin/src/test/java/org/glassfish/jersey/tools/plugins/releasenotes/GenerateReleaseNotesMojoTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2019 Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
@@ -23,17 +23,14 @@
import org.apache.maven.project.ProjectBuilder;
import org.apache.maven.project.ProjectBuildingRequest;
import org.eclipse.aether.DefaultRepositorySystemSession;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.JUnit4;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
import java.io.File;
-@RunWith(JUnit4.class)
public class GenerateReleaseNotesMojoTest extends AbstractMojoTestCase {
- @Before
+ @BeforeEach
public void setUp() throws Exception {
// required for mojo lookups to work