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

dkulp pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/cxf.git


The following commit(s) were added to refs/heads/main by this push:
     new 5ffdb906b5 Change from using aonymous inner classes to static classes 
to avoid holding onto "this" longer than needed. Fixes CXF-8946
5ffdb906b5 is described below

commit 5ffdb906b560458ad8df5a892554b6e806d98d9e
Author: Daniel Kulp <[email protected]>
AuthorDate: Thu Oct 19 16:03:36 2023 -0400

    Change from using aonymous inner classes to static classes to avoid holding 
onto "this" longer than needed.
    Fixes CXF-8946
---
 .../apache/cxf/jaxrs/client/AbstractClient.java    |   7 +
 .../cxf/transport/http/HttpClientHTTPConduit.java  | 232 ++++++++++++++-------
 2 files changed, 163 insertions(+), 76 deletions(-)

diff --git 
a/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java 
b/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java
index a8356ce002..3b83963804 100644
--- a/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java
+++ b/rt/rs/client/src/main/java/org/apache/cxf/jaxrs/client/AbstractClient.java
@@ -336,6 +336,13 @@ public abstract class AbstractClient implements Client {
         return this;
     }
 
+    @SuppressWarnings("deprecation")
+    @Override
+    protected void finalize() throws Throwable {
+        close();
+        super.finalize();
+    }
+    
     @Override
     public void close() {
         if (closed.compareAndSet(false, true)) {
diff --git 
a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HttpClientHTTPConduit.java
 
b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HttpClientHTTPConduit.java
index 86284ba093..10a65c6e50 100644
--- 
a/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HttpClientHTTPConduit.java
+++ 
b/rt/transports/http/src/main/java/org/apache/cxf/transport/http/HttpClientHTTPConduit.java
@@ -353,7 +353,141 @@ public class HttpClientHTTPConduit extends 
URLConnectionHTTPConduit {
         }
     }
 
-    class HttpClientWrappedOutputStream extends WrappedOutputStream {
+    static class HttpClientPipedOutputStream extends PipedOutputStream {
+        HttpClientWrappedOutputStream stream;
+        HTTPClientPolicy csPolicy;
+        HttpClientBodyPublisher publisher;
+        HttpClientPipedOutputStream(HttpClientWrappedOutputStream s, 
+                                    PipedInputStream pin,
+                                    HTTPClientPolicy cp,
+                                    HttpClientBodyPublisher bp) throws 
IOException {
+            super(pin);
+            stream = s;
+            csPolicy = cp;
+            publisher = bp;
+        }
+        public void close() throws IOException {
+            super.close();
+            csPolicy = null;
+            stream = null;  
+            if (publisher != null) {
+                publisher.close();
+                publisher = null;
+            }
+        }
+        synchronized boolean canWrite() throws IOException {
+            return stream.isConnectionAttemptCompleted(csPolicy, this);
+        }
+        @Override
+        public void write(int b) throws IOException {
+            if (stream != null && (stream.connectionComplete || canWrite())) {
+                super.write(b);
+            }
+        }
+        @Override
+        public void write(byte[] b, int off, int len) throws IOException {
+            if (stream != null && (stream.connectionComplete || canWrite())) {
+                super.write(b, off, len);
+            }
+        }
+
+    };
+    private static final class HttpClientFilteredInputStream extends 
FilterInputStream {
+        boolean closed;
+
+        private HttpClientFilteredInputStream(InputStream in) {
+            super(in);
+        }
+        @Override
+        public int read() throws IOException {
+            if (closed) {
+                throw new IOException("stream is closed");
+            }
+            return super.read();
+        }
+
+        @Override
+        public int read(byte[] b) throws IOException {
+            if (closed) {
+                throw new IOException("stream is closed");
+            }
+            return super.read(b);
+        }
+
+        @Override
+        public int read(byte[] b, int off, int len) throws IOException {
+            if (closed) {
+                throw new IOException("stream is closed");
+            }
+            return super.read(b, off, len);
+        }
+
+        @Override
+        public void close() throws IOException {
+            if (!closed) {
+                closed = true;
+                super.close();
+                in = null;
+            }
+        }
+    }
+    private static final class InputStreamSupplier implements 
Supplier<InputStream> {
+        final InputStream in;
+        InputStreamSupplier(InputStream i) {
+            in = i;
+        }
+        
+        public InputStream get() {
+            return in;
+        }
+    }
+    private static final class HttpClientBodyPublisher implements 
BodyPublisher {
+        PipedInputStream pin;
+        HttpClientWrappedOutputStream  stream;
+        long contentLen;
+
+        private HttpClientBodyPublisher(HttpClientWrappedOutputStream s, 
PipedInputStream pin) {
+            this.stream = s;
+            this.pin = pin;
+        }
+        synchronized void close() {
+            if (stream != null) {
+                contentLen = stream.contentLen;
+                stream = null;
+            }
+        }
+        
+        @Override
+        public synchronized void subscribe(Subscriber<? super ByteBuffer> 
subscriber) {
+            if (stream != null) {
+                stream.connectionComplete = true;
+                contentLen = stream.contentLen;
+                if (stream.pout != null) {
+                    synchronized (stream.pout) {
+                        stream.pout.notifyAll();                       
+                    }
+                    if (stream != null) {
+                        contentLen = stream.contentLen;
+                    }
+                    BodyPublishers.ofInputStream(new 
InputStreamSupplier(pin)).subscribe(subscriber);
+                    stream = null;
+                    pin = null;
+                    return;
+                }
+            }
+            BodyPublishers.noBody().subscribe(subscriber);
+        }
+
+        @Override
+        public long contentLength() {
+            if (stream != null) {
+                contentLen = stream.contentLen;
+            }
+            return contentLen;
+        }
+    }
+    class HttpClientWrappedOutputStream extends WrappedOutputStream {  
+
         List<Flow.Subscriber<? super ByteBuffer>> subscribers = new 
LinkedList<>();
         CompletableFuture<HttpResponse<InputStream>> future;
         long contentLen = -1;
@@ -361,6 +495,7 @@ public class HttpClientHTTPConduit extends 
URLConnectionHTTPConduit {
         volatile Throwable exception;
         volatile boolean connectionComplete;
         PipedOutputStream pout;
+        HttpClientBodyPublisher publisher;
         HttpRequest request;
         
         
@@ -371,7 +506,20 @@ public class HttpClientHTTPConduit extends 
URLConnectionHTTPConduit {
                   chunkThreshold, conduitName, 
((Address)message.get(KEY_HTTP_CONNECTION_ADDRESS)).getURI());
         }
 
-        
+        @Override
+        public void close() throws IOException {
+            super.close();
+            if (pout != null) {
+                pout.close();
+                pout = null;
+            }
+            if (publisher != null) {
+                publisher.close();
+                publisher = null;
+            }
+            request = null;
+            subscribers = null;            
+        }
         void addSubscriber(Flow.Subscriber<? super ByteBuffer> subscriber) {
             subscribers.add(subscriber);
         }
@@ -460,6 +608,7 @@ public class HttpClientHTTPConduit extends 
URLConnectionHTTPConduit {
             return true;
         }
         
+        
         @Override
         protected void setProtocolHeaders() throws IOException {
             HttpClient cl = outMessage.get(HttpClient.class);
@@ -476,52 +625,14 @@ public class HttpClientHTTPConduit extends 
URLConnectionHTTPConduit {
 
             final PipedInputStream pin = new 
PipedInputStream(csPolicy.getChunkLength() <= 0
                 ? 4096 : csPolicy.getChunkLength());
+            
+            this.publisher = new HttpClientBodyPublisher(this, pin);
             if (contentLen != 0) {
-                pout = new PipedOutputStream(pin) {
-                    synchronized boolean canWrite() throws IOException {
-                        return isConnectionAttemptCompleted(csPolicy, this);
-                    }
-                    @Override
-                    public void write(int b) throws IOException {
-                        if (connectionComplete || canWrite()) {
-                            super.write(b);
-                        }
-                    }
-                    @Override
-                    public void write(byte[] b, int off, int len) throws 
IOException {
-                        if (connectionComplete || canWrite()) {
-                            super.write(b, off, len);
-                        }
-                    }
-                };
+                pout = new HttpClientPipedOutputStream(this, pin, csPolicy, 
publisher);
             }
-            
-            BodyPublisher bp = new BodyPublisher() {
-                @Override
-                public void subscribe(Subscriber<? super ByteBuffer> 
subscriber) {
-                    connectionComplete = true;
-                    if (pout != null) {
-                        synchronized (pout) {
-                            pout.notifyAll();                       
-                        }
-                        BodyPublishers.ofInputStream(new 
Supplier<InputStream>() {
-                            public InputStream get() {
-                                return pin;
-                            }                
-                        }).subscribe(subscriber);
-                    } else {
-                        BodyPublishers.noBody().subscribe(subscriber);
-                    }
-                }
-
-                @Override
-                public long contentLength() {
-                    return contentLen;
-                }                
-            };
 
             HttpRequest.Builder rb = HttpRequest.newBuilder()
-                .method(httpRequestMethod, bp);  
+                .method(httpRequestMethod, publisher);  
             String verc = 
(String)outMessage.getContextualProperty(FORCE_HTTP_VERSION);
             if (verc == null) {
                 verc = csPolicy.getVersion();
@@ -684,38 +795,7 @@ public class HttpClientHTTPConduit extends 
URLConnectionHTTPConduit {
                     }
                 }
             }
-            return new FilterInputStream(resp.body()) {
-                boolean closed;
-                @Override
-                public int read() throws IOException {
-                    if (closed) {
-                        throw new IOException("stream is closed");
-                    }
-                    return super.read();
-                }
-
-                @Override
-                public int read(byte[] b) throws IOException {
-                    if (closed) {
-                        throw new IOException("stream is closed");
-                    }
-                    return super.read(b);
-                }
-
-                @Override
-                public int read(byte[] b, int off, int len) throws IOException 
{
-                    if (closed) {
-                        throw new IOException("stream is closed");
-                    }
-                    return super.read(b, off, len);
-                }
-
-                @Override
-                public void close() throws IOException {
-                    closed = true;
-                    super.close();
-                }
-            };
+            return new HttpClientFilteredInputStream(resp.body());
         }
 
         @Override

Reply via email to