package org.societies.comm.xmpp.client.impl; import static android.content.Context.BIND_AUTO_CREATE; import java.security.InvalidParameterException; import java.util.List; import org.societies.api.comm.xmpp.datatypes.Stanza; import org.societies.api.comm.xmpp.exceptions.CommunicationException; import org.societies.api.comm.xmpp.exceptions.XMPPError; import org.societies.api.comm.xmpp.interfaces.ICommCallback; import org.societies.api.identity.IIdentity; import org.societies.api.identity.IIdentityManager; import org.societies.api.identity.INetworkNode; import org.societies.api.identity.InvalidFormatException; import org.societies.identity.IdentityManagerImpl; import org.societies.interfaces.XMPPAgent; import org.societies.comm.android.ipc.MethodInvocationServiceConnection; import org.societies.comm.android.ipc.IMethodInvocation; import org.societies.comm.android.ipc.Stub; import org.jivesoftware.smack.packet.IQ; import org.jivesoftware.smack.packet.Message; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; import android.os.Messenger; import android.util.Log; public class ClientCommunicationMgr { private static final String LOG_TAG = ClientCommunicationMgr.class.getName(); private static final ComponentName serviceCN = new ComponentName("org.societies.comms", "org.societies.comms.AgentService"); // TODO private Context androidContext; private PacketMarshaller marshaller = new PacketMarshaller(); private ServiceConnection registerConnection; private MethodInvocationServiceConnection<XMPPAgent> miServiceConnection; protected IIdentityManager idm; public ClientCommunicationMgr(Context androidContext) { Log.d(LOG_TAG, ""); this.androidContext = androidContext; Intent intent = new Intent(); intent.setComponent(serviceCN); miServiceConnection = new MethodInvocationServiceConnection<XMPPAgent>(intent, androidContext, BIND_AUTO_CREATE, XMPPAgent.class); } public void register(final List<String> elementNames, final ICommCallback callback) { Log.d(LOG_TAG, "register element names"); for (String element : elementNames) { // Log.d(LOG_TAG, "register element: " + element); } final List<String> namespaces = callback.getXMLNamespaces(); marshaller.register(elementNames, callback.getXMLNamespaces(), callback.getJavaPackages()); registerConnection = new ServiceConnection() { public void onServiceConnected(ComponentName cn, IBinder binder) { XMPPAgent agent = (XMPPAgent)Stub.newInstance(new Class<?>[]{XMPPAgent.class}, new Messenger(binder)); agent.register(elementNames.toArray(new String[0]), namespaces.toArray(new String[0]), new CallbackAdapter(callback, androidContext, this, marshaller)); } public void onServiceDisconnected(ComponentName cn) { } }; bindService(registerConnection); } public void unregister(final List<String> elementNames, final ICommCallback callback) { Log.d(LOG_TAG, "unregister"); for (String element : elementNames) { // Log.d(LOG_TAG, "unregister element: " + element); } final List<String> namespaces = callback.getXMLNamespaces(); ServiceConnection connection = new ServiceConnection() { public void onServiceConnected(ComponentName cn, IBinder binder) { XMPPAgent agent = (XMPPAgent)Stub.newInstance(new Class<?>[]{XMPPAgent.class}, new Messenger(binder)); agent.unregister(elementNames.toArray(new String[0]), namespaces.toArray(new String[0])); try { Log.d(LOG_TAG, "unregister element names unbindService for : " + this.toString() + " " + System.currentTimeMillis()); androidContext.unbindService(this); Log.d(LOG_TAG, "unregister element names previous registration unbindService for: " + registerConnection.toString() + " " + System.currentTimeMillis()); androidContext.unbindService(registerConnection); } catch(Exception e) { Log.e(LOG_TAG, "Exception while unbinding service.", e); } } public void onServiceDisconnected(ComponentName cn) { } }; bindService(connection); } public boolean UnRegisterCommManager() { Log.d(LOG_TAG, "UnRegisterCommManager"); boolean rv; try { rv = (Boolean)miServiceConnection.invoke(new IMethodInvocation<XMPPAgent>() { public Object invoke(XMPPAgent agent) throws Throwable { return agent.UnRegisterCommManager(); } }); } catch (Throwable e) { throw new RuntimeException(e.getMessage(), e); } return rv; } public void sendMessage(Stanza stanza, Message.Type type, Object payload) throws CommunicationException { stanza.setFrom(getIdManager().getThisNetworkNode()); if (type==null) type = Message.Type.normal; if (payload == null) { throw new InvalidParameterException("Payload cannot be null"); } try { String xml = marshaller.marshallMessage(stanza, type, payload); sendMessage(xml); } catch (Exception e) { throw new CommunicationException("Error sending message", e); } } public void sendMessage(Stanza stanza, Object payload) throws CommunicationException { stanza.setFrom(getIdManager().getThisNetworkNode()); Log.d(LOG_TAG, "sendMessage stanza from : " + stanza.getFrom() + " to: " + stanza.getTo()); sendMessage(stanza, null, payload); } public void sendIQ(Stanza stanza, IQ.Type type, Object payload, ICommCallback callback) throws CommunicationException { stanza.setFrom(getIdManager().getThisNetworkNode()); Log.d(LOG_TAG, "sendIQ IQtype: " + type.toString() + " from: " + stanza.getFrom() + " to: " + stanza.getTo()); try { String xml = marshaller.marshallIQ(stanza, type, payload); sendIQ(xml, callback); } catch (Exception e) { throw new CommunicationException("Error sending IQ message", e); } } public IIdentity getIdentity() { Log.d(LOG_TAG, "getIdentity"); String identityJid = getIdentityJid(); Log.d(LOG_TAG, "getIdentity identity: " + identityJid); try { return IdentityManagerImpl.staticfromJid(identityJid); } catch (InvalidFormatException e) { throw new RuntimeException(e.getMessage(), e); } } public IIdentityManager getIdManager() { Log.d(LOG_TAG, "getIdManager"); if(idm == null) { try { idm = createIdentityManager(getIdentityJid(), getDomainAuthorityNode()); } catch (InvalidFormatException e) { throw new RuntimeException(e); } } return idm; } public String getItems(final IIdentity entity, final String node, final ICommCallback callback) throws CommunicationException { Log.d(LOG_TAG, "getItems for node: " + node); try { return (String)miServiceConnection.invokeAndKeepBound(new IMethodInvocation<XMPPAgent>() { public Object invoke(XMPPAgent agent) throws Throwable { return agent.getItems(entity.getJid(), node, new CallbackAdapter(callback, androidContext, miServiceConnection, marshaller)); } }); } catch (Throwable e) { if(e instanceof CommunicationException) throw (CommunicationException)e; else throw new CommunicationException(e.getMessage(), e); } } private void sendMessage(final String xml) { // Log.d(LOG_TAG, "sendMessage message" + xml); ServiceConnection connection = new ServiceConnection() { public void onServiceConnected(ComponentName cn, IBinder binder) { XMPPAgent agent = (XMPPAgent)Stub.newInstance(new Class<?>[]{XMPPAgent.class}, new Messenger(binder)); agent.sendMessage(xml); Log.d(LOG_TAG, "sendMessage unbindService for: " + this.toString() + " " + System.currentTimeMillis()); androidContext.unbindService(this); } public void onServiceDisconnected(ComponentName cn) { } }; bindService(connection); } private void sendIQ(final String xml, final ICommCallback callback) { // Log.d(LOG_TAG, "sendIQ message: " + xml); ServiceConnection connection = new ServiceConnection() { public void onServiceConnected(ComponentName cn, IBinder binder) { XMPPAgent agent = (XMPPAgent)Stub.newInstance(new Class<?>[]{XMPPAgent.class}, new Messenger(binder)); agent.sendIQ(xml, new CallbackAdapter(callback, androidContext, this, marshaller)); } public void onServiceDisconnected(ComponentName cn) { } }; bindService(connection); } private void bindService(ServiceConnection connection) { Log.d(LOG_TAG, "bindService bindService for: " + connection.toString() + " " + System.currentTimeMillis()); Intent intent = new Intent(); intent.setComponent(serviceCN); androidContext.bindService(intent, connection, BIND_AUTO_CREATE); } private String getIdentityJid() { Log.d(LOG_TAG, "getIdentityJid"); String identityJid; try { identityJid = (String)miServiceConnection.invoke(new IMethodInvocation<XMPPAgent>() { public Object invoke(XMPPAgent agent) throws Throwable { return agent.getIdentity(); } }); } catch (Throwable e) { throw new RuntimeException(e.getMessage(), e); } Log.d(LOG_TAG, "getIdentityJid: " + identityJid); return identityJid; } private String getDomainAuthorityNode() { Log.d(LOG_TAG, "getIdentityJid"); String daNode; try { daNode = (String)miServiceConnection.invoke(new IMethodInvocation<XMPPAgent>() { public Object invoke(XMPPAgent agent) throws Throwable { return agent.getDomainAuthorityNode(); } }); } catch (Throwable e) { throw new RuntimeException(e.getMessage(), e); } return daNode; } public boolean isConnected() { Log.d(LOG_TAG, "isConnected"); boolean connected; try { connected = (Boolean)miServiceConnection.invoke(new IMethodInvocation<XMPPAgent>() { public Object invoke(XMPPAgent agent) throws Throwable { Log.d(LOG_TAG, "connect ?: " + agent.isConnected()); return agent.isConnected(); } }); } catch (Throwable e) { throw new RuntimeException(e.getMessage(), e); } return connected; } public INetworkNode newMainIdentity(final String identifier, final String domain, final String password) throws XMPPError { // TODO this takes no credentials in a private/public key case Log.d(LOG_TAG, "newMainIdentity domain: " + domain + " identifier: " + identifier + " password: " + password); try { String rv = (String)miServiceConnection.invoke(new IMethodInvocation<XMPPAgent>() { public Object invoke(XMPPAgent agent) throws Throwable { return agent.newMainIdentity(identifier, domain, password); } }); if(rv == null) return null; idm = createIdentityManager(rv, getDomainAuthorityNode()); return idm.getThisNetworkNode(); } catch (Throwable e) { throw new RuntimeException(e.getMessage(), e); } } public INetworkNode login(final String identifier, final String domain, final String password) { Log.d(LOG_TAG, "login domain: " + domain + " identifier: " + identifier + " password: " + password); try { String rv; rv = (String)miServiceConnection.invoke(new IMethodInvocation<XMPPAgent>() { public Object invoke(XMPPAgent agent) throws Throwable { return agent.login(identifier, domain, password); } }); if(rv == null) return null; idm = createIdentityManager(rv, getDomainAuthorityNode()); return idm.getThisNetworkNode(); } catch (Throwable e) { throw new RuntimeException(e.getMessage(), e); } } public INetworkNode login(final String identifier, final String domain, final String password, final String host) { Log.d(LOG_TAG, "login domain: " + domain + " identifier: " + identifier + " password: " + password + " host: "+ host); try { String rv; rv = (String)miServiceConnection.invoke(new IMethodInvocation<XMPPAgent>() { public Object invoke(XMPPAgent agent) throws Throwable { return agent.login(identifier, domain, password, host); } }); if(rv == null) return null; idm = createIdentityManager(rv, getDomainAuthorityNode()); return idm.getThisNetworkNode(); } catch (Throwable e) { throw new RuntimeException(e.getMessage(), e); } } public INetworkNode loginFromConfig() { Log.d(LOG_TAG, "loginFromConfig"); try { String rv = (String)miServiceConnection.invoke(new IMethodInvocation<XMPPAgent>() { public Object invoke(XMPPAgent agent) throws Throwable { return agent.loginFromConfig(); } }); if(rv == null) return null; idm = createIdentityManager(rv, getDomainAuthorityNode()); return idm.getThisNetworkNode(); } catch (Throwable e) { throw new RuntimeException(e.getMessage(), e); } } public boolean logout() { Log.d(LOG_TAG, "logout"); boolean rv; try { rv = (Boolean)miServiceConnection.invoke(new IMethodInvocation<XMPPAgent>() { public Object invoke(XMPPAgent agent) throws Throwable { return agent.logout(); } }); } catch (Throwable e) { throw new RuntimeException(e.getMessage(), e); } return rv; } public boolean destroyMainIdentity() { Log.d(LOG_TAG, "destroyMainIdentity"); boolean rv; try { rv = (Boolean)miServiceConnection.invoke(new IMethodInvocation<XMPPAgent>() { public Object invoke(XMPPAgent agent) throws Throwable { return agent.destroyMainIdentity(); } }); } catch (Throwable e) { throw new RuntimeException(e.getMessage(), e); } return rv; } public void setDomainAuthorityNode(final String domainAuthorityNode) { try { miServiceConnection.invoke(new IMethodInvocation<XMPPAgent>() { public Object invoke(XMPPAgent agent) throws Throwable { agent.setDomainAuthorityNode(domainAuthorityNode); return null; } }); } catch (Throwable e) { throw new RuntimeException(e.getMessage(), e); } } public void setPortNumber(final int port) { try { miServiceConnection.invoke(new IMethodInvocation<XMPPAgent>() { public Object invoke(XMPPAgent agent) throws Throwable { agent.setPortNumber(port); return null; } }); } catch (Throwable e) { throw new RuntimeException(e.getMessage(), e); } } public void setResource(final String resource) { try { miServiceConnection.invoke(new IMethodInvocation<XMPPAgent>() { public Object invoke(XMPPAgent agent) throws Throwable { agent.setResource(resource); return null; } }); } catch (Throwable e) { throw new RuntimeException(e.getMessage(), e); } } public void setDebug(final boolean enabled) { try { miServiceConnection.invoke(new IMethodInvocation<XMPPAgent>() { public Object invoke(XMPPAgent agent) throws Throwable { agent.setDebug(enabled); return null; } }); } catch (Throwable e) { throw new RuntimeException(e.getMessage(), e); } } private static IIdentityManager createIdentityManager(String thisNode, String daNode) throws InvalidFormatException { IIdentityManager idm; if(daNode == null) idm = new IdentityManagerImpl(thisNode); else idm = new IdentityManagerImpl(thisNode, daNode); return idm; } }