revert #5962 and #5806 for TCK compatibility
diff --git a/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/ServletEntityInputStream.java b/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/ServletEntityInputStream.java deleted file mode 100644 index fcbee2d..0000000 --- a/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/ServletEntityInputStream.java +++ /dev/null
@@ -1,109 +0,0 @@ -/* - * Copyright (c) 2024, 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 - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package org.glassfish.jersey.servlet; - -import jakarta.servlet.ReadListener; -import jakarta.servlet.ServletInputStream; -import org.glassfish.jersey.innate.io.StreamListener; -import org.glassfish.jersey.innate.io.StreamListenerCouple; - -import java.io.IOException; -import java.io.InputStream; -import java.io.UncheckedIOException; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicBoolean; - -abstract class ServletEntityInputStream implements StreamListenerCouple { - - private final boolean waitForInputEnable; - private final long waitForInputTimeOut; - - private final StreamListener listener = new StreamListener() { - - @Override - public boolean isEmpty() { - try { - return getWrappedStream().available() == 0 - || getWrappedStream().isFinished(); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - @Override - public boolean isReady() { - return processReadiness(); - } - - boolean processReadiness() { - - final AtomicBoolean ready = new AtomicBoolean(getWrappedStream().isReady()); - if (waitForInputEnable && !ready.get()) { - - final CountDownLatch latch = new CountDownLatch(1); - - getWrappedStream().setReadListener(new ReadListener() { - @Override - public void onDataAvailable() { - ready.set(true); - latch.countDown(); - } - - @Override - public void onAllDataRead() { - ready.set(false); - latch.countDown(); - } - - @Override - public void onError(Throwable t) { - ready.set(false); - latch.countDown(); - } - - }); - if (!ready.get()) { - try { - latch.await(waitForInputTimeOut, TimeUnit.MILLISECONDS); - } catch (InterruptedException e) { - ready.set(getWrappedStream().isReady()); - } - } - } - return ready.get() || getWrappedStream().isReady(); - } - - }; - - public ServletEntityInputStream(boolean waitForInputEnable, long waitForInputTimeOut) { - this.waitForInputEnable = waitForInputEnable; - this.waitForInputTimeOut = waitForInputTimeOut; - } - - protected abstract ServletInputStream getWrappedStream(); - - @Override - public StreamListener getListener() { - return listener; - } - - @Override - public InputStream getExternalStream() { - return getWrappedStream(); - } -}
diff --git a/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/ServletProperties.java b/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/ServletProperties.java index bb3a52a..f4a489d 100644 --- a/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/ServletProperties.java +++ b/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/ServletProperties.java
@@ -139,30 +139,6 @@ public static final String QUERY_PARAMS_AS_FORM_PARAMS_DISABLED = "jersey.config.servlet.form.queryParams.disabled"; /** - * Indicates if any input stream is expected and shall be waited while using POST method. It can happen that a delay - * appear between the time the request is received and the time the input stream is available. In this case, the - * server will wait for the input stream to be available before processing the request. - * - * @since 3.1.11 - */ - public static final String WAIT_FOR_INPUT = "jersey.config.servlet.expect.input"; - - /** - * Timeout which shall be respected while waiting for the input stream to be available. - * The timeout is in milliseconds. - * - * @since 3.1.11 - */ - public static final String WAIT_FOR_INPUT_TIMEOUT = "jersey.config.servlet.input.timeout"; - - /** - * Default timeout which shall be respected while waiting for the input stream to be available. - * - * @since 3.1.11 - */ - public static final Long WAIT_FOR_INPUT_DEFAULT_TIMEOUT = 100L; - - /** * Identifies the object that will be used as a parent {@code HK2 ServiceLocator} in the Jersey * {@link WebComponent}. * <p></p>
diff --git a/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/WebComponent.java b/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/WebComponent.java index e3c6344..f35c720 100644 --- a/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/WebComponent.java +++ b/containers/jersey-servlet-core/src/main/java/org/glassfish/jersey/servlet/WebComponent.java
@@ -17,6 +17,7 @@ package org.glassfish.jersey.servlet; import java.io.IOException; +import java.io.InputStream; import java.io.UncheckedIOException; import java.lang.reflect.Type; import java.net.URI; @@ -56,6 +57,7 @@ import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; +import org.glassfish.jersey.innate.io.InputStreamWrapper; import org.glassfish.jersey.internal.ServiceFinderBinder; import org.glassfish.jersey.internal.inject.AbstractBinder; import org.glassfish.jersey.internal.inject.InjectionManager; @@ -423,15 +425,11 @@ final ResponseWriter responseWriter) throws IOException { try { - boolean waitForInputEnable = requestContext.resolveProperty(ServletProperties.WAIT_FOR_INPUT, Boolean.TRUE); - long waitForInputTimeOut = requestContext.resolveProperty(ServletProperties.WAIT_FOR_INPUT_TIMEOUT, - ServletProperties.WAIT_FOR_INPUT_DEFAULT_TIMEOUT); - requestContext.wrapEntityInputStream(new ServletEntityInputStream(waitForInputEnable, - waitForInputTimeOut) { - private ServletInputStream wrappedStream; + requestContext.setEntityStream(new InputStreamWrapper() { + private ServletInputStream wrappedStream; @Override - protected ServletInputStream getWrappedStream() { + protected InputStream getWrapped() { if (wrappedStream == null) { try { wrappedStream = servletRequest.getInputStream();
diff --git a/core-common/src/main/java/org/glassfish/jersey/http/JerseyCookie.java b/core-common/src/main/java/org/glassfish/jersey/http/JerseyCookie.java deleted file mode 100644 index 30ef997..0000000 --- a/core-common/src/main/java/org/glassfish/jersey/http/JerseyCookie.java +++ /dev/null
@@ -1,76 +0,0 @@ -/* - * Copyright (c) 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 - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package org.glassfish.jersey.http; - -import jakarta.ws.rs.core.Cookie; - -/** - * Jersey subclass of {@link Cookie} bearing information about optional version. - * Complies with RFC 6265. - */ -public final class JerseyCookie extends Cookie implements VersionOptional { - private final Integer version; - private JerseyCookie(Builder builder) throws IllegalArgumentException { - super(builder); - this.version = builder.version; - } - - @Override - public boolean hasVersion() { - return version != null; - } - - /** - * Builder for building Cookie. - */ - public static final class Builder extends AbstractCookieBuilder<JerseyCookie.Builder> { - private Integer version; - /** - * Create a new instance. - * - * @param name the name of the cookie. - */ - public Builder(String name) { - super(name); - } - - @Override - public Builder version(int version) { - super.version(version); - this.version = version; - return this; - } - - /** - * Set version as nullable Integer. {@code null} refers to RFC 6265 Cookie without a version. - * @param version the version of the HTTP Cookie. - * @return updated builder. - */ - public Builder version(Integer version) { - super.version(version == null ? VersionOptional.NETSCAPE_VERSION : version); - this.version = version; - return this; - } - - @Override - public Cookie build() { - return new JerseyCookie(this); - } - - } - -}
diff --git a/core-common/src/main/java/org/glassfish/jersey/http/JerseyNewCookie.java b/core-common/src/main/java/org/glassfish/jersey/http/JerseyNewCookie.java deleted file mode 100644 index 81419c6..0000000 --- a/core-common/src/main/java/org/glassfish/jersey/http/JerseyNewCookie.java +++ /dev/null
@@ -1,91 +0,0 @@ -/* - * Copyright (c) 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 - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package org.glassfish.jersey.http; - -import jakarta.ws.rs.core.Cookie; -import jakarta.ws.rs.core.NewCookie; - -/** - * Jersey subclass of {@link NewCookie} bearing information about optional version. - * Complies with RFC 6265. - */ -public final class JerseyNewCookie extends NewCookie implements VersionOptional { - private final Integer version; - private JerseyNewCookie(JerseyNewCookie.Builder builder) { - super(builder); - this.version = builder.version; - } - - @Override - public boolean hasVersion() { - return version != null; - } - - /** - * Builder class building the Jersey NewCookie subclass. - */ - public static final class Builder extends AbstractNewCookieBuilder<JerseyNewCookie.Builder> { - private Integer version; - - - /** - * Create a new instance. - * - * @param name the name of the cookie. - */ - public Builder(String name) { - super(name); - } - - /** - * Create a new instance supplementing the information in the supplied cookie. - * - * @param cookie the cookie to copy. - */ - public Builder(Cookie cookie) { - super(cookie); - if (cookie instanceof VersionOptional) { - this.version = ((VersionOptional) cookie).hasVersion() ? cookie.getVersion() : null; - } - } - - @Override - public Builder version(int version) { - super.version(version); - this.version = version; - return this; - } - - /** - * Set version. Can be {@code null} if RFC 6265. - * @param version the cookie version. - * @return updated builder. - */ - public Builder version(Integer version) { - // Version 0 should refer to NETSCAPE, but NewCookie should be for RFC 2109 & 2965 - version 1, and forward - 6265. - // Hence in this case, 0 would be "no version" in RFC 6265. - super.version(version == null ? 0 : version); - this.version = version; - return this; - } - - @Override - public NewCookie build() { - return new JerseyNewCookie(this); - } - } -}
diff --git a/core-common/src/main/java/org/glassfish/jersey/http/VersionOptional.java b/core-common/src/main/java/org/glassfish/jersey/http/VersionOptional.java deleted file mode 100644 index 2023d0d..0000000 --- a/core-common/src/main/java/org/glassfish/jersey/http/VersionOptional.java +++ /dev/null
@@ -1,35 +0,0 @@ -/* - * Copyright (c) 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 - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package org.glassfish.jersey.http; - -/** - * Provides information about optionality of version in {@code Cookie} and {@code NewCookie}. - * The version is as follows: 0 - Netscape, 1 - RFC 2109 & 2965, not set RFC 6265. - */ -public interface VersionOptional { - - /** - * The version from the original Netscape specification. - */ - public static final int NETSCAPE_VERSION = 0; - - /** - * Defines if the version is set. - * @return {@code true} when the version is set. - */ - boolean hasVersion(); -}
diff --git a/core-common/src/main/java/org/glassfish/jersey/innate/io/StreamListener.java b/core-common/src/main/java/org/glassfish/jersey/innate/io/StreamListener.java deleted file mode 100644 index 406c765..0000000 --- a/core-common/src/main/java/org/glassfish/jersey/innate/io/StreamListener.java +++ /dev/null
@@ -1,53 +0,0 @@ -/* - * Copyright (c) 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 - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package org.glassfish.jersey.innate.io; - -import org.glassfish.jersey.message.internal.EntityInputStream; - -import java.util.EventListener; - -/** - * Provides possibility to check whether an input stream for an entity is empty or not. - * <p> - * Is being used in the {@link EntityInputStream#isEmpty()} check - * </p> - */ -public interface StreamListener extends EventListener { - - /** - * Provides information if the underlying stream is empty - * - * @return true if the underlying stream is empty - */ - boolean isEmpty(); - - /** - * Can be used to provide readiness information. - * <p> - * If the stream is not ready the calling check in the {@link EntityInputStream#isEmpty()} method will validate - * the underlying stream as not empty. - * </p> - * <p> - * Throws: - * IllegalStateException - if one of the following conditions is true - * the associated request is neither upgraded nor the async started - * underlying setReadListener is called more than once within the scope of the same request. - * </p> - * @return true if the underlying stream is ready. - */ - boolean isReady(); -}
diff --git a/core-common/src/main/java/org/glassfish/jersey/innate/io/StreamListenerCouple.java b/core-common/src/main/java/org/glassfish/jersey/innate/io/StreamListenerCouple.java deleted file mode 100644 index 34d141d..0000000 --- a/core-common/src/main/java/org/glassfish/jersey/innate/io/StreamListenerCouple.java +++ /dev/null
@@ -1,41 +0,0 @@ -/* - * Copyright (c) 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 - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package org.glassfish.jersey.innate.io; - -import java.io.InputStream; - -/** - * Couples stream and its listener (if any). - * Could be used in connectors to help determine the stream's emptiness. - */ -public interface StreamListenerCouple { - - /** - * Provides a listener for the underlying input stream. The listener can reflect a particular state which - * helps to determine whether the underlying stream is empty or not. - * - * @return listener - */ - StreamListener getListener(); - - /** - * Provides underlying input stream. - * @return underlying input stream - */ - InputStream getExternalStream(); - -}
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/CookieProvider.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/CookieProvider.java index 9a4b29a..a509120 100644 --- a/core-common/src/main/java/org/glassfish/jersey/message/internal/CookieProvider.java +++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/CookieProvider.java
@@ -21,7 +21,6 @@ import jakarta.inject.Singleton; import org.glassfish.jersey.internal.LocalizationMessages; -import org.glassfish.jersey.http.VersionOptional; import org.glassfish.jersey.spi.HeaderDelegateProvider; import static org.glassfish.jersey.message.internal.Utils.throwIllegalArgumentExceptionIfNull; @@ -47,15 +46,7 @@ StringBuilder b = new StringBuilder(); - boolean printVersion = false; - if (cookie instanceof VersionOptional) { - printVersion = ((VersionOptional) cookie).hasVersion(); - } else if (cookie.getVersion() == Cookie.DEFAULT_VERSION || cookie.getVersion() == VersionOptional.NETSCAPE_VERSION) { - printVersion = true; - } - if (printVersion) { - b.append("$Version=").append(cookie.getVersion()).append(';'); - } + b.append("$Version=").append(cookie.getVersion()).append(';'); b.append(cookie.getName()).append('='); StringBuilderUtils.appendQuotedIfWhitespace(b, cookie.getValue());
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 d535094..958a1bc 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
@@ -28,8 +28,6 @@ import jakarta.ws.rs.core.NewCookie; import org.glassfish.jersey.internal.LocalizationMessages; -import org.glassfish.jersey.http.JerseyCookie; -import org.glassfish.jersey.http.JerseyNewCookie; /** * Cookies parser. @@ -45,7 +43,7 @@ String name; String value; - Integer version = null; + int version = Cookie.DEFAULT_VERSION; String path = null; String domain = null; @@ -55,14 +53,14 @@ } public Cookie getImmutableCookie() { - return new JerseyCookie.Builder(name).version(version).value(value).path(path).domain(domain).build(); + return new Cookie(name, value, path, domain, version); } } public static Map<String, Cookie> parseCookies(String header) { String bites[] = header.split("[;,]"); Map<String, Cookie> cookies = new LinkedHashMap<String, Cookie>(); - Integer version = null; + int version = 0; MutableCookie cookie = null; for (String bite : bites) { String crumbs[] = bite.split("=", 2); @@ -125,7 +123,7 @@ String value = null; String path = null; String domain = null; - Integer version = null; + int version = Cookie.DEFAULT_VERSION; String comment = null; int maxAge = NewCookie.DEFAULT_MAX_AGE; boolean secure = false; @@ -139,8 +137,7 @@ } public NewCookie getImmutableNewCookie() { - return new JerseyNewCookie.Builder(name).version(version).value(value).path(path).domain(domain).comment(comment) - .maxAge(maxAge).expiry(expiry).secure(secure).httpOnly(httpOnly).sameSite(sameSite).build(); + return new NewCookie(name, value, path, domain, version, comment, maxAge, expiry, secure, httpOnly, sameSite); } }
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/EntityInputStream.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/EntityInputStream.java index ab5a3ec..72a5227 100644 --- a/core-common/src/main/java/org/glassfish/jersey/message/internal/EntityInputStream.java +++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/EntityInputStream.java
@@ -22,8 +22,6 @@ import jakarta.ws.rs.ProcessingException; -import org.glassfish.jersey.innate.io.StreamListener; -import org.glassfish.jersey.innate.io.StreamListenerCouple; import org.glassfish.jersey.innate.io.InputStreamWrapper; import org.glassfish.jersey.internal.LocalizationMessages; @@ -39,9 +37,6 @@ public class EntityInputStream extends InputStreamWrapper { private InputStream input; - - private StreamListener listener; - private boolean closed = false; /** @@ -98,12 +93,13 @@ */ @Override public void close() throws ProcessingException { - if (input == null) { + final InputStream in = input; + if (in == null) { return; } if (!closed) { try { - input.close(); + in.close(); } catch (IOException ex) { // This e.g. means that the underlying socket stream got closed by other thread somehow... throw new ProcessingException(LocalizationMessages.MESSAGE_CONTENT_INPUT_STREAM_CLOSE_FAILED(), ex); @@ -123,46 +119,43 @@ */ public boolean isEmpty() { ensureNotClosed(); - if (input == null) { + + final InputStream in = input; + if (in == null) { return true; } try { // Try #markSupported first - #available on WLS waits until socked timeout is reached when chunked encoding is used. - if (input.markSupported()) { - input.mark(1); - int i = input.read(); - input.reset(); + if (in.markSupported()) { + in.mark(1); + int i = in.read(); + in.reset(); return i == -1; } else { - int availableBytes = 0; try { - availableBytes = input.available(); + if (in.available() > 0) { + return false; + } } catch (IOException ioe) { // NOOP. Try other approaches as this can fail on WLS. } - if (availableBytes > 0) { - return false; + int b = in.read(); + if (b == -1) { + return true; } - if (listener != null) { - try { - if (!listener.isReady()) { - return false; - } - return listener.isEmpty(); - } catch (IllegalStateException ex) { - // NOOP. Listener failed to process the emptiness, the final method to be applied - } + PushbackInputStream pbis; + if (in instanceof PushbackInputStream) { + pbis = (PushbackInputStream) in; + } else { + pbis = new PushbackInputStream(in, 1); + input = pbis; } + pbis.unread(b); - final PushbackInputStream in = (input instanceof PushbackInputStream) ? (PushbackInputStream) input - : new PushbackInputStream(input); - int i = in.read(); - in.unread(i); - input = in; - return i == -1; + return false; } } catch (IOException ex) { throw new ProcessingException(ex); @@ -195,7 +188,7 @@ * @return wrapped input stream instance. */ public final InputStream getWrappedStream() { - return getWrapped(); + return input; } /** @@ -208,21 +201,7 @@ } @Override - public InputStream getWrapped() { + protected InputStream getWrapped() { return input; } - - /** - * Decomposes existing {@link EntityInputStream} into this input stream - * @param stream instance of the {@link EntityInputStream} - */ - public void wrapExternalStream(StreamListenerCouple stream) { - input = new InputStreamWrapper() { - @Override - public InputStream getWrapped() { - return stream.getExternalStream(); - } - }; - listener = stream.getListener(); - } }
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 0d88f13..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
@@ -45,7 +45,6 @@ import javax.xml.transform.Source; -import org.glassfish.jersey.innate.io.StreamListenerCouple; import org.glassfish.jersey.innate.io.SafelyClosable; import org.glassfish.jersey.internal.LocalizationMessages; import org.glassfish.jersey.internal.PropertiesDelegate; @@ -600,16 +599,6 @@ } /** - * Provides the whole {@link EntityInputStream} to the request - * - * @param stream the whole input stream entity - */ - public void wrapEntityInputStream(StreamListenerCouple stream) { - this.entityContent.wrapExternalStream(stream); - this.entityContent.buffered = false; - } - - /** * Read entity from a context entity input stream. * * @param <T> entity Java object type.
diff --git a/core-common/src/main/java/org/glassfish/jersey/message/internal/NewCookieProvider.java b/core-common/src/main/java/org/glassfish/jersey/message/internal/NewCookieProvider.java index 4808a3c..2d7a2ea 100644 --- a/core-common/src/main/java/org/glassfish/jersey/message/internal/NewCookieProvider.java +++ b/core-common/src/main/java/org/glassfish/jersey/message/internal/NewCookieProvider.java
@@ -16,13 +16,11 @@ package org.glassfish.jersey.message.internal; -import jakarta.ws.rs.core.Cookie; import jakarta.ws.rs.core.NewCookie; import jakarta.inject.Singleton; import org.glassfish.jersey.internal.LocalizationMessages; -import org.glassfish.jersey.http.VersionOptional; import org.glassfish.jersey.spi.HeaderDelegateProvider; import java.util.Locale; @@ -53,15 +51,7 @@ b.append(cookie.getName()).append('='); StringBuilderUtils.appendQuotedIfWhitespace(b, cookie.getValue()); - boolean printVersion = false; - if (cookie instanceof VersionOptional) { - printVersion = ((VersionOptional) cookie).hasVersion(); - } else if (cookie.getVersion() == Cookie.DEFAULT_VERSION) { - printVersion = true; - } - if (printVersion) { - b.append(";").append("Version=").append(cookie.getVersion()); - } + b.append(";").append("Version=").append(cookie.getVersion()); if (cookie.getComment() != null) { b.append(";Comment=");
diff --git a/core-server/src/main/java/org/glassfish/jersey/server/ContainerRequest.java b/core-server/src/main/java/org/glassfish/jersey/server/ContainerRequest.java index 65b033e..325bf93 100644 --- a/core-server/src/main/java/org/glassfish/jersey/server/ContainerRequest.java +++ b/core-server/src/main/java/org/glassfish/jersey/server/ContainerRequest.java
@@ -48,7 +48,6 @@ import jakarta.ws.rs.ext.WriterInterceptor; import org.glassfish.jersey.http.HttpHeaders; -import org.glassfish.jersey.innate.io.StreamListenerCouple; import org.glassfish.jersey.internal.PropertiesDelegate; import org.glassfish.jersey.internal.guava.Preconditions; import org.glassfish.jersey.internal.PropertiesResolver; @@ -548,12 +547,6 @@ } @Override - public void wrapEntityInputStream(final StreamListenerCouple input) { - Preconditions.checkState(!inResponseProcessingPhase, ERROR_REQUEST_SET_ENTITY_STREAM_IN_RESPONSE_PHASE); - super.wrapEntityInputStream(input); - } - - @Override public Request getRequest() { return this; }
diff --git a/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/CookieParamAsCookieTest.java b/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/CookieParamAsCookieTest.java index 3eaa637..e81c446 100644 --- a/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/CookieParamAsCookieTest.java +++ b/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/CookieParamAsCookieTest.java
@@ -16,24 +16,18 @@ package org.glassfish.jersey.server.internal.inject; -import java.util.List; import java.util.Map; import java.util.concurrent.ExecutionException; import jakarta.ws.rs.CookieParam; -import jakarta.ws.rs.GET; -import jakarta.ws.rs.HeaderParam; -import jakarta.ws.rs.HttpMethod; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; import jakarta.ws.rs.core.Context; import jakarta.ws.rs.core.Cookie; import jakarta.ws.rs.core.HttpHeaders; -import org.glassfish.jersey.http.JerseyCookie; import org.glassfish.jersey.server.RequestContextBuilder; -import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -44,63 +38,39 @@ */ public class CookieParamAsCookieTest extends AbstractTest { - private static final String ONE = "one"; - private static final String TWO = "two"; - private static final String VALUE_ONE = "value_one"; - private static final String VALUE_TWO = "value_two"; - @Path("/") public static class CookieTypeResource { @POST public String post( @Context HttpHeaders h, - @CookieParam(ONE) Cookie one, - @CookieParam(TWO) Cookie two, + @CookieParam("one") Cookie one, + @CookieParam("two") Cookie two, @CookieParam("three") Cookie three) { - assertEquals(ONE, one.getName()); - assertEquals(VALUE_ONE, one.getValue()); + assertEquals("one", one.getName()); + assertEquals("value_one", one.getValue()); - assertEquals(TWO, two.getName()); - assertEquals(VALUE_TWO, two.getValue()); + assertEquals("two", two.getName()); + assertEquals("value_two", two.getValue()); assertEquals(null, three); Map<String, Cookie> cs = h.getCookies(); assertEquals(2, cs.size()); - assertEquals(VALUE_ONE, cs.get(ONE).getValue()); - assertEquals(VALUE_TWO, cs.get(TWO).getValue()); + assertEquals("value_one", cs.get("one").getValue()); + assertEquals("value_two", cs.get("two").getValue()); return "content"; } - - @Path("list") - @GET - public String list(@CookieParam(ONE) Cookie one, - @CookieParam(TWO) Cookie two, - @HeaderParam("Cookie") List<Cookie> cookies) { - return cookies.get(0).toString() + ',' + cookies.get(1).toString(); - } - } @Test public void testCookieParam() throws ExecutionException, InterruptedException { initiateWebApplication(CookieTypeResource.class); - Cookie one = new Cookie(ONE, VALUE_ONE); - Cookie two = new Cookie(TWO, VALUE_TWO); + Cookie one = new Cookie("one", "value_one"); + Cookie two = new Cookie("two", "value_two"); assertEquals("content", apply(RequestContextBuilder.from("/", "POST").cookie(one).cookie(two).build()).getEntity()); } - - @Test - public void testCookieList() throws ExecutionException, InterruptedException { - initiateWebApplication(CookieTypeResource.class); - - Cookie one = new Cookie.Builder(ONE).version(-1).value(VALUE_ONE).build(); - Cookie two = new JerseyCookie.Builder(TWO).value(VALUE_TWO).build(); - Object response = apply(RequestContextBuilder.from("/list", HttpMethod.GET).cookie(one).cookie(two).build()).getEntity(); - Assertions.assertEquals(ONE + '=' + VALUE_ONE + ',' + TWO + '=' + VALUE_TWO, response); - } }
diff --git a/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/CookieParamAsStringTest.java b/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/CookieParamAsStringTest.java index 1ba1be5..0426b4b 100644 --- a/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/CookieParamAsStringTest.java +++ b/core-server/src/test/java/org/glassfish/jersey/server/internal/inject/CookieParamAsStringTest.java
@@ -22,14 +22,11 @@ import jakarta.ws.rs.CookieParam; import jakarta.ws.rs.DefaultValue; import jakarta.ws.rs.GET; -import jakarta.ws.rs.HeaderParam; import jakarta.ws.rs.POST; import jakarta.ws.rs.Path; import jakarta.ws.rs.Produces; import jakarta.ws.rs.core.Cookie; -import jakarta.ws.rs.core.MediaType; -import org.glassfish.jersey.http.JerseyCookie; import org.glassfish.jersey.server.ContainerResponse; import org.glassfish.jersey.server.RequestContextBuilder; @@ -105,19 +102,6 @@ assertEquals("a", args.get(0)); return "content"; } - - @GET - @Path("headerparam/list") - public String list(@HeaderParam("Cookie") List<String> cookies) { - StringBuilder sb = new StringBuilder(); - for (String c : cookies) { - if (sb.length() != 0) { - sb.append(','); - } - sb.append(c); - } - return sb.toString(); - } } @Path("/") @@ -282,22 +266,6 @@ } @Test - public void testStringListHeaderParam() throws ExecutionException, InterruptedException { - String cookieName1 = "COOKIE_1"; - String cookieValue1 = "VALUE_1"; - String cookieName2 = "COOKIE_2"; - String cookieValue2 = "VALUE_2"; - - initiateWebApplication(ResourceStringList.class); - - Cookie one = new Cookie.Builder(cookieName1).version(-1).value(cookieValue1).build(); - Cookie two = new JerseyCookie.Builder(cookieName2).value(cookieValue2).build(); - - assertEquals(cookieName1 + '=' + cookieValue1 + "," + cookieName2 + '=' + cookieValue2, - getResponseContext("/headerparam/list", MediaType.MEDIA_TYPE_WILDCARD, one, two).getEntity()); - } - - @Test public void testStringListEmptyGet() throws ExecutionException, InterruptedException { initiateWebApplication(ResourceStringListEmpty.class);
diff --git a/docs/src/main/docbook/appendix-properties.xml b/docs/src/main/docbook/appendix-properties.xml index c4d66aa..43b5bed 100644 --- a/docs/src/main/docbook/appendix-properties.xml +++ b/docs/src/main/docbook/appendix-properties.xml
@@ -1022,25 +1022,6 @@ </para> </entry> </row> - <row> - <entry>&jersey.servlet.ServletProperties.WAIT_FOR_INPUT;</entry> - <entry><literal>jersey.config.servlet.expect.input</literal></entry> - <entry> - <para> - If <literal>true</literal> then Jersey will wait for input when the request is a POST or PUT. - </para> - </entry> - </row> - <row> - <entry>&jersey.servlet.ServletProperties.WAIT_FOR_INPUT_TIMEOUT;</entry> - <entry><literal>jersey.config.servlet.expect.input</literal></entry> - <entry> - <para> - The timeout in milliseconds for waiting for input when the request is a POST or PUT. - Default value is <literal>100</literal> milliseconds. - </para> - </entry> - </row> </tbody> </tgroup> </table>
diff --git a/docs/src/main/docbook/jersey.ent b/docs/src/main/docbook/jersey.ent index 905b8d1..614c765 100644 --- a/docs/src/main/docbook/jersey.ent +++ b/docs/src/main/docbook/jersey.ent
@@ -726,8 +726,6 @@ <!ENTITY jersey.servlet.ServletProperties.PROVIDER_WEB_APP "<link xlink:href='&jersey.javadoc.uri.prefix;/servlet/ServletProperties.html#PROVIDER_WEB_APP'>ServletProperties.PROVIDER_WEB_APP</link>"> <!ENTITY jersey.servlet.ServletProperties.QUERY_PARAMS_AS_FORM_PARAMS_DISABLED "<link xlink:href='&jersey.javadoc.uri.prefix;/servlet/ServletProperties.html#QUERY_PARAMS_AS_FORM_PARAMS_DISABLED'>ServletProperties.QUERY_PARAMS_AS_FORM_PARAMS_DISABLED</link>"> <!ENTITY jersey.servlet.ServletProperties.SERVICE_LOCATOR "<link xlink:href='&jersey.javadoc.uri.prefix;/servlet/ServletProperties.html#SERVICE_LOCATOR'>ServletProperties.SERVICE_LOCATOR</link>"> -<!ENTITY jersey.servlet.ServletProperties.WAIT_FOR_INPUT "<link xlink:href='&jersey.javadoc.uri.prefix;/servlet/ServletProperties.html#WAIT_FOR_INPUT'>ServletProperties.WAIT_FOR_INPUT</link>"> -<!ENTITY jersey.servlet.ServletProperties.WAIT_FOR_INPUT_TIMEOUT "<link xlink:href='&jersey.javadoc.uri.prefix;/servlet/ServletProperties.html#WAIT_FOR_INPUT_TIMEOUT'>ServletProperties.WAIT_FOR_INPUT_TIMEOUT</link>"> <!ENTITY jersey.simple.SimpleContainer "<link xlink:href='&jersey.javadoc.uri.prefix;/simple/SimpleContainer.html'>SimpleContainer</link>"> <!ENTITY jersey.simple.SimpleContainerFactory "<link xlink:href='&jersey.javadoc.uri.prefix;/simple/SimpleContainerFactory.html'>SimpleContainerFactory</link>"> <!ENTITY jersey.simple.SimpleContainerProvider "<link xlink:href='&jersey.javadoc.uri.prefix;/simple/SimpleContainerProvider.html'>SimpleContainerProvider</link>">
diff --git a/tests/e2e-client/pom.xml b/tests/e2e-client/pom.xml index 90426d5..3dce2ff 100644 --- a/tests/e2e-client/pom.xml +++ b/tests/e2e-client/pom.xml
@@ -112,11 +112,6 @@ <scope>test</scope> </dependency> <dependency> - <groupId>org.glassfish.jersey.media</groupId> - <artifactId>jersey-media-json-jackson</artifactId> - <scope>test</scope> - </dependency> - <dependency> <groupId>org.glassfish.jersey.ext</groupId> <artifactId>jersey-entity-filtering</artifactId> <scope>test</scope> @@ -245,12 +240,6 @@ <groupId>org.glassfish.jersey.test-framework.providers</groupId> <artifactId>jersey-test-framework-provider-jetty</artifactId> </dependency> - <dependency> - <groupId>org.eclipse.jetty.ee10</groupId> - <artifactId>jetty-ee10-servlet</artifactId> - <version>${jetty.version}</version> - <scope>test</scope> - </dependency> </dependencies> </profile> <profile> @@ -343,7 +332,6 @@ <testExclude>org/glassfish/jersey/tests/e2e/client/connector/proxy/Proxy*Test.java</testExclude> <testExclude>org/glassfish/jersey/tests/e2e/client/connector/NoContentLengthTest.java</testExclude> <testExclude>org/glassfish/jersey/tests/e2e/client/nettyconnector/Expect100ContinueTest.java</testExclude> - <testExclude>org/glassfish/jersey/tests/e2e/client/ResponseReadEntityStreamTest.java</testExclude> </testExcludes> </configuration> <goals>
diff --git a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ResponseReadEntityStreamTest.java b/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ResponseReadEntityStreamTest.java deleted file mode 100644 index 2633d6b..0000000 --- a/tests/e2e-client/src/test/java/org/glassfish/jersey/tests/e2e/client/ResponseReadEntityStreamTest.java +++ /dev/null
@@ -1,203 +0,0 @@ -/* - * Copyright (c) 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 - * http://www.eclipse.org/legal/epl-2.0. - * - * This Source Code may also be made available under the following Secondary - * Licenses when the conditions for such availability set forth in the - * Eclipse Public License v. 2.0 are satisfied: GNU General Public License, - * version 2 with the GNU Classpath Exception, which is available at - * https://www.gnu.org/software/classpath/license.html. - * - * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 - */ - -package org.glassfish.jersey.tests.e2e.client; - -import jakarta.inject.Inject; -import jakarta.servlet.ServletInputStream; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.ws.rs.Consumes; -import jakarta.ws.rs.POST; -import jakarta.ws.rs.Path; -import jakarta.ws.rs.Produces; -import jakarta.ws.rs.client.Entity; -import jakarta.ws.rs.client.Invocation; -import jakarta.ws.rs.core.Application; -import jakarta.ws.rs.core.MediaType; -import jakarta.ws.rs.core.Response; -import com.fasterxml.jackson.core.JsonFactory; -import com.fasterxml.jackson.core.JsonGenerator; -import org.eclipse.jetty.ee10.servlet.ServletContextHandler; -import org.eclipse.jetty.ee10.servlet.ServletHolder; -import org.eclipse.jetty.server.Server; -import org.eclipse.jetty.server.ServerConnector; -import org.glassfish.jersey.client.ClientConfig; -import org.glassfish.jersey.jetty.JettyHttpContainerFactory; -import org.glassfish.jersey.server.ResourceConfig; -import org.glassfish.jersey.servlet.ServletContainer; -import org.glassfish.jersey.test.JerseyTest; -import org.glassfish.jersey.test.spi.TestContainer; -import org.glassfish.jersey.test.spi.TestContainerException; -import org.glassfish.jersey.test.spi.TestContainerFactory; -import org.junit.jupiter.api.Test; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileWriter; -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.nio.file.Files; -import java.nio.file.Paths; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -/** - * Tests the presence of the first byte in very large stream in each of 1000 requests - * Particularly for {@link org.glassfish.jersey.message.internal.EntityInputStream#isEmpty} method - * <p> - * Also introduces mixture of the Jetty server and servlet holder in which the error was reproduced. - */ -public class ResponseReadEntityStreamTest extends JerseyTest { - - @Override - protected TestContainerFactory getTestContainerFactory() throws TestContainerException { - return (baseUri, deploymentContext) -> { - final Server server = JettyHttpContainerFactory.createServer(baseUri, false); - final ServerConnector connector = new ServerConnector(server); - connector.setPort(9001); - server.addConnector(connector); - - final ResourceConfig resConfig = new ResourceConfig(Analyze.class); - - final ServletContainer jerseyServletContainer = new ServletContainer(resConfig); - final ServletHolder jettyServletHolder = new ServletHolder(jerseyServletContainer); - - final ServletContextHandler context = new ServletContextHandler(ServletContextHandler.NO_SESSIONS); - context.setContextPath("/"); - - context.addServlet(jettyServletHolder, "/api/*"); - - server.setHandler(context); - return new TestContainer() { - @Override - public ClientConfig getClientConfig() { - return new ClientConfig(); - } - - @Override - public URI getBaseUri() { - return baseUri; - } - - @Override - public void start() { - try { - server.start(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - @Override - public void stop() { - try { - server.stop(); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - }; - }; - } - - @Override - protected Application configure() { - return new ResourceConfig(ResponseReadEntityStreamTest.Analyze.class); - } - - private static void generateJson(final String filePath, int recordCount) throws IOException { - - try (final JsonGenerator generator = new JsonFactory().createGenerator(new FileWriter(filePath))) { - generator.writeStartArray(); - - for (int i = 0; i < recordCount; i++) { - generator.writeStartObject(); - generator.writeNumberField("id", i); - generator.writeStringField("name", "User" + i); - // Add more fields as needed - generator.writeEndObject(); - - if (i % 10000 == 0) { - generator.flush(); - } - } - - generator.writeEndArray(); - } - } - - @Test - public void readEntityTest() throws IOException { - final Invocation.Builder requestBuilder = target("/api/v1/analyze").request(); - //iterate 1000 requests to be sure the first byte is not lost - final String fileName = "bigFile.json"; - final String path = "target/" + fileName; - - final java.nio.file.Path pathResource = Paths.get(path); - - final java.nio.file.Path realFilePath = Files.createFile(pathResource.toAbsolutePath()); - - try { - - generateJson(realFilePath.toString(), 1000000); // 33Mb real file size - - final File bigFile = realFilePath.toFile(); - - for (int i = 1; i < 1000; i++) { - try (final FileInputStream stream = new FileInputStream(bigFile)) { - final Response response = requestBuilder.post(Entity.entity(stream, - MediaType.APPLICATION_FORM_URLENCODED_TYPE)); - assertEquals(200, response.getStatus()); - response.close(); - } - } - } finally { - Files.deleteIfExists(pathResource); - } - - } - - @Path("/v1") - @Produces(MediaType.APPLICATION_JSON) - public static class Analyze { - - @Inject - private HttpServletRequest request; - - @POST - @Path("/analyze") - @Produces(MediaType.APPLICATION_JSON) - @Consumes(MediaType.APPLICATION_FORM_URLENCODED) - public Response analyze() { - - try (final ServletInputStream inputStream = request.getInputStream()) { - final byte[] content = inputStream.readAllBytes(); - - if (content[0] != 91 /* character [ */) { // https://www.ascii-code.com/91 - throw new Exception("Oops"); - } - - return Response.ok("{\"status\":\"OK\"}").build(); - - } catch (Exception e) { - return Response.serverError().build(); - } - - } - } - -}
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 b54228e..53cd76d 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
@@ -46,8 +46,8 @@ expResult = "$Version=1;fred=flintstone;$Domain=.sun.com;$Path=/path"; assertEquals(expResult, cookie.toString()); - cookie = new Cookie("fred", "flintstone", "/path", ".sun.com", 0); - expResult = "$Version=0;fred=flintstone;$Domain=.sun.com;$Path=/path"; + cookie = new Cookie("fred", "flintstone", "/path", ".sun.com", 2); + expResult = "$Version=2;fred=flintstone;$Domain=.sun.com;$Path=/path"; assertEquals(expResult, cookie.toString()); }