Implement a disk cache for Capabilities.
#286 almost done.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/com/beem/project/beem/service/BeemCapsManager.java Tue Aug 10 01:46:51 2010 +0200
@@ -0,0 +1,162 @@
+/*
+ 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.service;
+
+import org.jivesoftware.smack.Connection;
+import org.jivesoftware.smackx.packet.DiscoverInfo;
+import org.jivesoftware.smackx.ServiceDiscoveryManager;
+import org.jivesoftware.smack.util.PacketParserUtils;
+import org.xmlpull.v1.XmlPullParserFactory;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParser;
+
+import android.util.Log;
+import java.io.FileReader;
+import java.io.Reader;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.FileWriter;
+import java.io.Writer;
+
+import java.io.File;
+import java.io.IOException;
+
+import android.content.Context;
+
+import com.beem.project.beem.smack.caps.CapsManager;
+
+/**
+ * An implementation of CapsManager which keeps DiscoverInfo on the Cache directory of the android application.
+ */
+public class BeemCapsManager extends CapsManager {
+
+ private static final String TAG = "BeemCapsManager";
+
+ private Context mContext;
+ private File mCacheDir;
+ private XmlPullParser mParser;
+
+ /**
+ * Create a BeemCapsManager.
+ *
+ * @param sdm the ServiceDiscoveryManager to use
+ * @param conn the connection to use
+ * @param context the Android context to use to store data
+ */
+ public BeemCapsManager(final ServiceDiscoveryManager sdm, final Connection conn, final Context context) {
+ super(sdm, conn);
+ mContext = context;
+ initCacheDirectory();
+ }
+
+
+ @Override
+ protected DiscoverInfo load(String ver) {
+ File fver = new File(mCacheDir, ver);
+ try {
+ Reader fr = new BufferedReader(new FileReader(fver));
+ try {
+ if (mParser == null)
+ mParser = makeParser();
+ mParser.setInput(fr);
+ return (DiscoverInfo) PacketParserUtils.parsePacketExtension("query",
+ "http://jabber.org/protocol/disco#info", mParser);
+
+ } finally {
+ fr.close();
+ }
+ } catch (Exception e) {
+ // The parsePacketExtension throw Exception on error
+ Log.d(TAG, "Error while loading Capabilities " + ver, e);
+ }
+ return null;
+ }
+
+ @Override
+ protected void store(String ver, DiscoverInfo info) {
+ File fver = new File(mCacheDir, ver);
+ try {
+ Writer fw = new BufferedWriter(new FileWriter(fver));
+ try {
+ String data = info.toXML();
+ fw.write(data, 0, data.length());
+ } finally {
+ fw.close();
+ }
+ } catch (IOException e) {
+ Log.d(TAG, "Error while saving Capabilities " + ver, e);
+ }
+ }
+
+ @Override
+ protected boolean isInCache(String ver) {
+ boolean result = super.isInCache(ver);
+ if (!result) {
+ File fver = new File(mCacheDir, ver);
+ result = fver.exists();
+ }
+ return result;
+ }
+
+ /**
+ * Init the cache directory.
+ */
+ private void initCacheDirectory() {
+ File dir = mContext.getCacheDir();
+ mCacheDir = new File(dir, "capabilities");
+ mCacheDir.mkdir();
+ }
+
+ /**
+ * Make an Xml parser.
+ *
+ * @return the created xml parser.
+ * @throws XmlPullParserException if an error occurs while creating the parser.
+ */
+ private XmlPullParser makeParser() throws XmlPullParserException {
+ XmlPullParserFactory fact = XmlPullParserFactory.newInstance();
+ fact.setNamespaceAware(true);
+ return fact.newPullParser();
+ }
+}
--- a/src/com/beem/project/beem/service/XmppConnectionAdapter.java Mon Jul 26 01:21:28 2010 +0200
+++ b/src/com/beem/project/beem/service/XmppConnectionAdapter.java Tue Aug 10 01:46:51 2010 +0200
@@ -76,7 +76,6 @@
import com.beem.project.beem.ui.Subscription;
import com.beem.project.beem.utils.BeemBroadcastReceiver;
import com.beem.project.beem.utils.Status;
-import com.beem.project.beem.smack.caps.CapsManager;
/**
* This class implements an adapter for XMPPConnection.
@@ -397,7 +396,7 @@
sdm.addFeature("jabber:iq:privacy");
sdm.addFeature("http://jabber.org/protocol/caps");
mChatStateManager = ChatStateManager.getInstance(mAdaptee);
- CapsManager caps = new CapsManager(sdm, mAdaptee);
+ BeemCapsManager caps = new BeemCapsManager(sdm, mAdaptee, mService);
caps.setNode("http://www.beem-project.com");
}
--- a/src/com/beem/project/beem/smack/caps/CapsExtension.java Mon Jul 26 01:21:28 2010 +0200
+++ b/src/com/beem/project/beem/smack/caps/CapsExtension.java Tue Aug 10 01:46:51 2010 +0200
@@ -49,8 +49,6 @@
/**
* This extension represents a capability of XEP-0115.
*
- * @author Frédéric Barthéléry
- * @version $Revision$
*/
public class CapsExtension implements PacketExtension {
--- a/src/com/beem/project/beem/smack/caps/CapsManager.java Mon Jul 26 01:21:28 2010 +0200
+++ b/src/com/beem/project/beem/smack/caps/CapsManager.java Tue Aug 10 01:46:51 2010 +0200
@@ -70,9 +70,8 @@
/**
* Capabilities manager to implements XEP-0115.
+ * The DiscoverInfo are cached in memory.
*
- * @author Frédéric Barthéléry
- * @version $Revision$
*/
public class CapsManager {
// the verCache should be stored on disk
@@ -97,6 +96,76 @@
}
/**
+ * 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) {
+ info = load(ver);
+ if (info == null)
+ info = mJidCache.get(jid);
+ }
+ return info;
+ }
+
+ /**
+ * 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;
+ }
+
+ /**
+ * Load a persistent DiscoverInfo.
+ * The default implementation does nothing and always return null.
+ *
+ * @param ver the ver hash of the discoverInfo.
+ * @return The discover info or null if not present.
+ */
+ protected DiscoverInfo load(String ver) {
+ return null;
+ }
+
+ /**
+ * Store a DiscoverInfo for persistence.
+ * The default implementation does nothing.
+ *
+ * @param ver the ver hash of the DiscoverInfo
+ * @param info the DiscoverInfo to store
+ */
+ protected void store(String ver, DiscoverInfo info) {
+ }
+
+ /**
+ * Check if the discover info correspondig to the ver hash is in cache.
+ * This implementation checks the memory cache.
+ * If the info is not in cache it is necessary to request it from the network.
+ *
+ * @param ver the ver hash
+ * @return true if it is in cache false otherwise
+ */
+ protected boolean isInCache(String ver) {
+ return mVerCache.containsKey(ver);
+ }
+
+ /**
* Initialize this CapsManageer.
*/
private void init() {
@@ -104,10 +173,13 @@
PacketFilter filter = new PacketExtensionFilter("c", "http://jabber.org/protocol/caps");
mConnection.addPacketListener(new PacketListener() {
public void processPacket(Packet packet) {
+ if (packet.getFrom().equals(mConnection.getUser()))
+ return;
PacketExtension p = packet.getExtension("c", "http://jabber.org/protocol/caps");
CapsExtension caps = (CapsExtension) p;
- if (!mVerCache.containsKey(caps.getVer()))
+ if (!isInCache(caps.getVer())) {
validate(packet.getFrom(), caps.getVer(), caps.getHash());
+ }
}
}, filter);
mConnection.addPacketInterceptor(new PacketInterceptor() {
@@ -129,40 +201,6 @@
}
/**
- * 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)
- info = mJidCache.get(jid);
- return info;
- }
-
- /**
- * 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.
@@ -179,8 +217,10 @@
}
String v = calculateVer(info, hashMethod);
boolean res = v.equals(ver);
- if (res)
+ if (res) {
mVerCache.put(ver, info);
+ store(ver, info);
+ }
return res;
} catch (XMPPException e) {
e.printStackTrace();