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 2021/02/25 01:36:06 UTC

[cxf] 01/02: CXF-8422: Unclosed input streams after using org.apache.cxf.tools.wsdlto.WSDLToJava (targeting StAX's XMLStreamReader) (#748)

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

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

commit b3f4c07597c2ba5b17d5ef881286606c780cc2fc
Author: Andriy Redko <dr...@gmail.com>
AuthorDate: Wed Feb 24 12:58:48 2021 -0500

    CXF-8422: Unclosed input streams after using org.apache.cxf.tools.wsdlto.WSDLToJava (targeting StAX's XMLStreamReader) (#748)
    
    (cherry picked from commit be75ea56aa3724bcdc7f8223cd8cc129a08fdf44)
    
    # Conflicts:
    #	core/src/main/java/org/apache/cxf/staxutils/StaxUtils.java
---
 .../staxutils/AutoCloseableXMLStreamReader.java    | 274 +++++++++++++++++++++
 .../java/org/apache/cxf/staxutils/StaxUtils.java   |  54 ++--
 .../cxf/ws/security/wss4j/StaxSerializer.java      |  13 +-
 3 files changed, 325 insertions(+), 16 deletions(-)

diff --git a/core/src/main/java/org/apache/cxf/staxutils/AutoCloseableXMLStreamReader.java b/core/src/main/java/org/apache/cxf/staxutils/AutoCloseableXMLStreamReader.java
new file mode 100644
index 0000000..103d13a
--- /dev/null
+++ b/core/src/main/java/org/apache/cxf/staxutils/AutoCloseableXMLStreamReader.java
@@ -0,0 +1,274 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.cxf.staxutils;
+
+import java.io.Closeable;
+import java.io.IOException;
+
+import javax.xml.namespace.NamespaceContext;
+import javax.xml.namespace.QName;
+import javax.xml.stream.Location;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+public class AutoCloseableXMLStreamReader implements XMLStreamReader, AutoCloseable {
+    private final XMLStreamReader delegate;
+    private final Closeable source;
+    
+    AutoCloseableXMLStreamReader(XMLStreamReader delegate, Closeable source) {
+        this.delegate = delegate;
+        this.source = source;
+    }
+
+    @Override
+    public void close() throws XMLStreamException {
+        if (delegate != null) {
+            delegate.close();
+        }
+        try {
+            if (source != null) {
+                source.close();
+            }
+        } catch (IOException ex) {
+            throw new XMLStreamException(ex);
+        }
+    }
+
+    @Override
+    public Object getProperty(String name) throws IllegalArgumentException {
+        return delegate.getProperty(name);
+    }
+
+    @Override
+    public int next() throws XMLStreamException {
+        return delegate.next();
+    }
+
+    @Override
+    public void require(int type, String namespaceURI, String localName) throws XMLStreamException {
+        delegate.require(type, namespaceURI, localName);
+    }
+
+    @Override
+    public String getElementText() throws XMLStreamException {
+        return delegate.getElementText();
+    }
+
+    @Override
+    public int nextTag() throws XMLStreamException {
+        return delegate.nextTag();
+    }
+
+    @Override
+    public boolean hasNext() throws XMLStreamException {
+        return delegate.hasNext();
+    }
+
+    @Override
+    public String getNamespaceURI(String prefix) {
+        return delegate.getNamespaceURI(prefix);
+    }
+
+    @Override
+    public boolean isStartElement() {
+        return delegate.isStartElement();
+    }
+
+    @Override
+    public boolean isEndElement() {
+        return delegate.isEndElement();
+    }
+
+    @Override
+    public boolean isCharacters() {
+        return delegate.isCharacters();
+    }
+
+    @Override
+    public boolean isWhiteSpace() {
+        return delegate.isWhiteSpace();
+    }
+
+    @Override
+    public String getAttributeValue(String namespaceURI, String localName) {
+        return delegate.getAttributeValue(namespaceURI, localName);
+    }
+
+    @Override
+    public int getAttributeCount() {
+        return delegate.getAttributeCount();
+    }
+
+    @Override
+    public QName getAttributeName(int index) {
+        return delegate.getAttributeName(index);
+    }
+
+    @Override
+    public String getAttributeNamespace(int index) {
+        return delegate.getAttributeNamespace(index);
+    }
+
+    @Override
+    public String getAttributeLocalName(int index) {
+        return delegate.getAttributeLocalName(index);
+    }
+
+    @Override
+    public String getAttributePrefix(int index) {
+        return delegate.getAttributePrefix(index);
+    }
+
+    @Override
+    public String getAttributeType(int index) {
+        return delegate.getAttributeType(index);
+    }
+
+    @Override
+    public String getAttributeValue(int index) {
+        return delegate.getAttributeValue(index);
+    }
+
+    @Override
+    public boolean isAttributeSpecified(int index) {
+        return delegate.isAttributeSpecified(index);
+    }
+
+    @Override
+    public int getNamespaceCount() {
+        return delegate.getNamespaceCount();
+    }
+
+    @Override
+    public String getNamespacePrefix(int index) {
+        return delegate.getNamespacePrefix(index);
+    }
+
+    @Override
+    public String getNamespaceURI(int index) {
+        return delegate.getNamespaceURI(index);
+    }
+
+    @Override
+    public NamespaceContext getNamespaceContext() {
+        return delegate.getNamespaceContext();
+    }
+
+    @Override
+    public int getEventType() {
+        return delegate.getEventType();
+    }
+
+    @Override
+    public String getText() {
+        return delegate.getText();
+    }
+
+    @Override
+    public char[] getTextCharacters() {
+        return delegate.getTextCharacters();
+    }
+
+    @Override
+    public int getTextCharacters(int sourceStart, char[] target, int targetStart, int length) 
+            throws XMLStreamException {
+        return delegate.getTextCharacters(sourceStart, target, targetStart, length);
+    }
+
+    @Override
+    public int getTextStart() {
+        return delegate.getTextStart();
+    }
+
+    @Override
+    public int getTextLength() {
+        return delegate.getTextLength();
+    }
+
+    @Override
+    public String getEncoding() {
+        return delegate.getEncoding();
+    }
+
+    @Override
+    public boolean hasText() {
+        return delegate.hasText();
+    }
+
+    @Override
+    public Location getLocation() {
+        return delegate.getLocation();
+    }
+
+    @Override
+    public QName getName() {
+        return delegate.getName();
+    }
+
+    @Override
+    public String getLocalName() {
+        return delegate.getLocalName();
+    }
+
+    @Override
+    public boolean hasName() {
+        return delegate.hasName();
+    }
+
+    @Override
+    public String getNamespaceURI() {
+        return delegate.getNamespaceURI();
+    }
+
+    @Override
+    public String getPrefix() {
+        return delegate.getPrefix();
+    }
+
+    @Override
+    public String getVersion() {
+        return delegate.getVersion();
+    }
+
+    @Override
+    public boolean isStandalone() {
+        return delegate.isStandalone();
+    }
+
+    @Override
+    public boolean standaloneSet() {
+        return delegate.standaloneSet();
+    }
+
+    @Override
+    public String getCharacterEncodingScheme() {
+        return delegate.getCharacterEncodingScheme();
+    }
+
+    @Override
+    public String getPITarget() {
+        return delegate.getPITarget();
+    }
+
+    @Override
+    public String getPIData() {
+        return delegate.getPIData();
+    }
+}
\ No newline at end of file
diff --git a/core/src/main/java/org/apache/cxf/staxutils/StaxUtils.java b/core/src/main/java/org/apache/cxf/staxutils/StaxUtils.java
index bdb2da4..b8fe2bf 100644
--- a/core/src/main/java/org/apache/cxf/staxutils/StaxUtils.java
+++ b/core/src/main/java/org/apache/cxf/staxutils/StaxUtils.java
@@ -122,6 +122,8 @@ public final class StaxUtils {
         "org.apache.cxf.staxutils.innerElementCountThreshold";
     private static final String INNER_ELEMENT_LEVEL_SYSTEM_PROP =
         "org.apache.cxf.staxutils.innerElementLevelThreshold";
+    private static final String AUTO_CLOSE_INPUT_SOURCE_PROP =
+        "org.apache.cxf.staxutils.autoCloseInputSource";
 
     private static final Logger LOG = LogUtils.getL7dLogger(StaxUtils.class);
 
@@ -145,6 +147,7 @@ public final class StaxUtils {
     private static int minTextSegment = 64; // Same default as woodstox
     private static long maxElementCount = Long.MAX_VALUE;
     private static long maxXMLCharacters = Long.MAX_VALUE;
+    private static final boolean AUTO_CLOSE_INPUT_SOURCE;
 
     private static boolean allowInsecureParser;
 
@@ -170,6 +173,15 @@ public final class StaxUtils {
         String s = SystemPropertyAction.getPropertyOrNull(ALLOW_INSECURE_PARSER);
         if (!StringUtils.isEmpty(s)) {
             allowInsecureParser = "1".equals(s) || Boolean.parseBoolean(s);
+        } else {
+            allowInsecureParser = false;
+        }
+        
+        String autoCloseInputSource = SystemPropertyAction.getPropertyOrNull(AUTO_CLOSE_INPUT_SOURCE_PROP);
+        if (!StringUtils.isEmpty(autoCloseInputSource)) {
+            AUTO_CLOSE_INPUT_SOURCE = "1".equals(autoCloseInputSource) || Boolean.parseBoolean(autoCloseInputSource);
+        } else {
+            AUTO_CLOSE_INPUT_SOURCE = false; /* set 'false' by default */
         }
 
         XMLInputFactory xif = null;
@@ -1157,15 +1169,12 @@ public final class StaxUtils {
         }
     }
     public static Document read(InputSource s) throws XMLStreamException {
-        XMLStreamReader reader = createXMLStreamReader(s);
+        XMLStreamReader reader = null;
         try {
+            reader = createXMLStreamReader(s);
             return read(reader);
         } finally {
-            try {
-                reader.close();
-            } catch (Exception ex) {
-                //ignore
-            }
+            StaxUtils.close(reader);
         }
     }
     public static Document read(XMLStreamReader reader) throws XMLStreamException {
@@ -1683,22 +1692,38 @@ public final class StaxUtils {
         String sysId = src.getSystemId() == null ? null : src.getSystemId();
         String pubId = src.getPublicId() == null ? null : src.getPublicId();
         if (src.getByteStream() != null) {
+            final InputStream is = src.getByteStream();
+
             if (src.getEncoding() == null) {
-                StreamSource ss = new StreamSource(src.getByteStream(), sysId);
+                final StreamSource ss = new StreamSource(is, sysId);
                 ss.setPublicId(pubId);
-                return createXMLStreamReader(ss);
+                
+                final XMLStreamReader xmlStreamReader = createXMLStreamReader(ss);
+                if (AUTO_CLOSE_INPUT_SOURCE) {
+                    return new AutoCloseableXMLStreamReader(xmlStreamReader, is);
+                } else {
+                    return xmlStreamReader;
+                }
             }
-            return createXMLStreamReader(src.getByteStream(), src.getEncoding());
+            
+            return new AutoCloseableXMLStreamReader(createXMLStreamReader(is, src.getEncoding()), is);
         } else if (src.getCharacterStream() != null) {
-            StreamSource ss = new StreamSource(src.getCharacterStream(), sysId);
+            final Reader reader = src.getCharacterStream();
+            final StreamSource ss = new StreamSource(reader, sysId);
             ss.setPublicId(pubId);
-            return createXMLStreamReader(ss);
+            final XMLStreamReader xmlStreamReader = createXMLStreamReader(ss);
+            if (AUTO_CLOSE_INPUT_SOURCE) {
+                return new AutoCloseableXMLStreamReader(xmlStreamReader, reader);
+            } else {
+                return xmlStreamReader;
+            }
         } else {
             try {
-                URL url = new URL(sysId);
-                StreamSource ss = new StreamSource(url.openStream(), sysId);
+                final URL url = new URL(sysId);
+                final InputStream is = url.openStream();
+                final StreamSource ss = new StreamSource(is, sysId);
                 ss.setPublicId(pubId);
-                return createXMLStreamReader(ss);
+                return new AutoCloseableXMLStreamReader(createXMLStreamReader(ss), is);
             } catch (Exception ex) {
                 //ignore - not a valid URL
             }
@@ -2220,4 +2245,5 @@ public final class StaxUtils {
         WoodstoxHelper.setProperty(reader, p, v);
     }
 
+    
 }
diff --git a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/StaxSerializer.java b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/StaxSerializer.java
index 495e3fa..9ae5063 100644
--- a/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/StaxSerializer.java
+++ b/rt/ws/security/src/main/java/org/apache/cxf/ws/security/wss4j/StaxSerializer.java
@@ -213,8 +213,17 @@ public class StaxSerializer extends AbstractSerializer {
      * @throws XMLEncryptionException
      */
     private Node deserialize(Node ctx, InputSource inputSource) throws XMLEncryptionException {
-        XMLStreamReader reader = StaxUtils.createXMLStreamReader(inputSource);
-        return deserialize(ctx, reader, true);
+        XMLStreamReader reader = null;
+        try {
+            reader = StaxUtils.createXMLStreamReader(inputSource);
+            return deserialize(ctx, reader, true);
+        } finally {
+            try {
+                StaxUtils.close(reader);
+            } catch (final XMLStreamException ex) {
+                throw new XMLEncryptionException(ex);
+            }
+        }
     }
     private Node deserialize(Node ctx, XMLStreamReader reader, boolean wrapped) throws XMLEncryptionException {
         Document contextDocument = null;