Package tigase.xmpp

Source Code of tigase.xmpp.XMPPIOService

/*
* 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: 1182 $
* Last modified by $Author: kobit $
* $Date: 2008-10-21 00:40:42 +0100 (Tue, 21 Oct 2008) $
*/
package tigase.xmpp;

import java.io.IOException;
import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Logger;
import java.util.logging.Level;
import tigase.net.IOService;
import tigase.server.Packet;
import tigase.xml.Element;
import tigase.xml.SimpleParser;
import tigase.xml.SingletonFactory;

/**
* Describe class XMPPIOService here.
*
*
* Created: Tue Feb  7 07:15:02 2006
*
* @author <a href="mailto:artur.hefczyc@tigase.org">Artur Hefczyc</a>
* @version $Rev: 1182 $
*/
public class XMPPIOService extends IOService {

  /**
   * Variable <code>log</code> is a class logger.
   */
  private static final Logger log =
    Logger.getLogger("tigase.xmpp.XMPPIOService");

  private XMPPDomBuilderHandler domHandler = null;
  private SimpleParser parser = SingletonFactory.getParserInstance();
  private XMPPIOServiceListener serviceListener = null;

  /**
   * The <code>waitingPackets</code> queue keeps data which have to be processed.
   */
  private ConcurrentLinkedQueue<Packet> waitingPackets =
    new ConcurrentLinkedQueue<Packet>();

  /**
   * The <code>readyPackets</code> queue keeps data which have been already
   * processed and they are actual processing results.
   */
  private ConcurrentLinkedQueue<Packet> receivedPackets =
    new ConcurrentLinkedQueue<Packet>();

  private String xmlns = null;

//   /**
//    * Variable <code>lock</code> keeps reference to object lock.
//    * It supports multi-threaded processing and can be called simultanously from
//    * many threads. It is not recommended however as lock prevents most of
//    * methods to be executed concurrently as they process data received from
//    * socket and the data should be processed in proper order.
//    */
  private Lock writeLock = new ReentrantLock();
  private Lock readLock = new ReentrantLock();

  //private boolean streamClosed = false;

  /**
   * Creates a new <code>XMPPIOService</code> instance.
   *
   */
  public XMPPIOService() {
    domHandler = new XMPPDomBuilderHandler(this);
  }

  public void setXMLNS(String xmlns) {
    this.xmlns = xmlns;
  }

  public String getXMLNS() {
    return this.xmlns;
  }

  public void setIOServiceListener(XMPPIOServiceListener sl) {
    this.serviceListener = sl;
    super.setIOServiceListener(sl);
  }

  protected void xmppStreamOpened(Map<String, String> attribs) {
    if (serviceListener != null) {
      String response = serviceListener.streamOpened(this, attribs);
      try {
        log.finest("Sending data: " + response);
        writeRawData(response);
        if (response != null && response.endsWith("</stream:stream>")) {
          stop();
        } // end of if (response.endsWith())
      } catch (IOException e) {
        log.warning("Error sending stream open data: " + e);
        forceStop();
      }
    }
  }

  public void xmppStreamOpen(final String data) {
    try {
      log.finest("Sending data: " + data);
      writeRawData(data);
      assert debug(data, "--SENT:");
    } catch (IOException e) {
      log.warning("Error sending stream open data: " + e);
      forceStop();
    }
  }

  /**
   * Describe <code>stop</code> method here.
   *
   * @exception IOException if an error occurs
   */
  public void stop() {
//     if (!streamClosed) {
//       streamClosed = true;
//       serviceListener.xmppStreamClosed(this);
//     } // end of if (!streamClosed)
    super.stop();
  }

  protected void xmppStreamClosed() {
    //streamClosed = true;
    if (serviceListener != null) {
      serviceListener.streamClosed(this);
    }
    try {
      log.finest("Sending data: </stream:stream>");
      writeRawData("</stream:stream>");
    } catch (IOException e) {
      log.warning("Error sending stream closed data: " + e);
    }
//     try {
//       stop();
//     } catch (IOException e) {
//       log.warning("Error stopping service: " + e);
//     } // end of try-catch
  }

  /**
   * Method <code>addPacketToSend</code> adds new data which will be processed
   * during next run.
   * Data are kept in proper order like in <em>FIFO</em> queue.
   *
   * @param packet a <code>Packet</code> value of data to process.
   */
  public void addPacketToSend(final Packet packet) {
    waitingPackets.offer(packet);
  }

  public Queue<Packet> getReceivedPackets() {
    return receivedPackets;
  }

  /**
   * Describe <code>processWaitingPackets</code> method here.
   *
   */
  public void processWaitingPackets() throws IOException {
    Packet packet = null;
    while ((packet = waitingPackets.poll()) != null) {
      if (log.isLoggable(Level.FINEST)) {
        log.finest("Sending packet: " + packet.toString());
      }
      writeRawData(packet.getStringData());
      if (log.isLoggable(Level.FINEST)) {
        log.finest("SENT: " + packet.getStringData());
      }
    } // end of while (packet = waitingPackets.poll() != null)
  }

  public void writeRawData(String data) throws IOException {
    // We change state of this object in this method
    // It can be called by many threads simultanously
    // so we need to make it thread-safe
     writeLock.lock();
    try {
      writeData(data);
    } finally {
       writeLock.unlock();
    }
  }

  /**
   * Describe <code>processSocketData</code> method here.
   *
   * @exception IOException if an error occurs
   */
  protected void processSocketData() throws IOException {
    // We change state of this object in this method
    // It can be called by many threads simultanously
    // so we need to make it thread-safe
    //log.finer("About to read socket data.");
     readLock.lock();
    try {
      if (isConnected()) {
        char[] data = readData();

        // Yes check again if we are still connected as
        // servce might be disconnected during data read
        if (isConnected() && data != null) {
          log.finest("READ:\n" + new String(data));
          // This is log for debuging only,
          // in normal mode don't even call below code
          assert debug(new String(data), "--RECEIVED:");
          try {
            parser.parse(domHandler, data, 0, data.length);
            if (domHandler.parseError()) {
              log.warning("Data parsing error: " + new String(data));
              domHandler = new XMPPDomBuilderHandler(this);
            }
            Queue<Element> elems = domHandler.getParsedElements();
            if (elems.size() > 0) {
              readCompleted();
            }
            Element elem = null;
            while ((elem = elems.poll()) != null) {
              //  assert debug(elem.toString() + "\n");
              //log.finer("Read element: " + elem.getName());
              if (log.isLoggable(Level.FINEST)) {
                log.finest("Read packet: " + elem.toString());
              }
              //              System.out.print(elem.toString());
              addReceivedPacket(new Packet(elem));
            } // end of while ((elem = elems.poll()) != null)
          catch (Exception ex) {
            log.log(Level.INFO, "Incorrect XML data: " + new String(data)
              + ", stopping connection: " + getUniqueId()
              + ", exception: ", ex);
            forceStop();
          } // end of try-catch
        } else {
          log.finest("Nothing read!!");
        }
      } else {
        log.info("function called when the service is not connected! forceStop()");
        forceStop();
      }
    } finally {
      readLock.unlock();
    }
  }

  protected int receivedPackets() {
    return receivedPackets.size();
  }

  /**
   * Method <code>addReceivedPacket</code> puts processing results to queue.
   * The processing results are usually data (messages) which has been
   * just received from socket.
   *
   * @param packet a <code>Packet</code> value of processing results.
   */
  private void addReceivedPacket(final Packet packet) {
    receivedPackets.offer(packet);
  }

} // XMPPIOService
TOP

Related Classes of tigase.xmpp.XMPPIOService

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.