Package tigase.server.sreceiver

Source Code of tigase.server.sreceiver.AbstractReceiverTask

/*
* 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: 1292 $
* Last modified by $Author: kobit $
* $Date: 2008-12-12 11:38:11 +0000 (Fri, 12 Dec 2008) $
*/
package tigase.server.sreceiver;


import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.TreeMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Pattern;
import tigase.xml.Element;
import tigase.server.Packet;
import tigase.stats.StatRecord;
import tigase.util.JIDUtils;
import tigase.xmpp.StanzaType;
import tigase.xmpp.Authorization;
import tigase.xmpp.PacketErrorTypeException;
import java.util.LinkedList;

import static tigase.server.sreceiver.PropertyConstants.*;
import static tigase.server.sreceiver.TaskCommons.*;

/**
* Describe class AbstractReceiverTask here.
*
*
* Created: Fri May 11 08:34:04 2007
*
* @author <a href="mailto:artur.hefczyc@tigase.org">Artur Hefczyc</a>
* @version $Rev: 1292 $
*/
public abstract class AbstractReceiverTask implements ReceiverTaskIfc {

  private static Logger log =
    Logger.getLogger("tigase.server.sreceiver.AbstractReceiverTask");

  private String jid = null;
  private String name = null;
  private String local_domain = null;
  private String description = null;
  private Map<String, PropertyItem> props = null;

  private SubscrRestrictions subsc_restr = SUBSCR_RESTRICTIONS_PROP_VAL;
  private SenderRestrictions send_restr = ALLOWED_SENDERS_PROP_VAL;
  private MessageType message_type = MESSAGE_TYPE_PROP_VAL;
  private boolean send_to_online_only = ONLINE_ONLY_PROP_VAL;
  private SenderAddress replace_sender_address = REPLACE_SENDER_PROP_VAL;
  private Pattern subscr_restr_regex =
    Pattern.compile(SUBSCR_RESTR_REGEX_PROP_VAL);
  private String owner = TASK_OWNER_PROP_VAL;
  private String[] admins = {};
  private StanzaReceiverIfc srecv = null;

  private long packets_received = 0;
  private long packets_sent = 0;

  private Map<String, RosterItem> roster = new HashMap<String, RosterItem>();

  // Implementation of tigase.server.sreceiver.ReceiverTaskIfc

  public void setStanzaReceiver(StanzaReceiverIfc srecv) {
    this.srecv = srecv;
  }

  protected boolean addOutPacket(Packet packet) {
    return srecv.addOutPacket(packet);
  }

  /**
   * Describe <code>getInstance</code> method here.
   *
   * @return a <code>ReceiverTaskIfc</code> value
   */
  public ReceiverTaskIfc getInstance() {
    try {
      return getClass().newInstance();
    } catch (Exception e) {
      log.log(Level.SEVERE, "Can't instantiate receiver task: " +
        getClass().getName(), e);
      return null;
    } // end of try-catch
  }

  /**
   * Describe <code>setJID</code> method here.
   *
   * @param jid a <code>String</code> value
   */
  public void setJID(final String jid) {
    this.jid = jid;
    log.fine("JID set to: " + this.jid);
    int idx = jid.indexOf(".");
    this.local_domain = jid.substring(idx+1);
    log.fine("Local domain set to: " + this.local_domain);
    this.name = JIDUtils.getNodeNick(jid);
  }

  /**
   * Describe <code>getJID</code> method here.
   *
   * @return a <code>String</code> value
   */
  public String getJID() {
    return jid;
  }

  /**
   * Describe <code>getDescription</code> method here.
   *
   * @return a <code>String</code> value
   */
  public String getDescription() {
    return description;
  }

  public boolean isAllowedToSubscribe(String buddy) {
    boolean result = false;
    switch (subsc_restr) {
    case LOCAL:
      String buddy_domain = JIDUtils.getNodeHost(buddy);
      if (buddy_domain.equals(local_domain)) {
        result = true;
      } // end of if (buddy_domain.equals(local_domain))
      break;
    case REGEX:
      result = subscr_restr_regex.matcher(buddy).matches();
      break;
    default:
      result = true;
      break;
    } // end of switch (subsc_restr)
    return result;
  }

  public boolean isAllowedToPost(String buddy) {
    boolean result = false;
    RosterItem ri = getRosterItem(buddy);
    switch (send_restr) {
    case SUBSCRIBED:
      result = ri != null && ri.isSubscribed() && ri.isModerationAccepted();
      break;
    case OWNER:
      result = ri != null && ri.isOwner();
      break;
    default:
      result = true;
      break;
    } // end of switch (send_restr)
    return result;
  }

