mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-23 06:42:05 +01:00
SMACK-403 Pulling this contribution until the related specs reach a draft status
git-svn-id: http://svn.igniterealtime.org/svn/repos/smack/branches/smack_3_3_0@13611 b35dd754-fafc-0310-a699-88a17e54d16e
This commit is contained in:
parent
3a4b05ac00
commit
9f0f676151
3 changed files with 0 additions and 477 deletions
|
@ -1,139 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright 2013 Georg Lukas
|
|
||||||
*
|
|
||||||
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jivesoftware.smackx.carbons;
|
|
||||||
|
|
||||||
import org.jivesoftware.smack.packet.Packet;
|
|
||||||
import org.jivesoftware.smack.packet.PacketExtension;
|
|
||||||
import org.jivesoftware.smack.provider.PacketExtensionProvider;
|
|
||||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
|
||||||
import org.jivesoftware.smackx.forward.Forwarded;
|
|
||||||
import org.jivesoftware.smackx.packet.DelayInfo;
|
|
||||||
import org.jivesoftware.smackx.provider.DelayInfoProvider;
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Packet extension for XEP-0280: Message Carbons. This class implements
|
|
||||||
* the packet extension and a {@link PacketExtensionProvider} to parse
|
|
||||||
* message carbon copies from a packet. The extension
|
|
||||||
* <a href="http://xmpp.org/extensions/xep-0280.html">XEP-0280</a> is
|
|
||||||
* meant to synchronize a message flow to multiple presences of a user.
|
|
||||||
*
|
|
||||||
* <p>The {@link Carbon.Provider} must be registered in the
|
|
||||||
* <b>smack.properties</b> file for the elements <b>sent</b> and
|
|
||||||
* <b>received</b> with namespace <b>urn:xmpp:carbons:2</b></p> to be used.
|
|
||||||
*
|
|
||||||
* @author Georg Lukas
|
|
||||||
*/
|
|
||||||
public class Carbon implements PacketExtension {
|
|
||||||
public static final String NAMESPACE = "urn:xmpp:carbons:2";
|
|
||||||
|
|
||||||
private Direction dir;
|
|
||||||
private Forwarded fwd;
|
|
||||||
|
|
||||||
public Carbon(Direction dir, Forwarded fwd) {
|
|
||||||
this.dir = dir;
|
|
||||||
this.fwd = fwd;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get the direction (sent or received) of the carbon.
|
|
||||||
*
|
|
||||||
* @return the {@link Direction} of the carbon.
|
|
||||||
*/
|
|
||||||
public Direction getDirection() {
|
|
||||||
return dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get the forwarded packet.
|
|
||||||
*
|
|
||||||
* @return the {@link Forwarded} message contained in this Carbon.
|
|
||||||
*/
|
|
||||||
public Forwarded getForwarded() {
|
|
||||||
return fwd;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getElementName() {
|
|
||||||
return dir.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getNamespace() {
|
|
||||||
return NAMESPACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toXML() {
|
|
||||||
StringBuilder buf = new StringBuilder();
|
|
||||||
buf.append("<").append(getElementName()).append(" xmlns=\"")
|
|
||||||
.append(getNamespace()).append("\">");
|
|
||||||
|
|
||||||
buf.append(fwd.toXML());
|
|
||||||
|
|
||||||
buf.append("</").append(getElementName()).append(">");
|
|
||||||
return buf.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* An enum to display the direction of a {@link Carbon} message.
|
|
||||||
*/
|
|
||||||
public static enum Direction {
|
|
||||||
received,
|
|
||||||
sent
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Provider implements PacketExtensionProvider {
|
|
||||||
|
|
||||||
public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
|
|
||||||
Direction dir = Direction.valueOf(parser.getName());
|
|
||||||
Forwarded fwd = null;
|
|
||||||
|
|
||||||
boolean done = false;
|
|
||||||
while (!done) {
|
|
||||||
int eventType = parser.next();
|
|
||||||
if (eventType == XmlPullParser.START_TAG && parser.getName().equals("forwarded")) {
|
|
||||||
fwd = (Forwarded)new Forwarded.Provider().parseExtension(parser);
|
|
||||||
}
|
|
||||||
else if (eventType == XmlPullParser.END_TAG && dir == Direction.valueOf(parser.getName()))
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
if (fwd == null)
|
|
||||||
throw new Exception("sent/received must contain exactly one <forwarded> tag");
|
|
||||||
return new Carbon(dir, fwd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Packet extension indicating that a message may not be carbon-copied.
|
|
||||||
*/
|
|
||||||
public static class Private implements PacketExtension {
|
|
||||||
public static final String ELEMENT = "private";
|
|
||||||
|
|
||||||
public String getElementName() {
|
|
||||||
return ELEMENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getNamespace() {
|
|
||||||
return Carbon.NAMESPACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String toXML() {
|
|
||||||
return "<" + ELEMENT + " xmlns=\"" + Carbon.NAMESPACE + "\"/>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,213 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright 2013 Georg Lukas
|
|
||||||
*
|
|
||||||
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jivesoftware.smackx.carbons;
|
|
||||||
|
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.WeakHashMap;
|
|
||||||
|
|
||||||
import org.jivesoftware.smack.Connection;
|
|
||||||
import org.jivesoftware.smack.ConnectionCreationListener;
|
|
||||||
import org.jivesoftware.smack.PacketCollector;
|
|
||||||
import org.jivesoftware.smack.PacketListener;
|
|
||||||
import org.jivesoftware.smack.SmackConfiguration;
|
|
||||||
import org.jivesoftware.smack.XMPPException;
|
|
||||||
import org.jivesoftware.smack.filter.PacketIDFilter;
|
|
||||||
import org.jivesoftware.smack.packet.IQ;
|
|
||||||
import org.jivesoftware.smack.packet.Message;
|
|
||||||
import org.jivesoftware.smack.packet.Packet;
|
|
||||||
import org.jivesoftware.smackx.ServiceDiscoveryManager;
|
|
||||||
import org.jivesoftware.smackx.packet.DiscoverInfo;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Packet extension for XEP-0280: Message Carbons. This class implements
|
|
||||||
* the manager for registering {@link Carbon} support, enabling and disabling
|
|
||||||
* message carbons.
|
|
||||||
*
|
|
||||||
* You should call enableCarbons() before sending your first undirected
|
|
||||||
* presence.
|
|
||||||
*
|
|
||||||
* @author Georg Lukas
|
|
||||||
*/
|
|
||||||
public class CarbonManager {
|
|
||||||
|
|
||||||
private static Map<Connection, CarbonManager> instances =
|
|
||||||
Collections.synchronizedMap(new WeakHashMap<Connection, CarbonManager>());
|
|
||||||
|
|
||||||
static {
|
|
||||||
Connection.addConnectionCreationListener(new ConnectionCreationListener() {
|
|
||||||
public void connectionCreated(Connection connection) {
|
|
||||||
new CarbonManager(connection);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private Connection connection;
|
|
||||||
private volatile boolean enabled_state = false;
|
|
||||||
|
|
||||||
private CarbonManager(Connection connection) {
|
|
||||||
ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
|
|
||||||
sdm.addFeature(Carbon.NAMESPACE);
|
|
||||||
this.connection = connection;
|
|
||||||
instances.put(connection, this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain the CarbonManager responsible for a connection.
|
|
||||||
*
|
|
||||||
* @param connection the connection object.
|
|
||||||
*
|
|
||||||
* @return a CarbonManager instance
|
|
||||||
*/
|
|
||||||
public static CarbonManager getInstanceFor(Connection connection) {
|
|
||||||
CarbonManager carbonManager = instances.get(connection);
|
|
||||||
|
|
||||||
if (carbonManager == null) {
|
|
||||||
carbonManager = new CarbonManager(connection);
|
|
||||||
}
|
|
||||||
|
|
||||||
return carbonManager;
|
|
||||||
}
|
|
||||||
|
|
||||||
private IQ carbonsEnabledIQ(final boolean new_state) {
|
|
||||||
IQ setIQ = new IQ() {
|
|
||||||
public String getChildElementXML() {
|
|
||||||
return "<" + (new_state? "enable" : "disable") + " xmlns='" + Carbon.NAMESPACE + "'/>";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
setIQ.setType(IQ.Type.SET);
|
|
||||||
return setIQ;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true if XMPP Carbons are supported by the server.
|
|
||||||
*
|
|
||||||
* @return true if supported
|
|
||||||
*/
|
|
||||||
public boolean isSupportedByServer() {
|
|
||||||
try {
|
|
||||||
DiscoverInfo result = ServiceDiscoveryManager
|
|
||||||
.getInstanceFor(connection).discoverInfo(connection.getServiceName());
|
|
||||||
return result.containsFeature(Carbon.NAMESPACE);
|
|
||||||
}
|
|
||||||
catch (XMPPException e) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify server to change the carbons state. This method returns
|
|
||||||
* immediately and changes the variable when the reply arrives.
|
|
||||||
*
|
|
||||||
* You should first check for support using isSupportedByServer().
|
|
||||||
*
|
|
||||||
* @param new_state whether carbons should be enabled or disabled
|
|
||||||
*/
|
|
||||||
public void sendCarbonsEnabled(final boolean new_state) {
|
|
||||||
IQ setIQ = carbonsEnabledIQ(new_state);
|
|
||||||
|
|
||||||
connection.addPacketListener(new PacketListener() {
|
|
||||||
public void processPacket(Packet packet) {
|
|
||||||
IQ result = (IQ)packet;
|
|
||||||
if (result.getType() == IQ.Type.RESULT) {
|
|
||||||
enabled_state = new_state;
|
|
||||||
}
|
|
||||||
connection.removePacketListener(this);
|
|
||||||
}
|
|
||||||
}, new PacketIDFilter(setIQ.getPacketID()));
|
|
||||||
|
|
||||||
connection.sendPacket(setIQ);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Notify server to change the carbons state. This method blocks
|
|
||||||
* some time until the server replies to the IQ and returns true on
|
|
||||||
* success.
|
|
||||||
*
|
|
||||||
* You should first check for support using isSupportedByServer().
|
|
||||||
*
|
|
||||||
* @param new_state whether carbons should be enabled or disabled
|
|
||||||
*
|
|
||||||
* @return true if the operation was successful
|
|
||||||
*/
|
|
||||||
public boolean setCarbonsEnabled(final boolean new_state) {
|
|
||||||
if (enabled_state == new_state)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
IQ setIQ = carbonsEnabledIQ(new_state);
|
|
||||||
|
|
||||||
PacketCollector collector =
|
|
||||||
connection.createPacketCollector(new PacketIDFilter(setIQ.getPacketID()));
|
|
||||||
connection.sendPacket(setIQ);
|
|
||||||
IQ result = (IQ) collector.nextResult(SmackConfiguration.getPacketReplyTimeout());
|
|
||||||
collector.cancel();
|
|
||||||
|
|
||||||
if (result != null && result.getType() == IQ.Type.RESULT) {
|
|
||||||
enabled_state = new_state;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper method to enable carbons.
|
|
||||||
*
|
|
||||||
* @return true if the operation was successful
|
|
||||||
*/
|
|
||||||
public boolean enableCarbons() {
|
|
||||||
return setCarbonsEnabled(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Helper method to disable carbons.
|
|
||||||
*
|
|
||||||
* @return true if the operation was successful
|
|
||||||
*/
|
|
||||||
public boolean disableCarbons() {
|
|
||||||
return setCarbonsEnabled(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if carbons are enabled on this connection.
|
|
||||||
*/
|
|
||||||
public boolean getCarbonsEnabled() {
|
|
||||||
return this.enabled_state;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Obtain a Carbon from a message, if available.
|
|
||||||
*
|
|
||||||
* @param msg Message object to check for carbons
|
|
||||||
*
|
|
||||||
* @return a Carbon if available, null otherwise.
|
|
||||||
*/
|
|
||||||
public static Carbon getCarbon(Message msg) {
|
|
||||||
Carbon cc = (Carbon)msg.getExtension("received", Carbon.NAMESPACE);
|
|
||||||
if (cc == null)
|
|
||||||
cc = (Carbon)msg.getExtension("sent", Carbon.NAMESPACE);
|
|
||||||
return cc;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Mark a message as "private", so it will not be carbon-copied.
|
|
||||||
*
|
|
||||||
* @param msg Message object to mark private
|
|
||||||
*/
|
|
||||||
public static void disableCarbons(Message msg) {
|
|
||||||
msg.addExtension(new Carbon.Private());
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,125 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright 2013 Georg Lukas
|
|
||||||
*
|
|
||||||
* All rights reserved. Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jivesoftware.smackx.forward;
|
|
||||||
|
|
||||||
import org.jivesoftware.smack.packet.Packet;
|
|
||||||
import org.jivesoftware.smack.packet.PacketExtension;
|
|
||||||
import org.jivesoftware.smack.provider.PacketExtensionProvider;
|
|
||||||
import org.jivesoftware.smack.util.PacketParserUtils;
|
|
||||||
import org.jivesoftware.smackx.packet.DelayInfo;
|
|
||||||
import org.jivesoftware.smackx.provider.DelayInfoProvider;
|
|
||||||
import org.xmlpull.v1.XmlPullParser;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Packet extension for XEP-0297: Stanza Forwarding. This class implements
|
|
||||||
* the packet extension and a {@link PacketExtensionProvider} to parse
|
|
||||||
* forwarded messages from a packet. The extension
|
|
||||||
* <a href="http://xmpp.org/extensions/xep-0297.html">XEP-0297</a> is
|
|
||||||
* a prerequisite for XEP-0280 (Message Carbons).
|
|
||||||
*
|
|
||||||
* <p>The {@link Forwarded.Provider} must be registered in the
|
|
||||||
* <b>smack.properties</b> file for the element <b>forwarded</b> with
|
|
||||||
* namespace <b>urn:xmpp:forwarded:0</b></p> to be used.
|
|
||||||
*
|
|
||||||
* @author Georg Lukas
|
|
||||||
*/
|
|
||||||
public class Forwarded implements PacketExtension {
|
|
||||||
public static final String NAMESPACE = "urn:xmpp:forward:0";
|
|
||||||
public static final String ELEMENT_NAME = "forwarded";
|
|
||||||
|
|
||||||
private DelayInfo delay;
|
|
||||||
private Packet forwardedPacket;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a new Forwarded packet extension.
|
|
||||||
*
|
|
||||||
* @param delay an optional {@link DelayInfo} timestamp of the packet.
|
|
||||||
* @param fwdPacket the packet that is forwarded (required).
|
|
||||||
*/
|
|
||||||
public Forwarded(DelayInfo delay, Packet fwdPacket) {
|
|
||||||
this.delay = delay;
|
|
||||||
this.forwardedPacket = fwdPacket;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getElementName() {
|
|
||||||
return ELEMENT_NAME;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getNamespace() {
|
|
||||||
return NAMESPACE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toXML() {
|
|
||||||
StringBuilder buf = new StringBuilder();
|
|
||||||
buf.append("<").append(getElementName()).append(" xmlns=\"")
|
|
||||||
.append(getNamespace()).append("\">");
|
|
||||||
|
|
||||||
if (delay != null)
|
|
||||||
buf.append(delay.toXML());
|
|
||||||
buf.append(forwardedPacket.toXML());
|
|
||||||
|
|
||||||
buf.append("</").append(getElementName()).append(">");
|
|
||||||
return buf.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get the packet forwarded by this stanza.
|
|
||||||
*
|
|
||||||
* @return the {@link Packet} instance (typically a message) that was forwarded.
|
|
||||||
*/
|
|
||||||
public Packet getForwardedPacket() {
|
|
||||||
return forwardedPacket;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* get the timestamp of the forwarded packet.
|
|
||||||
*
|
|
||||||
* @return the {@link DelayInfo} representing the time when the original packet was sent. May be null.
|
|
||||||
*/
|
|
||||||
public DelayInfo getDelayInfo() {
|
|
||||||
return delay;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Provider implements PacketExtensionProvider {
|
|
||||||
DelayInfoProvider dip = new DelayInfoProvider();
|
|
||||||
|
|
||||||
public PacketExtension parseExtension(XmlPullParser parser) throws Exception {
|
|
||||||
DelayInfo di = null;
|
|
||||||
Packet packet = null;
|
|
||||||
|
|
||||||
boolean done = false;
|
|
||||||
while (!done) {
|
|
||||||
int eventType = parser.next();
|
|
||||||
if (eventType == XmlPullParser.START_TAG) {
|
|
||||||
if (parser.getName().equals("delay"))
|
|
||||||
di = (DelayInfo)dip.parseExtension(parser);
|
|
||||||
else if (parser.getName().equals("message"))
|
|
||||||
packet = PacketParserUtils.parseMessage(parser);
|
|
||||||
else throw new Exception("Unsupported forwarded packet type: " + parser.getName());
|
|
||||||
}
|
|
||||||
else if (eventType == XmlPullParser.END_TAG && parser.getName().equals(ELEMENT_NAME))
|
|
||||||
done = true;
|
|
||||||
}
|
|
||||||
if (packet == null)
|
|
||||||
throw new Exception("forwarded extension must contain a packet");
|
|
||||||
return new Forwarded(di, packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue