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 
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}

--
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-unsubscr...@xmlbeans.apache.org
For additional commands, e-mail: dev-h...@xmlbeans.apache.org

Reply via email to