Complete XEP-0115. see #286
authorDa Risk <darisk972@gmail.com>
Mon, 26 Jul 2010 01:21:28 +0200
changeset 794 5dd9d68b6ad3
parent 793 4fb9df09ffdf
child 795 b2572c048dd7
Complete XEP-0115. see #286 Your capability is now calculate and send in each presence stanza. Still needs to use a disk cache to store the capabilities.
src/com/beem/project/beem/service/XmppConnectionAdapter.java
src/com/beem/project/beem/smack/caps/CapsExtension.java
src/com/beem/project/beem/smack/caps/CapsManager.java
src/com/beem/project/beem/smack/caps/CapsProvider.java
src/com/beem/project/beem/smack/caps/package-info.java
--- a/src/com/beem/project/beem/service/XmppConnectionAdapter.java	Thu Jul 22 23:34:36 2010 +0200
+++ b/src/com/beem/project/beem/service/XmppConnectionAdapter.java	Mon Jul 26 01:21:28 2010 +0200
@@ -388,6 +388,8 @@
      * enregistre les features dispo dans notre version Liste de features que Telepathy supporte.
      */
     private void initFeatures() {
+	ServiceDiscoveryManager.setIdentityName("Beem");
+	ServiceDiscoveryManager.setIdentityType("phone");
 	ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(mAdaptee);
 	if (sdm == null)
 	    sdm = new ServiceDiscoveryManager(mAdaptee);
@@ -396,6 +398,7 @@
 	sdm.addFeature("http://jabber.org/protocol/caps");
 	mChatStateManager = ChatStateManager.getInstance(mAdaptee);
 	CapsManager caps = new CapsManager(sdm, mAdaptee);
+	caps.setNode("http://www.beem-project.com");
     }
 
     /**
--- a/src/com/beem/project/beem/smack/caps/CapsExtension.java	Thu Jul 22 23:34:36 2010 +0200
+++ b/src/com/beem/project/beem/smack/caps/CapsExtension.java	Mon Jul 26 01:21:28 2010 +0200
@@ -1,7 +1,57 @@
+/*
+    BEEM is a videoconference application on the Android Platform.
+
+    Copyright (C) 2009 by Frederic-Charles Barthelery,
+                          Jean-Manuel Da Silva,
+                          Nikita Kozlov,
+                          Philippe Lago,
+                          Jean Baptiste Vergely,
+                          Vincent Veronis.
+
+    This file is part of BEEM.
+
+    BEEM is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    BEEM is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with BEEM.  If not, see <http://www.gnu.org/licenses/>.
+
+    Please send bug reports with examples or suggestions to
+    contact@beem-project.com or http://dev.beem-project.com/
+
+    Epitech, hereby disclaims all copyright interest in the program "Beem"
+    written by Frederic-Charles Barthelery,
+               Jean-Manuel Da Silva,
+               Nikita Kozlov,
+               Philippe Lago,
+               Jean Baptiste Vergely,
+               Vincent Veronis.
+
+    Nicolas Sadirac, November 26, 2009
+    President of Epitech.
+
+    Flavien Astraud, November 26, 2009
+    Head of the EIP Laboratory.
+
+*/
+
 package com.beem.project.beem.smack.caps;
 
 import org.jivesoftware.smack.packet.PacketExtension;
 
