You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@xmlbeans.apache.org by "Robby Morgan (Updated) (JIRA)" <xm...@xml.apache.org> on 2012/01/19 15:10:41 UTC

[jira] [Updated] (XMLBEANS-477) Piccolo parser improperly retains and re-closes InputStream from previous invocation

     [ https://issues.apache.org/jira/browse/XMLBEANS-477?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Robby Morgan updated XMLBEANS-477:
----------------------------------

    Description: 
I have uncovered odd behavior within the Piccolo parser when XMLBeans is asked to parse a second document on the same thread.  What I have observed is that, while the Piccolo parser closes the input stream after parsing the first document, it retains a reference to the input stream and closes it again immediately before parsing the input stream for the second document.  If the input stream reference is the same for the two documents, as is the case when a request is processed on the same thread in Tomcat, then the second document will fail to parse.

Here is sample code that demonstrates the issue:
{code}
import my.xmlbeans.ServerDocument;
import org.apache.commons.io.input.ProxyInputStream;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOptions;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * Issue:  XmlBeans (when using the Piccolo SAX parser) retains a reference to the previous input stream on the
 *  current thread, and if that stream is reopened and passed back into XmlBeans, then the stream will be closed
 *  prior to parsing any of the contents, producing the following exception:
 *
 * Exception in thread "main" java.lang.IllegalStateException: Stream is already closed
 * at XmlBeansReclosingIssue$ReopenableInputStream.beforeRead(XmlBeansReclosingIssue.java:50)
 * at org.apache.commons.io.input.ProxyInputStream.read(ProxyInputStream.java:98)
 * at org.apache.xmlbeans.impl.piccolo.xml.XMLStreamReader.fillByteBuffer(XMLStreamReader.java:209)
 * at org.apache.xmlbeans.impl.piccolo.xml.XMLStreamReader.reset(XMLStreamReader.java:97)
 * at org.apache.xmlbeans.impl.piccolo.xml.DocumentEntity.open(DocumentEntity.java:94)
 * at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.reset(PiccoloLexer.java:982)
 * at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.parse(Piccolo.java:709)
 * at org.apache.xmlbeans.impl.store.Locale$SaxLoader.load(Locale.java:3454)
 * at org.apache.xmlbeans.impl.store.Locale.parseToXmlObject(Locale.java:1276)
 * at org.apache.xmlbeans.impl.store.Locale.parseToXmlObject(Locale.java:1250)
 * at org.apache.xmlbeans.impl.schema.SchemaTypeLoaderBase.parse(SchemaTypeLoaderBase.java:345)
 * at my.xmlbeans.ServerDocument$Factory.parse(Unknown Source)
 * at XmlBeansReclosingIssue.main(XmlBeansReclosingIssue.java:40)
 */
public class XmlBeansReclosingIssue {

    public static void main(String[] args) throws IOException, XmlException {
        File inputFile = new File(args[0]);
        ReopenableInputStream reopenableInputStream = new ReopenableInputStream(new FileInputStream(inputFile));
        ServerDocument.Factory.parse(reopenableInputStream, new XmlOptions().setUnsynchronized());
        reopenableInputStream.reopen(new FileInputStream(inputFile));
        ServerDocument.Factory.parse(reopenableInputStream, new XmlOptions().setUnsynchronized());
    }

    private static class ReopenableInputStream extends ProxyInputStream {
        private boolean _closed;

        public ReopenableInputStream(FileInputStream inputStream) {
            super(inputStream);
            _closed = false;
        }

        public void reopen(InputStream in) {
            if (!_closed) {
                throw new IllegalStateException("Stream is not closed");
            }
            _closed = false;
            this.in = in;
        }

        @Override
        protected void beforeRead(int n) throws IOException {
            if (_closed) {
                throw new IllegalStateException("Stream is already closed");
            }
        }

        @Override
        public void close() throws IOException {
            if (_closed) {
                throw new IllegalStateException("Stream is already closed");
            }
            _closed = true;
            super.close();
        }
    }
}
{code}

  was:
I have uncovered odd behavior within the Piccolo parser when XMLBeans is asked to parse a second document on the same thread.  What I have observed is that, while the Piccolo parser closes the input stream after parsing the first document, it retains a reference to the input stream and closes it again immediately before parsing the input stream for the second document.  If the input stream reference is the same for the two documents, as is the case when a request is processed on the same thread in Tomcat, then the second document will fail to parse.

Here is sample code that demonstrates the issue:
{code}
import my.xmlbeans.ServerDocument;
import org.apache.commons.io.input.ProxyInputStream;
import org.apache.xmlbeans.XmlException;
import org.apache.xmlbeans.XmlOptions;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;

/**
 * Issue:  XmlBeans (when using the Piccolo SAX parser) retains a reference to the previous input stream on the
 *  current thread, and if that stream is reopened and passed back into XmlBeans, then the stream will be closed
 *  prior to parsing any of the contents, producing the following exception:
 *
 * Exception in thread "main" java.lang.IllegalStateException: Stream is already closed
 * at com.bazaarvoice.pacman.tools.XmlBeansReclosingIssue$ReopenableInputStream.beforeRead(XmlBeansReclosingIssue.java:50)
 * at org.apache.commons.io.input.ProxyInputStream.read(ProxyInputStream.java:98)
 * at org.apache.xmlbeans.impl.piccolo.xml.XMLStreamReader.fillByteBuffer(XMLStreamReader.java:209)
 * at org.apache.xmlbeans.impl.piccolo.xml.XMLStreamReader.reset(XMLStreamReader.java:97)
 * at org.apache.xmlbeans.impl.piccolo.xml.DocumentEntity.open(DocumentEntity.java:94)
 * at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.reset(PiccoloLexer.java:982)
 * at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.parse(Piccolo.java:709)
 * at org.apache.xmlbeans.impl.store.Locale$SaxLoader.load(Locale.java:3454)
 * at org.apache.xmlbeans.impl.store.Locale.parseToXmlObject(Locale.java:1276)
 * at org.apache.xmlbeans.impl.store.Locale.parseToXmlObject(Locale.java:1250)
 * at org.apache.xmlbeans.impl.schema.SchemaTypeLoaderBase.parse(SchemaTypeLoaderBase.java:345)
 * at my.xmlbeans.ServerDocument$Factory.parse(Unknown Source)
 * at XmlBeansReclosingIssue.main(XmlBeansReclosingIssue.java:40)
 */
public class XmlBeansReclosingIssue {

    public static void main(String[] args) throws IOException, XmlException {
        File inputFile = new File(args[0]);
        ReopenableInputStream reopenableInputStream = new ReopenableInputStream(new FileInputStream(inputFile));
        ServerDocument.Factory.parse(reopenableInputStream, new XmlOptions().setUnsynchronized());
        reopenableInputStream.reopen(new FileInputStream(inputFile));
        ServerDocument.Factory.parse(reopenableInputStream, new XmlOptions().setUnsynchronized());
    }

    private static class ReopenableInputStream extends ProxyInputStream {
        private boolean _closed;

        public ReopenableInputStream(FileInputStream inputStream) {
            super(inputStream);
            _closed = false;
        }

        public void reopen(InputStream in) {
            if (!_closed) {
                throw new IllegalStateException("Stream is not closed");
            }
            _closed = false;
            this.in = in;
        }

        @Override
        protected void beforeRead(int n) throws IOException {
            if (_closed) {
                throw new IllegalStateException("Stream is already closed");
            }
        }

        @Override
        public void close() throws IOException {
            if (_closed) {
                throw new IllegalStateException("Stream is already closed");
            }
            _closed = true;
            super.close();
        }
    }
}
{code}

    
> Piccolo parser improperly retains and re-closes InputStream from previous invocation
> ------------------------------------------------------------------------------------
>
>                 Key: XMLBEANS-477
>                 URL: https://issues.apache.org/jira/browse/XMLBEANS-477
>             Project: XMLBeans
>          Issue Type: Bug
>    Affects Versions: Version 2.4 , Version 2.5
>            Reporter: Robby Morgan
>
> I have uncovered odd behavior within the Piccolo parser when XMLBeans is asked to parse a second document on the same thread.  What I have observed is that, while the Piccolo parser closes the input stream after parsing the first document, it retains a reference to the input stream and closes it again immediately before parsing the input stream for the second document.  If the input stream reference is the same for the two documents, as is the case when a request is processed on the same thread in Tomcat, then the second document will fail to parse.
> Here is sample code that demonstrates the issue:
> {code}
> import my.xmlbeans.ServerDocument;
> import org.apache.commons.io.input.ProxyInputStream;
> import org.apache.xmlbeans.XmlException;
> import org.apache.xmlbeans.XmlOptions;
> import java.io.File;
> import java.io.FileInputStream;
> import java.io.IOException;
> import java.io.InputStream;
> /**
>  * Issue:  XmlBeans (when using the Piccolo SAX parser) retains a reference to the previous input stream on the
>  *  current thread, and if that stream is reopened and passed back into XmlBeans, then the stream will be closed
>  *  prior to parsing any of the contents, producing the following exception:
>  *
>  * Exception in thread "main" java.lang.IllegalStateException: Stream is already closed
>  * at XmlBeansReclosingIssue$ReopenableInputStream.beforeRead(XmlBeansReclosingIssue.java:50)
>  * at org.apache.commons.io.input.ProxyInputStream.read(ProxyInputStream.java:98)
>  * at org.apache.xmlbeans.impl.piccolo.xml.XMLStreamReader.fillByteBuffer(XMLStreamReader.java:209)
>  * at org.apache.xmlbeans.impl.piccolo.xml.XMLStreamReader.reset(XMLStreamReader.java:97)
>  * at org.apache.xmlbeans.impl.piccolo.xml.DocumentEntity.open(DocumentEntity.java:94)
>  * at org.apache.xmlbeans.impl.piccolo.xml.PiccoloLexer.reset(PiccoloLexer.java:982)
>  * at org.apache.xmlbeans.impl.piccolo.xml.Piccolo.parse(Piccolo.java:709)
>  * at org.apache.xmlbeans.impl.store.Locale$SaxLoader.load(Locale.java:3454)
>  * at org.apache.xmlbeans.impl.store.Locale.parseToXmlObject(Locale.java:1276)
>  * at org.apache.xmlbeans.impl.store.Locale.parseToXmlObject(Locale.java:1250)
>  * at org.apache.xmlbeans.impl.schema.SchemaTypeLoaderBase.parse(SchemaTypeLoaderBase.java:345)
>  * at my.xmlbeans.ServerDocument$Factory.parse(Unknown Source)
>  * at XmlBeansReclosingIssue.main(XmlBeansReclosingIssue.java:40)
>  */
> public class XmlBeansReclosingIssue {
>     public static void main(String[] args) throws IOException, XmlException {
>         File inputFile = new File(args[0]);
>         ReopenableInputStream reopenableInputStream = new ReopenableInputStream(new FileInputStream(inputFile));
>         ServerDocument.Factory.parse(reopenableInputStream, new XmlOptions().setUnsynchronized());
>         reopenableInputStream.reopen(new FileInputStream(inputFile));
>         ServerDocument.Factory.parse(reopenableInputStream, new XmlOptions().setUnsynchronized());
>     }
>     private static class ReopenableInputStream extends ProxyInputStream {
>         private boolean _closed;
>         public ReopenableInputStream(FileInputStream inputStream) {
>             super(inputStream);
>             _closed = false;
>         }
>         public void reopen(InputStream in) {
>             if (!_closed) {
>                 throw new IllegalStateException("Stream is not closed");
>             }
>             _closed = false;
>             this.in = in;
>         }
>         @Override
>         protected void beforeRead(int n) throws IOException {
>             if (_closed) {
>                 throw new IllegalStateException("Stream is already closed");
>             }
>         }
>         @Override
>         public void close() throws IOException {
>             if (_closed) {
>                 throw new IllegalStateException("Stream is already closed");
>             }
>             _closed = true;
>             super.close();
>         }
>     }
> }
> {code}

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators: https://issues.apache.org/jira/secure/ContactAdministrators!default.jspa
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@xmlbeans.apache.org
For additional commands, e-mail: dev-help@xmlbeans.apache.org