/** * $Id: $ * $Date: $ * */ package org.xmlsh.core.io; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; import java.io.UnsupportedEncodingException; import javanet.staxutils.ContentHandlerToXMLStreamWriter; import javanet.staxutils.XMLStreamEventWriter; import javax.xml.stream.XMLEventWriter; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; import net.sf.saxon.s9api.BuildingStreamWriter; import net.sf.saxon.s9api.Destination; import net.sf.saxon.s9api.Processor; import net.sf.saxon.s9api.SaxonApiException; import net.sf.saxon.s9api.Serializer; import net.sf.saxon.s9api.XdmDestination; import net.sf.saxon.trans.XPathException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.xml.sax.ContentHandler; import org.xmlsh.core.CoreException; import org.xmlsh.core.InvalidArgumentException; import org.xmlsh.core.XValue; import org.xmlsh.sh.shell.SerializeOpts; import org.xmlsh.sh.shell.Shell; import org.xmlsh.util.Util; public class XdmStreamOutputPort extends OutputPort { private IXdmItemWriter mWriter ; // Set to true if any asXXX method was caused which used a non-xml stream or access private boolean mAsText = false ; // Transient classes private XdmDestination mXdmDestination; private ByteArrayOutputStream mByteArrayOutputStream; private BuildingStreamWriter mBuilder; private SerializeOpts mSerializeOpts; // for converting from ByteArray to string private static Logger mLogger = LogManager.getLogger(); public XdmStreamOutputPort(IXdmItemWriter writer, SerializeOpts opts) { mWriter = writer; } @Override public OutputStream asOutputStream(SerializeOpts opts) { mSerializeOpts = opts ; mAsText = true ; return ( mByteArrayOutputStream = new ByteArrayOutputStream()); // BOS is synchroized } @Override public synchronized void flush() throws IOException { if (mXdmDestination != null){ mWriter.write( mXdmDestination.getXdmNode()); mXdmDestination.reset(); } // else if (mByteArrayOutputStream != null){ try { mWriter.write( XValue.newXValue(mByteArrayOutputStream.toString(mSerializeOpts.getOutputTextEncoding() )).toXdmValue() ); } catch (UnsupportedEncodingException |InvalidArgumentException e) { Util.wrapIOException(e); } mByteArrayOutputStream.reset(); } //else if (mBuilder != null){ try { mWriter.write(mBuilder.getDocumentNode()); } catch (SaxonApiException e) { throw new IOException(e); } // Cannot reset builder ! mBuilder = null ; } } @Override public void close() throws IOException { flush(); if( mWriter == null ) { mLogger .debug("mWriter null in close()"); } else mWriter.close(); mXdmDestination = null ; mByteArrayOutputStream = null ; mBuilder = null ; mWriter = null ; } @Override public synchronized PrintStream asPrintStream(SerializeOpts opts) { mAsText = true ; return new PrintStream(asOutputStream(opts)); } @Override public synchronized Destination asDestination(SerializeOpts opts) throws InvalidArgumentException, IOException { // If forcing text output then serialize to stream if( opts.isSerialize_xml() ){ return Util.streamToDestination(asOutputStream(opts), opts); } else { mXdmDestination = new XdmDestination(); return mXdmDestination; } } @Override public void writeSequenceSeperator(SerializeOpts serializeOpts) throws IOException, SaxonApiException, CoreException { flush(); } @Override public void writeSequenceTerminator(SerializeOpts serializeOpts) throws IOException, CoreException, SaxonApiException { flush(); } @Override public synchronized XMLStreamWriter asXMLStreamWriter(SerializeOpts opts) throws SaxonApiException, IOException { // If forcing text output then serialize to stream if( opts.isSerialize_xml() ){ // Saxon 9.3 supports serialization as a StreamWriter Serializer ser = Util.getSerializer(opts); ser.setOutputStream(asOutputStream(opts)); XMLStreamWriter sw = ser.getXMLStreamWriter(); return sw; } else { Processor proc = Shell.getProcessor(); BuildingStreamWriter bw = proc.newDocumentBuilder().newBuildingStreamWriter(); mBuilder = bw; return bw; } } @Override public XMLEventWriter asXMLEventWriter(SerializeOpts opts) throws InvalidArgumentException, SaxonApiException, XMLStreamException, IOException { // If forcing text output then serialize to stream if( opts.isSerialize_xml() ){ XMLOutputFactory fact = XMLOutputFactory.newInstance(); OutputStream os = asOutputStream(opts); if(opts.isOmit_xml_declaration() ) os = new OmittingOutputStream(os); // XMLOutputFactory fact = new OutputFactory(); XMLEventWriter writer = fact.createXMLEventWriter(os , opts.getOutputXmlEncoding() ); if( opts.isIndent()|| opts.isOmit_xml_declaration() ) writer = new OmittingIndentingXMLEventWriter(writer , os , opts.isIndent(), opts.isOmit_xml_declaration()); return writer ; } else { XMLStreamWriter sw = asXMLStreamWriter(opts); return new XMLStreamEventWriter( sw ); } } @Override public IXdmItemOutputStream asXdmItemOutputStream(SerializeOpts opts) throws CoreException, IOException { if( opts.isSerialize_xml()) return new DestinationXdmValueOutputStream( asDestination(opts) ); else return mWriter; } @Override public ContentHandler asContentHandler(SerializeOpts opts) throws XPathException, SaxonApiException, IOException { XMLStreamWriter sw = asXMLStreamWriter(opts); return new ContentHandlerToXMLStreamWriter(sw); } } // // //Copyright (C) 2008-2014 David A. Lee. // //The contents of this file are subject to the "Simplified BSD License" (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.opensource.org/licenses/bsd-license.php // //Software distributed under the License is distributed on an "AS IS" basis, //WITHOUT WARRANTY OF ANY KIND, either express or implied. //See the License for the specific language governing rights and limitations under the License. // //The Original Code is: all this file. // //The Initial Developer of the Original Code is David A. Lee // //Portions created by (your name) are Copyright (C) (your legal entity). All Rights Reserved. // //Contributor(s): none. //