  public void addToRoster(RosterItem ri) {
    roster.put(ri.getJid(), ri);
  }

  public RosterItem addToRoster(String jid) {
    String id = JIDUtils.getNodeID(jid);
    RosterItem ri = new RosterItem(id);
    if (id.equals(owner)) {
      ri.setOwner(true);
    } // end of if (id.equals(owner))
    if (subsc_restr != SubscrRestrictions.MODERATED) {
      ri.setModerationAccepted(true);
    } // end of if (subsc_restr != SubscrRestrictions.MODERATED)
    addToRoster(ri);
    return ri;
  }

  public RosterItem removeFromRoster(String jid) {
    return roster.remove(JIDUtils.getNodeID(jid));
  }

  public RosterItem getRosterItem(String jid) {
    return roster.get(JIDUtils.getNodeID(jid));
  }

  public void setRosterItemOnline(RosterItem ri, boolean online) {
    ri.setOnline(online);
  }

  public void setRosterItemAdmin(RosterItem ri, boolean admin) {
    ri.setAdmin(admin);
  }

  public void setRosterItemOwner(RosterItem ri, boolean owner) {
    ri.setOwner(owner);
  }

  public void setRosterItemSubscribed(RosterItem ri, boolean subscribed) {
    log.fine(getJID() + ": " +
      "Updating subscription for " + ri.getJid() + " to " + subscribed);
    ri.setSubscribed(subscribed);
  }

  public void setRosterItemModerationAccepted(RosterItem ri, boolean accepted) {
    ri.setModerationAccepted(accepted);
  }

  /**
   * Describe <code>addNewSubscribers</code> method here.
   *
   * @param new_subscr a <code>String[]</code> value
   */
  public void addNewSubscribers(Queue<Packet> results, String... new_subscr) {
    for (String buddy: new_subscr) {
      Packet presence = null;
      if (isAllowedToSubscribe(buddy)) {
        if (getRosterItem(buddy) == null) {
          addToRoster(buddy);
        } // end of if (getRosterItem(buddy) == null)
        log.info(getJID() + ": " + "Adding buddy to roster: " + buddy);
        presence = getPresence(buddy, jid, StanzaType.subscribe,
          JIDUtils.getNodeNick(jid), null);
      } else {
        log.info(getJID() + ": " +
          "Not allowed to subscribe, rejecting: " + buddy);
        presence = getPresence(buddy, jid, StanzaType.unsubscribed);
      } // end of else
      log.finest(getJID() + ": " +
        "Sending back: " + presence.toString());
      results.offer(presence);
    } // end of for (String buddy: new_subscr)
  }

  public void removeSubscribers(Queue<Packet> results, String... subscr) {
    for (String buddy: subscr) {
      RosterItem ri = removeFromRoster(buddy);
      if (ri != null) {
        log.info(getJID() + ": "
          + "Removing buddy from roster: " + buddy);
        results.offer(getPresence(buddy, jid, StanzaType.unsubscribed));
      } // end of if (getRosterItem(buddy) == null)
    } // end of for (String buddy: new_subscr)
  }

