/*
 * Copyright 2014 The Netty Project
 *
 * The Netty Project 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.
 */
package io.netty.handler.codec.xml;

import com.fasterxml.aalto.AsyncByteArrayFeeder;
import com.fasterxml.aalto.AsyncXMLInputFactory;
import com.fasterxml.aalto.AsyncXMLStreamReader;
import com.fasterxml.aalto.stax.InputFactoryImpl;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import java.util.List;

Async XML decoder based on Aalto XML parser. Parses the incoming data into one of XML messages defined in this package.
/** * Async XML decoder based on <a href="https://github.com/FasterXML/aalto-xml">Aalto XML parser</a>. * * Parses the incoming data into one of XML messages defined in this package. */
public class XmlDecoder extends ByteToMessageDecoder { private static final AsyncXMLInputFactory XML_INPUT_FACTORY = new InputFactoryImpl(); private static final XmlDocumentEnd XML_DOCUMENT_END = XmlDocumentEnd.INSTANCE; private final AsyncXMLStreamReader<AsyncByteArrayFeeder> streamReader = XML_INPUT_FACTORY.createAsyncForByteArray(); private final AsyncByteArrayFeeder streamFeeder = (AsyncByteArrayFeeder) streamReader.getInputFeeder(); @Override protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception { byte[] buffer = new byte[in.readableBytes()]; in.readBytes(buffer); try { streamFeeder.feedInput(buffer, 0, buffer.length); } catch (XMLStreamException exception) { in.skipBytes(in.readableBytes()); throw exception; } while (!streamFeeder.needMoreInput()) { int type = streamReader.next(); switch (type) { case XMLStreamConstants.START_DOCUMENT: out.add(new XmlDocumentStart(streamReader.getEncoding(), streamReader.getVersion(), streamReader.isStandalone(), streamReader.getCharacterEncodingScheme())); break; case XMLStreamConstants.END_DOCUMENT: out.add(XML_DOCUMENT_END); break; case XMLStreamConstants.START_ELEMENT: XmlElementStart elementStart = new XmlElementStart(streamReader.getLocalName(), streamReader.getName().getNamespaceURI(), streamReader.getPrefix()); for (int x = 0; x < streamReader.getAttributeCount(); x++) { XmlAttribute attribute = new XmlAttribute(streamReader.getAttributeType(x), streamReader.getAttributeLocalName(x), streamReader.getAttributePrefix(x), streamReader.getAttributeNamespace(x), streamReader.getAttributeValue(x)); elementStart.attributes().add(attribute); } for (int x = 0; x < streamReader.getNamespaceCount(); x++) { XmlNamespace namespace = new XmlNamespace(streamReader.getNamespacePrefix(x), streamReader.getNamespaceURI(x)); elementStart.namespaces().add(namespace); } out.add(elementStart); break; case XMLStreamConstants.END_ELEMENT: XmlElementEnd elementEnd = new XmlElementEnd(streamReader.getLocalName(), streamReader.getName().getNamespaceURI(), streamReader.getPrefix()); for (int x = 0; x < streamReader.getNamespaceCount(); x++) { XmlNamespace namespace = new XmlNamespace(streamReader.getNamespacePrefix(x), streamReader.getNamespaceURI(x)); elementEnd.namespaces().add(namespace); } out.add(elementEnd); break; case XMLStreamConstants.PROCESSING_INSTRUCTION: out.add(new XmlProcessingInstruction(streamReader.getPIData(), streamReader.getPITarget())); break; case XMLStreamConstants.CHARACTERS: out.add(new XmlCharacters(streamReader.getText())); break; case XMLStreamConstants.COMMENT: out.add(new XmlComment(streamReader.getText())); break; case XMLStreamConstants.SPACE: out.add(new XmlSpace(streamReader.getText())); break; case XMLStreamConstants.ENTITY_REFERENCE: out.add(new XmlEntityReference(streamReader.getLocalName(), streamReader.getText())); break; case XMLStreamConstants.DTD: out.add(new XmlDTD(streamReader.getText())); break; case XMLStreamConstants.CDATA: out.add(new XmlCdata(streamReader.getText())); break; } } } }