/**
*
*/
package com.beem.project.beem.service;
import org.jivesoftware.smack.ConnectionConfiguration;
import org.jivesoftware.smack.ConnectionCreationListener;
import org.jivesoftware.smack.ConnectionListener;
import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.XMPPConnection;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.XMPPError;
import org.jivesoftware.smackx.ChatStateManager;
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.BeemService;
import com.beem.project.beem.service.aidl.IBeemConnectionListener;
import com.beem.project.beem.service.aidl.IChatManager;
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 IChatManager mChatManager;
private String mLogin;
private String mPassword;
private RosterAdapter mRoster;
private Object mLastException;
private BeemService mService;
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, BeemService service) {
mAdaptee = con;
mLogin = login;
mPassword = password;
mService = service;
}
/**
* 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, BeemService service) {
this(new XMPPConnection(serviceName), login, password, service);
}
/**
* 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, BeemService service) {
this(new XMPPConnection(config), login, password, service);
}
/**
* {@inheritDoc}
*/
@Override
public boolean connectSync() throws RemoteException {
try {
mAdaptee.connect();
mAdaptee.addConnectionListener(mConListener);
mAdaptee.login(mLogin, mPassword, "BEEM");
mChatManager = new BeemChatManager(mAdaptee.getChatManager(), mService);
// TODO find why this cause a null pointer exception
this.initFeatures(); // pour declarer les features xmpp qu'on supporte
ChatStateManager.getInstance(mAdaptee);
mLastException = null;
triggerAsynchronousConnectEvent();
return true;
} catch (XMPPException e) {
Log.e(TAG, "Error while connecting", e);
mConListener.connectionFailed(e.getXMPPError().getMessage()); //
}
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);
}
/**
* {@inheritDoc}
*/
@Override
public IChatManager getChatManager() throws RemoteException {
return mChatManager;
}
/**
* Trigger Connection event.
*/
private void triggerAsynchronousConnectEvent() {
mConListener.onConnect();
}
/**
* enregistre les features dispo dans notre version Liste de features que Telepathy supporte.
*/
private void initFeatures() {
JingleManager.setJingleServiceEnabled();
ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(mAdaptee);
if (sdm == null)
sdm = new ServiceDiscoveryManager(mAdaptee);
sdm.addFeature("http://jabber.org/protocol/disco#info");
// sdm.addFeature("http://jabber.org/protocol/nick");
}
/**
* 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() {
mRoster = null;
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) {
mRoster = null;
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.
Log.w(TAG, "Error while triggering remote connection listeners", e);
}
}
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();
}
public void connectionFailed(String errorMsg) {
Log.i(TAG, "Connection Failed");
final int n = mRemoteConnListeners.beginBroadcast();
for (int i = 0; i < n; i++) {
IBeemConnectionListener listener = mRemoteConnListeners.getBroadcastItem(i);
try {
listener.connectionFailed(errorMsg);
} 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();
}
}
/**
* Returns true if currently authenticated by successfully calling the login method.
* @return true when successfully authenticated
*/
public boolean isAuthentificated() {
return mAdaptee.isAuthenticated();
}
public XMPPConnection getAdaptee() {
return mAdaptee;
}
public BeemService getContext() {
return mService;
}
}