  /**
   * Describe <code>setParams</code> method here.
   *
   * @param map a <code>Map</code> value
   */
  public void setParams(final Map<String, Object> map) {
    if (props == null) {
      props = new TreeMap<String, PropertyItem>();
    } // end of if (props == null)
    if (map.get(DESCRIPTION_PROP_KEY) != null) {
      description = (String)map.get(DESCRIPTION_PROP_KEY);
      props.put(DESCRIPTION_PROP_KEY, new PropertyItem(DESCRIPTION_PROP_KEY,
          DESCRIPTION_DISPL_NAME, description));
    } // end of if (map.get(DESCRIPTION_PROP_KEY) != null)
    if (map.get(SUBSCR_RESTR_REGEX_PROP_KEY) != null) {
      subscr_restr_regex =
        Pattern.compile((String)map.get(SUBSCR_RESTR_REGEX_PROP_KEY));
      props.put(SUBSCR_RESTR_REGEX_PROP_KEY,
        new PropertyItem(SUBSCR_RESTR_REGEX_PROP_KEY,
        SUBSCR_RESTR_REGEX_DISPL_NAME, subscr_restr_regex));
    } // end of if (map.get(SUBSCR_RESTR_REGEX_PROP_KEY) != null)
    String tmp = (String)map.get(SUBSCR_RESTRICTIONS_PROP_KEY);
    if (tmp != null) {
      subsc_restr = SubscrRestrictions.valueOf(tmp);
      props.put(SUBSCR_RESTRICTIONS_PROP_KEY,
        new PropertyItem(SUBSCR_RESTRICTIONS_PROP_KEY,
          SUBSCR_RESTRICTIONS_DISPL_NAME, subsc_restr));
    } // end of if (tmp != null)
    tmp = (String)map.get(ALLOWED_SENDERS_PROP_KEY);
    if (tmp != null) {
      send_restr = SenderRestrictions.valueOf(tmp);
      props.put(ALLOWED_SENDERS_PROP_KEY,
        new PropertyItem(ALLOWED_SENDERS_PROP_KEY,
          ALLOWED_SENDERS_DISPL_NAME, send_restr));
    } // end of if (tmp != null)
    tmp = (String)map.get(MESSAGE_TYPE_PROP_KEY);
    if (tmp != null) {
      message_type = MessageType.valueOf(tmp);
      props.put(MESSAGE_TYPE_PROP_KEY,
        new PropertyItem(MESSAGE_TYPE_PROP_KEY,
          MESSAGE_TYPE_DISPL_NAME, message_type));
    } // end of if (tmp != null)
    if (map.get(ONLINE_ONLY_PROP_KEY) != null) {
      send_to_online_only =  parseBool(map.get(ONLINE_ONLY_PROP_KEY));
      props.put(ONLINE_ONLY_PROP_KEY,
        new PropertyItem(ONLINE_ONLY_PROP_KEY,
          ONLINE_ONLY_DISPL_NAME, send_to_online_only));
    } // end of if (map.get(ONLINE_ONLY_PROP_KEY) != null)
    tmp = (String)map.get(REPLACE_SENDER_PROP_KEY);
    if (tmp != null) {
      replace_sender_address = SenderAddress.valueOf(tmp);
      props.put(REPLACE_SENDER_PROP_KEY,
        new PropertyItem(REPLACE_SENDER_PROP_KEY,
          REPLACE_SENDER_DISPL_NAME, replace_sender_address));
    } // end of if (map.get(REPLACE_SENDER_PROP_KEY) != null)
    tmp = (String)map.get(TASK_OWNER_PROP_KEY);
    if (tmp != null && tmp.length() > 0) {
      owner = tmp.trim();
      RosterItem ri = getRosterItem(owner);
      if (ri == null) {
        ri = addToRoster(owner);
      } // end of if (ri == null)
      setRosterItemOwner(ri, true);
      setRosterItemAdmin(ri, true);
      setRosterItemModerationAccepted(ri, true);
      props.put(TASK_OWNER_PROP_KEY,
        new PropertyItem(TASK_OWNER_PROP_KEY, TASK_OWNER_DISPL_NAME, owner));
    }
    if (props.get(TASK_OWNER_PROP_KEY) == null) {
      props.put(TASK_OWNER_PROP_KEY,
        new PropertyItem(TASK_OWNER_PROP_KEY, TASK_OWNER_DISPL_NAME, ""));
    }
    tmp = (String)map.get(TASK_ADMINS_PROP_KEY);
    if (tmp != null && tmp.length() > 0) {
      admins = tmp.split(",");
      for (String admin: admins) {
        RosterItem ri = getRosterItem(admin.trim());
        if (ri == null) {
          ri = addToRoster(admin.trim());
        } // end of if (ri == null)
        setRosterItemAdmin(ri, true);
        setRosterItemModerationAccepted(ri, true);
      } // end of for (String tmp_b: tmp_arr)
      props.put(TASK_ADMINS_PROP_KEY,
        new PropertyItem(TASK_ADMINS_PROP_KEY, TASK_ADMINS_DISPL_NAME, tmp));
    }
    if (props.get(TASK_ADMINS_PROP_KEY) == null) {
      props.put(TASK_ADMINS_PROP_KEY,
        new PropertyItem(TASK_ADMINS_PROP_KEY, TASK_ADMINS_DISPL_NAME, ""));
    }
  }

  /**
   * Describe <code>getParams</code> method here.
   *
   * @return a <code>Map</code> value
   */
  public Map<String, PropertyItem> getParams() {
    return props;
  }

