Commit 1c07320a authored by Axel Brand's avatar Axel Brand Committed by daeva

Finished Refactoring for GoJara 2.0, testing and finetuning coming up.

git-svn-id: http://svn.igniterealtime.org/svn/repos/openfire/branches/plugins@13546 b35dd754-fafc-0310-a699-88a17e54d16e
parent a660277a
......@@ -44,6 +44,17 @@
GoJara Plugin Changelog
</h1>
<p><b>2.0.0</b> -- Mar 07, 2013</p>
<ul>
<li>Major refactoring of the Interceptor- and Processor-Structure used by GoJara</li>
<li>One-Interceptor structure should allow easier Debugging & control of Features</li>
<li>We completely ignore Packets with malformed JIDs now, this should cause less Warnings/Errors</li>
<li>Freezing the Interceptor on Destroy of the Plugin should make GoJara properly shutdown and not cause trouble on reload/update</li>
<li>Optimized Processors have better performance</li>
</ul>
<p><b>1.2.5</b> -- Feb 22, 2013</p>
<ul>
......
......@@ -6,9 +6,9 @@
<name>GoJara</name>
<description>ProtoXEP-xxxx: Remote Roster Management support</description>
<author>Holger Bergunde and Daniel Henninger</author>
<version>1.2.5</version>
<date>02/22/2013</date>
<author>Holger Bergunde / Daniel Henninger / Axel-F. Brand</author>
<version>2.0.0</version>
<date>03/07/2013</date>
<databaseKey>gojara</databaseKey>
<databaseVersion>0</databaseVersion>
<minServerVersion>3.7.0</minServerVersion>
......
......@@ -31,6 +31,7 @@ import org.xmpp.packet.JID;
/**
* @author Holger Bergunde
* @author axel.frederik.brand
*
* This class is the basic reprasentation for the GoJara plugin. It is
* the entry point for openfire to start or stop this plugin.
......@@ -47,8 +48,6 @@ public class RemoteRosterPlugin implements Plugin {
private static final Logger Log = LoggerFactory.getLogger(RemoteRosterPlugin.class);
private static PluginManager pluginManager;
// private final SessionManager _sessionManager = SessionManager.getInstance();
// private Map<String, AbstractInterceptorHandler> _interceptors = new HashMap<String, AbstractInterceptorHandler>();
private Set<String> _waitingForIQResponse = new HashSet<String>();
private PropertyEventListener _settingsObserver;
private MainInterceptor mainInterceptor = new MainInterceptor();
......@@ -62,7 +61,6 @@ public class RemoteRosterPlugin implements Plugin {
manageExternalComponents();
listenToSettings();
Log.debug("Started Gojara successfully. Currently running interceptors: "+iManager.getInterceptors().size());
}
/*
......@@ -134,9 +132,7 @@ public class RemoteRosterPlugin implements Plugin {
}
public void destroyPlugin() {
// for (String key : _interceptors.keySet()) {
// _interceptors.get(key).stop();
// }
mainInterceptor.freeze();
iManager.removeInterceptor(mainInterceptor);
PropertyEventDispatcher.removeListener(_settingsObserver);
......@@ -147,14 +143,8 @@ public class RemoteRosterPlugin implements Plugin {
private void updateInterceptors(String componentJID) {
boolean allowed = JiveGlobals.getBooleanProperty("plugin.remoteroster.jids." + componentJID, false);
if (allowed) {
// if (!_interceptors.containsKey(componentJID)) {
// createNewPackageIntercetor(componentJID);
// }
mainInterceptor.addTransport(componentJID);
} else {
// if (_interceptors.containsKey(componentJID)) {
// removeInterceptor(componentJID);
// }
mainInterceptor.removeTransport(componentJID);
}
}
......@@ -168,25 +158,4 @@ public class RemoteRosterPlugin implements Plugin {
return pluginManager;
}
// private void removeInterceptor(String initialSubdomain) {
// mainInterceptor.removeTransport(initialSubdomain);
//// AbstractInterceptorHandler interceptor = _interceptors.get(initialSubdomain);
//// if (interceptor != null) {
//// _interceptors.remove(initialSubdomain);
//// interceptor.stop();
//// }
// }
//
// /*
// * We are handling all our gateways in a Map with subdomain, like
// * icq.myserver.com, to ensure that there is only one interceptor for a
// * specified gateway
// */
// private void createNewPackageIntercetor(String initialSubdomain) {
// mainInterceptor.addTransport(initialSubdomain);
//// AbstractInterceptorHandler interceptor = new GatewayInterceptorHandler(initialSubdomain);
//// _interceptors.put(initialSubdomain, interceptor);
//// interceptor.start();
// }
}
......@@ -24,22 +24,18 @@ public class MainInterceptor implements PacketInterceptor {
private Set<String> activeTransports = new ConcurrentHashSet<String>();
private Map<String, AbstractRemoteRosterProcessor> packetProcessors = new HashMap<String, AbstractRemoteRosterProcessor>();
private String serverDomain;
private Boolean frozen;
public MainInterceptor() {
Log.debug("Started MainInterceptor for GoJara Plugin.");
XMPPServer server = XMPPServer.getInstance();
serverDomain = server.getServerInfo().getXMPPDomain();
//Now we need to add the PacketProcessors.
RosterManager rosterMananger = server.getRosterManager();
AbstractRemoteRosterProcessor updateToComponent = new ClientToComponentUpdateProcessor();
AbstractRemoteRosterProcessor iqRegistered = new DiscoIQRegisteredProcessor();
AbstractRemoteRosterProcessor iqRosterPayload = new IQRosterPayloadProcessor(rosterMananger);
AbstractRemoteRosterProcessor nonPersistant = new NonPersistantRosterProcessor(rosterMananger);
// Check if we need rostermanager for these....
AbstractRemoteRosterProcessor statisticsProcessor = new StatisticsProcessor();
AbstractRemoteRosterProcessor iqLastProcessor = new IQLastProcessor();
AbstractRemoteRosterProcessor whitelistProcessor = new WhitelistProcessor();
......@@ -79,7 +75,6 @@ public class MainInterceptor implements PacketInterceptor {
As our Set of Subdomains is a Hash of Strings like icq.domain.tld, if we
want to check if a jid CONTAINS a watched subdomain we need to iterate over the set.
We also return the subdomain as a string so we can use it if we find it.
*
*/
private String searchJIDforSubdomain(String jid) {
for (String subdomain : activeTransports) {
......@@ -113,48 +108,49 @@ public class MainInterceptor implements PacketInterceptor {
from = (packet.getFrom() != null) ? packet.getFrom().toString() : "";
to = (packet.getTo() != null) ? packet.getTo().toString() : "";
} catch (IllegalArgumentException e) {
Log.warn("There was an illegal JID while intercepting Message for GoJara! "+e.getMessage());
Log.warn("There was an illegal JID while intercepting Message for GoJara. Not Intercepting it! "+e.getMessage());
return;
}
//We dont want this to get too packed, so here we test only for stuff we can test on PACKET
//We dont want this to get too packed, so here we test only for stuff we can test on PACKET + Instanceof
if (incoming && processed) {
Log.debug("Incoming processed Package i might be interested in. I'm "+ this.hashCode() + "\n Package: \n " + packet.toString() + "\n");
//if to is Empty, this might be a Client to Component Update we have to forward.
if (to.isEmpty())
packetProcessors.get("clientToComponentUpdate").process(packet, generateSubdomainString());
//This might be a Disco IQ from the SERVER itself, so we have to check for Acess-Restriction
packetProcessors.get("clientToComponentUpdate").process(packet, generateSubdomainString(), to, from);
//if to is equal to a subdomain of a INCOMING package we need to check if its for registering
else if (activeTransports.contains(to) && packet instanceof IQ)
packetProcessors.get("sparkIQRegistered").process(packet,to);
//If FROM EQUALS a watched subdomain, we test for IQ:ROSTER Payload, we test for "" again as we cant be sure from is not empty
packetProcessors.get("sparkIQRegistered").process(packet,to, to, from);
//If from EQUALS the subdomain, this is likely a RosterPush or Presence we have to react to.
else if (!from.isEmpty() && activeTransports.contains(from)) {
//If from EQUALS the subdomain, this is likely a RosterPush or Presence we have to react to.
if (packet instanceof IQ)
packetProcessors.get("iqRosterPayload").process(packet,from);
packetProcessors.get("iqRosterPayload").process(packet,from, to, from);
//it could also be a presence from Transport, so we test for Non-Persistancy
else if (!JiveGlobals.getBooleanProperty("plugin.remoteroster.persistent", false) && (packet instanceof Presence))
packetProcessors.get("handleNonPersistant").process(packet,from);
else if (packet instanceof Presence && !JiveGlobals.getBooleanProperty("plugin.remoteroster.persistent", false))
packetProcessors.get("handleNonPersistant").process(packet,from, to, from);
}
//Functionality Processors for this Case are Done, now Logging. We need to be sure its not
//The Ping Spectrum send itself, and one of from or to contains a watched subdomain.
String from_s = searchJIDforSubdomain(from);
String to_s = searchJIDforSubdomain(to);
String subdomain = from_s.isEmpty() ? to_s : from_s;
if (!from.equals(to) && !subdomain.isEmpty())
packetProcessors.get("statisticsProcessor").process(packet,subdomain);
if (!from.equals(to) && !subdomain.isEmpty() && !(from.isEmpty() && to.isEmpty()) && packet instanceof IQ)
packetProcessors.get("statisticsProcessor").process(packet,subdomain, to, from);
}
else if (incoming && !processed) {
else if (incoming && !processed && JiveGlobals.getBooleanProperty("plugin.remoteroster.iqLastFilter", false)) {
Log.debug("Incoming unprocessed Package i might be interested in. I'm "+ this.hashCode() + "\n Package: \n " + packet.toString() + "\n");
// if to is EQUAL to the subdomain or a string containing a subdomain
String to_s = searchJIDforSubdomain(to);
if (!to_s.isEmpty())
packetProcessors.get("iqLastProcessor").process(packet,to_s);
String subdomain = searchJIDforSubdomain(to);
if (!subdomain.isEmpty() && packet instanceof IQ)
packetProcessors.get("iqLastProcessor").process(packet,subdomain, to, from);
}
else if(!incoming && processed) {
Log.debug("Outgoing processed Package i might be interested in. I'm "+ this.hashCode() + "\n Package: \n " + packet.toString() + "\n");
if (from.isEmpty() || from.equals(serverDomain))
packetProcessors.get("whiteListProcessor").process(packet);
Log.debug("Outgoing processed Package i might be interested in. I'm "+ this.hashCode() + " Package: \n " + packet.toString() + "\n");
if ((from.isEmpty() || from.equals(serverDomain)) && packet instanceof IQ)
//This might be a Disco IQ from the SERVER itself, so we have to check for Acess-Restriction
packetProcessors.get("whiteListProcessor").process(packet, generateSubdomainString(), to, from);
//If we want the StatisticsProcessor to diff between Outgoing and Incoming, it would go here
}
}
......
package org.jivesoftware.openfire.plugin.gojara.messagefilter.interceptors;
import java.util.List;
import org.dom4j.Element;
import org.dom4j.Node;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.interceptor.PacketInterceptor;
import org.jivesoftware.openfire.interceptor.PacketRejectedException;
import org.jivesoftware.openfire.plugin.gojara.permissions.PermissionManager;
import org.jivesoftware.openfire.plugin.gojara.utils.XpathHelper;
import org.jivesoftware.openfire.session.Session;
import org.xmpp.packet.IQ;
import org.xmpp.packet.Packet;
/**
*
* If the access to external components or gateways is limited to a special
* group in GoJara settings we have to filter the disco#infos from the server to
* the client. If the user is not on the list we are hiding the specified info
* and remove the item containing the gateways subdomain
*
* @author Holger Bergunde
*
*/
public class DiscoPackageInterceptorHandler implements PacketInterceptor {
private PermissionManager _permissions;
private String _subDomain;
private String _host;
public DiscoPackageInterceptorHandler(String subdomain) {
_permissions = new PermissionManager();
_subDomain = subdomain;
XMPPServer server = XMPPServer.getInstance();
_host = server.getServerInfo().getHostname();
}
@Override
public void interceptPacket(Packet packet, Session session, boolean incoming, boolean processed)
throws PacketRejectedException {
if (_permissions.isGatewayLimited(_subDomain)) {
if (packet instanceof IQ) {
IQ iqpacket = (IQ) packet;
Element root = iqpacket.getChildElement();
if (root == null)
return;
String ns = root.getNamespaceURI();
if (ns.equals("http://jabber.org/protocol/disco#items") && iqpacket.getType().equals(IQ.Type.result)) {
if (!_permissions.allowedForUser(_subDomain, iqpacket.getTo())) {
if (iqpacket.getFrom().toString().equals(_host)) {
List<Node> nodes = XpathHelper.findNodesInDocument(root.getDocument(), "//discoitems:item");
for (Node node : nodes) {
if (node.valueOf("@jid").equals(_subDomain)) {
root.remove(node);
}
}
}
}
}
}
}
}
}
package org.jivesoftware.openfire.plugin.gojara.messagefilter.interceptors;
import org.dom4j.Element;
import org.dom4j.tree.DefaultElement;
import org.jivesoftware.openfire.PacketRouter;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.interceptor.PacketInterceptor;
import org.jivesoftware.openfire.interceptor.PacketRejectedException;
import org.jivesoftware.openfire.session.Session;
import org.jivesoftware.util.JiveGlobals;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmpp.packet.IQ;
import org.xmpp.packet.Packet;
/**
*
* Some clients try to check how long a contact is already offline. This feature
* is not supported by spectrum so it won't response to this IQ stanza. To
* prevent the client from waiting for a response we could answer with a
* service-unavailable message as described in XEP-12.
*
* @author Holger Bergunde
*
*/
public class IQLastInterceptor implements PacketInterceptor {
private String _subDomain;
protected static final Logger Log = LoggerFactory.getLogger(IQLastInterceptor.class);
public IQLastInterceptor(String subdomain) {
Log.debug("Createt IQLastInterceptor for " + subdomain);
_subDomain = subdomain;
}
@Override
public void interceptPacket(Packet packet, Session session, boolean incoming, boolean processed)
throws PacketRejectedException {
if (!iqLastInterceptorEnabled()) {
Log.debug("Auto repsonse to jabber:iq:last is deactivated. You could enabled it using the webinterface ");
return;
}
if (packet instanceof IQ && incoming && processed) {
IQ iqpacket = (IQ) packet;
if (iqpacket.getTo() == null || !iqpacket.getTo().toString().contains(_subDomain))
return;
Element root = iqpacket.getChildElement();
if (root == null)
return;
String ns = root.getNamespaceURI();
if (ns.equals("jabber:iq:last") && iqpacket.getType().equals(IQ.Type.get)) {
IQ answer = new IQ();
answer.setType(IQ.Type.error);
answer.setFrom(iqpacket.getTo());
answer.setTo(iqpacket.getFrom());
answer.setID(iqpacket.getID());
DefaultElement errorElement = new DefaultElement("error");
errorElement.addAttribute("type", "cancel");
errorElement.addAttribute("code", "503");
DefaultElement serviceElement = new DefaultElement("service-unavailable");
serviceElement.addNamespace("", "urn:ietf:params:xml:ns:xmpp-stanzas");
errorElement.add(serviceElement);
answer.setChildElement(errorElement);
Log.debug("Auto response to jabber:iq:last for " + _subDomain);
PacketRouter router = XMPPServer.getInstance().getPacketRouter();
router.route(answer);
}
}
}
private boolean iqLastInterceptorEnabled() {
return JiveGlobals.getBooleanProperty("plugin.remoteroster.iqLastFilter", false);
}
}
......@@ -7,7 +7,6 @@ import org.dom4j.Node;
import org.jivesoftware.openfire.PacketRouter;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.interceptor.PacketRejectedException;
import org.jivesoftware.openfire.plugin.gojara.messagefilter.remoteroster.RemoteRosterInterceptor;
import org.jivesoftware.openfire.plugin.gojara.utils.XpathHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
......@@ -20,6 +19,7 @@ import org.xmpp.packet.Packet;
* this processor and redirect packages according to their functionality
*
* @author Holger Bergunde
* @author axel.frederik.brand
*
*/
abstract public class AbstractRemoteRosterProcessor {
......@@ -35,18 +35,19 @@ abstract public class AbstractRemoteRosterProcessor {
/**
* Handles the passed packet. Might throw {@link PacketRejectedException} if
* the package should not be processed by openfire
*
* @param packet
* the package should not be processed by openfire.
* See actual classes for info about their implementation.
* @param packet Packet itself
* @param subdomain String with subdomain contained in either from or to, or string with several watched subdomains that needs to be splitted (see Maininterceptor)
* @param to String with recipient of packet, may be ""
* @param from String with sender of packet, may be ""
* @throws PacketRejectedException
*/
abstract public void process(Packet packet,String subdomain) throws PacketRejectedException;
abstract public void process(Packet packet,String subdomain, String to, String from) throws PacketRejectedException;
/**
* Use this method if you want to send your own packets through openfire
*
* @param packet
* packet to send
* @param packet packet to send
*/
protected void dispatchPacket(Packet packet) {
Log.debug("Sending package to PacketRouter: \n" + packet.toString() + "\n");
......
......@@ -3,7 +3,6 @@ package org.jivesoftware.openfire.plugin.gojara.messagefilter.processors;
import org.dom4j.Element;
import org.dom4j.Node;
import org.jivesoftware.openfire.interceptor.PacketRejectedException;
import org.jivesoftware.openfire.plugin.gojara.messagefilter.remoteroster.RemoteRosterInterceptor;
import org.xmpp.packet.IQ;
import org.xmpp.packet.Packet;
......@@ -17,9 +16,9 @@ import org.xmpp.packet.Packet;
* >Here</a>
*
* @author Holger Bergunde
* // Our Query is now a <item jid="Example@subdomain" name="contact"><group></item>iq id="FSwIU-68" type="set" from="axel.brand@lxhamrztst02.ger.win.int.kn/Spark 2.7.0 #272">
<iq id="FSwIU-68" type="set" from="user@example/resource">
// <query xmlns="jabber:iq:roster">
// <item jid="129443529@icq.lxhamrztst02.ger.win.int.kn" name="wulschti" subscription="both">
// <item jid="123456789@subdomain" name="wulschti" subscription="both">
// <group>General</group>
// </item>
// </query>
......@@ -38,15 +37,17 @@ public class ClientToComponentUpdateProcessor extends AbstractRemoteRosterProces
}
return "";
}
@Override
public void process(Packet packet, String subdomain) throws PacketRejectedException {
public void process(Packet packet, String subdomain, String to, String from) throws PacketRejectedException {
Log.debug("Processing packet in ClientToComponentUpdateProcessor");
Element query = ((IQ) packet).getChildElement();
if (query != null && query.getNamespaceURI().equals("jabber:iq:roster")) {
if (findNodesInDocument(query.getDocument(), "//roster:item").size() > 0) {
// We now know we have to check the JID of the to be added User against our valid subdomains.
String[] valid_subdomains = subdomain.split("#");
String[] valid_subdomains = subdomain.split("[#]");
for (Node n : findNodesInDocument(query.getDocument(), "//roster:item")) {
String jid = n.valueOf("@jid");
// TODO: We ignore remove iq packets for now. There might be
......@@ -54,6 +55,7 @@ public class ClientToComponentUpdateProcessor extends AbstractRemoteRosterProces
// when we remove our legacy network registration.
String found_subdomain = searchJIDforSubdomain(valid_subdomains, jid);
if (!found_subdomain.isEmpty() && !n.valueOf("@subscription").equals("remove")) {
Log.debug("Mirroring packet from local network to legacy component " + found_subdomain);
IQ forward = (IQ) packet.createCopy();
forward.setTo(found_subdomain);
......
......@@ -10,7 +10,6 @@ import org.dom4j.tree.DefaultElement;
import org.jivesoftware.openfire.interceptor.InterceptorManager;
import org.jivesoftware.openfire.interceptor.PacketInterceptor;
import org.jivesoftware.openfire.interceptor.PacketRejectedException;
import org.jivesoftware.openfire.plugin.gojara.messagefilter.remoteroster.RemoteRosterInterceptor;
import org.jivesoftware.openfire.session.Session;
import org.jivesoftware.util.JiveGlobals;
import org.xmpp.packet.IQ;
......@@ -34,7 +33,7 @@ public class DiscoIQRegisteredProcessor extends AbstractRemoteRosterProcessor {
}
@Override
public void process(Packet packet, final String subdomain) throws PacketRejectedException {
public void process(Packet packet, final String subdomain, String to, String from) throws PacketRejectedException {
Log.debug("Processing packet in DiscoIQRegisteredProcessor for " + subdomain);
// Check if the jabber:iq:register is enabled in admin panel
boolean isFeatureEnabled = JiveGlobals.getBooleanProperty("plugin.remoteroster.sparkDiscoInfo", false);
......@@ -43,8 +42,6 @@ public class DiscoIQRegisteredProcessor extends AbstractRemoteRosterProcessor {
return;
}
String from = packet.getFrom().toString();
String to = packet.getTo().toString();
final InterceptorManager interceptorManager = InterceptorManager.getInstance();
final PacketInterceptor interceptor = new PacketInterceptor() {
......
package org.jivesoftware.openfire.plugin.gojara.messagefilter.processors;
import org.dom4j.Element;
import org.dom4j.tree.DefaultElement;
import org.jivesoftware.openfire.PacketRouter;
import org.jivesoftware.openfire.interceptor.PacketRejectedException;
import org.xmpp.packet.IQ;
import org.xmpp.packet.Packet;
/**
*
* Some clients try to check how long a contact is already offline. This feature
* is not supported by spectrum so it won't response to this IQ stanza. To
* prevent the client from waiting for a response we could answer with a
* service-unavailable message as described in XEP-12.
*
* @author Holger Bergunde
* @author axel.frederik.brand
*
*/
public class IQLastProcessor extends AbstractRemoteRosterProcessor{
public IQLastProcessor() {
Log.debug("Created IQLastProcessor");
}
/**
* At this point we know:
* IQLastFilter is ACTIVATED
* Packet is incoming and NOT processed
* Packet is instance of IQ
* To contains the watched subdomain represented in String subdomain
*/
@Override
public void process(Packet packet, String subdomain, String to, String from)
throws PacketRejectedException {
IQ iqpacket = (IQ) packet;
Element root = iqpacket.getChildElement();
if (root == null)
return;
String ns = root.getNamespaceURI();
if (ns.equals("jabber:iq:last") && iqpacket.getType().equals(IQ.Type.get)) {
Log.debug("Processing IQLast Packet for " + subdomain);
IQ answer = IQ.createResultIQ(iqpacket);
answer.setType(IQ.Type.error);
DefaultElement errorElement = new DefaultElement("error");
errorElement.addAttribute("type", "cancel");
errorElement.addAttribute("code", "503");
DefaultElement serviceElement = new DefaultElement("service-unavailable");
serviceElement.addNamespace("", "urn:ietf:params:xml:ns:xmpp-stanzas");
errorElement.add(serviceElement);
answer.setChildElement(errorElement);
Log.debug("Auto response to jabber:iq:last for " + subdomain);
PacketRouter router = _server.getPacketRouter();
router.route(answer);
//There is no need for the Server to process this Package if S2 doesn't support it.
throw new PacketRejectedException();
}
}
}
package org.jivesoftware.openfire.plugin.gojara.messagefilter.processors;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.tree.DefaultAttribute;
import org.dom4j.tree.DefaultElement;
import org.jivesoftware.openfire.SharedGroupException;
import org.jivesoftware.openfire.interceptor.PacketRejectedException;
import org.jivesoftware.openfire.plugin.gojara.messagefilter.remoteroster.RemoteRosterInterceptor;
import org.jivesoftware.openfire.roster.Roster;
import org.jivesoftware.openfire.roster.RosterItem;
import org.jivesoftware.openfire.roster.RosterManager;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.jivesoftware.util.JiveGlobals;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.Packet;
/**
......@@ -32,34 +36,49 @@ public class IQRosterPayloadProcessor extends AbstractRemoteRosterProcessor {
private RosterManager _rosterManager;
public IQRosterPayloadProcessor(RosterManager rosterMananger) {
Log.debug("Created SendRosterProcessor");
Log.debug("Created IQRosterPayloadProcessor");
_rosterManager = rosterMananger;
}
@Override
public void process(Packet packet, String subdomain) throws PacketRejectedException {
public void process(Packet packet, String subdomain, String to, String from) throws PacketRejectedException {
Log.debug("Processing packet in SendRosterProcessor for " + subdomain);
IQ myPacket = (IQ) packet;
Element query = myPacket.getChildElement();
String username = getUsernameFromJid(to);
if (query != null && query.getNamespaceURI().equals("jabber:iq:roster")) {
if (myPacket.getType().equals(IQ.Type.get)) {
handleIQget(myPacket,subdomain,username);
}
else if (myPacket.getType().equals(IQ.Type.set)) {
handleIQset(myPacket,subdomain,username);
}
}
}
String user = myPacket.getTo().toString();
String username = getUsernameFromJid(user);
Roster roster;
private void handleIQget(IQ myPacket, String subdomain, String username){
if(JiveGlobals.getBooleanProperty("plugin.remoteroster.persistent", false)){
Roster roster;
try {
roster = _rosterManager.getRoster(username);
Collection<RosterItem> items = roster.getRosterItems();
Log.debug("Sending contacts with subdomain " + subdomain + " from user " +username + " to external Component");
sendRosterToComponent(myPacket, items, subdomain);
} catch (UserNotFoundException e) {
e.printStackTrace();
}
} else {
Log.debug("Sending nonpersistant-RemoteRosterResponse to external Component for User: " + username);
sendEmptyRoster(myPacket, subdomain);
}
}
}
private void sendRosterToComponent(IQ requestPacket, Collection<RosterItem> items, String subdomain) {
Log.debug("Sending contacts from user " + requestPacket.getFrom().toString() + " to external Component");
IQ response = IQ.createResultIQ(requestPacket);
response.setTo(subdomain);
Element query = new DefaultElement("query");
......@@ -80,13 +99,12 @@ public class IQRosterPayloadProcessor extends AbstractRemoteRosterProcessor {
}
}
query.addNamespace("", "jabber:iq:roster");
response.setChildElement(query);
dispatchPacket(response);
}
private void sendEmptyRoster(Packet requestPacket, String subdomain){
Log.debug("Sending nonpersistant-RemoteRosterResponse to external Component");
IQ iq = (IQ) requestPacket;
IQ response = IQ.createResultIQ(iq);
response.setTo(subdomain);
......@@ -95,5 +113,63 @@ public class IQRosterPayloadProcessor extends AbstractRemoteRosterProcessor {
response.setChildElement(query);
dispatchPacket(response);
}
private void handleIQset(IQ myPacket, String subdomain, String username) {
IQ response = IQ.createResultIQ(myPacket);
List<Node> nodes = findNodesInDocument(myPacket.getElement().getDocument(), "//roster:item");
for (Node n : nodes) {
Roster roster;
String jid = n.valueOf("@jid");
String name = n.valueOf("@name");
String subvalue = n.valueOf("@subscription");
//We dont want to add or delete the subdomain itself
if (jid.equals(subdomain))
continue;
if(subvalue.equals("both")){
try {
roster = _rosterManager.getRoster(username);
List<String> grouplist = new ArrayList<String>();
List<Node> groupnodes = findNodesInDocument(n.getDocument(), "//roster:group");
for (Node ne : groupnodes) {
String groupName = ne.getText();
grouplist.add(groupName);
}
boolean rosterPersistent = JiveGlobals.getBooleanProperty("plugin.remoteroster.persistent", true);
Log.debug("Adding/Updating Contact " + jid + " to roster of" + username);
try {
RosterItem item = roster.getRosterItem(new JID(jid));
item.setGroups(grouplist);
roster.updateRosterItem(item);
//dont send iq-result if just updating user
continue;
} catch (UserNotFoundException exc) {
//Then we should add him!
}
RosterItem item = roster.createRosterItem(new JID(jid), name, grouplist, false, rosterPersistent);
item.setSubStatus(RosterItem.SUB_BOTH);
roster.updateRosterItem(item);
} catch (Exception e) {
Log.debug("Could not add user to Roster although no entry should exist..." + username, e);
e.printStackTrace();
}
} else if (subvalue.equals("remove")){
try {
roster = _rosterManager.getRoster(username);
roster.deleteRosterItem(new JID(jid), false);
Log.debug("Removed contact " + jid + " from contact list of " + username);
} catch (UserNotFoundException e) {
Log.debug("Could not find user while cleaning up the roster in GoJara for user " + username, e);
response.setType(IQ.Type.error);
} catch (SharedGroupException e) {
// We should ignore this. External contacts cannot be in
// shared groups
}
}
dispatchPacket(response);
}
}
}
package org.jivesoftware.openfire.plugin.gojara.messagefilter.remoteroster.processors;
package org.jivesoftware.openfire.plugin.gojara.messagefilter.processors;
import java.util.Collection;
import org.jivesoftware.openfire.interceptor.PacketRejectedException;
import org.jivesoftware.openfire.plugin.gojara.messagefilter.processors.AbstractRemoteRosterProcessor;
import org.jivesoftware.openfire.plugin.gojara.messagefilter.remoteroster.RemoteRosterInterceptor;
import org.jivesoftware.openfire.roster.Roster;
import org.jivesoftware.openfire.roster.RosterItem;
import org.jivesoftware.openfire.roster.RosterManager;
......@@ -12,34 +10,29 @@ import org.xmpp.packet.Packet;
import org.xmpp.packet.Presence;
/**
* This class is a part of the command pattern used in
* {@link RemoteRosterInterceptor}. If the remote contacts should not be
* saved permanently in the users Roster, this command will delete
* contacts to the corresponding Transport upon receiving unavailable presence
* from transport. This way the Users Roster will not get modified by the automated
* unsubscribe presences triggered by deleting RosterItem in OF-Roster
*
* When this Processor gets called, it deletes all Contacts of a given User that contain a specific subdomain.
* We use this to clean up all Contacts of a Users Gateway registration as soon as he logs out. In this case
* the Transport sends a Unavailable Presence without subtext "Connecting" to the user.
* @author Holger Bergunde
* @author axel.frederik.brand
*
*/
public class NonPersistantRosterProcessor extends AbstractRemoteRosterProcessor {
private RosterManager _rosterManager;
// private String _subDomain;
public NonPersistantRosterProcessor(RosterManager rostermananger) {
Log.debug("Created NonPersistantProcessor");
_rosterManager = rostermananger;
// _subDomain = subdomain;
}
@Override
public void process(Packet packet, String subdomain) throws PacketRejectedException {
Log.debug("Processing packet in NonPersistantRosterProcessor for " + subdomain);
public void process(Packet packet, String subdomain, String to, String from) throws PacketRejectedException {
Presence myPacket = (Presence) packet;
String to = myPacket.getTo().toString();
String username = getUsernameFromJid(to);
if (myPacket.getType() != null && myPacket.getType().equals(Presence.Type.unavailable)) {
if (myPacket.getType() != null && myPacket.getType().equals(Presence.Type.unavailable) && !myPacket.getElement().getStringValue().equals("Connecting")) {
String username = getUsernameFromJid(to);
Log.debug("Processing packet in NonPersistantRosterProcessor for " + subdomain + "and user " + username);
try {
Roster roster = _rosterManager.getRoster(username);
Collection<RosterItem> items = roster.getRosterItems();
......@@ -50,12 +43,12 @@ public class NonPersistantRosterProcessor extends AbstractRemoteRosterProcessor
roster.deleteRosterItem(item.getJid(), false);
}
}
} catch (Exception e) {
Log.debug("Execption occured when cleaning up the Roster.", e);
e.printStackTrace();
}
}
}
}
package org.jivesoftware.openfire.plugin.gojara.messagefilter.interceptors;
package org.jivesoftware.openfire.plugin.gojara.messagefilter.processors;
import org.jivesoftware.openfire.interceptor.PacketInterceptor;
import org.jivesoftware.openfire.interceptor.PacketRejectedException;
import org.jivesoftware.openfire.plugin.gojara.database.DatabaseManager;
import org.jivesoftware.openfire.session.Session;
import org.xmpp.packet.JID;
import org.xmpp.packet.Packet;
/**
......@@ -14,36 +11,32 @@ import org.xmpp.packet.Packet;
* (configurable) minutes.
*
* @author Holger Bergunde
*
* @author axel.frederik.brand
*/
public class StatisticPackageInterceptor implements PacketInterceptor {
public class StatisticsProcessor extends AbstractRemoteRosterProcessor{
private String _subdomain;
private DatabaseManager _db;
public StatisticPackageInterceptor(String subdomain) {
_subdomain = subdomain;
public StatisticsProcessor() {
Log.debug("Created StatisticsProcessor");
_db = DatabaseManager.getInstance();
}
/**
* At this Point we Already know:
* neither of both JIDS is malformed (Package wouldn't have been intercepted)
* Package is incoming & processed
* Either From or To contains the watched,passed subdomain
* From does not Equal To (This way we exclude PING sent by spectrum To spectrum
* From AND To are NOT empty (null), this way we exclude packets sent to server itself...change Maininterceptor if we want to change this
*
*/
@Override
public void interceptPacket(Packet packet, Session session, boolean incoming, boolean processed)
public void process(Packet packet, String subdomain, String to, String from)
throws PacketRejectedException {
JID from = packet.getFrom();
JID to = packet.getTo();
if (from != null && to != null && processed && incoming) {
if (from.toString().contains(_subdomain) || to.toString().contains(_subdomain)) {
/*
* Spectrum sends a Ping to itself through the server to check
* if the server is alive. We ignore that for statistics
*/
if (to.toString().equals(from.toString()) && to.toString().equals(_subdomain))
return;
String type = packet.getClass().getName();
_db.addNewLogEntry(_subdomain, type, from.toString(), to.toString());
}
}
String type = packet.getClass().getName();
_db.addNewLogEntry(subdomain, type, from, to);
}
}
package org.jivesoftware.openfire.plugin.gojara.messagefilter.remoteroster.processors;
package org.jivesoftware.openfire.plugin.gojara.messagefilter.processors;
import java.util.List;
import org.dom4j.Element;
import org.dom4j.Node;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.interceptor.PacketInterceptor;
import org.jivesoftware.openfire.interceptor.PacketRejectedException;
import org.jivesoftware.openfire.plugin.gojara.messagefilter.processors.AbstractRemoteRosterProcessor;
import org.jivesoftware.openfire.plugin.gojara.messagefilter.remoteroster.RemoteRosterInterceptor;
import org.jivesoftware.openfire.plugin.gojara.permissions.PermissionManager;
import org.jivesoftware.openfire.plugin.gojara.utils.XpathHelper;
import org.jivesoftware.openfire.session.Session;
import org.xmpp.packet.IQ;
import org.xmpp.packet.Packet;
......@@ -23,29 +18,45 @@ import org.xmpp.packet.Packet;
* and remove the item containing the gateways subdomain
*
* @author Holger Bergunde
*
* @author axel.frederik.brand
*/
public class DiscoPackageProcessor extends AbstractRemoteRosterProcessor{
public class WhitelistProcessor extends AbstractRemoteRosterProcessor{
private PermissionManager _permissions;
public DiscoPackageProcessor() {
public WhitelistProcessor() {
_permissions = new PermissionManager();
Log.debug("Created WhitelistProcessor");
}
/**
* At this point we already know:
* Package is NOT incoming
* Package is processed
* From is either Empty (it was null) or equals the serverDomain.
* Package is a IQ
*
* @param subdomain A String containing several watched subdomains separated by [#]
*/
@Override
public void process (Packet packet, String subdomain) throws PacketRejectedException {
if (_permissions.isGatewayLimited(subdomain)) {
IQ iqpacket = (IQ) packet;
Element root = iqpacket.getChildElement();
if (root == null)
return;
String ns = root.getNamespaceURI();
if (ns.equals("http://jabber.org/protocol/disco#items") && iqpacket.getType().equals(IQ.Type.result)) {
if (!_permissions.allowedForUser(subdomain, iqpacket.getTo())) {
public void process (Packet packet, String subdomain, String to, String from) throws PacketRejectedException {
IQ myPacket = (IQ) packet;
Element root = myPacket.getChildElement();
if (root == null)
return;
String ns = root.getNamespaceURI();
if (ns.equals("http://jabber.org/protocol/disco#items") && myPacket.getType().equals(IQ.Type.result)) {
Log.debug("Processing packet in Whitelistprocessor for " + to);
//As some users can be allowed to use only specific Gateways, we have to do this for every subdomain separately
String[] valid_subdomains = subdomain.split("[#]");
for (String single_subdomain : valid_subdomains) {
if (_permissions.isGatewayLimited(single_subdomain) && !_permissions.allowedForUser(single_subdomain, myPacket.getTo())) {
List<Node> nodes = XpathHelper.findNodesInDocument(root.getDocument(), "//discoitems:item");
for (Node node : nodes) {
if (node.valueOf("@jid").equals(subdomain)) {
if (node.valueOf("@jid").equals(single_subdomain)) {
root.remove(node);
}
}
......@@ -53,5 +64,6 @@ public class DiscoPackageProcessor extends AbstractRemoteRosterProcessor{
}
}
}
}
package org.jivesoftware.openfire.plugin.gojara.messagefilter.remoteroster;
import java.util.HashMap;
import java.util.Map;
import org.jivesoftware.openfire.XMPPServer;
import org.jivesoftware.openfire.interceptor.PacketInterceptor;
import org.jivesoftware.openfire.interceptor.PacketRejectedException;
import org.jivesoftware.openfire.plugin.gojara.database.DatabaseManager;
import org.jivesoftware.openfire.plugin.gojara.messagefilter.processors.AbstractRemoteRosterProcessor;
import org.jivesoftware.openfire.plugin.gojara.messagefilter.processors.ClientToComponentUpdateProcessor;
import org.jivesoftware.openfire.plugin.gojara.messagefilter.processors.DiscoIQRegisteredProcessor;
import org.jivesoftware.openfire.plugin.gojara.messagefilter.processors.IQRosterPayloadProcessor;
import org.jivesoftware.openfire.plugin.gojara.messagefilter.remoteroster.processors.*;
import org.jivesoftware.openfire.plugin.gojara.utils.XpathHelper;
import org.jivesoftware.openfire.roster.RosterManager;
import org.jivesoftware.openfire.session.Session;
import org.jivesoftware.util.JiveGlobals;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xmpp.packet.IQ;
import org.xmpp.packet.Packet;
import org.xmpp.packet.Presence;
/**
* This intercepter handles the main functionality described in the XEP-xxx
* Remote Roster Management standard. <a
* href="http://jkaluza.fedorapeople.org/remote-roster.html">XEP-xxx</a>
*
* It must be registered as an PacketInterceptor for each gateway. It will check
* the incoming packages for several preconditions and redirects the packages
* using a command pattern to individual packet handles.
*
* @author Holger Bergunde
*
*/
public class RemoteRosterInterceptor {
private static final Logger Log = LoggerFactory
.getLogger(RemoteRosterInterceptor.class);
// private String _mySubdomain;
private Map<String, AbstractRemoteRosterProcessor> _packetProcessor = new HashMap<String, AbstractRemoteRosterProcessor>();
private DatabaseManager _db;
private String _host;
public RemoteRosterInterceptor(String initialSubdomain) {
_db = DatabaseManager.getInstance();
Log.debug("Starting Package Interceptor for " + initialSubdomain);
XMPPServer server = XMPPServer.getInstance();
RosterManager rosterMananger = server.getRosterManager();
AbstractRemoteRosterProcessor sendroster = new IQRosterPayloadProcessor(
rosterMananger);
AbstractRemoteRosterProcessor receiveChanges = new ReceiveComponentUpdatesProcessor(rosterMananger);
AbstractRemoteRosterProcessor iqRegistered = new DiscoIQRegisteredProcessor();
AbstractRemoteRosterProcessor nonPersistant = new NonPersistantRosterProcessor(
rosterMananger);
AbstractRemoteRosterProcessor updateToComponent = new ClientToComponentUpdateProcessor();
_packetProcessor.put("sendRoster", sendroster);
_packetProcessor.put("receiveChanges", receiveChanges);
_packetProcessor.put("sparkIQRegistered", iqRegistered);
_packetProcessor.put("handleNonPersistant", nonPersistant);
_packetProcessor.put("clientToComponentUpdate", updateToComponent);
}
public RemoteRosterInterceptor() {
_db = DatabaseManager.getInstance();
Log.debug("Starting RemoteRosterInterceptor - BINGO");
XMPPServer server = XMPPServer.getInstance();
RosterManager rosterMananger = server.getRosterManager();
AbstractRemoteRosterProcessor sendroster = new IQRosterPayloadProcessor(
rosterMananger);
AbstractRemoteRosterProcessor receiveChanges = new ReceiveComponentUpdatesProcessor(rosterMananger);
AbstractRemoteRosterProcessor iqRegistered = new DiscoIQRegisteredProcessor();
AbstractRemoteRosterProcessor nonPersistant = new NonPersistantRosterProcessor(
rosterMananger);
AbstractRemoteRosterProcessor updateToComponent = new ClientToComponentUpdateProcessor();
AbstractRemoteRosterProcessor discoPackage = new DiscoPackageProcessor();
_packetProcessor.put("sendRoster", sendroster);
_packetProcessor.put("receiveChanges", receiveChanges);
_packetProcessor.put("sparkIQRegistered", iqRegistered);
_packetProcessor.put("handleNonPersistant", nonPersistant);
_packetProcessor.put("clientToComponentUpdate", updateToComponent);
_packetProcessor.put("DiscoPackage",discoPackage);
_host = server.getServerInfo().getHostname();
}
public void interceptPacket(Packet packet, Session session,
boolean incoming, boolean processed, String subdomain)
throws PacketRejectedException {
if (!processed && incoming) {
if (packet instanceof IQ) {
Log.debug("Incoming unprocessed package i might be interested in. I am: "
+ this.hashCode()
+ " my subd: "
+ subdomain
+ " Package: \n" + packet.toString() + "\n");
IQ myPacket = (IQ) packet;
if (myPacket.getTo() == null) {
/*
* If getTo() == null this is maybe a roster update from the
* Client to the Server, check if we should mirror this
* package to external component
*/
if (myPacket.getFrom() != null
&& myPacket.getType().equals(IQ.Type.set)) {
if (XpathHelper.findNodesInDocument(
myPacket.getChildElement().getDocument(),
"//roster:item").size() > 0) {
_packetProcessor.get("clientToComponentUpdate")
.process(myPacket, subdomain);
}
}
return;
}
// String ns = root.getNamespaceURI();
// if (ns.equals("http://jabber.org/protocol/disco#items") && iqpacket.getType().equals(IQ.Type.result)){
//
// }
@SuppressWarnings("unused")
String from = myPacket.getFrom().toString();
String to = myPacket.getTo().toString();
if (from.equals(_host)){
_packetProcessor.get("DiscoPackage").process(packet,subdomain);
} else if (from.equals(subdomain)) {
if (myPacket.getType().equals(IQ.Type.get)
&& XpathHelper.findNodesInDocument(
myPacket.getElement().getDocument(),
"//roster:*").size() == 1) {
// This Package is a roster request by remote component
_packetProcessor.get("sendRoster").process(packet,
subdomain);
} else if (myPacket.getType().equals(IQ.Type.set)
&& XpathHelper.findNodesInDocument(
myPacket.getElement().getDocument(),
"//roster:item").size() >= 1) {
// Component sends roster update
_packetProcessor.get("receiveChanges").process(packet,
subdomain);
}
} else if (to.equals(subdomain)
&& myPacket.getType().equals(IQ.Type.get)
&& myPacket.toString().contains(
"http://jabber.org/protocol/disco#info")) {
/*
* modify the disco#info for spark clients if enabled in
* admin panel
*/
_packetProcessor.get("sparkIQRegistered").process(packet,
subdomain);
}
} else if (!JiveGlobals.getBooleanProperty(
"plugin.remoteroster.persistent", false)) {
if (packet instanceof Presence
&& packet.getFrom().toString().equals(subdomain)
&& !packet.getElement().getStringValue()
.equals("Connecting")) {
System.out
.println("Test for NonPersistant-Roster Cleanup!");
_packetProcessor.get("handleNonPersistant").process(packet,
subdomain);
}
}
}
}
}
// currently we dont need this, and it didnt seem to occur often anyway. Will
// test it later.
// could potentially save some traffic
// else if (packet instanceof Presence){
// String to = packet.getTo().toString();
// if (!to.equals(_mySubdomain) && to.contains(_mySubdomain)){
//
// Presence myPacket = ((Presence) packet);
// if (myPacket.getType().equals(Presence.Type.unavailable) ||
// myPacket.getType().equals(Presence.Type.probe) ||
// myPacket.getType().equals(null)){
// System.out.println("this presence would be wasted");
// throw new PacketRejectedException();
// }
// }
\ No newline at end of file
package org.jivesoftware.openfire.plugin.gojara.messagefilter.remoteroster.processors;
import java.util.Collection;
import org.jivesoftware.openfire.SharedGroupException;
import org.jivesoftware.openfire.interceptor.PacketRejectedException;
import org.jivesoftware.openfire.plugin.gojara.messagefilter.processors.AbstractRemoteRosterProcessor;
import org.jivesoftware.openfire.roster.Roster;
import org.jivesoftware.openfire.roster.RosterItem;
import org.jivesoftware.openfire.roster.RosterManager;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.xmpp.packet.IQ;
import org.xmpp.packet.Packet;
/**
*
* This class cleans up a roster from contacts if the user removes/deletes the
* gateway registration. After deleting a registration there should not be any
* gateway related contacts left
*
* @author holger.bergunde
*
*/
public class CleanUpRosterProcessor extends AbstractRemoteRosterProcessor {
private String _myDomain;
private RosterManager _rosterManager;
public CleanUpRosterProcessor(RosterManager rosterMananger, String mySubdomain) {
Log.debug("Created CleanUpRosterProcessor for " + mySubdomain);
_myDomain = mySubdomain;
_rosterManager = rosterMananger;
}
@Override
public void process(Packet packet, String subdomain) throws PacketRejectedException {
if (packet instanceof IQ) {
IQ iqPacket = (IQ) packet;
if (findNodesInDocument(iqPacket.getElement().getDocument(), "//register:remove").size() > 0) {
String username = getUsernameFromJid(packet.getFrom().toString());
Roster roster;
try {
roster = _rosterManager.getRoster(username);
Collection<RosterItem> items = roster.getRosterItems();
for (RosterItem item : items) {
String itemName = item.getJid().toString();
if (itemName.contains(_myDomain) && !itemName.equals(_myDomain)) {
Log.debug("Removing contact " + username + " from contact list.");
roster.deleteRosterItem(item.getJid(), false);
}
}
} catch (UserNotFoundException e) {
Log.debug("Could not found user while cleaning up the roster in GoJara for user " + username, e);
} catch (SharedGroupException e) {
// We should ignore this. External contacts cannot be in
// shared groups
}
}
}
}
}
\ No newline at end of file
package org.jivesoftware.openfire.plugin.gojara.messagefilter.remoteroster.processors;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.tree.DefaultElement;
import org.jivesoftware.openfire.SharedGroupException;
import org.jivesoftware.openfire.interceptor.PacketRejectedException;
import org.jivesoftware.openfire.plugin.gojara.messagefilter.processors.AbstractRemoteRosterProcessor;
import org.jivesoftware.openfire.plugin.gojara.messagefilter.remoteroster.RemoteRosterInterceptor;
import org.jivesoftware.openfire.roster.Roster;
import org.jivesoftware.openfire.roster.RosterItem;
import org.jivesoftware.openfire.roster.RosterManager;
import org.jivesoftware.openfire.user.UserNotFoundException;
import org.jivesoftware.util.JiveGlobals;
import org.xmpp.packet.IQ;
import org.xmpp.packet.JID;
import org.xmpp.packet.Packet;
/**
*
* This class implements the XEP-xxx Remote Roster Management standard
* "2.5 Component sends roster update". Part of command pattern used in
* {@link RemoteRosterInterceptor}
*
* Further information: <a
* href="http://jkaluza.fedorapeople.org/remote-roster.html#sect-id215516"
* >Here</a>
*
* @author Holger Bergunde
*
*/
public class ReceiveComponentUpdatesProcessor extends AbstractRemoteRosterProcessor {
private RosterManager _rosterManager;
// private String _mySubdomain;
public ReceiveComponentUpdatesProcessor(RosterManager rosterManager) {
// _mySubdomain = subdomain;
Log.debug("Created ReceiveComponentUpdatesProcessor");
_rosterManager = rosterManager;
}
@Override
public void process(Packet packet, String subdomain) throws PacketRejectedException {
Log.debug("Processing packet in ClientToComponentUpdateProcessor for " + subdomain);
IQ myPacket = (IQ) packet;
IQ response = IQ.createResultIQ(myPacket);
String to = myPacket.getTo().toString();
String username = getUsernameFromJid(to);
List<Node> nodes = findNodesInDocument(myPacket.getElement().getDocument(), "//roster:item");
for (Node n : nodes) {
Roster roster;
String jid = n.valueOf("@jid");
String name = n.valueOf("@name");
String subvalue = n.valueOf("@subscription");
if(subvalue.equals("both")){
try {
if (jid.equals(myPacket.getFrom().toString())) {
// Do not add the component itself to the contact list
break;
}
roster = _rosterManager.getRoster(username);
List<String> grouplist = new ArrayList<String>();
List<Node> groupnodes = findNodesInDocument(n.getDocument(), "//roster:group");
for (Node ne : groupnodes) {
String groupName = ne.getText();
grouplist.add(groupName);
}
boolean rosterPersisten = JiveGlobals.getBooleanProperty("plugin.remoteroster.persistent", true);
Log.debug("Adding/Updating User " + jid + " to roster " + to);
try {
RosterItem item = roster.getRosterItem(new JID(jid));
item.setGroups(grouplist);
roster.updateRosterItem(item);
//dont send iq-result if just updating user
break;
} catch (UserNotFoundException exc) {
//Then we should add him!
}
RosterItem item = roster.createRosterItem(new JID(jid), name, grouplist, false, rosterPersisten);
item.setSubStatus(RosterItem.SUB_BOTH);
roster.updateRosterItem(item);
} catch (Exception e) {
Log.debug("Could not add user to Roster although no entry should exist..." + username, e);
e.printStackTrace();
}
} else if (subvalue.equals("remove")){
try {
if (jid.equals(myPacket.getFrom().toString())) {
// Do not Try to Remove component itself as its not added.
break;
}
roster = _rosterManager.getRoster(username);
roster.deleteRosterItem(new JID(jid), false);
Log.debug("Removed contact " + jid + " from contact list of " + username);
} catch (UserNotFoundException e) {
Log.debug("Could not find user while cleaning up the roster in GoJara for user " + username, e);
response.setType(IQ.Type.error);
} catch (SharedGroupException e) {
// We should ignore this. External contacts cannot be in
// shared groups
}
}
dispatchPacket(response);
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment