You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by re...@apache.org on 2022/01/23 17:55:24 UTC

[cxf] branch 3.4.x-fixes updated: CXF-8642: ResponseImpl#hasEntity return 'false' when entity is buffered but entity stream is fully consumed with processing exception (#893)

This is an automated email from the ASF dual-hosted git repository.

reta pushed a commit to branch 3.4.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/3.4.x-fixes by this push:
     new 97ada30  CXF-8642: ResponseImpl#hasEntity return 'false' when entity is buffered but entity stream is fully consumed with processing exception (#893)
97ada30 is described below

commit 97ada30ae538dd9d4a6519e8cfe1efc88b792729
Author: Andriy Redko <dr...@gmail.com>
AuthorDate: Sun Jan 23 11:14:03 2022 -0500

    CXF-8642: ResponseImpl#hasEntity return 'false' when entity is buffered but entity stream is fully consumed with processing exception (#893)
    
    (cherry picked from commit c047c2a446716c90f9f198abb16fca66199ea2e1)
    (cherry picked from commit 143a8c0d33bba236e8edca9d13b1b8e2f94e58c1)
---
 .../org/apache/cxf/jaxrs/impl/ResponseImpl.java    |  3 +
 .../apache/cxf/jaxrs/impl/ResponseImplTest.java    | 83 +++++++++++++++++++++-
 2 files changed, 85 insertions(+), 1 deletion(-)

diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseImpl.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseImpl.java
index f157c2a..a5c0d31 100644
--- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseImpl.java
+++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/impl/ResponseImpl.java
@@ -152,6 +152,9 @@ public final class ResponseImpl extends Response {
         Object actualEntity = getActualEntity();
         if (actualEntity == null) {
             return false;
+        } else if (entityBufferred) {
+            // if actualEntity is not null and entity was buffered, the response definitely has entity
+            return true;
         } else if (actualEntity instanceof InputStream) {
             final InputStream is = (InputStream) actualEntity;
             try {
diff --git a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/ResponseImplTest.java b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/ResponseImplTest.java
index d140070..d71400f 100644
--- a/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/ResponseImplTest.java
+++ b/rt/frontend/jaxrs/src/test/java/org/apache/cxf/jaxrs/impl/ResponseImplTest.java
@@ -25,6 +25,7 @@ import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
 import java.lang.annotation.Annotation;
+import java.lang.reflect.Type;
 import java.net.URI;
 import java.nio.CharBuffer;
 import java.nio.charset.StandardCharsets;
@@ -34,6 +35,9 @@ import java.util.Map;
 import java.util.Set;
 
 import javax.activation.DataSource;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.client.ResponseProcessingException;
 import javax.ws.rs.core.Application;
 import javax.ws.rs.core.EntityTag;
 import javax.ws.rs.core.GenericEntity;
@@ -50,6 +54,8 @@ import javax.ws.rs.core.Response.StatusType;
 import javax.ws.rs.core.UriBuilder;
 import javax.ws.rs.core.Variant;
 import javax.ws.rs.core.Variant.VariantListBuilder;
+import javax.ws.rs.ext.MessageBodyReader;
+import javax.ws.rs.ext.Provider;
 import javax.ws.rs.ext.RuntimeDelegate;
 import javax.ws.rs.ext.RuntimeDelegate.HeaderDelegate;
 import javax.xml.transform.Source;
@@ -60,6 +66,7 @@ import javax.xml.transform.dom.DOMResult;
 import org.w3c.dom.Document;
 
 import org.apache.cxf.endpoint.Endpoint;
+import org.apache.cxf.helpers.IOUtils;
 import org.apache.cxf.jaxrs.provider.ProviderFactory;
 import org.apache.cxf.jaxrs.provider.ServerProviderFactory;
 import org.apache.cxf.jaxrs.resources.Book;
@@ -641,7 +648,7 @@ public class ResponseImplTest {
         
         response.close();
     }
-    
+
     @Test
     public void testReadDataSource() throws IOException {
         final String str = "ouch";
@@ -683,6 +690,80 @@ public class ResponseImplTest {
         assertThrows(IllegalStateException.class, 
             () -> response.readEntity(Reader.class, annotations));
     }
+
+    @Test
+    public void testBufferAndReadInputStream() throws IOException {
+        final String str = "ouch";
+
+        try (ByteArrayInputStream out = new ByteArrayInputStream(str.getBytes())) {
+            final ResponseImpl response = new ResponseImpl(500, out);
+            final Message outMessage = createMessage();
+            outMessage.put(Message.REQUEST_URI, "http://localhost");
+            response.setOutMessage(outMessage);
+
+            final MultivaluedMap<String, Object> headers = new MetadataMap<>();
+            headers.putSingle("Content-Type", "text/rdf");
+            response.addMetadata(headers);
+            
+            assertTrue(response.bufferEntity());
+            assertNotNull(response.readEntity(InputStream.class));
+            assertNotNull(response.getEntity());
+            assertTrue(response.hasEntity());
+    
+            assertNotNull(response.readEntity(InputStream.class));
+            assertNotNull(response.getEntity());
+            assertTrue(response.hasEntity());
+    
+            response.close();
+        }
+    }
+    
+    @Test
+    public void testBufferAndReadInputStreamWithException() throws IOException {
+        final String str = "ouch";
+
+        try (ByteArrayInputStream out = new ByteArrayInputStream(str.getBytes())) {
+            final ResponseImpl response = new ResponseImpl(500, out);
+            final Message outMessage = createMessage();
+            outMessage.put(Message.REQUEST_URI, "http://localhost");
+            response.setOutMessage(outMessage);
+
+            ProviderFactory factory = ProviderFactory.getInstance(outMessage);
+            factory.registerUserProvider(new FaultyMessageBodyReader<InputStream>());
+
+            final MultivaluedMap<String, Object> headers = new MetadataMap<>();
+            headers.putSingle("Content-Type", "text/rdf");
+            response.addMetadata(headers);
+            
+            assertTrue(response.bufferEntity());
+            assertThrows(ResponseProcessingException.class, () -> response.readEntity(InputStream.class));
+            assertNotNull(response.getEntity());
+            assertTrue(response.hasEntity());
+    
+            assertThrows(ResponseProcessingException.class, () -> response.readEntity(InputStream.class));
+            assertNotNull(response.getEntity());
+            assertTrue(response.hasEntity());
+    
+            response.close();
+        }
+    }
+    
+    @Provider
+    @Consumes("text/rdf")
+    public static class FaultyMessageBodyReader<T> implements MessageBodyReader<T> {
+        @Override
+        public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
+            return true;
+        }
+        
+        @Override
+        public T readFrom(Class<T> type, Type genericType, Annotation[] annotations, MediaType mediaType,
+                MultivaluedMap<String, String> httpHeaders, InputStream entityStream) 
+                    throws IOException, WebApplicationException {
+            IOUtils.consume(entityStream);
+            throw new IOException();
+        }
+    }
     
     public static class StringBean {
         private String header;