/** * Copyright 2012 José Martínez * * Licensed 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 es.udc.pfc.xmpp.handler; import javax.xml.stream.XMLEventWriter; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.events.XMLEvent; import javax.xml.transform.dom.DOMResult; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.channel.Channels; import org.jboss.netty.channel.MessageEvent; import org.jboss.netty.channel.SimpleChannelUpstreamHandler; import org.w3c.dom.Document; import com.fasterxml.aalto.stax.OutputFactoryImpl; import es.udc.pfc.xmpp.xml.XMLElementImpl; import es.udc.pfc.xmpp.xml.XMLUtil; /** * Processes XML Events into XML Elements. */ public class XMLElementDecoder extends SimpleChannelUpstreamHandler { private static final XMLOutputFactory xmlOutputFactory = new OutputFactoryImpl(); private final int skip; private XMLEventWriter writer; private DOMResult result; private Document document; private int depth; public XMLElementDecoder() { this(1); } public XMLElementDecoder(int skip) { this.skip = skip; resetWriter(); } @Override public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception { if (!(e.getMessage() instanceof XMLEvent)) { ctx.sendUpstream(e); return; } final XMLEvent event = (XMLEvent) e.getMessage(); if (event.isStartDocument() || event.isEndDocument()) return; if (depth < skip && event.isStartElement()) { ctx.sendUpstream(e); depth++; return; } if (depth <= skip && event.isEndElement()) { ctx.sendUpstream(e); depth--; return; } writer.add(event); if (event.isStartElement()) { depth++; } else if (event.isEndElement()) { depth--; if (depth == skip) { writer.flush(); Channels.fireMessageReceived(ctx, XMLElementImpl.fromElement(document.getDocumentElement())); writer.close(); resetWriter(); } } } private void resetWriter() { try { document = XMLUtil.newDocument(); result = new DOMResult(document); writer = xmlOutputFactory.createXMLEventWriter(result); } catch (XMLStreamException e) { throw new InternalError("Error creating writer"); } } }