Package tigase.xmpp

Source Code of tigase.xmpp.XMPPDomBuilderHandler

/*
* Tigase Jabber/XMPP Server
* Copyright (C) 2004-2007 "Artur Hefczyc" <artur.hefczyc@tigase.org>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. Look for COPYING file in the top folder.
* If not, see http://www.gnu.org/licenses/.
*
* $Rev: 1161 $
* Last modified by $Author: kobit $
* $Date: 2008-10-01 13:05:00 +0100 (Wed, 01 Oct 2008) $
*/

package tigase.xmpp;

import java.util.Arrays;
import java.util.EmptyStackException;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Queue;
import java.util.Stack;
import java.util.TreeMap;
import java.util.logging.Logger;
import java.util.logging.Level;
import tigase.xml.DefaultElementFactory;
import tigase.xml.Element;
import tigase.xml.ElementFactory;
import tigase.xml.SimpleHandler;

/**
* <code>XMPPDomBuilderHandler</code> - implementation of
<code>SimpleHandler</code> building <em>DOM</em> strctures during parsing
*  time.
*  It also supports creation multiple, sperate document trees if parsed
*  buffer contains a few <em>XML</em> documents. As a result of work it returns
*  always <code>Queue</code> containing all found <em>XML</em> trees in the
*  same order as they were found in network data.<br/>
*  Document trees created by this <em>DOM</em> builder consist of instances of
<code>Element</code> class or instances of class extending
<code>Element</code> class. To receive trees built with instances of proper
*  class user must provide <code>ElementFactory</code> implementation creating
*  instances of required <code>ELement</code> extension.
*
* <p>
* Created: Sat Oct  2 22:01:34 2004
* </p>
* @author <a href="mailto:artur.hefczyc@tigase.org">Artur Hefczyc</a>
* @version $Rev: 1161 $
*/

public class XMPPDomBuilderHandler implements SimpleHandler {

  private static Logger log =
    Logger.getLogger("tigase.xmpp.XMPPDomBuilderHandler");

  private static final String ELEM_STREAM_STREAM = "stream:stream";
  private static ElementFactory defaultFactory = new DefaultElementFactory();

  private ElementFactory customFactory = null;

  private Object parserState = null;
  private String top_xmlns = null;
  private XMPPIOService service = null;
  private boolean error = false;

  private LinkedList<Element> all_roots = new LinkedList<Element>();
  private Stack<Element> el_stack = new Stack<Element>();
  private Map<String, String> namespaces = new TreeMap<String, String>();

  public XMPPDomBuilderHandler(XMPPIOService ioserv, ElementFactory factory) {
    customFactory = factory;
    service = ioserv;
  }

  public XMPPDomBuilderHandler(XMPPIOService ioserv) {
    customFactory = defaultFactory;
    service = ioserv;
  }

  public Queue<Element> getParsedElements() {
    return all_roots;
  }

  public void error(String errorMessage) {
    log.warning("XML content parse error.");
    log.warning(errorMessage);
    error = true;
  }

  public boolean parseError() {
    return error;
  }

  private Element newElement(String name, String cdata,
    StringBuilder[] attnames, StringBuilder[] attvals) {
    return customFactory.elementInstance(name, cdata, attnames, attvals);
  }

  public void startElement(StringBuilder name,
    StringBuilder[] attr_names, StringBuilder[] attr_values) {
    if (log.isLoggable(Level.FINEST)) {
      log.finest("Start element name: "+name);
      log.finest("Element attributes names: "+Arrays.toString(attr_names));
      log.finest("Element attributes values: "+Arrays.toString(attr_values));
    }

    // Look for 'xmlns:' declarations:
    if (attr_names != null) {
      for (int i = 0; i < attr_names.length; ++i) {
        // Exit the loop as soon as we reach end of attributes set
        if (attr_names[i] == null) { break}
        if (attr_names[i].toString().startsWith("xmlns:")) {
          namespaces.put(attr_names[i].substring("xmlns:".length(),
              attr_names[i].length()),
            attr_values[i].toString());
          log.finest("Namespace found: " + attr_values[i].toString());
        } // end of if (att_name.startsWith("xmlns:"))
      } // end of for (String att_name : attnames)
    } // end of if (attr_names != null)

    String tmp_name = name.toString();
    if (tmp_name.equals(ELEM_STREAM_STREAM)) {
      Map<String, String> attribs = new HashMap<String, String>();
      if (attr_names != null) {
        for (int i = 0; i < attr_names.length; i++) {
          if (attr_names[i] != null && attr_values[i] != null) {
            attribs.put(attr_names[i].toString(), attr_values[i].toString());
          } else {
            break;
          } // end of else
        } // end of for (int i = 0; i < attr_names.length; i++)
      } // end of if (attr_name != null)
      service.xmppStreamOpened(attribs);
      return;
    } // end of if (tmp_name.equals(ELEM_STREAM_STREAM))

    String new_xmlns = null;
    String prefix = null;
    for (String pref: namespaces.keySet()) {
      if (tmp_name.startsWith(pref)) {
        new_xmlns = namespaces.get(pref);
        tmp_name = tmp_name.substring(pref.length()+1, tmp_name.length());
        prefix = pref;
        log.finest("new_xmlns = " + new_xmlns);
      } // end of if (tmp_name.startsWith(xmlns))
    } // end of for (String xmlns: namespaces.keys())
    Element elem = newElement(tmp_name, null, attr_names, attr_values);
    String ns = elem.getXMLNS();
    if (ns == null) {
      if (el_stack.isEmpty() || el_stack.peek().getXMLNS() == null) {
        //elem.setDefXMLNS(top_xmlns);
      } else {
        elem.setDefXMLNS(el_stack.peek().getXMLNS());
        log.finest("DefXMLNS assigned: " + elem.toString());
      }
    }
    if (new_xmlns != null) {
      elem.setXMLNS(new_xmlns);
      elem.removeAttribute("xmlns:" + prefix);
      log.finest("new_xmlns assigned: " + elem.toString());
    }
    el_stack.push(elem);
  }

  public void elementCData(StringBuilder cdata) {
    log.finest("Element CDATA: "+cdata);
    try {
      el_stack.peek().setCData(cdata.toString());
    } catch (EmptyStackException e) {
      // Do nothing here, it happens sometimes that client sends
      // some white characters after sending open stream data....
    }
  }

  public void endElement(StringBuilder name) {
    log.finest("End element name: "+name);

    String tmp_name = name.toString();
    if (tmp_name.equals(ELEM_STREAM_STREAM)) {
      service.xmppStreamClosed();
      return;
    } // end of if (tmp_name.equals(ELEM_STREAM_STREAM))

    if (el_stack.isEmpty()) {
      el_stack.push(newElement(tmp_name, null, null, null));
    } // end of if (tmp_name.equals())

    Element elem = el_stack.pop();
    if (el_stack.isEmpty()) {
      all_roots.offer(elem);
      if (log.isLoggable(Level.FINEST)) {
        log.finest("Adding new request: "+elem.toString());
      }
    } else {
      el_stack.peek().addChild(elem);
    } // end of if (el_stack.isEmpty()) else
  }

  public void otherXML(StringBuilder other) {
    log.finest("Other XML content: "+other);

    // Just ignore
  }

  public void saveParserState(Object state) {
    parserState = state;
  }

  public Object restoreParserState() {
    return parserState;
  }

}// XMPPDomBuilderHandler
TOP

Related Classes of tigase.xmpp.XMPPDomBuilderHandler

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.