Package org.apache.xindice.xml.sax

Source Code of org.apache.xindice.xml.sax.SAXEventGenerator

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* $Id: SAXEventGenerator.java 566464 2007-08-16 01:21:52Z vgritsenko $
*/

package org.apache.xindice.xml.sax;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xindice.util.ByteArrayInput;
import org.apache.xindice.xml.SymbolTable;
import org.apache.xindice.xml.XMLCompressedInput;
import org.apache.xindice.xml.dom.DOMCompressor;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.xml.sax.ContentHandler;
import org.xml.sax.DTDHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.AttributesImpl;

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
* SAXEventGenerator
*
* @version $Revision: 566464 $, $Date: 2007-08-15 21:21:52 -0400 (Wed, 15 Aug 2007) $
*/
public final class SAXEventGenerator implements XMLReader {

    private static final Log log = LogFactory.getLog(SAXEventGenerator.class);

    private static final int XMLNS_MAP_INCREMENT = 5;

    /**
     * This is a SAX feature that controls how namespaces are reported in SAX.
     * In accordance with the SAX2 specification by default this feature is <em>on</em>.
     *
     * @see <a href="http://sax.sourceforge.net/?selected=namespaces">sax.sourceforge.net/?selected=namespaces</a>
     */
    public static final String SAX_NAMESPACES_FEATURE
            = "http://xml.org/sax/features/namespaces";

    /**
     * This is a SAX feature that controls how namespaces are reported in SAX.
     * In accordance with the SAX2 specification by default this feature is <em>off</em>.
     *
     * @see <a href="http://sax.sourceforge.net/?selected=namespaces">sax.sourceforge.net/?selected=namespaces</a>
     */
    public static final String SAX_NAMESPACE_PREFIXES_FEATURE
            = "http://xml.org/sax/features/namespace-prefixes";

    /*
     * State of the SAX_NAMESPACES_FEATURE. True indicates namespace URIs and unprefixed local
     * names for element and attribute names will be available.
     *
     * For SAX2 the default is true.
     */
    private boolean hasSaxNamespaces = true;

    /*
     * State of the SAX_NAMESPACE_PREFIXES_FEATURE. True indicates XML 1.0 names (with prefixes)
     * and attributes (including xmlns* attributes) will be available.
     *
     * For SAX2 the default is off.
     */
    private boolean hasSaxNamespacesPrefixes;

    private SymbolTable symbols;
    private byte[] data;
    private int pos;
    private int len;

    private Map properties = new HashMap();
    private ContentHandler content;
    private CompressionHandler comp;
    private ErrorHandler errors;
    private EntityResolver entities;
    private DTDHandler dtd;

    private boolean interrupt;


    public SAXEventGenerator(SymbolTable symbols, byte[] data) {
        this(symbols, data, 0, data.length);
    }

    public SAXEventGenerator(SymbolTable symbols, byte[] data, int pos, int len) {
        this.symbols = symbols;
        this.data = data;
        this.pos = pos;
        this.len = len;
    }

    public SAXEventGenerator(SymbolTable symbols, Document doc) {
        this.symbols = symbols != null ? symbols : new SymbolTable();
        data = DOMCompressor.compress(doc, this.symbols);
        pos = 0;
        len = data.length;
    }

    /**
     * Return SAX feature setting for the SAX generated by this class.
     *
     * @param name feature name. Supported features are the standard SAX namespace
     *    reporting features as documented in the specification.
     * @return whether feature is turned on
     * @see <a href="http://sax.sourceforge.net/?selected=namespaces">sax.sourceforge.net/?selected=namespaces</a>
     */
    public boolean getFeature(String name) throws SAXNotRecognizedException, SAXNotSupportedException {

        if (SAX_NAMESPACES_FEATURE.equals(name)) {

            return hasSaxNamespaces;
        } else if (SAX_NAMESPACE_PREFIXES_FEATURE.equals(name)) {

            return hasSaxNamespacesPrefixes;
        } else {

            return false;
        }
    }

