Package org.syrup.helpers

Source Code of org.syrup.helpers.XMLOutput$PartialContentHandler

package org.syrup.helpers;

import org.apache.xml.serializer.OutputPropertiesFactory;
import org.apache.xml.serializer.SerializationHandler;
import org.apache.xml.serializer.Serializer;
import org.apache.xml.serializer.SerializerFactory;
import org.syrup.Context;
import org.syrup.Data;
import org.syrup.LogEntry;
import org.syrup.PTask;
import org.syrup.Port;
import org.syrup.Task;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.AttributesImpl;
import org.xml.sax.helpers.DefaultHandler;
import org.xml.sax.helpers.XMLReaderFactory;

import java.io.ByteArrayInputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.util.Properties;

/**
* Helper class that enables the serialization of Syrup types.
*
* @author Robbert van Dalen
*/
public class XMLOutput implements EntityResolver
{
    static final String COPYRIGHT = "Copyright 2005 Robbert van Dalen."
        + "At your option, you may copy, distribute, or make derivative works under "
        + "the terms of The Artistic License. This License may be found at "
        + "http://www.opensource.org/licenses/artistic-license.php. "
        + "THERE IS NO WARRANTY; USE THIS PRODUCT AT YOUR OWN RISK.";

    private final static InputSource defaultEntityResolver = new InputSource(new ByteArrayInputStream("<?xml version='1.0' encoding='UTF-8'?>".getBytes()));

    /**
     * Wraps an OutputStream with a SerializationHandler.
     *
     * @param o
     *            The OutputStream to output XML.
     * @return The SerializationHandler to send SAX-events to.
     */
    public SerializationHandler wrap(OutputStream o) throws Exception
    {
        Properties p = OutputPropertiesFactory.getDefaultMethodProperties("xml");

        p.put("indent", "yes");
        p.put("{http://xml.apache.org/xalan}indent-amount", "4");

        if (p.containsKey("standalone"))
        {
            p.remove("standalone");
        }
        Serializer serializer = SerializerFactory.getSerializer(p);
        serializer.setOutputStream(o);
        return (SerializationHandler) serializer;
    }

    /**
     * Starts the serialization with a start tag.
     *
     * @param tag
     *            The start tag.
     * @param handler
     *            The serialization handler.
     */
    public synchronized void startDocument(String tag,
        SerializationHandler handler) throws Exception
    {
        handler.startDocument();
        handler.startElement("", "", tag, null);

    }

    /**
     * Ends the serialization with an end tag.
     *
     * @param tag
     *            The end tag.
     * @param handler
     *            The serialization handler.
     */
    public synchronized void endDocument(String tag,
        SerializationHandler handler) throws Exception
    {
        handler.endElement("", "", tag);
        handler.endDocument();

    }

    /**
     * Starts a new element tag.
     *
     * @param tag
     *            The element tag
     * @param handler
     *            The serialization handler
     */
    public synchronized void start(String tag, SerializationHandler handler)
        throws Exception
    {
        handler.startElement("", "", tag, null);
        handler.flushPending();
        handler.getWriter().flush();
    }

    /**
     * Ends an element tag.
     *
     * @param tag
     *            The element tag
     * @param handler
     *            The serialization handler
     */
    public synchronized void end(String tag, SerializationHandler handler)
        throws Exception
    {
        handler.endElement("", "", tag);
        handler.flushPending();
        handler.getWriter().flush();
    }

    /**
     * Serializes a PTask.
     *
     * @param t
     *            The Ptask to be serialized.
     * @param handler
     *            The serialization handler.
     */
    public synchronized void output(PTask t, SerializationHandler handler)
        throws Exception
    {
        start(t, handler);
        end(t, handler);
    }

    /**
     * Starts the PTask to be serialized.
     *
     * @param t
     *            The Ptask to start serializing.
     * @param handler
     *            The serialization handler.
     */
    public synchronized void start(PTask t, SerializationHandler handler)
        throws Exception
    {
        handler.startElement("", "", "ptask", taskAttributes(t));
    }