  public Map<String, PropertyItem> getDefaultParams() {
    Map<String, PropertyItem> defs = new TreeMap<String, PropertyItem>();
    defs.put(SUBSCR_RESTRICTIONS_PROP_KEY,
      new PropertyItem(SUBSCR_RESTRICTIONS_PROP_KEY,
        SUBSCR_RESTRICTIONS_DISPL_NAME, SUBSCR_RESTRICTIONS_PROP_VAL));
    defs.put(MESSAGE_TYPE_PROP_KEY,
      new PropertyItem(MESSAGE_TYPE_PROP_KEY,
        MESSAGE_TYPE_DISPL_NAME, MESSAGE_TYPE_PROP_VAL));
    defs.put(ALLOWED_SENDERS_PROP_KEY,
      new PropertyItem(ALLOWED_SENDERS_PROP_KEY,
        ALLOWED_SENDERS_DISPL_NAME, ALLOWED_SENDERS_PROP_VAL));
    defs.put(SUBSCR_RESTR_REGEX_PROP_KEY,
      new PropertyItem(SUBSCR_RESTR_REGEX_PROP_KEY,
        SUBSCR_RESTR_REGEX_DISPL_NAME, SUBSCR_RESTR_REGEX_PROP_VAL));
    defs.put(ONLINE_ONLY_PROP_KEY,
      new PropertyItem(ONLINE_ONLY_PROP_KEY,
        ONLINE_ONLY_DISPL_NAME, ONLINE_ONLY_PROP_VAL));
    defs.put(REPLACE_SENDER_PROP_KEY,
      new PropertyItem(REPLACE_SENDER_PROP_KEY,
        REPLACE_SENDER_DISPL_NAME, REPLACE_SENDER_PROP_VAL));
    defs.put(ALLOWED_SENDERS_LIST_PROP_KEY,
      new PropertyItem(ALLOWED_SENDERS_LIST_PROP_KEY,
        ALLOWED_SENDERS_LIST_DISPL_NAME, ALLOWED_SENDERS_LIST_PROP_VAL));
    defs.put(DESCRIPTION_PROP_KEY,
      new PropertyItem(DESCRIPTION_PROP_KEY,
        DESCRIPTION_DISPL_NAME, DESCRIPTION_PROP_VAL));
    defs.put(TASK_ADMINS_PROP_KEY,
      new PropertyItem(TASK_ADMINS_PROP_KEY,
        TASK_ADMINS_DISPL_NAME, TASK_ADMINS_PROP_VAL));
    defs.put(TASK_OWNER_PROP_KEY,
      new PropertyItem(TASK_OWNER_PROP_KEY,
        TASK_OWNER_DISPL_NAME, TASK_OWNER_PROP_VAL));
    return defs;
  }

  public void init(final Queue<Packet> results) {
    for (RosterItem ri: roster.values()) {
      Packet presence = null;
      if (ri.isSubscribed()) {
        presence = getPresence(ri.getJid(), jid, StanzaType.available,
          null, getDescription());
      } else {
        presence = getPresence(ri.getJid(), jid, StanzaType.subscribe,
          JIDUtils.getNodeNick(jid), null);
      } // end of if (ri.isSubscribed()) else
      results.offer(presence);
    }
  }

  public void destroy(Queue<Packet> results) {
    for (RosterItem ri: roster.values()) {
      Packet presence = getPresence(ri.getJid(), jid, StanzaType.unsubscribe);
      results.offer(presence);
      presence = getPresence(ri.getJid(), jid, StanzaType.unsubscribed);
      results.offer(presence);
    }
  }

  /**
   * Describe <code>processPacket</code> method here.
   *
   * @param packet a <code>Packet</code> value
   * @param results a <code>Queue</code> value
   */
  public void processPacket(final Packet packet, final Queue<Packet> results) {
    ++packets_received;
    log.finest(getJID() + ": " + "Processing packet: " + packet.toString());
    if (packet.getType() == StanzaType.error) {
      log.fine("Ignoring error stanza: " + packet.toString());
      return;
    }
    if (packet.getElemName().equals("presence")) {
      processPresence(packet, results);
    } // end of if (packet.getElemName().equals("presence))
    if (packet.getElemName().equals("message")) {
      if (isAllowedToPost(JIDUtils.getNodeID(packet.getElemFrom()))) {
        processMessage(packet, results);
      } else {
        try {
          results.offer(Authorization.NOT_ALLOWED.getResponseMessage(packet,
              "You are not allowed to post a message.", true));
        } catch (PacketErrorTypeException e) {
          log.warning("Packet processing exception: " + e);
        }
      }
    } // end of if (packet.getElemName().equals("message"))
    packets_sent += results.size();
  }

