javacommons/comms/src/listeners.cpp
changeset 21 2a9601315dfc
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javacommons/comms/src/listeners.cpp	Mon May 03 12:27:20 2010 +0300
@@ -0,0 +1,148 @@
+/*
+* Copyright (c) 2008 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:  Class for hiding differences between native and java listeners
+*
+*/
+
+#include "logger.h"
+
+#include "commsmessage.h"
+#include "listeners.h"
+
+namespace java
+{
+namespace comms
+{
+
+ListenerWrapper::ListenerWrapper(CommsListener* aListener) : mListener(aListener), mObject(0), mMethodID(0)
+{
+}
+
+ListenerWrapper::ListenerWrapper(jobject aListener, JNIEnv* aEnv) : mListener(0), mObject(0), mMethodID(0)
+{
+    mObject = aEnv->NewGlobalRef(aListener);
+    jclass cls = aEnv->GetObjectClass(aListener);
+    if (cls != NULL)
+    {
+        mMethodID = aEnv->GetMethodID(cls, "processMessage", "(Lcom/nokia/mj/impl/comms/CommsMessage;)V");
+    }
+
+    if (mObject == NULL || mMethodID == NULL)
+    {
+        ELOG3(EJavaComms, "%s failed, mObject=%d - cls=%d", __PRETTY_FUNCTION__, mObject, mMethodID);
+    }
+}
+
+ListenerWrapper::~ListenerWrapper()
+{
+}
+
+void ListenerWrapper::processMessage(CommsMessage& aMessage, JNIEnv* aEnv)
+{
+    JELOG2(EJavaComms);
+    if (mListener)
+    {
+        mListener->processMessage(aMessage);
+        return;
+    }
+
+    char* buf = aMessage.toByteArray();
+    int len = (reinterpret_cast<ipcMessage_t*>(buf))->ipcHeader.length;
+
+    // create bytearray
+    jbyteArray bytes = aEnv->NewByteArray(len);
+    if (bytes!=NULL)
+    {
+        aEnv->SetByteArrayRegion(bytes, 0, len, (jbyte*)buf);
+        // find CommsMessage java class
+        jclass clazz = aEnv->FindClass("com/nokia/mj/impl/comms/CommsMessage");
+        if (clazz!=NULL)
+        {
+            // find CommsMessage java class ctor
+            jmethodID mid = aEnv->GetMethodID(clazz, "<init>", "([B)V");
+            if (mid!=NULL)
+            {
+                // create CommsMessage java object
+                jobject messageObj = aEnv->NewObject(clazz, mid, bytes);
+                if (messageObj!=NULL)
+                {
+                    // make callback
+                    callVoidJavaMethod(aEnv, mObject, mMethodID,
+                                       "(Lcom/nokia/mj/impl/comms/CommsMessage;)V", messageObj);
+                    // free local references manually as we run in dispatch loop that does not return to VM
+                    aEnv->DeleteLocalRef(messageObj);
+                }
+                else
+                {
+                    ELOG(EJavaComms, "NewObject() failed");
+                }
+            }
+            else
+            {
+                ELOG(EJavaComms, "GetMethodID() failed");
+            }
+            aEnv->DeleteLocalRef(clazz);
+        }
+        else
+        {
+            ELOG(EJavaComms, "FindClass() failed");
+        }
+        aEnv->DeleteLocalRef(bytes);
+    }
+    else
+    {
+        ELOG(EJavaComms, "NewByteArray() failed");
+    }
+}
+
+void ListenerWrapper::callVoidJavaMethod(JNIEnv* aEnv, jobject aObject, jmethodID aMethodID, const char* aMethodSignature, ...)
+{
+    // make the callback
+    va_list args;
+    va_start(args, aMethodSignature);
+    aEnv->CallVoidMethodV(aObject, aMethodID, args);
+    va_end(args);
+
+    // check for pending exception
+    jboolean hasException = aEnv->ExceptionCheck();
+    if (hasException == JNI_TRUE)
+    {
+        // Report any exceptions that were generated and
+        // then clear them from the JNI environment
+        aEnv->ExceptionDescribe();
+        aEnv->ExceptionClear();
+        WLOG(EJavaComms, "processMessage() threw exception (in CallVoidMethodV)");
+    }
+}
+
+CommsListener* ListenerWrapper::getListener()
+{
+    return mListener;
+}
+
+void ListenerWrapper::release(JNIEnv* aEnv)
+{
+    // aEnv can be NULL if message loop thread has not attached to VM
+    // (aka no messages have been received)
+    if (aEnv)
+    {
+        aEnv->DeleteGlobalRef(mObject);
+    }
+}
+
+
+
+
+} // namespace comms
+} // namespace java