    /**
     * Ends the PTask to be serialized.
     *
     * @param t
     *            The Ptask to end serializing.
     * @param handler
     *            The serialization handler.
     */
    public synchronized void end(PTask t, SerializationHandler handler)
        throws Exception
    {
        handler.endElement("", "", "ptask");
    }

    /**
     * Serializes a Context.
     *
     * @param handler
     *            The serialization handler.
     * @param c
     *            The Context to be serialized
     */
    public synchronized void output(Context c, SerializationHandler handler)
        throws Exception
    {

        start(c, handler);
        end(c, handler);

        handler.flushPending();
        handler.getWriter().flush();
    }

    public synchronized void output(LogEntry l, SerializationHandler handler)
        throws Exception
    {

        start(l, handler);
        end(l, handler);

        handler.flushPending();
        handler.getWriter().flush();
    }

    public synchronized void start(LogEntry l, SerializationHandler handler)
        throws Exception
    {
        AttributesImpl a = new AttributesImpl();
        a.addAttribute("", "", "time", "string", "" + org.syrup.helpers.Utils.asDate(l.time()));
        a.addAttribute("", "", "key", "string", l.key());
        a.addAttribute("", "", "event", "string", LogEntryImpl.map(l.event()));
        a.addAttribute("", "", "worker", "string", l.worker());
        handler.startElement("", "", "log-entry", a);
    }

    public synchronized void end(LogEntry l, SerializationHandler handler)
        throws Exception
    {
        handler.endElement("", "", "log-entry");
    }

    /**
     * Description of the Method
     *
     * @param c
     *            Description of the Parameter
     * @param handler
     *            Description of the Parameter
     */
    public synchronized void start(Context c, SerializationHandler handler)
        throws Exception
    {
        Attributes a = taskAttributes(c.task());
        handler.startElement("", "", "ptask-context", a);

        if (c.in_1_link() != null)
        {
            a = portAttributes(c.in_1_link().from());
            handler.startElement("", "", "in-1", a);
            output(c.in_1_link().content(), handler);
            handler.endElement("", "", "in-1");
        }
        if (c.in_2_link() != null)
        {
            a = portAttributes(c.in_2_link().from());
            handler.startElement("", "", "in-2", a);
            output(c.in_2_link().content(), handler);
            handler.endElement("", "", "in-2");
        }
        if (c.out_1_link() != null)
        {
            a = portAttributes(c.out_1_link().to());
            handler.startElement("", "", "out-1", a);
            output(c.out_1_link().content(), handler);
            handler.endElement("", "", "out-1");
        }
        if (c.out_2_link() != null)
        {
            a = portAttributes(c.out_2_link().to());
            handler.startElement("", "", "out-2", a);
            output(c.out_2_link().content(), handler);
            handler.endElement("", "", "out-2");
        }
    }

    /**
     * Description of the Method
     *
     * @param c
     *            Description of the Parameter
     * @param handler
     *            Description of the Parameter
     */
    public synchronized void end(Context c, SerializationHandler handler)
        throws Exception
    {
        handler.endElement("", "", "ptask-context");

    }

    /**
     * Serializes a Data instance..
     *
     * @param handler
     *            The serialization handler.
     * @param d
     *            The Data instance.
     */
    public synchronized void output(Data d, SerializationHandler handler)
        throws Exception
    {
        if (d != null)
        {
            output(d.bytes(), handler);
        }
    }

    /**
     * Returns the mapped Attributes of a Task.
     *
     * @param t
     *            The Task to map the Attributes to.
     * @return The mapped Attributes of a Task.
     */
    protected synchronized AttributesImpl taskAttributes(Task t)
    {
        if (t instanceof PTask)
        {
            return taskAttributes((PTask) t);
        }
        return new AttributesImpl();
    }

