You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by dk...@apache.org on 2021/09/29 17:37:26 UTC

[cxf] 01/03: [CXF-7396] Close some input streams/readers when copying from various source objects to output

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

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

commit 69590fe82d3dc1a1e0d7c42753c2465a1380abea
Author: Daniel Kulp <dk...@apache.org>
AuthorDate: Tue Aug 17 16:54:09 2021 -0400

    [CXF-7396] Close some input streams/readers when copying from various source objects to output
    
    (cherry picked from commit 148f59425afbe5c95786d5f65912cd7c3c1fcc9c)
---
 .../databinding/source/XMLStreamDataWriter.java    | 29 +++++++--
 .../apache/cxf/systest/jaxws/ClientServerTest.java | 69 ++++++++++++++++++++++
 2 files changed, 94 insertions(+), 4 deletions(-)

diff --git a/core/src/main/java/org/apache/cxf/databinding/source/XMLStreamDataWriter.java b/core/src/main/java/org/apache/cxf/databinding/source/XMLStreamDataWriter.java
index 1a388a7..fa01975 100644
--- a/core/src/main/java/org/apache/cxf/databinding/source/XMLStreamDataWriter.java
+++ b/core/src/main/java/org/apache/cxf/databinding/source/XMLStreamDataWriter.java
@@ -18,7 +18,9 @@
  */
 package org.apache.cxf.databinding.source;
 
+import java.io.Closeable;
 import java.io.IOException;
+import java.io.InputStream;
 import java.util.Collection;
 import java.util.logging.Logger;
 
@@ -28,6 +30,7 @@ import javax.xml.stream.XMLStreamReader;
 import javax.xml.stream.XMLStreamWriter;
 import javax.xml.transform.Source;
 import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamSource;
 import javax.xml.validation.Schema;
 import javax.xml.validation.Validator;
 
