/** * $Id: $ * $Date: $ * */ package org.xmlsh.json; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.util.List; import javax.xml.namespace.QName; import javax.xml.stream.FactoryConfigurationError; import javax.xml.stream.XMLEventReader; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamWriter; import javax.xml.stream.events.EndElement; import javax.xml.stream.events.StartElement; import javax.xml.stream.events.XMLEvent; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.xmlsh.builtin.commands.exit; import org.xmlsh.core.InvalidArgumentException; import org.xmlsh.core.XValue; import org.xmlsh.sh.shell.SerializeOpts; import org.xmlsh.util.Util; import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonToken; public abstract class JXConverter { /* * A class helper/config for JSON to XML conversions */ static Logger mLogger = LogManager.getLogger(); private SerializeOpts mSerializeOpts; private List<XValue> mArgs; SerializeOpts getSerializeOpts() { return mSerializeOpts; } interface IJSONConverter { public abstract boolean parse() throws ConverterException; public void close() throws ConverterException; } interface IXMLConverter { public abstract boolean parse() throws ConverterException; public void close() throws ConverterException; } // Private class for converting FROM JSON abstract class JSONConverter implements IJSONConverter { XMLEventReader mReader; XMLStreamReader mStreamReader; JsonGenerator mGenerator; protected JSONConverter(XMLStreamReader reader, OutputStream os) throws ConverterException { super(); mStreamReader = reader; try { mGenerator = JSONUtils.createGenerator(os, getSerializeOpts()); mReader = XMLInputFactory.newInstance().createXMLEventReader( mStreamReader); } catch (XMLStreamException e) { throw new ConverterException(e); } catch (FactoryConfigurationError e) { throw new ConverterException(e); } catch (IOException e) { throw new ConverterException(e); } } /* * Returns TRUE if the end of this element/doc is reached * * @see org.xmlsh.json.IJSONConverter#parse() */ @Override public boolean parse() throws ConverterException { mLogger.entry(); try { boolean nested = true ; while (nested && mReader.hasNext()) { XMLEvent e = mReader.nextEvent(); nested = dispatch(e); } } catch (Exception e) { Util.wrapException(e, ConverterException.class); } return mLogger.exit(false); } private boolean dispatch(XMLEvent e) throws ConverterException { boolean nested = false ; if (e.isStartDocument()) nested = startDocument(e); else if (e.isStartElement()) { StartElement start = e.asStartElement(); QName name = start.getName(); nested = startElement(start, name); } else if (e.isEndElement()) { nested = endElement(e.asEndElement()); } else if (e.isEndDocument()) { nested = endDocument(e); } else if (e.isCharacters()) { nested = characters(e); } else throw mLogger.throwing(new ConverterException( "Unexpected XML element: " + e.getEventType())); return nested ; } abstract protected boolean startElement(StartElement start, QName name) throws ConverterException; abstract protected boolean startDocument(XMLEvent e) throws ConverterException;; abstract protected boolean endElement(EndElement asEndElement) throws ConverterException;; abstract protected boolean endDocument(XMLEvent e) throws ConverterException;; abstract protected boolean characters(XMLEvent e); protected String readString() throws XMLStreamException, UnsupportedEncodingException, IOException { mLogger.entry(); String s = mReader.getElementText(); return mLogger.exit(s); } @Override public void close() { mLogger.entry(); JSONUtils.safeClose(mGenerator); mGenerator = null; Util.safeClose(mReader); mReader = null; } } abstract class XMLConverter implements IXMLConverter { JsonParser mParser; InputStream mInput; XMLStreamWriter mWriter; protected XMLConverter(InputStream is, XMLStreamWriter sw) throws ConverterException { mInput = is; try { mParser = JSONUtils.getJsonFactory().createParser(is); } catch (JsonParseException e) { throw new ConverterException(e); } catch (IOException e) { throw new ConverterException(e); } mWriter = sw; } @Override public boolean parse() throws ConverterException { JsonToken tok = nextToken(); writeValue(tok); return true; } protected JsonToken nextToken() throws ConverterException { try { return mParser.nextToken(); } catch (JsonParseException e) { throw new ConverterException(e); } catch (IOException e) { throw new ConverterException(e); } } protected void writeValue(JsonToken tok) throws ConverterException { if (tok == null) return; switch (tok) { case START_ARRAY: writeArray(); break; case START_OBJECT: writeObject(); break; case VALUE_EMBEDDED_OBJECT: break; case VALUE_FALSE: writeBoolean(false); break; case VALUE_NULL: writeNull(); break; case VALUE_NUMBER_FLOAT: case VALUE_NUMBER_INT: writeNumber(); break; case VALUE_STRING: writeString(getStringValue()); break; case VALUE_TRUE: writeBoolean(true); break; default: break; } } protected String getStringValue() throws ConverterException { try { return mParser.getText(); } catch (IOException e) { throw new ConverterException(e); } } protected Number getNumberValue() throws ConverterException { try { return mParser.getNumberValue(); } catch (IOException e) { throw new ConverterException(e); } } abstract void writeArray() throws ConverterException; abstract void writeObject() throws ConverterException; abstract void writeBoolean(boolean value) throws ConverterException; abstract void writeNull() throws ConverterException; abstract void writeNumber() throws ConverterException; abstract void writeString(String value) throws ConverterException; protected void writeStartElement(QName qn) throws XMLStreamException { mWriter.writeStartElement(qn.getPrefix(), qn.getLocalPart(), qn.getNamespaceURI()); } protected void writeAttribute(QName qn, String value) throws XMLStreamException { mWriter.writeAttribute(qn.getPrefix(), qn.getNamespaceURI(), qn.getLocalPart(), value); } protected void writeEndElement() throws XMLStreamException { mWriter.writeEndElement(); } protected void writeCharacters(String s) throws XMLStreamException { mWriter.writeCharacters(s); } @Override public void close() throws ConverterException { try { mWriter.flush(); } catch (XMLStreamException e) { throw new ConverterException(e); } JSONUtils.safeClose(mParser); mParser = null; } } abstract IJSONConverter newJConverter(XMLStreamReader reader, OutputStream os) throws ConverterException; abstract IXMLConverter newXMLConverter(InputStream is, XMLStreamWriter sw) throws ConverterException; /* * Converter To and/or From JSON */ public JXConverter(SerializeOpts serializeOpts, List<XValue> args) { super(); mSerializeOpts = serializeOpts; mArgs = args; } public void convertToJson(XMLStreamReader reader, OutputStream os) throws ConverterException { IJSONConverter converter = newJConverter(new XMLRewritingStreamReader( reader), os); try { converter.parse(); } finally { converter.close(); } } public void convertFromJson(InputStream is, XMLStreamWriter sw) throws ConverterException { IXMLConverter converter = newXMLConverter(is, sw); try { converter.parse(); } finally { converter.close(); } } public static JXConverter getConverter(String format, SerializeOpts serializeOpts, List<XValue> args) throws InvalidArgumentException { if (Util.isEqual(format, "jxon")) return new JXONConverter(serializeOpts, args); else if (Util.isEqual(format, "jsonx")) return new JSONXConverter(serializeOpts, args); else if (Util.isEqual(format, "jackson")) return new JacksonConverter(serializeOpts, args); else throw new InvalidArgumentException("Unknown convert format: " + format); } protected List<XValue> getArgs() { return mArgs; } } /* * Copyright (C) 2008-2012 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): David A. Lee */