package tigase.xmpp.impl;
//~--- non-JDK imports --------------------------------------------------------
import tigase.db.NonAuthUserRepository;
import tigase.db.TigaseDBException;
import tigase.server.BasicComponent;
import tigase.server.Packet;
import tigase.xml.Element;
import tigase.xmpp.Authorization;
import tigase.xmpp.BareJID;
import tigase.xmpp.JID;
import tigase.xmpp.NotAuthorizedException;
import tigase.xmpp.PacketErrorTypeException;
import tigase.xmpp.XMPPException;
import tigase.xmpp.XMPPProcessorAbstract;
import tigase.xmpp.XMPPResourceConnection;
import tigase.xmpp.impl.roster.RosterAbstract;
import tigase.xmpp.impl.roster.RosterAbstract.SubscriptionType;
import tigase.xmpp.impl.roster.RosterFactory;
//~--- JDK imports ------------------------------------------------------------
import java.util.EnumSet;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.logging.Level;
import java.util.logging.Logger;
//~--- classes ----------------------------------------------------------------
/**
* Class description
*
*
* @version 5.0.0, 2010.03.01 at 03:12:30 GMT
* @author Artur Hefczyc <artur.hefczyc@tigase.org>
*/
public class PepPlugin extends XMPPProcessorAbstract {
private static final String _XMLNS = "http://jabber.org/protocol/pubsub";
private static final Element[] DISCO_FEATURES = { new Element("feature", new String[] { "var" }, new String[] { _XMLNS }),
new Element("feature", new String[] { "var" }, new String[] { _XMLNS + "#owner" }),
new Element("feature", new String[] { "var" }, new String[] { _XMLNS + "#publish" }),
new Element("identity", new String[] { "category", "type" }, new String[] { "pubsub", "pep" }), };
private static final String[] ELEMENTS = { "pubsub" };
private static final String ID = "pep";
private static final Logger log = Logger.getLogger("tigase.xmpp.impl.PepPlugin");
private static final String PUBSUB_COMPONENT_URL = "pubsub-component";
private static RosterAbstract roster = RosterFactory.getRosterImplementation(true);
private static final EnumSet<SubscriptionType> SUBSCRITION_TYPES = EnumSet.of(SubscriptionType.both, SubscriptionType.from);
private static final String[] XMLNSS = { _XMLNS };
// ~--- fields
// ---------------------------------------------------------------
private final HashSet<String> supportedNodes = new HashSet<String>();
// ~--- constructors
// ---------------------------------------------------------
/**
* Constructs ...
*
*/
public PepPlugin() {
this.supportedNodes.add("http://jabber.org/protocol/tune");
this.supportedNodes.add("http://jabber.org/protocol/mood");
this.supportedNodes.add("http://jabber.org/protocol/activity");
this.supportedNodes.add("http://jabber.org/protocol/geoloc");
this.supportedNodes.add("urn:xmpp:avatar:data");
this.supportedNodes.add("urn:xmpp:avatar:metadata");
}
// ~--- methods
// --------------------------------------------------------------
/**
* Method description
*
*
* @return
*/
@Override
public String id() {
return ID;
}
/**
* Method description
*
*
* @param connectionId
* @param packet
* @param session
* @param repo
* @param results
* @param settings
*
* @throws PacketErrorTypeException
*/
@Override
public void processFromUserToServerPacket(JID connectionId, Packet packet, XMPPResourceConnection session,
NonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings) throws PacketErrorTypeException {
try {
List<Element> x = packet.getElemChildren("/iq/pubsub");
boolean processed = false;
for (Element element : x) {
String action = element.getName();
String node = element.getAttribute("node");
if (this.supportedNodes.contains(node)) {
if (action == "retract") {
Element item = element.getChild("item", null);
Element retract = new Element("retract");
if (item.getAttribute("id") != null) {
retract.addAttribute("id", item.getAttribute("id"));
}
processed = true;
processPEPPublish(packet, node, retract, session, repo, results, settings);
break;
} else {
if (action == "publish") {
Element item = element.getChild("item", null);
processed = true;
processPEPPublish(packet, node, item, session, repo, results, settings);
break;
}
}
}
}
if (processed) {
results.offer(packet.okResult((Element) null, 0));
} else {
results.offer(Authorization.FEATURE_NOT_IMPLEMENTED.getResponseMessage(packet,
"The PEP node is not yet supported.", true));
}
} catch (NotAuthorizedException ex) {
log.warning("NotAuthorizedException for packet: " + packet);
results.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet, "You must authorize session first.", true));
} catch (TigaseDBException ex) {
Logger.getLogger(PepPlugin.class.getName()).log(Level.SEVERE, null, ex);
}
}
/**
* Method description
*
*
* @param packet
* @param repo
* @param results
* @param settings
*
* @throws PacketErrorTypeException
*/
@Override
public void processNullSessionPacket(Packet packet, NonAuthUserRepository repo, Queue<Packet> results,
Map<String, Object> settings) throws PacketErrorTypeException {
results.offer(Authorization.SERVICE_UNAVAILABLE.getResponseMessage(packet, "Service not available.", true));
}
/**
* Method description
*
*
* @param packet
* @param session
* @param repo
* @param results
* @param settings
*
* @throws PacketErrorTypeException
*/
@Override
public void processServerSessionPacket(Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo,
Queue<Packet> results, Map<String, Object> settings) throws PacketErrorTypeException {
// I guess we ignore such packets here, no pep support for the server
// itself yet
}
/**
* Method description
*
*
* @param session
*
* @return
*/
@Override
public Element[] supDiscoFeatures(final XMPPResourceConnection session) {
return DISCO_FEATURES;
}
/**
* Method description
*
*
* @return
*/
@Override
public String[] supElements() {
return ELEMENTS;
}
/**
* Method description
*
*
* @return
*/
@Override
public String[] supNamespaces() {
return XMLNSS;
}
private void forward(Packet packet, XMPPResourceConnection session, NonAuthUserRepository repo, Queue<Packet> results,
Map<String, Object> settings) throws XMPPException {
String pubSubComponentUrl = (settings == null) ? null : (String) settings.get(PUBSUB_COMPONENT_URL);
if ((session == null) || (pubSubComponentUrl == null)) {
if (log.isLoggable(Level.FINE)) {
log.fine("Packet reject. No Session or PubSub Component URL.");
}
return;
} // end of if (session == null)
try {
packet.getElement().setAttribute("to", pubSubComponentUrl);
BareJID id = packet.getStanzaTo().getBareJID();
if (session.isUserId(id)) {
// Yes this is message to 'this' client
Packet result = packet.copyElementOnly();
result.setPacketTo(session.getConnectionId());
result.setPacketFrom(packet.getTo());
results.offer(result);
} else {
// This is message to some other client
results.offer(packet.copyElementOnly());
} // end of else
} catch (NotAuthorizedException e) {
log.warning("NotAuthorizedException for packet: " + packet);
results.offer(Authorization.NOT_AUTHORIZED.getResponseMessage(packet, "You must authorize session first.", true));
} // end of try-catch
}
private void processPEPPublish(Packet packet, String node, Element pepItem, XMPPResourceConnection session,
NonAuthUserRepository repo, Queue<Packet> results, Map<String, Object> settings) throws NotAuthorizedException,
TigaseDBException {
JID[] buddies = roster.getBuddies(session, SUBSCRITION_TYPES);
Element event = new Element("event", new String[] { "xmlns" },
new String[] { "http://jabber.org/protocol/pubsub#event" });
Element items = new Element("items", new String[] { "node" }, new String[] { node });
event.addChild(items);
items.addChild(pepItem);
JID from = packet.getStanzaFrom();
if (buddies != null)
for (JID buddy : buddies) {
Element message = new Element("message", new String[] { "from", "to", "type", "id" }, new String[] {
from.toString(), buddy.toString(), "headline", packet.getStanzaId() });
message.addChild(event);
results.offer(Packet.packetInstance(message, from, buddy));
}
Element message = new Element("message", new String[] { "from", "to", "type", "id" }, new String[] { from.toString(),
from.toString(), "headline", packet.getStanzaId() });
message.addChild(event);
results.offer(Packet.packetInstance(message, from, from));
}
}
// ~ Formatted in Sun Code Convention
// ~ Formatted by Jindent --- http://www.jindent.com