@@ -67,22 +70,24 @@ public class XMLStreamDataWriter implements DataWriter<XMLStreamWriter> {
 
     @SuppressWarnings("PMD.UseTryWithResources")
     public void write(Object obj, XMLStreamWriter writer) {
-        try {
+        Closeable toClose = null;
+        try {            
             if (obj instanceof DataSource) {
                 DataSource ds = (DataSource)obj;
+                InputStream is = ds.getInputStream();
+                toClose = is;                    
                 if (schema != null) {
-                    DOMSource domSource = new DOMSource(StaxUtils.read(ds.getInputStream()));
+                    DOMSource domSource = new DOMSource(StaxUtils.read(is));
                     Validator schemaValidator = schema.newValidator();
                     schemaValidator.setErrorHandler(
                         new MtomValidationErrorHandler(schemaValidator.getErrorHandler(), domSource.getNode()));
                     schemaValidator.validate(domSource);
                     StaxUtils.copy(domSource, writer);
                 } else {
-                    XMLStreamReader reader = StaxUtils.createXMLStreamReader(ds.getInputStream());
+                    XMLStreamReader reader = StaxUtils.createXMLStreamReader(is);
                     StaxUtils.copy(reader, writer);
                     reader.close();
                 }
-
             } else if (obj instanceof Node) {
                 if (obj instanceof DocumentFragment) {
                     obj = org.apache.cxf.helpers.DOMUtils.getDomDocumentFragment((DocumentFragment)obj);
@@ -111,6 +116,14 @@ public class XMLStreamDataWriter implements DataWriter<XMLStreamWriter> {
                     && ((DOMSource) s).getNode() == null) {
                     return;
                 }
+                if (s instanceof StreamSource) {
+                    StreamSource ss = (StreamSource)s;
+                    if (ss.getInputStream() != null) {
+                        toClose = ss.getInputStream();
+                    } else {
+                        toClose = ss.getReader();
+                    }
+                }
                 StaxUtils.copy(s, writer);
             }
         } catch (XMLStreamException e) {
@@ -121,6 +134,14 @@ public class XMLStreamDataWriter implements DataWriter<XMLStreamWriter> {
         } catch (SAXException e) {
             throw new Fault("COULD_NOT_WRITE_XML_STREAM_CAUSED_BY", LOG, e,
                             e.getClass().getCanonicalName(), e.getMessage());
+        } finally {
+            if (toClose != null) {
+                try {
+                    toClose.close();
+                } catch (IOException ex) {
+                    //likely already closed, not something we need to worry about
+                }
+            }
         }
     }
 
diff --git a/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerTest.java b/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerTest.java
index 912aa8a..72b37e6 100644
--- a/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerTest.java
+++ b/systests/jaxws/src/test/java/org/apache/cxf/systest/jaxws/ClientServerTest.java
@@ -20,6 +20,7 @@
 package org.apache.cxf.systest.jaxws;
 
 import java.io.ByteArrayInputStream;
+import java.io.File;
 import java.io.InputStream;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
@@ -53,6 +54,8 @@ import javax.xml.ws.soap.SOAPFaultException;
 
 import org.w3c.dom.Document;
 
+import com.google.common.io.Files;
+
 import org.apache.cxf.Bus;
 import org.apache.cxf.bus.CXFBusFactory;
 import org.apache.cxf.common.logging.LogUtils;
@@ -61,6 +64,8 @@ import org.apache.cxf.endpoint.Client;
 import org.apache.cxf.endpoint.dynamic.DynamicClientFactory;
 import org.apache.cxf.ext.logging.LoggingFeature;
 import org.apache.cxf.frontend.ClientProxy;
+import org.apache.cxf.helpers.FileUtils;
+import org.apache.cxf.io.CachedOutputStream;
 import org.apache.cxf.jaxws.DispatchImpl;
 import org.apache.cxf.message.Message;
 import org.apache.cxf.staxutils.StaxUtils;
@@ -1001,6 +1006,70 @@ public class ClientServerTest extends AbstractBusClientServerTestBase {
 
         assertEquals(requestString, StaxUtils.toString(response));
     }
+    
+    @Test
+    public void testEchoProviderThresholdAsync() throws Exception {
+        final File f = Files.createTempDir();
+        LOG.info("Using temp folder: " + f.getAbsolutePath());
+        
+        System.setProperty("org.apache.cxf.io.CachedOutputStream.OutputDirectory", f.getAbsolutePath());
+        CachedOutputStream.setDefaultThreshold(5);
+        
+        String requestString = "<echo/>";
+        Service service = Service.create(serviceName);
+        service.addPort(fakePortName, javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_BINDING,
+                        "http://localhost:" + PORT + "/SoapContext/AsyncEchoProvider");
+        Dispatch<StreamSource> dispatcher = service.createDispatch(fakePortName,
+                                                                   StreamSource.class,
+                                                                   Service.Mode.PAYLOAD);
+        dispatcher.getRequestContext().put("javax.xml.ws.client.receiveTimeout", "5000");
+        
+        StreamSource request = new StreamSource(new ByteArrayInputStream(requestString.getBytes()));
+        StreamSource response = dispatcher.invoke(request);
+
+        assertEquals(requestString, StaxUtils.toString(response));
+        
+        //give the server side a little time to process it's part and close the files
+        if (f.list().length > 0) {
+            Thread.sleep(500);
+        }
+        
+        assertEquals("Expected no files but there is at list one", 0, f.list().length);
+        FileUtils.removeDir(f);
+    }
+    
+    @Test
+    public void testEchoProviderThresholdAsyncThrows() throws Exception {
+        final File f = Files.createTempDir();
+        LOG.info("Using temp folder: " + f.getAbsolutePath());
+        
+        System.setProperty("org.apache.cxf.io.CachedOutputStream.OutputDirectory", f.getAbsolutePath());
+        CachedOutputStream.setDefaultThreshold(5);
+        
+        String requestString = "<echo/>";
+        Service service = Service.create(serviceName);
+        service.addPort(fakePortName, javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_BINDING,
+                        "http://localhost:" + PORT + "/SoapContext/AsyncEchoProvider");
+        Dispatch<StreamSource> dispatcher = service.createDispatch(fakePortName,
+                                                                   StreamSource.class,
+                                                                   Service.Mode.PAYLOAD);
+        dispatcher.getRequestContext().put("javax.xml.ws.client.receiveTimeout", "500");
+        
+        try {
+            StreamSource request = new StreamSource(new ByteArrayInputStream(requestString.getBytes()));
+            StreamSource response = dispatcher.invoke(request);
+            assertEquals(requestString, StaxUtils.toString(response));
+        } catch (final WebServiceException ex) {
+            ((DispatchImpl<StreamSource>)dispatcher).getClient().close();
+        }
+        //give the server side a little time to process it's part and close the files
+        if (f.list().length > 0) {
+            Thread.sleep(500);
+        }
+        
+        assertEquals("Expected no files but there is at list one", 0, f.list().length);
+        FileUtils.removeDir(f);
+    }
 
     @Test
     public void testEchoProviderAsyncDecoupledEndpoints() throws Exception {