Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/Jingle.java')
-rw-r--r--protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/Jingle.java589
1 files changed, 589 insertions, 0 deletions
diff --git a/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/Jingle.java b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/Jingle.java
new file mode 100644
index 000000000..800e42898
--- /dev/null
+++ b/protocols/bundles/org.jivesoftware.smack/src/org/jivesoftware/smackx/packet/Jingle.java
@@ -0,0 +1,589 @@
+/**
+ * $RCSfile: Jingle.java,v $
+ * $Revision: 1.1 $
+ * $Date: 2006/10/17 19:14:14 $
+ *
+ * Copyright 2003-2004 Jive Software.
+ *
+ * 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.packet;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+import org.jivesoftware.smack.packet.IQ;
+
+/**
+ * An Jingle sub-packet, which is used by XMPP clients to exchange info like
+ * descriptions and transports. <p/> The following link summarizes the
+ * requirements of Jingle IM: <a
+ * href="http://www.jabber.org/jeps/jep-0166.html">Valid tags</a>.
+ * <p>
+ * <p/> Warning: this is an non-standard protocol documented by <a
+ * href="http://www.jabber.org/jeps/jep-0166.html">JEP-166</a>. Because this is
+ * a non-standard protocol, it is subject to change.
+ *
+ * @author Alvaro Saurin
+ */
+public class Jingle extends IQ {
+
+ // static
+
+ public static final String NAMESPACE = "http://jabber.org/protocol/jingle";
+
+ public static final String NODENAME = "jingle";
+
+ // non-static
+
+ private String sid; // The session id
+
+ private Action action; // The action associated to the Jingle
+
+ private String initiator; // The initiator as a "user@host/resource"
+
+ private String responder; // The responder
+
+ // Sub-elements of a Jingle object.
+
+ private final List descriptions = new ArrayList();
+
+ private final List transports = new ArrayList();
+
+ private JingleContentInfo contentInfo;
+
+ /**
+ * A constructor where the main components can be initialized.
+ */
+ public Jingle(final List descs, final List trans, final JingleContentInfo mi,
+ final String sid) {
+ super();
+
+ if (descs != null) {
+ descriptions.addAll(descs);
+ }
+
+ if (trans != null) {
+ transports.addAll(trans);
+ }
+
+ setContentInfo(mi);
+ setSid(sid);
+
+ // Set null all other fields in the packet
+ initiator = null;
+ responder = null;
+ action = null;
+ }
+
+ /**
+ * Constructor with a description.
+ *
+ * @param descr a description
+ */
+ public Jingle(final JingleContentDescription descr) {
+ super();
+
+ addDescription(descr);
+
+ // Set null all other fields in the packet
+ initiator = null;
+ responder = null;
+
+ // Some default values for the most common situation...
+ action = Jingle.Action.CONTENTINFO;
+ this.setType(IQ.Type.SET);
+ }
+
+ /**
+ * Constructor with a transport.
+ *
+ * @param trans a transport
+ */
+ public Jingle(final JingleTransport trans) {
+ super();
+
+ addTransport(trans);
+
+ // Set null all other fields in the packet
+ initiator = null;
+ responder = null;
+
+ // Some default values for the most common situation...
+ action = Jingle.Action.TRANSPORTINFO;
+ this.setType(IQ.Type.SET);
+ }
+
+ /**
+ * Constructor with a content info.
+ *
+ * @param info The content info
+ */
+ public Jingle(final JingleContentInfo info) {
+ super();
+
+ setContentInfo(info);
+
+ // Set null all other fields in the packet
+ initiator = null;
+ responder = null;
+
+ // Some default values for the most common situation...
+ action = Jingle.Action.CONTENTINFO;
+ this.setType(IQ.Type.SET);
+ }
+
+ /**
+ * A constructor where the action can be specified.
+ *
+ * @param action The action.
+ */
+ public Jingle(final Jingle.Action action) {
+ this(null, null, null, null);
+ this.action = action;
+
+ // In general, a Jingle with an action is used in a SET packet...
+ this.setType(IQ.Type.SET);
+ }
+
+ /**
+ * A constructor where the session ID can be specified.
+ *
+ * @param sid The session ID related to the negotiation.
+ * @see #setSid(String)
+ */
+ public Jingle(final String sid) {
+ this(null, null, null, sid);
+ }
+
+ /**
+ * The default constructor
+ */
+ public Jingle() {
+ super();
+ }
+
+ /**
+ * Set the session ID related to this session. The session ID is a unique
+ * identifier generated by the initiator. This should match the XML Nmtoken
+ * production so that XML character escaping is not needed for characters
+ * such as &.
+ *
+ * @param sid the session ID
+ */
+ public final void setSid(final String sid) {
+ this.sid = sid;
+ }
+
+ /**
+ * Returns the session ID related to the session. The session ID is a unique
+ * identifier generated by the initiator. This should match the XML Nmtoken
+ * production so that XML character escaping is not needed for characters
+ * such as &.
+ *
+ * @return Returns the session ID related to the session.
+ * @see #setSid(String)
+ */
+ public String getSid() {
+ return sid;
+ }
+
+ /**
+ * Returns the XML element name of the extension sub-packet root element.
+ * Always returns "jingle"
+ *
+ * @return the XML element name of the packet extension.
+ */
+ public static String getElementName() {
+ return NODENAME;
+ }
+
+ /**
+ * Returns the XML namespace of the extension sub-packet root element.
+ * According the specification the namespace is always
+ * "http://jabber.org/protocol/jingle"
+ *
+ * @return the XML namespace of the packet extension.
+ */
+ public static String getNamespace() {
+ return NAMESPACE;
+ }
+
+ /**
+ * @return the audioInfo
+ */
+ public JingleContentInfo getContentInfo() {
+ return contentInfo;
+ }
+
+ /**
+ * @param contentInfo the audioInfo to set
+ */
+ public void setContentInfo(final JingleContentInfo contentInfo) {
+ this.contentInfo = contentInfo;
+ }
+
+ /**
+ * Get an iterator for the content descriptions
+ *
+ * @return the descriptions
+ */
+ public Iterator getDescriptions() {
+ synchronized (descriptions) {
+ return Collections.unmodifiableList(new ArrayList(descriptions)).iterator();
+ }
+ }
+
+ /**
+ * Get an iterator for the content descriptions
+ *
+ * @return the descriptions
+ */
+ public ArrayList getDescriptionsList() {
+ synchronized (descriptions) {
+ return new ArrayList(descriptions);
+ }
+ }
+
+ /**
+ * Add a new content description.
+ *
+ * @param desc the descriptions to add
+ */
+ public void addDescription(final JingleContentDescription desc) {
+ if (desc != null) {
+ synchronized (descriptions) {
+ descriptions.add(desc);
+ }
+ }
+ }
+
+ /**
+ * Add a list of JingleContentDescription elements
+ *
+ * @param descsList the list of transports to add
+ */
+ public void addDescriptions(final List descsList) {
+ if (descsList != null) {
+ synchronized (descriptions) {
+ descriptions.addAll(descsList);
+ }
+ }
+ }
+
+ /**
+ * Get an iterator for the transport.
+ *
+ * @return the transports
+ */
+ public Iterator getTransports() {
+ synchronized (transports) {
+ return Collections.unmodifiableList(new ArrayList(transports)).iterator();
+ }
+ }
+
+ /**
+ * Get the list of transports.
+ *
+ * @return the transports list.
+ */
+ public ArrayList getTransportsList() {
+ synchronized (transports) {
+ return new ArrayList(transports);
+ }
+ }
+
+ /**
+ * Add a new JingleTransport element
+ *
+ * @param trans the transports to add
+ */
+ public void addTransport(final JingleTransport trans) {
+ if (trans != null) {
+ synchronized (transports) {
+ transports.add(trans);
+ }
+ }
+ }
+
+ /**
+ * Add a list of JingleTransport elements
+ *
+ * @param transList the list of transports to add
+ */
+ public void addTransports(final List transList) {
+ if (transList != null) {
+ synchronized (transports) {
+ transports.addAll(transList);
+ }
+ }
+ }
+
+ /**
+ * Get the action specified in the packet
+ *
+ * @return the action
+ */
+ public Action getAction() {
+ return action;
+ }
+
+ /**
+ * Set the action in the packet
+ *
+ * @param action the action to set
+ */
+ public void setAction(final Action action) {
+ this.action = action;
+ }
+
+ /**
+ * Get the initiator. The initiator will be the full JID of the entity that
+ * has initiated the flow (which may be different to the "from" address in
+ * the IQ)
+ *
+ * @return the initiator
+ */
+ public String getInitiator() {
+ return initiator;
+ }
+
+ /**
+ * Set the initiator. The initiator must be the full JID of the entity that
+ * has initiated the flow (which may be different to the "from" address in
+ * the IQ)
+ *
+ * @param initiator the initiator to set
+ */
+ public void setInitiator(final String initiator) {
+ this.initiator = initiator;
+ }
+
+ /**
+ * Get the responder. The responder is the full JID of the entity that has
+ * replied to the initiation (which may be different to the "to" addresss in
+ * the IQ).
+ *
+ * @return the responder
+ */
+ public String getResponder() {
+ return responder;
+ }
+
+ /**
+ * Set the responder. The responder must be the full JID of the entity that
+ * has replied to the initiation (which may be different to the "to"
+ * addresss in the IQ).
+ *
+ * @param resp the responder to set
+ */
+ public void setResponder(final String resp) {
+ responder = resp;
+ }
+
+ /**
+ * Get a hash key for the session this packet belongs to.
+ *
+ * @param sid The session id
+ * @param initiator The initiator
+ * @return A hash key
+ */
+ public static int getSessionHash(final String sid, final String initiator) {
+ final int PRIME = 31;
+ int result = 1;
+ result = PRIME * result + (initiator == null ? 0 : initiator.hashCode());
+ result = PRIME * result + (sid == null ? 0 : sid.hashCode());
+ return result;
+ }
+
+ /**
+ * Return the XML representation of the packet.
+ *
+ * @return the XML string
+ */
+ public String getChildElementXML() {
+ StringBuffer buf = new StringBuffer();
+
+ buf.append("<").append(getElementName());
+ buf.append(" xmlns=\"").append(getNamespace()).append("\"");
+ if (getInitiator() != null) {
+ buf.append(" initiator=\"").append(getInitiator()).append("\"");
+ }
+ if (getResponder() != null) {
+ buf.append(" responder=\"").append(getResponder()).append("\"");
+ }
+ if (getAction() != null) {
+ buf.append(" action=\"").append(getAction()).append("\"");
+ }
+ if (getSid() != null) {
+ buf.append(" sid=\"").append(getSid()).append("\"");
+ }
+ buf.append(">");
+
+ // Look for possible payload types, and dump them.
+ synchronized (descriptions) {
+ for (int i = 0; i < descriptions.size(); i++) {
+ JingleContentDescription desc = (JingleContentDescription) descriptions
+ .get(i);
+ buf.append(desc.toXML());
+ }
+ }
+
+ // If the packet has transports, dump them.
+ synchronized (transports) {
+ for (int i = 0; i < transports.size(); i++) {
+ JingleTransport trans = (JingleTransport) transports.get(i);
+ buf.append(trans.toXML());
+ }
+ }
+
+ // and the same for audio media info
+ if (contentInfo != null) {
+ buf.append(contentInfo.toXML());
+ }
+
+ buf.append("</").append(getElementName()).append(">");
+ return buf.toString();
+ }
+
+ /**
+ * The "action" in the jingle packet, as an enum.
+ */
+ public static class Action {
+
+ public static final Action CONTENTACCEPT = new Action("description-accept");
+
+ public static final Action CONTENTDECLINE = new Action("description-decline");
+
+ public static final Action CONTENTINFO = new Action("description-info");
+
+ public static final Action CONTENTMODIFY = new Action("description-modify");
+
+ public static final Action SESSIONACCEPT = new Action("session-accept");
+
+ public static final Action SESSIONINFO = new Action("session-info");
+
+ public static final Action SESSIONINITIATE = new Action("session-initiate");
+
+ public static final Action SESSIONREDIRECT = new Action("session-redirect");
+
+ public static final Action SESSIONEXTEND = new Action("session-extend");
+
+ public static final Action SESSIONREDUCE = new Action("session-reduce");
+
+ public static final Action SESSIONTERMINATE = new Action("session-terminate");
+
+ public static final Action TRANSPORTACCEPT = new Action("transport-accept");
+
+ public static final Action TRANSPORTDECLINE = new Action("transport-decline");
+
+ public static final Action TRANSPORTINFO = new Action("transport-info");
+
+ public static final Action TRANSPORTMODIFY = new Action("transport-modify");
+
+ private String value;
+
+ public Action(final String value) {
+ this.value = value;
+ }
+
+ /**
+ * Returns the String value for an Action.
+ */
+ public String toString() {
+ return value;
+ }
+
+ /**
+ * Returns a Action instance associated with the String value.
+ */
+ public static Action fromString(String value) {
+ if (value != null) {
+ value = value.toLowerCase();
+ if (value.equals("description-accept")) {
+ return CONTENTACCEPT;
+ } else if (value.equals("description-decline")) {
+ return CONTENTDECLINE;
+ } else if (value.equals("description-info")) {
+ return CONTENTINFO;
+ } else if (value.equals("description-modify")) {
+ return CONTENTMODIFY;
+ } else if (value.equals("session-accept")) {
+ return SESSIONACCEPT;
+ } else if (value.equals("session-info")) {
+ return SESSIONINFO;
+ } else if (value.equals("session-initiate")) {
+ return SESSIONINITIATE;
+ } else if (value.equals("session-redirect")) {
+ return SESSIONACCEPT;
+ } else if (value.equals("session-extend")) {
+ return SESSIONEXTEND;
+ } else if (value.equals("session-reduce")) {
+ return SESSIONREDUCE;
+ } else if (value.equals("session-terminate")) {
+ return SESSIONTERMINATE;
+ } else if (value.equals("transport-accept")) {
+ return TRANSPORTACCEPT;
+ } else if (value.equals("transport-decline")) {
+ return TRANSPORTDECLINE;
+ } else if (value.equals("transport-info")) {
+ return TRANSPORTINFO;
+ } else if (value.equals("transport-modify")) {
+ return TRANSPORTMODIFY;
+ }
+ }
+ return null;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#hashCode()
+ */
+ public int hashCode() {
+ final int PRIME = 31;
+ int result = 1;
+ result = PRIME * result + (value == null ? 0 : value.hashCode());
+ return result;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see java.lang.Object#equals(java.lang.Object)
+ */
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ final Action other = (Action) obj;
+ if (value == null) {
+ if (other.value != null) {
+ return false;
+ }
+ } else if (!value.equals(other.value)) {
+ return false;
+ }
+ return true;
+ }
+ }
+}

Back to the top