Adds Rayo IQ provider to jabber extensions.

fix-message-formatting
paweldomas 11 years ago
parent e07f0d07d9
commit 5418689151

@ -0,0 +1,104 @@
/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.protocol.jabber.extensions.rayo;
import net.java.sip.communicator.impl.protocol.jabber.extensions.*;
import org.jivesoftware.smack.packet.*;
/**
* 'End' Rayo packet extension used to notify the client about call ended event.
*
* @author Pawel Domas
*/
public class EndExtension
extends AbstractPacketExtension
{
/**
* XML element name of this extension.
*/
public static final String ELEMENT_NAME = "end";
/**
* End reason.
*/
private ReasonExtension reason;
/**
* Creates new instance.
*/
protected EndExtension()
{
super(RayoIqProvider.NAMESPACE, ELEMENT_NAME);
}
/**
* Checks if given <tt>elementName</tt> is valid end reason element.
* @param elementName the XML element name to check.
* @return <tt>true</tt> if given <tt>elementName</tt> is valid end reason
* element.
*/
public static boolean isValidReason(String elementName)
{
return ReasonExtension.BUSY.equals(elementName)
|| ReasonExtension.ERROR.equals(elementName)
|| ReasonExtension.HANGUP.equals(elementName)
|| ReasonExtension.HANGUP_COMMND.equals(elementName)
|| ReasonExtension.REJECTED.equals(elementName)
|| ReasonExtension.TIMEOUT.equals(elementName);
}
/**
* Returns {@link ReasonExtension} associated with this instance.
* @return {@link ReasonExtension} associated with this instance.
*/
public ReasonExtension getReason()
{
return reason;
}
/**
* Sets new {@link ReasonExtension} for this <tt>EndExtension</tt> instance.
* @param newReason the new {@link ReasonExtension} to set.
*/
public void setReason(ReasonExtension newReason)
{
if (this.reason != null)
{
getChildExtensions().remove(this.reason);
}
this.reason = newReason;
addChildExtension(newReason);
}
/**
* Creates 'Presence' packet containing call ended Rayo notification that
* contains specified end <tt>reason</tt>.
* @param from source JID of this event.
* @param to destination JID.
* @param reason call end reason string. One of {@link ReasonExtension}
* static constants.
* @return 'Presence' packet containing call ended Rayo notification.
*/
public static Presence createEnd(String from, String to, String reason)
{
Presence presence = new Presence(Presence.Type.unavailable);
presence.setFrom(from);
presence.setTo(to);
EndExtension end = new EndExtension();
end.setReason(new ReasonExtension(reason));
presence.addExtension(end);
return presence;
}
}

@ -0,0 +1,78 @@
/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.protocol.jabber.extensions.rayo;
import net.java.sip.communicator.impl.protocol.jabber.extensions.*;
/**
* Header packet extension optionally included in {@link RayoIqProvider.RayoIq}.
* Holds 'name' and 'value' attributes.
*
* @author Pawel Domas
*/
public class HeaderExtension
extends AbstractPacketExtension
{
/**
* XML element name.
*/
public static final String ELEMENT_NAME = "header";
/**
* The name of 'name' attribute.
*/
public static final String NAME_ATTR_NAME = "name";
/**
* The name of 'value' attribute.
*/
public static final String VALUE_ATTR_NAME = "value";
/**
* Creates new instance of <tt>HeaderPacketExtension</tt>.
*/
public HeaderExtension()
{
super(null, ELEMENT_NAME);
}
/**
* Return the value of 'name' attribute.
* @return the value of 'name' attribute.
*/
public String getName()
{
return getAttributeAsString(NAME_ATTR_NAME);
}
/**
* Sets new value for 'name' attribute of this extension.
* @param name the new value to set for 'name' attribute.
*/
public void setName(String name)
{
setAttribute(NAME_ATTR_NAME, name);
}
/**
* Returns the value of 'value' attribute.
* @return the value of 'value' attribute.
*/
public String getValue()
{
return getAttributeAsString(VALUE_ATTR_NAME);
}
/**
* Sets new value for the 'value' attribute.
* @param value new value for the 'value' attribute to set.
*/
public void setValue(String value)
{
setAttribute(VALUE_ATTR_NAME, value);
}
}