    /**
     * Set SAX feature for the SAX generated by this class.
     *
     * @param name feature name. Supported features are the standard SAX namespace
     *    reporting features as documented in the specification.
     * @param value specified the status of the feature.
     * @see <a href="http://sax.sourceforge.net/?selected=namespaces">sax.sourceforge.net/?selected=namespaces</a>
     */
    public void setFeature(String name, boolean value) throws SAXNotRecognizedException, SAXNotSupportedException {

        if (SAX_NAMESPACES_FEATURE.equals(name)) {

            hasSaxNamespaces = value;
        } else if (SAX_NAMESPACE_PREFIXES_FEATURE.equals(name)) {

            hasSaxNamespacesPrefixes = value;
        }
    }

    public Object getProperty(String name) throws SAXNotRecognizedException, SAXNotSupportedException {
        return properties.get(name);
    }

    public void setProperty(String name, Object value) throws SAXNotRecognizedException, SAXNotSupportedException {
        properties.put(name, value);

        if (name.equals(CompressionHandler.HANDLER)
                && value instanceof CompressionHandler) {
            comp = (CompressionHandler) value;
        }
    }

    public void setEntityResolver(EntityResolver resolver) {
        entities = resolver;
    }

    public EntityResolver getEntityResolver() {
        return entities;
    }

    public void setDTDHandler(DTDHandler handler) {
        dtd = handler;
    }

    public DTDHandler getDTDHandler() {
        return dtd;
    }

    public void setContentHandler(ContentHandler handler) {
        content = handler;
    }

    public ContentHandler getContentHandler() {
        return content;
    }

    public void setErrorHandler(ErrorHandler handler) {
        errors = handler;
    }

    public ErrorHandler getErrorHandler() {
        return errors;
    }

    public void parse(InputSource input) throws IOException, SAXException {
    }

    public void parse(String systemId) throws IOException, SAXException {
    }

    private String getLocalName(String qname) {
        int idx = qname.indexOf(":");
        if (idx != -1) {
            return qname.substring(idx + 1);
        } else {
            return qname;
        }
    }

    private boolean isNSAttr(final String qName) {
        return "xmlns".equals(qName) || qName.startsWith("xmlns:");
    }