    /**
     * Returns the mapped Attributes of a Port.
     *
     * @param p
     *            The Port to map the Attributes to.
     * @return the mapped Attributes of a Port.
     */
    protected synchronized AttributesImpl portAttributes(Port p)
    {
        AttributesImpl a = new AttributesImpl();

        if (p != null)
        {
            if (p.task() instanceof PTask)
            {
                PTask t = (PTask) p.task();
                if (p.isSecond())
                {
                    a.addAttribute("", "", "lkey", "string", t.key()
                        + "-2");
                }
                else
                {
                    a.addAttribute("", "", "lkey", "string", t.key()
                        + "-1");
                }
                a.addAttribute("", "", "lparentKey", "string", t.parentKey());
                a.addAttribute("", "", "lname", "string", t.name());
            }
        }
        return a;
    }

    /**
     * Returns the mapped Attributes of a PTask.
     *
     * @param t
     *            The PTask to map the Attributes to.
     * @return The mapped Attributes of a PTask.
     */
    protected synchronized AttributesImpl taskAttributes(PTask t)
    {
        AttributesImpl a = new AttributesImpl();

        if (t != null)
        {
            a.addAttribute("", "", "key", "string", t.key());
            a.addAttribute("", "", "parentKey", "string", t.parentKey());
            a.addAttribute("", "", "name", "string", t.name());
            a.addAttribute("", "", "functionClass", "string", t.functionClass());
            if (t.description() != null)
            {
                a.addAttribute("", "", "description", "string", t.description());
            }
            if (t.environment() != null)
            {
                a.addAttribute("", "", "environment", "string", t.environment());
            }
            if (t.parameter() != null)
            {
                a.addAttribute("", "", "parameter", "string", t.parameter());               
            }
            a.addAttribute("", "", "orType", "string", ""
                + t.orType());
            a.addAttribute("", "", "executable", "string", ""
                + t.executable());
            a.addAttribute("", "", "done", "string", ""
                + t.done());
            a.addAttribute("", "", "creationTime", "string", ""
                + org.syrup.helpers.Utils.asDate(t.creationTime()));
            a.addAttribute("", "", "modificationTime", "string", ""
                + org.syrup.helpers.Utils.asDate(t.modificationTime()));
            a.addAttribute("", "", "modifications", "string", ""
                + t.modifications());
            if (t.worker() != null)
            {
                a.addAttribute("", "", "worker", "string",
                    t.worker());
            }

            a.addAttribute("", "", "isParent", "string", ""
                + t.isParent());
        }
        return a;
    }

    /**
     * Writes the byte array as SAX event(s). If the byte array can be parsed by
     * an XML reader, the fired SAX events will be the events generated by the
     * XML Reader. <br>
     * If the byte array can be turned into UTF-8 String, and a Characters SAX
     * Event will be fired with the (encoded) UTF-8 String.<br>
     * Otherwise, the byte array will be encoded in base64 and with this encoded
     * string a Character event will be fired.
     *
     * @param b
     *            The byte array to be mapped to SAX events.
     * @param handler
     *            The handler to send SAX events to.
     */
    protected synchronized void output(byte[] b, SerializationHandler handler)
        throws Exception
    {
        if (b != null)
        {
            XMLReader r = XMLReaderFactory.createXMLReader("org.apache.crimson.parser.XMLReaderImpl");

            ByteArrayInputStream i = new ByteArrayInputStream(b);

            // [TODO: make this work in a streaming fashion]
            try
            {
                r.setFeature("http://xml.org/sax/features/validation", false);
                r.setEntityResolver(this);
                InputSource in = new InputSource(i);
                in.setSystemId("localhost");
                r.parse(in);
            }
            catch (Exception e)
            {
                // Could not be parsed
                CharBuffer ch = java.nio.charset.Charset.forName("UTF-8").decode(ByteBuffer.wrap(b));
                char cbuf[] = ch.array();
                for (int m = 0; m < cbuf.length; m++)
                {
                    if (!(cbuf[m] >= 32
                        || cbuf[m] == '\n' || cbuf[m] == '\t' || cbuf[m] == '\r'))
                    {
                        base64(b, handler);
                        return;
                    }
                }

                AttributesImpl a = new AttributesImpl();
                a.addAttribute("", "", "encoding", "string", "text");
                handler.startElement("", "", "content", a);
                handler.characters(cbuf, 0, cbuf.length);
                handler.endElement("", "", "content");

                return;
            }

            i = new ByteArrayInputStream(b);
            r.setContentHandler(new PartialContentHandler(handler));

            AttributesImpl a = new AttributesImpl();
            a.addAttribute("", "", "encoding", "string", "xml");
            handler.startElement("", "", "content", a);

            InputSource in = new InputSource(i);
            in.setSystemId("localhost");
            r.parse(in);

            handler.endElement("", "", "content");
        }
    }