+/**
+ * This extension represents a capability of XEP-0115.
+ *
+ * @author 	Frédéric Barthéléry
+ * @version 	$Revision$
+ */
 public class CapsExtension implements PacketExtension {
 
     private String mVer;
@@ -10,69 +60,117 @@
     private String mExt;
 
 
-    public CapsExtension(String hash, String node, String ver) {
+    /**
+     * Create a CapsExtension.
+     *
+     * @param hash The value of the hash attribute.
+     * @param node the value of the node attribute
+     * @param ver the value of the ver attribute.
+     */
+    public CapsExtension(final String hash, final String node, final String ver) {
 	mHash = hash;
 	mNode = node;
 	mVer = ver;
     }
 
-    public String getVer(){
+    /**
+     * Get the ver attribute value.
+     *
+     * @return the value of the ver attribute.
+     */
+    public String getVer() {
 	return mVer;
     }
 
-    public String getHash(){
+    /**
+     * Get the hash attribute value.
+     *
+     * @return the value of the hash attribute.
+     */
+    public String getHash() {
 	return mHash;
     }
 
-    public String getNode(){
+    /**
+     * Get the node attribute value.
+     *
+     * @return the value of the node attribute.
+     */
+    public String getNode() {
 	return mNode;
     }
 
-    public String getExt(){
+    /**
+     * Get the ext attribute value.
+     *
+     * @return the value of the ext attribute.
+     */
+    public String getExt() {
 	return mExt;
     }
 
+    /**
+     * Set the hash attribute.
+     *
+     * @param hash the value of hash
+     */
     public void setHash(String hash) {
 	mHash = hash;
     }
 
+    /**
+     * Set the ver attribute.
+     *
+     * @param ver the value of ver
+     */
     public void setVer(String ver) {
 	mVer = ver;
     }
 
+    /**
+     * Set the node attribute.
+     *
+     * @param node the value of node
+     */
     public void setNode(String node) {
 	mNode = node;
     }
 
+    /**
+     * Set the ext attribute.
+     *
+     * @param ext the value of ext
+     */
     public void setExt(String ext) {
 	mExt = ext;
     }
 
     @Override
-     public String getElementName() {
+    public String getElementName() {
 	return "c";
-     }
+    }
+
+    @Override
+    public String getNamespace() {
+	return "http://jabber.org/protocol/caps";
+    }
 
     @Override
-     public String getNamespace() {
-	 return "http://jabber.org/protocol/caps";
-     }
-		
-    @Override
-     public String toXML(){
-	 StringBuilder b = new StringBuilder("<");
-	 b.append(getElementName());
-	 b.append(" xmlns=\"").append(getNamespace()).append("\" ");
-	 if (mHash != null){
-	     b.append("hash=\"").append(mHash).append("\" ");
-	 }
-	 if (mNode != null)
-	     b.append("node=\"").append(mNode).append("\" ");
-	 if (mVer != null)
-	     b.append("ver=\"").append(mVer).append("\" ");
-	 if (mExt!= null)
-	     b.append("ext=\"").append(mExt).append("\" ");
-	 b.append("/>");
-	 return b.toString();
-     }
+    public String toXML() {
+	StringBuilder b = new StringBuilder("<");
+	b.append(getElementName());
+	b.append(" xmlns=\"").append(getNamespace()).append("\" ");
+	if (mHash != null) {
+	    b.append("hash=\"").append(mHash).append("\" ");
+	}
+	if (mNode != null)
+	    b.append("node=\"").append(mNode).append("\" ");
+	if (mVer != null)
+	    b.append("ver=\"").append(mVer).append("\" ");
+	if (mExt != null)
+	    b.append("ext=\"").append(mExt).append("\" ");
+	b.append("/>");
+	return b.toString();
+    }
+
 }
--- a/src/com/beem/project/beem/smack/caps/CapsManager.java	Thu Jul 22 23:34:36 2010 +0200
+++ b/src/com/beem/project/beem/smack/caps/CapsManager.java	Mon Jul 26 01:21:28 2010 +0200
@@ -1,15 +1,60 @@
+/*
+    BEEM is a videoconference application on the Android Platform.
 
+    Copyright (C) 2009 by Frederic-Charles Barthelery,
+                          Jean-Manuel Da Silva,
+                          Nikita Kozlov,
+                          Philippe Lago,
+                          Jean Baptiste Vergely,
+                          Vincent Veronis.
+
+    This file is part of BEEM.
+
+    BEEM is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    BEEM is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with BEEM.  If not, see <http://www.gnu.org/licenses/>.
+
+    Please send bug reports with examples or suggestions to
+    contact@beem-project.com or http://dev.beem-project.com/
+
+    Epitech, hereby disclaims all copyright interest in the program "Beem"
+    written by Frederic-Charles Barthelery,
+               Jean-Manuel Da Silva,
+               Nikita Kozlov,
+               Philippe Lago,
+               Jean Baptiste Vergely,
+               Vincent Veronis.
+
+    Nicolas Sadirac, November 26, 2009
+    President of Epitech.
+
+    Flavien Astraud, November 26, 2009
+    Head of the EIP Laboratory.
+
+*/
 package com.beem.project.beem.smack.caps;
 
 import org.jivesoftware.smack.Connection;
+import org.jivesoftware.smack.PacketInterceptor;
 import org.jivesoftware.smack.XMPPException;
 import org.jivesoftware.smackx.packet.DiscoverInfo;
 import org.jivesoftware.smack.packet.Packet;
 import org.jivesoftware.smack.packet.PacketExtension;
+import org.jivesoftware.smack.packet.Presence;
 import org.jivesoftware.smackx.ServiceDiscoveryManager;
 import org.jivesoftware.smack.util.collections.ReferenceMap;
 import org.jivesoftware.smack.PacketListener;
 import org.jivesoftware.smack.filter.PacketFilter;
+import org.jivesoftware.smack.filter.PacketTypeFilter;
 import org.jivesoftware.smack.filter.PacketExtensionFilter;
 
 import java.util.Map;
@@ -23,25 +68,41 @@
 
 import org.jivesoftware.smack.util.StringUtils;
 
+/**
+ * Capabilities manager to implements XEP-0115.
+ *
+ * @author 	Frédéric Barthéléry
+ * @version 	$Revision$
+ */
 public class CapsManager {
     // the verCache should be stored on disk
-    Map<String, DiscoverInfo> mVerCache = new ReferenceMap<String, DiscoverInfo>();
-    Map<String, DiscoverInfo> mJidCache = new ReferenceMap<String, DiscoverInfo>();
+    private Map<String, DiscoverInfo> mVerCache = new ReferenceMap<String, DiscoverInfo>();
+    private Map<String, DiscoverInfo> mJidCache = new ReferenceMap<String, DiscoverInfo>();
 
     private ServiceDiscoveryManager mSdm;
     private Connection mConnection;
+    private String mNode;
     private List<String> mSupportedAlgorithm = new ArrayList<String>();
 
-    public CapsManager(ServiceDiscoveryManager sdm, Connection conn) {
+    /**
+     * Create a CapsManager.
+     *
+     * @param sdm The service discovery manager to use.
+     * @param conn The connection to manage.
+     */
+    public CapsManager(final ServiceDiscoveryManager sdm, final Connection conn) {
 	mSdm = sdm;
 	mConnection = conn;
 	init();
     }
 
+    /**
+     * Initialize this CapsManageer.
+     */
     private void init() {
 	initSupportedAlgorithm();
 	PacketFilter filter = new PacketExtensionFilter("c", "http://jabber.org/protocol/caps");
-	mConnection.addPacketListener( new PacketListener() {
+	mConnection.addPacketListener(new PacketListener() {
 	    public void processPacket(Packet packet) {
 		PacketExtension p = packet.getExtension("c", "http://jabber.org/protocol/caps");
 		CapsExtension caps = (CapsExtension) p;
@@ -49,12 +110,41 @@
 		    validate(packet.getFrom(), caps.getVer(), caps.getHash());
 	    }
 	}, filter);
+	mConnection.addPacketInterceptor(new PacketInterceptor() {
+
+	    public void interceptPacket(Packet packet) {
+		DiscoverInfo info = getOwnInformation();
+		if (mSupportedAlgorithm.size() > 0) {
+		    try {
+			String algo = mSupportedAlgorithm.get(0);
+			String ver = calculateVer(info, algo);
+			CapsExtension caps = new CapsExtension(algo, mNode, ver);
+			packet.addExtension(caps);
+		    } catch (NoSuchAlgorithmException e) {
+			e.printStackTrace();
+		    }
+		}
+	    }
+	}, new PacketTypeFilter(Presence.class));
     }
 
+    /**
+     * Get the discover info associated with a ver attribute.
+     *
+     * @param ver the ver attribute.
+     * @return the discover info or null if it was not cached.
+     */
     public DiscoverInfo getDiscoverInfo(String ver) {
 	return mVerCache.get(ver);
     }
 
+    /**
+     * Get the discover info of a contact.
+     *
+     * @param jid the jid of the contact.
+     * @param ver the ver attribute of the contact capability.
+     * @return The info of the client null if the info was not cached.
+     */
     public DiscoverInfo getDiscoverInfo(String jid, String ver) {
 	DiscoverInfo info = mVerCache.get(ver);
 	if (info == null)
@@ -62,13 +152,23 @@
 	return info;
     }
 
-    /** 
-     * 
-     * 
-     * @param jid 
-     * @param ver 
-     * @param hashMethod 
-     * @return 
+    /**
+     * Set the node attribute to send in your capability.
+     * This is usually an uri to identify the client.
+     *
+     * @param node the node attribute to set.
+     */
+    public void setNode(String node) {
+	mNode = node;
+    }
+
+    /**
+     * Validate the ver attribute of a received capability.
+     *
+     * @param jid the jid of the sender of the capability.
+     * @param ver the ver attribute of the capability.
+     * @param hashMethod the hash algorithm to use to calculate ver
+     * @return true if the ver attribute is valid false otherwise.
      */
     private boolean validate(String jid, String ver, String hashMethod) {
 	try {
@@ -84,43 +184,56 @@
 	    return res;
 	} catch (XMPPException e) {
 	    e.printStackTrace();
-	    return false;
 	} catch (NoSuchAlgorithmException e) {
 	    e.printStackTrace();
-	    return false;
 	}
+	return false;
     }
 
+    /**
+     * Calculate the ver attribute.
+     *
+     * @param info The discover info to calculate the ver.
+     * @param hashMethod the hash algorithm to use.
+     * @return the value of the ver attribute
+     * @throws NoSuchAlgorithmException if the hash algorithm is not supported.
+     */
     private String calculateVer(DiscoverInfo info, String hashMethod) throws NoSuchAlgorithmException {
-	StringBuilder S = new StringBuilder();
-	for(DiscoverInfo.Identity identity : getSortedIdentity(info)) {
+	StringBuilder s = new StringBuilder();
+	for (DiscoverInfo.Identity identity : getSortedIdentity(info)) {
 	    String c = identity.getCategory();
 	    if (c != null)
-		S.append(c);
-	    S.append('/');
+		s.append(c);
+	    s.append('/');
 	    c = identity.getType();
 	    if (c != null)
-		S.append(c);
-	    S.append('/');
+		s.append(c);
+	    s.append('/');
 	    // Should add lang but it is not available
 //             c = identity.getType();
 //             if (c != null)
 //                 S.append(c);
-	    S.append('/');
+	    s.append('/');
 	    c = identity.getName();
 	    if (c != null)
-		S.append(c);
-	    S.append('<');
+		s.append(c);
+	    s.append('<');
 	}
 	for (String f : getSortedFeature(info)) {
-	    S.append(f);
-	    S.append('<');
+	    s.append(f);
+	    s.append('<');
 	}
 	// Should add data form (XEP 0128) but it is not available
-	byte[] hash = getHash(hashMethod, S.toString().getBytes());
+	byte[] hash = getHash(hashMethod, s.toString().getBytes());
 	return StringUtils.encodeBase64(hash);
     }
 
+    /**
+     * Get the identities sorted correctly to calculate the ver attribute.
+     *
+     * @param info the DiscoverInfo containing the identities
+     * @return the sorted list of identities.
+     */
     private List<DiscoverInfo.Identity> getSortedIdentity(DiscoverInfo info) {
 	List<DiscoverInfo.Identity> result = new ArrayList<DiscoverInfo.Identity>();
 	Iterator<DiscoverInfo.Identity> it = info.getIdentities();
@@ -152,6 +265,12 @@
 	return result;
     }
 
+    /**
+     * Get the features sorted correctly to calculate the ver attribute.
+     *
+     * @param info the DiscoverInfo containing the features
+     * @return the sorted list of features.
+     */
     private List<String> getSortedFeature(DiscoverInfo info) {
 	List<String> result = new ArrayList<String>();
 	Iterator<DiscoverInfo.Feature> it = info.getFeatures();
@@ -163,18 +282,47 @@
 	return result;
     }
 
-    private byte[] getHash(String algo, byte[] data) throws NoSuchAlgorithmException {
-	    MessageDigest md = MessageDigest.getInstance(algo);
-	    return md.digest(data);
+    /**
+     * Get the Discover Information send by your own connection.
+     *
+     * @return your own DiscoverInfo
+     */
+    private DiscoverInfo getOwnInformation() {
+	DiscoverInfo result = new DiscoverInfo();
+	DiscoverInfo.Identity id = new DiscoverInfo.Identity("client", ServiceDiscoveryManager.getIdentityName());
+	id.setType(ServiceDiscoveryManager.getIdentityType());
+	result.addIdentity(id);
+	Iterator<String> it = mSdm.getFeatures();
+	while (it.hasNext()) {
+	    result.addFeature(it.next());
+	}
+	return result;
     }
 
+    /**
+     * Calculate a Hash (digest).
+     *
+     * @param algo the algorithm to use
+     * @param data the data to compute
+     * @return the resulting hash
+     * @throws NoSuchAlgorithmException if the algorithm is not supported
+     */
+    private byte[] getHash(String algo, byte[] data) throws NoSuchAlgorithmException {
+	MessageDigest md = MessageDigest.getInstance(algo);
+	return md.digest(data);
+    }
+
+    /**
+     * Initialize a list of supported Hash algorithm.
+     */
     private void initSupportedAlgorithm() {
-	String algo[] = new String[] {"md2", "md5", "sha-1", "sha-224", "sha-256", "sha-384", "sha-512" };
+	// sort by ""preference"
+	String[] algo = new String[] {"sha-1", "md2", "md5", "sha-224", "sha-256", "sha-384", "sha-512" };
 	for (String a : algo) {
 	    try {
 		MessageDigest md = MessageDigest.getInstance(a);
 		mSupportedAlgorithm.add(a);
-	    } catch(NoSuchAlgorithmException e) {
+	    } catch (NoSuchAlgorithmException e) {
 		System.err.println("Hash algorithm " + a + " not supported");
 	    }
 	}
--- a/src/com/beem/project/beem/smack/caps/CapsProvider.java	Thu Jul 22 23:34:36 2010 +0200
+++ b/src/com/beem/project/beem/smack/caps/CapsProvider.java	Mon Jul 26 01:21:28 2010 +0200
@@ -1,12 +1,65 @@
+/*
+    BEEM is a videoconference application on the Android Platform.
 
+    Copyright (C) 2009 by Frederic-Charles Barthelery,
+                          Jean-Manuel Da Silva,
+                          Nikita Kozlov,
+                          Philippe Lago,
+                          Jean Baptiste Vergely,
+                          Vincent Veronis.
+
+    This file is part of BEEM.
+
+    BEEM is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    BEEM is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with BEEM.  If not, see <http://www.gnu.org/licenses/>.
+
+    Please send bug reports with examples or suggestions to
+    contact@beem-project.com or http://dev.beem-project.com/
+
+    Epitech, hereby disclaims all copyright interest in the program "Beem"
+    written by Frederic-Charles Barthelery,
+               Jean-Manuel Da Silva,
+               Nikita Kozlov,
+               Philippe Lago,
+               Jean Baptiste Vergely,
+               Vincent Veronis.
+
+    Nicolas Sadirac, November 26, 2009
+    President of Epitech.
+
+    Flavien Astraud, November 26, 2009
+    Head of the EIP Laboratory.
+
+*/
 package com.beem.project.beem.smack.caps;
 
 import org.xmlpull.v1.XmlPullParser;
 import org.jivesoftware.smack.provider.PacketExtensionProvider;
 import org.jivesoftware.smack.packet.PacketExtension;
 
+/**
+ * PacketExtensionProvider for XEP-0115.
+ * This provider parse c element of namespace
+ * http://jabber.org/protocol/caps which represents a capability of XEP-0115
+ *
+ */
 public class CapsProvider implements PacketExtensionProvider {
 
+    /**
+     * Constructor.
+     */
+    public CapsProvider() { }
+
     @Override
     public PacketExtension parseExtension(XmlPullParser parser) {
 	String ver = parser.getAttributeValue("", "ver");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/beem/project/beem/smack/caps/package-info.java	Mon Jul 26 01:21:28 2010 +0200
@@ -0,0 +1,48 @@
+/*
+    BEEM is a videoconference application on the Android Platform.
+
+    Copyright (C) 2009 by Frederic-Charles Barthelery,
+                          Jean-Manuel Da Silva,
+                          Nikita Kozlov,
+                          Philippe Lago,
+                          Jean Baptiste Vergely,
+                          Vincent Veronis.
+
+    This file is part of BEEM.
+
+    BEEM is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    BEEM is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with BEEM.  If not, see <http://www.gnu.org/licenses/>.
+
+    Please send bug reports with examples or suggestions to
+    contact@beem-project.com or http://dev.beem-project.com/
+
+    Epitech, hereby disclaims all copyright interest in the program "Beem"
+    written by Frederic-Charles Barthelery,
+               Jean-Manuel Da Silva,
+               Nikita Kozlov,
+               Philippe Lago,
+               Jean Baptiste Vergely,
+               Vincent Veronis.
+
+    Nicolas Sadirac, November 26, 2009
+    President of Epitech.
+
+    Flavien Astraud, November 26, 2009
+    Head of the EIP Laboratory.
+
+*/
+
+/**
+ * This package contains implementation of XEP-0115.
+ */
+package com.beem.project.beem.smack.caps;