    public boolean processContainer(boolean element, int pos, int len) throws IOException, SAXException {
        ByteArrayInput bis = new ByteArrayInput(data, pos, len);
        XMLCompressedInput in = new XMLCompressedInput(bis, symbols);
        String elemName = null;
        String localName = null;
        String nsURI = null;
        String[] mappedPrefixes = null;
        int nsMapCount = 0;

        if (element) {
            in.readSignature();
            in.readContentSize();

            short elemSymbol = in.readShort();
            elemName = symbols.getName(elemSymbol);
            localName = getLocalName(elemName);
            nsURI = symbols.getNamespaceURI(elemSymbol);
            int attrCount = in.readAttributeCount();
            AttributesImpl attrs = new AttributesImpl();
            for (int i = 0; i < attrCount; i++) {
                short symbol = in.readShort();
                short strLen = in.readShort();
                byte[] b = new byte[strLen];
                in.read(b);

                String attrName = symbols.getName(symbol);
                String attrURI = symbols.getNamespaceURI(symbol);
                String lclName = getLocalName(attrName);

                String attrValue = new String(b, "UTF8");

                // look for and buffer newly mapped namespace prefixes
                if (isNSAttr(attrName)) {

                    // create the buffer if needed
                    if (mappedPrefixes == null) {
                        mappedPrefixes = new String[XMLNS_MAP_INCREMENT];

                    }

                    // check the buffer's capacity
                    if (nsMapCount >= mappedPrefixes.length) {
                        String[] newBuf = new String[mappedPrefixes.length + XMLNS_MAP_INCREMENT];
                        System.arraycopy(mappedPrefixes, 0, newBuf, 0, mappedPrefixes.length);
                        mappedPrefixes = newBuf;
                    }

                    // The prefix is the attr "local name", unless this is the
                    // default namespace, in which case the prefix is the empty
                    // string
                    String prefix = ("xmlns".equals(attrName) ? "" : lclName);

                    // Prefix mappings MAY always be reported, regardless of
                    // feature settings.
                    content.startPrefixMapping(prefix, attrValue);
                    mappedPrefixes[nsMapCount++] = prefix;

                    if (hasSaxNamespacesPrefixes) {
                        // According to SAX, the local name should be EMPTY
                        attrs.addAttribute("", "", attrName, "CDATA", attrValue);
                    }
                } else {
                    // Regular attribute
                    attrs.addAttribute(attrURI != null ? attrURI : "",
                                       lclName, attrName, "", attrValue);
                }
            }

            if (comp != null) {
                comp.symbolID(elemSymbol);
                comp.dataLocation(pos, len);
            }
            content.startElement(nsURI != null ? nsURI : "", localName, elemName, attrs);
        } else {
            in.readInt();
        }

        while (!interrupt && bis.available() > 0) {
            pos = bis.getPos();
            in.readSignature(); // Read signature
            len = in.readContentSize();
            if (len == 0) {
                len = 1;
            }

            int type = in.getNodeType();
            switch (type) {

                case Node.ELEMENT_NODE:
                    processContainer(true, pos, len);
                    break;

                case Node.TEXT_NODE:
                case Node.PROCESSING_INSTRUCTION_NODE:
                case Node.CDATA_SECTION_NODE:
                case Node.COMMENT_NODE:
                    {
                        ByteArrayInput tbis = new ByteArrayInput(data, pos, len);
                        XMLCompressedInput tin = new XMLCompressedInput(tbis, symbols);

                        tin.readSignature(); // Skip The Signature
                        if (type == Node.TEXT_NODE) {
                            tin.readContentSize();
                        } else {
                            tin.readInt();
                        }

                        byte[] buf = new byte[tbis.available()];
                        tin.read(buf);

                        String value = new String(buf, "UTF-8");

                        switch (type) {

                            case Node.TEXT_NODE:
                                char[] c = value.toCharArray();
                                content.characters(c, 0, c.length);
                                break;

                            case Node.PROCESSING_INSTRUCTION_NODE:
                                int i = value.indexOf(' ');
                                content.processingInstruction(value.substring(0, i), value.substring(i + 1));
                                break;

                            case Node.CDATA_SECTION_NODE:
                            case Node.COMMENT_NODE:
                                // TODO: This
                                break;

                            default:
                                if (log.isWarnEnabled()) {
                                    log.warn("invalid type : " + type);
                                }
                        }

                        break;
                    }

                case Node.ENTITY_REFERENCE_NODE:
                    // TODO: This
                    break;

                case Node.NOTATION_NODE:
                    break;

                default:
                    if (log.isWarnEnabled()) {
                        log.warn("invalid node type : " + type);
                    }
            }

            bis.setPos(pos);
            bis.skip(len);
        }

        if (element && !interrupt) {
            // First, close element ...
            content.endElement(nsURI != null ? nsURI : "", localName, elemName);

            // ... and then any mapped NS prefixes
            for (int i = 0; i < nsMapCount; i++) {
                content.endPrefixMapping(mappedPrefixes[i]);
            }
        }

        return !interrupt;
    }

    public boolean start() throws IOException, SAXException {
        if (comp != null) {
            comp.symbols(symbols);
            comp.dataBytes(data);
        }
        content.startDocument();
        boolean result = processContainer(false, pos, len);
        if (result) {
            content.endDocument();
        }
        return result;
    }

    public void stop() {
        interrupt = true;
    }
}
TOP

Related Classes of org.apache.xindice.xml.sax.SAXEventGenerator

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.