@ -0,0 +1,587 @@
/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.protocol.jabber.extensions.rayo;
import net.java.sip.communicator.impl.protocol.jabber.extensions.*;
import org.jitsi.util.*;
import org.jivesoftware.smack.packet.*;
import org.jivesoftware.smack.provider.*;
import org.xmlpull.v1.*;
import java.util.*;
/**
* Provider handles parsing of Rayo IQ stanzas and converting objects back to
* their XML representation.
*
* FIXME: implements only the minimum required to start and hang up a call
*
* @author Pawel Domas
*/
public class RayoIqProvider
implements IQProvider
{
/**
* Rayo namespace.
*/
public final static String NAMESPACE = "urn:xmpp:rayo:1";
/**
* Registers this IQ provider into given <tt>ProviderManager</tt>.
* @param providerManager the <tt>ProviderManager</tt> to which this
* instance wil be bound to.
*/
public void registerRayoIQs(ProviderManager providerManager)
{
// <dial>
providerManager.addIQProvider(
DialIq.ELEMENT_NAME,
NAMESPACE,
this);
// <ref>
providerManager.addIQProvider(
RefIq.ELEMENT_NAME,
NAMESPACE,
this);
// <hangup>
providerManager.addIQProvider(
HangUp.ELEMENT_NAME,
NAMESPACE,
this);
// <end> presence extension
providerManager.addExtensionProvider(
EndExtension.ELEMENT_NAME,
NAMESPACE,
new DefaultPacketExtensionProvider<EndExtension>(
EndExtension.class));
// <header> extension
providerManager.addExtensionProvider(
HeaderExtension.ELEMENT_NAME,
"",
new DefaultPacketExtensionProvider<HeaderExtension>(
HeaderExtension.class));
}
/**
* {@inheritDoc}
*/
@Override
public IQ parseIQ(XmlPullParser parser)
throws Exception
{
String namespace = parser.getNamespace();
// Check the namespace
if (!NAMESPACE.equals(namespace))
{
return null;
}
String rootElement = parser.getName();
RayoIq iq;
DialIq dial;
RefIq ref;
//End end = null;
if (DialIq.ELEMENT_NAME.equals(rootElement))
{
iq = dial = new DialIq();
String src = parser.getAttributeValue("", DialIq.SRC_ATTR_NAME);
String dst = parser.getAttributeValue("", DialIq.DST_ATTR_NAME);
// Destination is mandatory
if (StringUtils.isNullOrEmpty(dst))
return null;
dial.setSource(src);
dial.setDestination(dst);
}
else if (RefIq.ELEMENT_NAME.equals(rootElement))
{
iq = ref = new RefIq();
String uri = parser.getAttributeValue("", RefIq.URI_ATTR_NAME);
if (StringUtils.isNullOrEmpty(uri))
return null;
ref.setUri(uri);
}
else if (HangUp.ELEMENT_NAME.equals(rootElement))
{
iq = new HangUp();
}
/*else if (End.ELEMENT_NAME.equals(rootElement))
{
iq = end = new End();
}*/
else
{
return null;
}
boolean done = false;
HeaderExtension header = null;
//ReasonExtension reason = null;
while (!done)
{
switch (parser.next())
{
case XmlPullParser.END_TAG:
{
String name = parser.getName();
if (rootElement.equals(name))
{
done = true;
}
else if (HeaderExtension.ELEMENT_NAME.equals(
name))
{
if (header != null)
{
iq.addExtension(header);
header = null;
}
}
/*else if (End.isValidReason(name))
{
if (end != null && reason != null)
{
end.setReason(reason);
reason = null;
}
}*/
break;
}
case XmlPullParser.START_TAG:
{
String name = parser.getName();
if (HeaderExtension.ELEMENT_NAME.equals(name))
{
header = new HeaderExtension();
String nameAttr
= parser.getAttributeValue(
"", HeaderExtension.NAME_ATTR_NAME);
header.setName(nameAttr);
String valueAttr
= parser.getAttributeValue(
"", HeaderExtension.VALUE_ATTR_NAME);
header.setValue(valueAttr);
}
/*else if (End.isValidReason(name))
{
reason = new ReasonPacketExtension(name);
String platformCode
= parser.getAttributeValue(
"", ReasonPacketExtension.PLATFORM_CODE_ATTRIBUTE);
if (!StringUtils.isNullOrEmpty(platformCode))
{
reason.setPlatformCode(platformCode);
}
}*/
break;
}
case XmlPullParser.TEXT:
{
// Parse some text here
break;
}
}
}
return iq;
}
/**
* Base class for all Ray IQs. Takes care of <header /> extension handling
* as well as other functions shared by all IQs.
*/
public static abstract class RayoIq
extends IQ
{
/**
* The XML element name that will be used.
*/
private final String elementName;
/**
* Creates new instance of <tt>RayoIq</tt>.
*
* @param elementName the name of XML element that will be used.
*/
protected RayoIq(String elementName)
{
this.elementName = elementName;
}
/**
* Implementing classes should print their attributes if any in XML
* format to given <tt>out</tt> <tt>StringBuilder</tt>.
* @param out the <tt>StringBuilder</tt> instance used to construct XML
* representation of this element.
*/
protected abstract void printAttributes(StringBuilder out);
/**
* {@inheritDoc}
*/
@Override
public String getChildElementXML()
{
StringBuilder xml = new StringBuilder();
xml.append('<').append(elementName);
xml.append(" xmlns='").append(NAMESPACE).append("' ");
printAttributes(xml);
Collection<PacketExtension> extensions = getExtensions();
if (extensions.size() > 0)
{
xml.append(">");
for (PacketExtension extension : extensions)
{
xml.append(extension.toXML());
}
xml.append("</").append(elementName).append(">");
}
else
{
xml.append("/>");
}
return xml.toString();
}
/**
* Returns value of the header extension with given <tt>name</tt>
* (if any).
* @param name the name of header extension which value we want to
* retrieve.
* @return value of header extension with given <tt>name</tt> if it
* exists or <tt>null</tt> otherwise.
*/
public String getHeader(String name)
{
HeaderExtension header = findHeader(name);
return header != null ? header.getValue() : null;
}
private HeaderExtension findHeader(String name)
{
for(PacketExtension ext: getExtensions())
{
if (ext instanceof HeaderExtension)
{
HeaderExtension header = (HeaderExtension) ext;
if(name.equals(header.getName()))
return header;
}
}
return null;
}
/**
* Adds 'header' extension to this Rayo IQ with given name and value
* attributes.
* @param name the attribute name of the 'header' extension to be added.
* @param value the 'value' attribute of the 'header' extension that
* will be added to this IQ.
*/
public void setHeader(String name, String value)
{
HeaderExtension headerExt = findHeader(name);
if (headerExt == null)
{
headerExt = new HeaderExtension();
headerExt.setName(name);
addExtension(headerExt);
}
headerExt.setValue(value);
}
}
/**
* The 'dial' IQ used to initiate new outgoing call session in Rayo
* protocol.
*/
public static class DialIq
extends RayoIq
{
/**
* The name of XML element for this IQ.
*/
public static final String ELEMENT_NAME = "dial";
/**
* The name of source URI/address attribute. Referred as "source" to
* avoid confusion with "getFrom" and "setFrom" in {@link IQ} class.
*/
public static final String SRC_ATTR_NAME = "from";
/**
* The name of destination URI/address attribute. Referred as "source"
* to avoid confusion with "getFrom" and "setFrom" in {@link IQ} class.
*/
public static final String DST_ATTR_NAME = "to";
/**
* Source URI/address.
*/
private String source;
/**
* Destination URI/address.
*/
private String destination;
/**
* Creates new instance of <tt>DialIq</tt>.
*/
public DialIq()
{
super(DialIq.ELEMENT_NAME);
}
/**
* Creates new <tt>DialIq</tt> for given source and destination
* addresses.
* @param to the destination address/call URI to be used.
* @param from the source address that will be set on
* new <tt>DialIq</tt> instance.
* @return new <tt>DialIq</tt> parametrized with given source and
* destination addresses.
*/
public static DialIq create(String to, String from)
{
DialIq dialIq = new DialIq();
dialIq.setSource(from);
dialIq.setDestination(to);
return dialIq;
}
/**
* Return source address value set on this <tt>DialIq</tt>.
* @return source address value of this <tt>DialIq</tt>.
*/
public String getSource()
{
return source;
}
/**
* Sets new source address value on this <tt>DialIq</tt>.
* @param source the new source address value to be set.
*/
public void setSource(String source)
{
this.source = source;
}
/**
* Returns destination address/call URI associated with this instance.
* @return destination address/call URI associated with this instance.
*/
public String getDestination()
{
return destination;
}
/**
* Sets new destination address/call URI on this <tt>DialIq</tt>.
* @param destination the new destination address/call URI to set.
*/
public void setDestination(String destination)
{
this.destination = destination;
}
/**
* {@inheritDoc}
*/
@Override
protected void printAttributes(StringBuilder out)
{
String src = getSource();
if (!StringUtils.isNullOrEmpty(src))
out.append(SRC_ATTR_NAME).append("='")
.append(src).append("' ");
String dst = getDestination();
if (!StringUtils.isNullOrEmpty(dst))
out.append(DST_ATTR_NAME).append("='")
.append(dst).append("' ");
}
}
/**
* Rayo 'ref' IQ sent by the server as a reply to 'dial' request. Holds
* created call's resource in 'uri' attribute.
*/
public static class RefIq
extends RayoIq
{
/**
* XML element name of <tt>RefIq</tt>.
*/
public static final String ELEMENT_NAME = "ref";
/**
* Name of the URI attribute that stores call resource reference.
*/
public static final String URI_ATTR_NAME = "uri";
/**
* Call resource/uri reference.
*/
private String uri;
/**
* Creates new <tt>RefIq</tt>.
*/
protected RefIq()
{
super(RefIq.ELEMENT_NAME);
}
/**
* Creates new <tt>RefIq</tt> parametrized with given call <tt>uri</tt>.
* @param uri the call URI to be set on newly created <tt>RefIq</tt>.
* @return new <tt>RefIq</tt> parametrized with given call <tt>uri</tt>.
*/
public static RefIq create(String uri)
{
RefIq refIq = new RefIq();
refIq.setUri(uri);
return refIq;
}
/**
* Creates result <tt>RefIq</tt> for given <tt>requestIq</tt>
* parametrized with given call <tt>uri</tt>.
* @param requestIq the request IQ which 'from', 'to' and 'id'
* attributes will be used for constructing result IQ.
* @param uri the call URI that will be included in newly created
* <tt>RefIq</tt>.
* @return result <tt>RefIq</tt> for given <tt>requestIq</tt>
* parametrized with given call <tt>uri</tt>.
*/
public static RefIq createResult(IQ requestIq, String uri)
{
RefIq refIq = create(uri);
refIq.setType(IQ.Type.RESULT);
refIq.setPacketID(requestIq.getPacketID());
refIq.setFrom(requestIq.getTo());
refIq.setTo(requestIq.getFrom());
return refIq;
}
/**
* {@inheritDoc}
*/
@Override
protected void printAttributes(StringBuilder out)
{
String uri = getUri();
if (!StringUtils.isNullOrEmpty(uri))
out.append(URI_ATTR_NAME).append("='")
.append(uri).append("' ");
}
/**
* Sets given call <tt>uri</tt> value on this instance.
* @param uri the call <tt>uri</tt> to be stored in this instance.
*/
public void setUri(String uri)
{
this.uri = uri;
}
/**
* Returns call URI held by this instance.
* @return the call URI held by this instance.
*/
public String getUri()
{
return uri;
}
}
/**
* Rayo hangup IQ is sent by the controlling agent to tell the server that
* call whose resource is mentioned in IQ's 'to' attribute should be
* terminated. Server immediately replies with result IQ which means that
* hangup operation is now scheduled. After it is actually executed presence
* indication with {@link EndExtension} is sent through the presence to
* confirm the operation.
*/
public static class HangUp
extends RayoIq
{
/**
* The name of 'hangup' element.
*/
public static final String ELEMENT_NAME = "hangup";
/**
* Creates new instance of <tt>HangUp</tt> IQ.
*/
protected HangUp()
{
super(ELEMENT_NAME);
}
/**
* Creates new, parametrized instance of {@link HangUp} IQ.
* @param from source JID.
* @param to the destination address/call URI to be ended by this IQ.
* @return new, parametrized instance of {@link HangUp} IQ.
*/
public static HangUp create(String from, String to)
{
HangUp hangUp = new HangUp();
hangUp.setFrom(from);
hangUp.setTo(to);
hangUp.setType(Type.SET);
return hangUp;
}
@Override
protected void printAttributes(StringBuilder out){ }
}
}

