/**
*
*/
package com.beem.project.beem.service;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smackx.ServiceDiscoveryManager;
import org.jivesoftware.smackx.jingle.JingleManager;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.util.Log;
import com.beem.project.beem.BeemException;
import com.beem.project.beem.service.aidl.IBeemConnectionListener;
import com.beem.project.beem.service.aidl.IRoster;
import com.beem.project.beem.service.aidl.IXmppConnection;
/**
* This class implements an adapter for XMPPConnection.
* @author darisk
*/
public class XMPPConnectionAdapter extends IXmppConnection.Stub {
private static final String TAG = "XMPPConnectionAdapter";
private XMPPConnection mAdaptee;
private BeemException mLastException;
private String mLogin;
private String mPassword;
private RosterAdapter mRoster;
private RemoteCallbackList<IBeemConnectionListener> mRemoteConnListeners =
new RemoteCallbackList<IBeemConnectionListener>();
private ConnexionListenerAdapter mConListener = new ConnexionListenerAdapter();
/**
* Constructor.
* @param con The connection to adapt
* @param login The login to use
* @param password The password to use
*/
public XMPPConnectionAdapter(final XMPPConnection con, final String login, final String password) {
mAdaptee = con;
mLogin = login;
mPassword = password;
}
/**
* Constructor.
* @param serviceName name of the service to connect to
* @param login login to use on connect
* @param password password to use on connect
*/
public XMPPConnectionAdapter(final String serviceName, final String login, final String password) {
this(new XMPPConnection(serviceName), login, password);
}
/**
* Constructor.
* @param config Configuration to use in order to connect
* @param login login to use on connect
* @param password password to use on connect
*/
public XMPPConnectionAdapter(final ConnectionConfiguration config, final String login, final String password) {
this(new XMPPConnection(config), login, password);
}
/**
* {@inheritDoc}
*/
@Override
public boolean connectSync() throws RemoteException {
try {
mAdaptee.connect();
mAdaptee.addConnectionListener(mConListener);
mAdaptee.login(mLogin, mPassword, "BEEM");
// TODO find why this cause a null pointer exception
// this.initFeatures(); // pour declarer les features xmpp qu'on supporte
mLastException = null;
triggerAsynchronousConnectEvent();
return true;
} catch (XMPPException e) {
mLastException = new BeemException(e);
}
return false;
}
/**
* {@inheritDoc}
*/
@Override
public boolean disconnect() {
mAdaptee.disconnect();
mLastException = null;
return true;
}
/**
* {@inheritDoc}
*/
@Override
public IRoster getRoster() throws RemoteException {
if (mRoster != null)
return mRoster;
Roster adap = mAdaptee.getRoster();
if (adap == null)
return null;
mRoster = new RosterAdapter(adap);
return mRoster;
}
/**
* {@inheritDoc}
*/
@Override
public final void connectAsync() throws RemoteException {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
connectSync();
} catch (RemoteException e) {
Log.e(TAG, "Error while connecting", e);
}
}
});
t.start();
}
/**
* {@inheritDoc}
*/
@Override
public void addConnectionListener(IBeemConnectionListener listen) throws RemoteException {
if (listen != null)
mRemoteConnListeners.register(listen);
}
/**
* {@inheritDoc}
*/
@Override
public void removeConnectionListener(IBeemConnectionListener listen) throws RemoteException {
if (listen != null)
mRemoteConnListeners.unregister(listen);
}
/**
* Trigger Connection event.
*/
private void triggerAsynchronousConnectEvent() {
mConListener.onConnect();
}
/**
* Listener for XMPP connection events.
* It will calls the remote listeners for connexion events.
* @author darisk
*/
private class ConnexionListenerAdapter implements ConnectionListener {
/**
* Defaut constructor.
*/
public ConnexionListenerAdapter() {
// TODO Auto-generated constructor stub
}
/**
* Method to execute when a connection event occurs.
*/
public void onConnect() {
final int n = mRemoteConnListeners.beginBroadcast();
for (int i = 0; i < n; i++) {
IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i);
try {
listener.onConnect();
} catch (RemoteException e) {
// The RemoteCallbackList will take care of removing the
// dead listeners.
Log.w(TAG, "Error while triggering remote connection listeners", e);
}
}
mRemoteConnListeners.finishBroadcast();
}
/**
* {@inheritDoc}
*/
@Override
public void connectionClosed() {
final int n = mRemoteConnListeners.beginBroadcast();
for (int i = 0; i < n; i++) {
IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i);
try {
listener.connectionClosed();
} catch (RemoteException e) {
// The RemoteCallbackList will take care of removing the
// dead listeners.
Log.w(TAG, "Error while triggering remote connection listeners", e);
}
}
mRemoteConnListeners.finishBroadcast();
}
/**
* {@inheritDoc}
*/
@Override
public void connectionClosedOnError(Exception arg0) {
final int n = mRemoteConnListeners.beginBroadcast();
for (int i = 0; i < n; i++) {
IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i);
try {
listener.connectionClosedOnError();
} catch (RemoteException e) {
// The RemoteCallbackList will take care of removing the
// dead listeners.
Log.w(TAG, "Error while triggering remote connection listeners", e);
}
}
mRemoteConnListeners.finishBroadcast();
}
/**
* {@inheritDoc}
*/
@Override
public void reconnectingIn(int arg0) {
final int n = mRemoteConnListeners.beginBroadcast();
for (int i = 0; i < n; i++) {
IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i);
try {
listener.reconnectingIn(arg0);
} catch (RemoteException e) {
// The RemoteCallbackList will take care of removing the
// dead listeners.
}
}
mRemoteConnListeners.finishBroadcast();
}
/**
* {@inheritDoc}
*/
@Override
public void reconnectionFailed(Exception arg0) {
final int r = mRemoteConnListeners.beginBroadcast();
for (int i = 0; i < r; i++) {
IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i);
try {
listener.reconnectionFailed();
} catch (RemoteException e) {
// The RemoteCallbackList will take care of removing the
// dead listeners.
Log.w(TAG, "Error while triggering remote connection listeners", e);
}
}
mRemoteConnListeners.finishBroadcast();
}
/**
* {@inheritDoc}
*/
@Override
public void reconnectionSuccessful() {
final int n = mRemoteConnListeners.beginBroadcast();
for (int i = 0; i < n; i++) {
IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i);
try {
listener.reconnectionSuccessful();
} catch (RemoteException e) {
// The RemoteCallbackList will take care of removing the
// dead listeners.
Log.w(TAG, "Error while triggering remote connection listeners", e);
}
}
mRemoteConnListeners.finishBroadcast();
}
}
/**
* enregistre les features dispo dans notre version Liste de features que Telepathy supporte.
* "http://www.google.com/xmpp/protocol/session" "http://www.google.com/transport/p2p"
* "http://jabber.org/protocol/jingle" "http://jabber.org/protocol/chatstates" "http://jabber.org/protocol/nick"
* "http://jabber.org/protocol/nick+notify" "http://jabber.org/protocol/si" "ttp://jabber.org/protocol/ibb"
* "ttp://telepathy.freedesktop.org/xmpp/tubes" "http://www.google.com/xmpp/protocol/voice/v1"
* "http://jabber.org/protocol/jingle/description/audio" "http://jabber.org/protocol/jingle/description/video" Liste
* de features que pidgin `supporte' (on notera la cradence de l'annonce): "jabber:iq:last" "jabber:iq:oob"
* "jabber:iq:time" "jabber:iq:version" "jabber:x:conference" "urn:xmpp:attention:0" "urn:xmpp:bob" "urn:xmpp:ping"
* "xmpp:urn:time" "http://jabber.org/protocol/bytestreams" "http://jabber.org/protocol/disco#info"
* "http://jabber.org/protocol/disco#items" "http://jabber.org/protocol/ibb" "http://jabber.org/protocol/muc"
* "http://jabber.org/protocol/muc#user" "http://jabber.org/protocol/si"
* "http://jabber.org/protocol/si/profile/file-transfer" "http://jabber.org/protocol/xhtml-im"
* "http://www.xmpp.org/extensions/xep-0199.html#ns" "http://jabber.org/protocol/mood"
* "http://jabber.org/protocol/mood+notify" "http://jabber.org/protocol/nick"
* "http://jabber.org/protocol/nick+notify" "http://jabber.org/protocol/tune"
* "http://jabber.org/protocol/tune+notify" "http://www.xmpp.org/extensions/xep-0084.html#ns-metadata"
* "http://www.xmpp.org/extensions/xep-0084.html#ns-data"
* "http://www.xmpp.org/extensions/xep-0084.html#ns-metadata+notify"
* "http://www.xmpp.org/extensions/xep-0167.html#ns" << Jingle RTP Sessions
*/
private void initFeatures() {
JingleManager.setJingleServiceEnabled();
ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(mAdaptee);
sdm.addFeature("http://jabber.org/protocol/disco#info");
// sdm.addFeature("http://jabber.org/protocol/nick");
}
}