  private void processPresence(Packet packet, Queue<Packet> results) {
    StanzaType presence_type = StanzaType.available;
    if (packet.getType() != null) {
      presence_type = packet.getType();
    }
    RosterItem ri = getRosterItem(packet.getElemFrom());
    switch (presence_type) {
    case available:
    case probe:
      if (ri != null) {
        setRosterItemOnline(ri, true);
        results.offer(getPresence(packet.getElemFrom(), jid,
            StanzaType.available, null, getDescription()));
      } // end of if (ri != null)
      break;
    case unavailable:
      if (ri != null) {
        setRosterItemOnline(ri, false);
      // This is really not necessary as the task is always on-line
      // It should only mark remote contact as off-line and that's it.
//         results.offer(getPresence(packet.getElemFrom(), jid,
//             StanzaType.unavailable));
      } // end of if (ri != null)
      break;
    case subscribe:
      addNewSubscribers(results, packet.getElemFrom());
      results.offer(getPresence(packet.getElemFrom(), jid,
          StanzaType.subscribed));
      break;
    case subscribed:
      if (ri != null) {
        setRosterItemSubscribed(ri, true);
        results.offer(getPresence(packet.getElemFrom(), jid,
            StanzaType.available, null, getDescription()));
        if (!ri.isModerationAccepted()) {
          results.offer(getMessage(packet.getElemFrom(), jid,
              StanzaType.headline,
              "You are now subscribed to " + getJID() + ".\n\n"
              + "Your subscription, however awaits moderation.\n\n"
              + "Once your subscription is approved next message\n"
              + "will be sent confirming your membership."));
        }
      } // end of if (ri != null)
      break;
    case unsubscribe:
    case unsubscribed:
      removeSubscribers(results, packet.getElemFrom());
      break;
    default:
      break;
    } // end of switch (packet.getType())
  }

  protected void processMessage(Packet packet, Queue<Packet> results) {
    for (RosterItem ri : roster.values()) {
      if (ri.isSubscribed() && ri.isModerationAccepted() &&
              (!send_to_online_only || ri.isOnline()) &&
              (!JIDUtils.getNodeID(packet.getElemFrom()).equals(ri.getJid()))) {
        Element message = packet.getElement().clone();
        Element body = message.getChild("body");
        if (body == null) {
          return;
        } // end of if (body == null)
        message.setAttribute("to", ri.getJid());
        message.setAttribute("type", message_type.toString().toLowerCase());
        switch (replace_sender_address) {
          case REPLACE: {
            String old_from = message.getAttribute("from");
            message.setAttribute("from", jid);
            String cdata = body.getCData();
            body.setCData(old_from + " sends:\n\n" + cdata);
            break;
          }
          case REMOVE:
            message.setAttribute("from", jid);
            break;
          case REPLACE_SRECV: {
            String old_from = message.getAttribute("from");
            message.setAttribute("from", JIDUtils.getJID(srecv.getName(),
                    local_domain, name));
            String cdata = body.getCData();
            body.setCData(old_from + " sends for installation at " +
                    srecv.getDefHostName() + ":\n\n" + cdata);
            break;
          }
          default:
            break;
        }
        results.offer(new Packet(message));
      } // end of if (ri.isSubscribed() && ri.isModerationAccepted())
    } // end of for (RosterItem ri: roster.values())
  }

  public List<StatRecord> getStats() {
    List<StatRecord> stats = new LinkedList<StatRecord>();
    stats.add(new StatRecord(getJID(), "Roster size", "int",
        roster.size(), Level.INFO));
    stats.add(new StatRecord(getJID(), "Packets received", "long",
        packets_received, Level.INFO));
    stats.add(new StatRecord(getJID(), "Packets sent", "long",
        packets_sent, Level.INFO));
    int moderation_needed = 0;
    for (RosterItem ri: roster.values()) {
      moderation_needed += (ri.isModerationAccepted() ? 0 : 1);
    } // end of for (RosterItem ri: roster)
    stats.add(new StatRecord(getJID(), "Awaiting moderation", "int",
        moderation_needed, Level.INFO));
    return stats;
  }

  public boolean isAdmin(String jid) {
    RosterItem ri = getRosterItem(jid);
    return ri != null && (ri.isAdmin() || ri.isOwner());
  }

  public Map<String, RosterItem> getRoster() {
    return roster;
  }

} // AbstractReceiverTask
TOP

Related Classes of tigase.server.sreceiver.AbstractReceiverTask

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.