@ -0,0 +1,88 @@
/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.protocol.jabber.extensions.rayo;
import net.java.sip.communicator.impl.protocol.jabber.extensions.*;
/**
* Rayo 'reason' packet extension.
*
* @author Pawel Domas
*/
public class ReasonExtension
extends AbstractPacketExtension
{
/**
* The name of optional platform code attribute.
*/
public static final String PLATFORM_CODE_ATTRIBUTE = "platform-code";
/**
* Indication that the call ended due to a normal hangup by the remote
* party.
*/
public static final String HANGUP = "hangup";
/**
* Indication that the call ended due to a normal hangup triggered by
* a hangup command.
*/
public static final String HANGUP_COMMND = "hangup-command";
/**
* Indication that the call ended due to a timeout in contacting the remote
* party.
*/
public static final String TIMEOUT = "timeout";
/**
* Indication that the call ended due to being rejected by the remote party
* subsequent to being accepted.
*/
public static final String BUSY = "busy";
/**
* Indication that the call ended due to being rejected by the remote party
* before being accepted.
*/
public static final String REJECTED = "rejected";
/**
* Indication that the call ended due to a system error.
*/
public static final String ERROR = "error";
/**
* Creates an {@link ReasonExtension} instance for the specified
* <tt>namespace</tt> and <tt>elementName</tt>.
*
* @param elementName the name of the element
*/
public ReasonExtension(String elementName)
{
super(null, elementName);
}
/**
* Returns the value of platform code attribute.
* @return the value of platform code attribute.
*/
public String getPlatformCode()
{
return getAttributeAsString(PLATFORM_CODE_ATTRIBUTE);
}
/**
* Sets new value of platform code attribute. Pass <tt>null</tt> to remove.
* @param code new value of platform code attribute. Pass <tt>null</tt> to
* remove.
*/
public void setPlatformCode(String code)
{
setAttribute(PLATFORM_CODE_ATTRIBUTE, code);
}
}
Loading…
Cancel
Save