    /**
     * Utility function that writes a Character SAX event with a base64 encoding
     * of a byte array.
     *
     * @param b
     *            The byte array to be encoded.
     * @param handler
     *            The handler to send SAX events to.
     */
    protected void base64(byte[] b, SerializationHandler handler)
        throws Exception
    {
        // [TODO: optimize this to a streaming version]
        String s = new sun.misc.BASE64Encoder().encode(b);
        AttributesImpl a = new AttributesImpl();
        a.addAttribute("", "", "encoding", "string", "base64");
        handler.startElement("", "", "content", a);
        handler.characters(s.toCharArray(), 0, s.length());
        handler.endElement("", "", "content");
    }

    public InputSource resolveEntity(String s1, String s2)
    {
        return defaultEntityResolver;
    }

    /**
     * Utility ContentHandler that ignores startDocument and endDocument events.
     *
     * @author Robbert van Dalen
     */
    private class PartialContentHandler extends DefaultHandler
    {
        private ContentHandler handler;

        /**
         * Constructor for the PartialContentHandler object
         *
         * @param h
         *            The handler that is wrapped.
         */
        public PartialContentHandler(ContentHandler h)
        {
            handler = h;
        }

        /**
         */
        public void setDocumentLocator(Locator locator)
        {
            handler.setDocumentLocator(locator);
        }

        /**
         */
        public void startDocument() throws org.xml.sax.SAXException
        {
            // no
        }

        /**
         */
        public void endDocument() throws org.xml.sax.SAXException
        {
            // no
        }

        /**
         */
        public void startPrefixMapping(java.lang.String prefix,
            java.lang.String namespaceUri) throws org.xml.sax.SAXException
        {
            handler.startPrefixMapping(prefix, namespaceUri);
        }

        /**
         */
        public void endPrefixMapping(java.lang.String prefix)
            throws org.xml.sax.SAXException
        {
            handler.endPrefixMapping(prefix);
        }

        /**
         */
        public void startElement(String namespaceUri, String localName,
            String qName, Attributes att) throws org.xml.sax.SAXException
        {
            handler.startElement(namespaceUri, localName, qName, att);
        }

        /**
         */
        public void endElement(String namespaceUri, String localName,
            String qName) throws org.xml.sax.SAXException
        {
            handler.endElement(namespaceUri, localName, qName);
        }

        /**
         */
        public void characters(char[] arg1, int arg2, int arg3)
            throws org.xml.sax.SAXException
        {
            handler.characters(arg1, arg2, arg3);
        }

        /**
         */
        public void ignorableWhitespace(char[] arg1, int arg2, int arg3)
            throws org.xml.sax.SAXException
        {
            handler.ignorableWhitespace(arg1, arg2, arg3);
        }

        /**
         */
        public void processingInstruction(String target, String data)
            throws org.xml.sax.SAXException
        {
            handler.processingInstruction(target, data);
        }

        /**
         */
        public void skippedEntity(java.lang.String arg1)
            throws org.xml.sax.SAXException
        {
            handler.skippedEntity(arg1);
        }
    }
}
TOP

Related Classes of org.syrup.helpers.XMLOutput$PartialContentHandler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.