/** * $Id: $ * $Date: $ * */ package org.xmlsh.core.io; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintStream; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.math.BigDecimal; import java.math.BigInteger; import javanet.staxutils.ContentHandlerToXMLStreamWriter; import javanet.staxutils.XMLStreamEventWriter; import javax.xml.stream.XMLEventWriter; 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.XdmAtomicValue; import net.sf.saxon.s9api.XdmDestination; import net.sf.saxon.s9api.XdmItem; import net.sf.saxon.s9api.XdmNode; import net.sf.saxon.trans.XPathException; import org.xml.sax.ContentHandler; import org.xmlsh.core.CoreException; import org.xmlsh.core.InvalidArgumentException; import org.xmlsh.core.XValue; import org.xmlsh.core.XVariable; import org.xmlsh.json.JSONUtils; import org.xmlsh.json.JSONUtils.JsonNodeBuilder; import org.xmlsh.sh.shell.SerializeOpts; import org.xmlsh.sh.shell.Shell; import org.xmlsh.types.TypeFamily; import org.xmlsh.util.Util; import com.fasterxml.jackson.core.Base64Variant; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonGenerator.Feature; import com.fasterxml.jackson.core.JsonStreamContext; import com.fasterxml.jackson.core.ObjectCodec; import com.fasterxml.jackson.core.SerializableString; import com.fasterxml.jackson.core.TreeNode; import com.fasterxml.jackson.core.Version; import com.fasterxml.jackson.core.base.GeneratorBase; import com.fasterxml.jackson.core.json.JsonWriteContext; import com.fasterxml.jackson.core.util.JsonGeneratorDelegate; import com.fasterxml.jackson.databind.JsonNode; import com.jayway.jsonpath.internal.Utils; /* * An OutputPort represents an output sync of data, either Stream (bytes) or XML data * */ public class VariableOutputPort extends OutputPort { public class VariableJsonGenerator extends JsonGeneratorDelegate { @Override public void close() throws IOException { JsonNodeBuilder b = getNodeBuilder(); super.close(); try { appendVar(XValue.newXValue(TypeFamily.JSON , b.build() )); } catch (InvalidArgumentException e) { Util.wrapIOException(e); } } public VariableJsonGenerator() { super( JSONUtils.createJsonNodeBuilder()); // TODO Auto-generated constructor stub } JsonNodeBuilder getNodeBuilder() { return (JsonNodeBuilder) getDelegate(); } } // Set to true if any asXXX method was caused which used a non-xml stream or access private boolean mAsText = false ; private class VariableXdmItemOutputStream extends AbstractXdmItemOutputStream { @Override public void write(XdmItem item) throws IOException { try { appendVar(item); } catch (InvalidArgumentException e) { throw new IOException(e); } } } private XVariable mVariable; // Transient classes private XdmDestination mXdmDestination; private ByteArrayOutputStream mByteArrayOutputStream; private BuildingStreamWriter mBuilder; private SerializeOpts mSerializeOpts; // for converting from ByteArray to string public VariableOutputPort( XVariable var) { assert( var != null ); mVariable = var ; } /* * Standard input stream - created on first request */ @Override public synchronized OutputStream asOutputStream( SerializeOpts serializeOpts ) throws IOException { flush(); mAsText = true ; /* * If going to a variable, then create a variable stream */ mSerializeOpts = serializeOpts ; return ( mByteArrayOutputStream = new ByteArrayOutputStream()); // BOS is synchroized } @Override public synchronized void flush() throws IOException { try { if (mXdmDestination != null) appendVar( mXdmDestination.getXdmNode()); // else if (mByteArrayOutputStream != null) appendVar( mByteArrayOutputStream.toString(mSerializeOpts.getOutputTextEncoding() ) ); //else if (mBuilder != null) appendVar(mBuilder.getDocumentNode()); } catch (InvalidArgumentException | UnsupportedEncodingException | SaxonApiException e) { Util.wrapIOException("Exception flushing VariableOutputPort" , e ); } finally { mXdmDestination = null; mByteArrayOutputStream = null ; mBuilder = null ; } } @Override public synchronized void close() throws IOException { flush(); } @Override public synchronized PrintStream asPrintStream(SerializeOpts opts) throws IOException { flush(); mAsText = true ; return new PrintStream(asOutputStream(opts)); } @Override public synchronized Destination asDestination(SerializeOpts opts) throws InvalidArgumentException, IOException { flush(); // mVariable.clear(); mXdmDestination = newXdmDestination(); return mXdmDestination; } private XdmDestination newXdmDestination() { XdmDestination dest = new XdmDestination(); // setupDestination(dest); return dest; } @Override public synchronized PrintWriter asPrintWriter(SerializeOpts opts) throws IOException { flush(); mAsText = true ; return new PrintWriter( new OutputStreamWriter(asOutputStream(opts) , opts.getOutputTextEncoding() )); } /* private void appendVar(String string) throws InvalidArgumentException { XValue value = mVariable.getValue(); if (value == null) mVariable.setValue(new XValue(string)); else { mVariable.setValue( value.append(XValue.asXValue(string))); } } */ private void appendVar(String string) throws InvalidArgumentException { XValue value = mVariable.getValue(); if (value == null || value.isNull()) mVariable.setValue(XValue.newXValue(string)); else { if (value.isAtomic()) mVariable.setValue(XValue.newXValue(value.toString() + string)); else { mVariable.setValue(value.append(new XdmAtomicValue(string))); } } } private void appendVar(XValue xv) throws InvalidArgumentException { XValue value = mVariable.getValue(); if (value == null || value.isNull()) mVariable.setValue(xv); else { mVariable.setValue(value.append(xv)); } } /* * Append an item to the current output */ private void appendVar( XdmItem xitem ) throws InvalidArgumentException { if( xitem instanceof XdmNode ){ XdmNode node = (XdmNode)xitem; node.getUnderlyingNode().setSystemId(getSystemId()); } XValue value = mVariable.getValue(); if (value == null) mVariable.setValue(XValue.newXValue(xitem)); else { mVariable.setValue( value.append(xitem)); } } @Override public synchronized void writeSequenceSeperator(SerializeOpts opts) throws IOException, InvalidArgumentException, SaxonApiException { if( mXdmDestination != null ){ appendVar(mXdmDestination.getXdmNode() ); mXdmDestination.reset(); } else if( mBuilder != null ){ appendVar( mBuilder.getDocumentNode() ); mBuilder = null ; // close ? } } @Override public void writeSequenceTerminator(SerializeOpts opts) throws IOException { flush(); } @Override public synchronized XMLStreamWriter asXMLStreamWriter(SerializeOpts opts) throws SaxonApiException, IOException { flush(); Processor proc = Shell.getProcessor(); BuildingStreamWriter bw = proc.newDocumentBuilder().newBuildingStreamWriter(); mBuilder = bw; return bw; } /* (non-Javadoc) * @see org.xmlsh.core.OutputPort#asXMLEventWriter(org.xmlsh.sh.shell.SerializeOpts) */ @Override public XMLEventWriter asXMLEventWriter(SerializeOpts opts) throws InvalidArgumentException, SaxonApiException, IOException { flush(); XMLStreamWriter sw = asXMLStreamWriter(opts); return new XMLStreamEventWriter( sw ); } @Override public IXdmItemOutputStream asXdmItemOutputStream(SerializeOpts opts) throws CoreException, IOException { flush(); return new VariableXdmItemOutputStream( ); } /** * @return the asText */ public boolean isAsText() { return mAsText; } /* (non-Javadoc) * @see org.xmlsh.core.OutputPort#asContentHandler(org.xmlsh.sh.shell.SerializeOpts) */ @Override public synchronized ContentHandler asContentHandler(SerializeOpts opts) throws XPathException, SaxonApiException, IOException { flush(); XMLStreamWriter sw = asXMLStreamWriter(opts); return new ContentHandlerToXMLStreamWriter(sw); } @Override public JsonGenerator asJsonGenerator(SerializeOpts opts) throws IOException, CoreException { return new VariableJsonGenerator(); } } // // //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. //