/**********************************************************************
 * Copyright (c) 2005, 2009 IBM Corporation and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * $Id: hcjbnd.c,v 1.7 2009/08/26 14:59:59 jwest Exp $
 *
 * Contributors:
 * IBM - Initial API and implementation
 **********************************************************************/

#include <stdlib.h>
#include <assert.h> /* fix 89008: partial */
#include "RABindings.h"
#include "RASocket.h"
#include "RADataTransfer.h"
#include "RAComm.h"
#include "hcjbnd.h"

#if defined MVS && defined _LP64
	#include <limits.h>
#endif

/* MACRO's to simplify the JNI code. */
#if defined __cplusplus && defined _HPUX
 #define ENV(e) e
 #define ENVPARM(e)
#else
 #define ENV(e) (*e)
 #define ENVPARM(e) e,
#endif


/* MACRO to work with jlong on AS400 as it is a struct */
#ifndef __OS400__
 #define JLONG(value)  value
#else
 #define JLONG(value) value.ll
#endif

/* The size to grow the agent list by when it is full */
#define AGENT_LIST_INCREMENT 6

static BOOL _firstInstance=TRUE;
static ra_critsec_t _lock;


/* The command handlers for each of the languages */
static void _java_notifyMessage(ra_command_t *command);
static void _native_notifyMessage(ra_command_t *command);

/* Global reference to the JVM. */
static JavaVM		*_agent_vm;

typedef logAgent_t agent_list_entry_t;


typedef struct {
	unsigned int size;
	agent_list_entry_t **entries;
}agent_list_t;


static agent_list_t	_agent_list;

#ifdef _DEBUG2
#include <stdio.h>
static FILE *traceFile;
#endif

/** GROW_AGENT_LIST  ***********************************************************
  *
  */
static void growAgentList(int delta) {
	int newSize=_agent_list.size+delta;
	agent_list_entry_t **current=_agent_list.entries;

	#ifdef _DEBUG
	#ifdef MVS                    /* 198066 */
	#pragma convlit(suspend)
	#endif
	printf("LogAgent: Resizing agent list\n");
	#ifdef MVS                    /* 198066 */
	#pragma convlit(resume)
	#endif
	#endif

	_agent_list.entries=(agent_list_entry_t**)malloc(sizeof(agent_list_entry_t*)*newSize);
	BZERO(_agent_list.entries, newSize*sizeof(agent_list_entry_t*));
	if (current != NULL) {
		memcpy(_agent_list.entries, current, _agent_list.size*sizeof(agent_list_entry_t*));
	}
	_agent_list.size=newSize;
	if (current != NULL) {
		free(current);
	}

	#ifdef _DEBUG
	#ifdef MVS                    /* 198066 */
	#pragma convlit(suspend)
	#endif
	printf("LogAgent: Agent list resized to %d\n", _agent_list.size);
	#ifdef MVS                    /* 198066 */
	#pragma convlit(resume)
	#endif
	#endif
}

/** FIND_AGENT  ****************************************************************
  *
  */
static agent_list_entry_t *findAgent(char *name) {
	agent_list_entry_t *result=NULL;
	ra_mutexEnter(&_lock);
	if(name) {
		unsigned int i;
		for(i=0; i<_agent_list.size; i++) {
			if(_agent_list.entries[i] && _agent_list.entries[i]->dirty && _agent_list.entries[i]->agent_name &&strcmp(_agent_list.entries[i]->agent_name, name)==0) {
				result=_agent_list.entries[i];
				break;
			}
		}
	}
	ra_mutexExit(&_lock);
	return result;
}

/** INSERT_AGENT  **************************************************************
  *
  */
static  agent_list_entry_t *insertAgent(char *name) {
	if(name) {
		agent_list_entry_t *entry=findAgent(name);
		if(!entry) {
			unsigned int i;
			ra_mutexEnter(&_lock);
			for(i=0; i<_agent_list.size; i++) {
				if(!_agent_list.entries[i] || !_agent_list.entries[i]->dirty) {
					_agent_list.entries[i]=(agent_list_entry_t*)malloc(sizeof(agent_list_entry_t));
					_agent_list.entries[i]->dirty=TRUE;
					_agent_list.entries[i]->monitored=FALSE;
					_agent_list.entries[i]->agent_name=name;
					entry=_agent_list.entries[i];
					break;
				}
			}
			if(i==_agent_list.size) {
				growAgentList(AGENT_LIST_INCREMENT);
				_agent_list.entries[i]=(agent_list_entry_t*)malloc(sizeof(agent_list_entry_t));
				_agent_list.entries[i]->dirty=TRUE;
				_agent_list.entries[i]->monitored=FALSE;
				_agent_list.entries[i]->agent_name=name;
				entry=_agent_list.entries[i];
			}
			ra_mutexExit(&_lock);
	#ifdef _DEBUG
	#ifdef MVS                    
	#pragma convlit(suspend)
	#endif
	printf("Log Agent: insertAgent: inserted agent %s in position %d\n", name,i);
	#ifdef MVS                    
	#pragma convlit(resume)
	#endif
	#endif
		   return entry;
		}
	/* bugzilla 65470 start */
      else if (!entry->dirty) {
		/* An entry was found with the same name but it is not active so we will insert the new agent here */
         entry->dirty = TRUE;
         entry->monitored = FALSE;
         entry->waitingServiceAvailMessage = FALSE;
	#ifdef _DEBUG
	#ifdef MVS                    
	#pragma convlit(suspend)
	#endif
	printf("Log Agent: insertAgent: agent %s was found in the list but it wasn't dirty\n", name);
	#ifdef MVS                    
	#pragma convlit(resume)
	#endif
	#endif
		   return entry;
		}
		/* bugzilla 65470 end */
	}
	#ifdef _DEBUG
	#ifdef MVS                    
	#pragma convlit(suspend)
	#endif
	printf("Log Agent: insertAgent: findAgent found an active agent with name %s\n", name);
	#ifdef MVS                    
	#pragma convlit(resume)
	#endif
	#endif

	/* Insert failed either because the name was empty or an active agent already exists in the list with the same name */
	return NULL;
}


/**  GET_AGENT_OFFSET  *********************************************************
  *
  */
static int getAgentOffset(logAgent_t *agent) {
    unsigned int i;
    for(i=0; i<_agent_list.size; i++) {
		if(_agent_list.entries[i] == agent) {
			return i;
		}
	}
    return -1;
}



/** GET_CURRENT_PROCESS_ID  ****************************************************
  *
  */
ra_string_t* logAgent_getCurrentProcessId( ) {
	PID pid;
	char tempString[256];

	pid=ra_getProcessId();

#ifdef _WIN32
	   ltoa(pid,tempString,10);
#else
	   sprintf(tempString, "%d", pid);
#endif
  return ra_createRASTRING2(tempString);
}


/** GET_CURRENT_THREAD_ID  *****************************************************
  * Returns an integer thread id for the current thread.
  */

/* 198066 - Thread ID's have different types on different platforms so we'll return
            a TID as defined in RAComm.h
*/
TID logAgent_getCurrentThreadId()
{
#ifdef WIN32
   return GetCurrentThreadId();
#else
   return pthread_self();
#endif
}

/** CLEANUP_AT_EXIT  **********************************************************
  * The runtime calls this function when this dll is unloaded during application
  * termination.  This is our chance to clean up our resources.  This function
  * is actually pushed on the stack once per agent, yet cleans all the agents
  * resources each time.  This could possibly be optimized
  */
void cleanupAtExit(void) {
	unsigned int i;
	#ifdef _DEBUG
	#ifdef MVS                    /* 198066 */
	#pragma convlit(suspend)
	#endif
	printf("LogAgent: Cleaning up\n");
	#ifdef MVS                    /* 198066 */
	#pragma convlit(resume)
	#endif
	#endif
	for(i=0; i<_agent_list.size; i++) {
		if(_agent_list.entries[i] && _agent_list.entries[i]->dirty && _agent_list.entries[i]->monitored) {
			if(_agent_list.entries[i]->targetHdl.dtarget==RA_SHAREDMEMORY
						&& _agent_list.entries[i]->monitored) {
				#ifdef _DEBUG
				#ifdef MVS                    /* 198066 */
				#pragma convlit(suspend)
				#endif
				printf("LogAgent: Closing shared memory pipe\n");
				#ifdef MVS                    /* 198066 */
				#pragma convlit(resume)
				#endif
				#endif
				ra_stopFlushingShm(&_agent_list.entries[i]->targetHdl.dtargetHdl.shmHdl);
			}
			else if(_agent_list.entries[i]->targetHdl.dtarget==RA_SOCKET
						&& _agent_list.entries[i]->targetHdl.dtargetHdl.socketFD) {
				#ifdef _DEBUG
				#ifdef MVS                    /* 198066 */
				#pragma convlit(suspend)
				#endif
				printf("LogAgent: Closing socket\n");
				#ifdef MVS                    /* 198066 */
				#pragma convlit(resume)
				#endif
				#endif
				/** On windows the socket layer is already disabled at this point */
#ifndef _WIN32
				ra_closeSocket(_agent_list.entries[i]->targetHdl.dtargetHdl.socketFD);
#endif
			}
			/* Mark this agent as clean */
			_agent_list.entries[i]->dirty=FALSE;
			_agent_list.entries[i]->monitored=FALSE;
		}
	}
	#ifdef _DEBUG2
	if (traceFile != NULL) {
		#ifdef MVS                    /* 198066 */
		#pragma convlit(suspend)
		#endif
		fprintf(traceFile, "LogAgent: Cleanup complete\n");
		#ifdef MVS                    /* 198066 */
		#pragma convlit(resume)
		#endif
		fflush(traceFile);
		fclose(traceFile);
		traceFile = NULL;
	}
	#endif

    return;
}

/** INITIALIZE_AGENT_TABLE  ************************************************
  * Initialize the agent table to zero
  */
static void initializeAgentTable() {
	_agent_list.size=0;
	_agent_list.entries=NULL;
	ra_mutexCreate(&_lock);
}


void logAgent_deregisterAgent(logAgent_t *agent) {

	/* If someone is collecting data, close the connection */
	/* Close the appropriate logging mechanism */
	if(agent->targetHdl.dtarget==RA_SOCKET) {
		ra_closeSocket(agent->targetHdl.dtargetHdl.socketFD);

	}
	else if(agent->targetHdl.dtarget==RA_SHAREDMEMORY) {
		ra_stopFlushingShm(&agent->targetHdl.dtargetHdl.shmHdl);
	}

	#ifdef _DEBUG2
	#ifdef MVS
	#pragma convlit(suspend)
	#endif
	fprintf(traceFile, "logAgent_deregisterAgent: About to stop listener thread\n");
	fflush(traceFile);
	#ifdef MVS
	#pragma convlit(resume)
	#endif
	#endif

	ra_stopListener(agent->bindingStorage);
	/* ra_finalizeBindings(agent->bindingStorage); */  /* bugzilla 68521 - causing crash
													   when RAC is not running */

	agent->dirty=FALSE;
/*	free(agent->agent_name); */ /* Bug 168884 */
}


/** DEREGISTER_AGENT  ******************************************************
  * Clean up the resources associated with a single instance of a LogAgent.

  */
static void deregisterAgent(JNIEnv *env,
						   jobject obj) {
	jclass cls;
	jfieldID   isRegisteredDecl;
	jboolean isRegisteredInstance;

	/* Get the class object */
	cls=ENV(env)->GetObjectClass(ENVPARM(env) obj);
	if (cls == 0) {
		return;
	}

	/* Get the registered field from the instance */
#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
	isRegisteredDecl=ENV(env)->GetFieldID(ENVPARM(env) cls, "isRegistered", "Z");
	if (isRegisteredDecl == 0) {
		return;
	}
#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif
	isRegisteredInstance=ENV(env)->GetBooleanField(ENVPARM(env) obj, isRegisteredDecl);


	if(isRegisteredInstance) {
		jlong jl_minus1;
		jfieldID mechDecl;
		jlong mech;

#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
		mechDecl=ENV(env)->GetFieldID(ENVPARM(env) cls, "mechanism", "J");
#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif
		if (mechDecl == 0) {
			return;
		}
		mech=ENV(env)->GetLongField(ENVPARM(env) obj, mechDecl);

		if(JLONG(mech) >-1 && JLONG(mech)<_agent_list.size) {
			agent_list_entry_t *agent;
			agent=_agent_list.entries[JLONG(mech)];

			logAgent_deregisterAgent(agent);

			/* Set _isRegistered to FALSE */
			ENV(env)->SetBooleanField(ENVPARM(env) obj, isRegisteredDecl, (jboolean)FALSE);
			/* Clear the mechanism BRP */

            JLONG(jl_minus1)=-1;
			ENV(env)->SetLongField(ENVPARM(env) obj, mechDecl, jl_minus1);

			/* Clean up the global ref */
			ENV(env)->DeleteGlobalRef(ENVPARM(env) agent->agent_logger);
		}
	}

	#ifdef _DEBUG2
	if (traceFile != NULL) {
		#ifdef MVS                    /* 198066 */
		#pragma convlit(suspend)
		#endif
		fprintf(traceFile, "deregisterAgent: Agent was deregistered - close trace file.\n");
		fflush(traceFile);
		#ifdef MVS                    /* 198066 */
		#pragma convlit(resume)
		#endif
		fflush(traceFile);
		fclose(traceFile);
		traceFile = NULL;
	}
	#endif
}

static logAgent_t* registerAgent(char *name, char*type, BOOL java, JNIEnv *env, jobject obj) {
	logAgent_t *agent;

	#ifdef _DEBUG2
	#ifdef MVS
	#pragma convlit(suspend)
	#endif
	fprintf(traceFile, "Log Agent: In registerAgent\n");
	fflush(traceFile);
	#ifdef MVS
	#pragma convlit(resume)
	#endif
	#endif

	/* If this is the first instance initialize the agent table */
	if(_firstInstance) {
        atexit((void(*)())cleanupAtExit);
		initializeAgentTable();
		_firstInstance=FALSE;
	}

	#ifdef _DEBUG
	#ifdef MVS                    /* 198066 */
	#pragma convlit(suspend)
	#endif
	printf("Log Agent: registerAgent: after initializing agent table\n");
	#ifdef MVS                    /* 198066 */
	#pragma convlit(resume)
	#endif
	#endif

	agent=insertAgent(name);
	if(agent) {

		#ifdef _DEBUG
		#ifdef MVS                    /* 198066 */
		#pragma convlit(suspend)
		#endif
		printf("Log Agent: registerAgent: insertAgent succeeded for agent %s and about to initialize Bindings\n", name);
		#ifdef MVS                    /* 198066 */
		#pragma convlit(resume)
		#endif
		#endif

		/* Set the command handler for the appropriate language */
		if(java) {

			/* Create a reference to the logging agent */
			agent->agent_logger = ENV(env)->NewGlobalRef(ENVPARM(env) obj);

			/* Initialize the bindings for "server" mode initially */
			agent->bindingStorage=ra_initializeBindings(name,
				                                        type,
														_java_notifyMessage,
														FALSE);
		}
		else {
			agent->bindingStorage=ra_initializeBindings(name,
				                                        type,
														_native_notifyMessage,
														FALSE);
		}

		#ifdef _DEBUG2
		#ifdef MVS                    /* 198066 */
		#pragma convlit(suspend)
		#endif
		fprintf(traceFile, "Log Agent: registerAgent: starting Listener\n");
		fflush(traceFile);
		#ifdef MVS                    /* 198066 */
		#pragma convlit(resume)
		#endif
		#endif

		ra_startListener(agent->bindingStorage, 0);

		#ifdef _DEBUG2
		#ifdef MVS                    /* 198066 */
		#pragma convlit(suspend)
		#endif
		fprintf(traceFile, "Log Agent: registerAgent: after starting Listener\n");
		fflush(traceFile);
		#ifdef MVS                    /* 198066 */
		#pragma convlit(resume)
		#endif
		#endif

		agent->nativeCommandHandler = NULL;
		return agent;
	}
	return NULL;
}



logAgent_t* logAgent_registerAgent(char *name, char *type) {
	/* Make our ouw copies of the strings */
	char *nameCopy, *typeCopy;
	STRDUP(nameCopy, name);
	STRDUP(typeCopy, type);
	return registerAgent(nameCopy, typeCopy, FALSE, (JNIEnv*)NULL, (jobject)NULL);
}


/*
 * Class:     Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton
 * Method:    initializeEngine0
 * Signature: (Ljava/lang/String;Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL
Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton_initializeEngine0(JNIEnv *env,
                                                                  jobject obj,
                                                                  jstring name,
                                                                  jstring type) {
	jclass cls;
	jfieldID   isRegisteredDecl, mechDecl;
	jboolean isRegisteredInstance;
	agent_list_entry_t *agent;
	char *nameBytes, *typeBytes;
    jlong agentIndex;

	#ifdef _DEBUG2
	#ifdef MVS                    /* 198066 */
	#pragma convlit(suspend)
	#endif
	traceFile = fopen("logAgent.dbg", "w");
	fprintf(traceFile, "Log Agent: initializeEngine0: Inside Agent Intialization\n");
	fflush(traceFile);
	#ifdef MVS                    /* 198066 */
	#pragma convlit(resume)
	#endif
	#endif

	/* Copy the string bytes */
	if(name) {
		#ifdef _DEBUG
		#ifdef MVS                    /* 198066 */
		#pragma convlit(suspend)
		#endif
		printf("Log Agent: Copy the string bytes\n");
		#ifdef MVS                    /* 198066 */
		#pragma convlit(resume)
		#endif
		#endif

		nameBytes=copyJavaStringToNative(env, name);
	}
	else {
		#ifdef _DEBUG
		#ifdef MVS                    /* 198066 */
		#pragma convlit(suspend)
		#endif
		printf("Log Agent: No name to copy, return\n");
		#ifdef MVS                    /* 198066 */
		#pragma convlit(resume)
		#endif
		#endif

		return;
	}
	if(type) {
		#ifdef _DEBUG
		#ifdef MVS                    /* 198066 */
		#pragma convlit(suspend)
		#endif
		printf("Log Agent: Copy the type bytes\n");
		#ifdef MVS                    /* 198066 */
		#pragma convlit(resume)
		#endif
		#endif

		typeBytes=copyJavaStringToNative(env, type);
	}
	else {
		#ifdef _DEBUG
		#ifdef MVS                    /* 198066 */
		#pragma convlit(suspend)
		#endif
		printf("Log Agent: No type to copy, return\n");
		#ifdef MVS                    /* 198066 */
		#pragma convlit(resume)
		#endif
		#endif

		return;
	}

	/* Get the class object */
	#ifdef _DEBUG
	#ifdef MVS                    /* 198066 */
	#pragma convlit(suspend)
	#endif
	printf("Log Agent: Get the class object\n");
	#ifdef MVS                    /* 198066 */
	#pragma convlit(resume)
	#endif
	#endif

	cls=ENV(env)->GetObjectClass(ENVPARM(env) obj);

	/* Get the registered field from the instance */
	#ifdef _DEBUG
	#ifdef MVS                    /* 198066 */
	#pragma convlit(suspend)
	#endif
	printf("Log Agent: Get the registered field from the instance: GetFieldID()\n");
	#endif
#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
	
	isRegisteredDecl=ENV(env)->GetFieldID(ENVPARM(env) cls, "isRegistered", "Z");

#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif

	#ifdef _DEBUG
	#ifdef MVS                    /* 198066 */
	#pragma convlit(suspend)
	#endif
	printf("Log Agent: Get the registered field from the instance: GetBooleanField()\n");	
	#ifdef MVS                    /* 198066 */
	#pragma convlit(resume)
	#endif
	#endif

	isRegisteredInstance=ENV(env)->GetBooleanField(ENVPARM(env) obj, isRegisteredDecl);

	#ifdef _DEBUG
	#ifdef MVS                    /* 198066 */
	#pragma convlit(suspend)
	#endif
	printf("Log Agent: Finished getting the registered field from the instance\n");
	#ifdef MVS                    /* 198066 */
	#pragma convlit(resume)
	#endif
	#endif

	#ifdef _DEBUG2
	#ifdef MVS                    /* 198066 */
	#pragma convlit(suspend)
	#endif
	fprintf(traceFile, "Log Agent: IsRegisteredInstance = %d\n", isRegisteredInstance);
	fflush(traceFile);
	#ifdef MVS                    /* 198066 */
	#pragma convlit(resume)
	#endif
	#endif

	/* Only run this method once */
	if(isRegisteredInstance) {

		#ifdef _DEBUG
		#ifdef MVS                    /* 198066 */
		#pragma convlit(suspend)
		#endif
		printf("Log Agent: isRegisteredInstance = true, return\n");
		#ifdef MVS                    /* 198066 */
		#pragma convlit(resume)
		#endif
		#endif

		return;
	}

	/* Resolve pointers back to relevent methods inside of JVM */
	#ifdef _DEBUG
	#ifdef MVS                    /* 198066 */
	#pragma convlit(suspend)
	#endif
	printf("Log Agent: Resolve pointer back to revelent methods inside of JVM\n");
	#ifdef MVS                    /* 198066 */
	#pragma convlit(resume)
	#endif
	#endif

	ENV(env)->GetJavaVM(ENVPARM(env) &_agent_vm);

	#ifdef _DEBUG2
	#ifdef MVS                    /* 198066 */
	#pragma convlit(suspend)
	#endif
	fprintf(traceFile, "Log Agent: about to register Agent name >%s<  type >%s<\n", nameBytes, typeBytes);
	fflush(traceFile);
	#ifdef MVS                    /* 198066 */
	#pragma convlit(resume)
	#endif
	#endif

	/* Create a global reference of this object (this needs to removed later)*/
	agent=registerAgent(nameBytes, typeBytes, TRUE, env, obj);
	if(agent) {
		jmethodID setAgentUUID;
		jstring agentUUID;

		/* Place the index of the agent in the Java layer for fast reference later */
#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
	    mechDecl=ENV(env)->GetFieldID(ENVPARM(env) cls, "mechanism", "J");

#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif
        if(mechDecl) {
            JLONG(agentIndex)=getAgentOffset(agent);
            if(JLONG(agentIndex)>-1) {
	    	    ENV(env)->SetLongField(ENVPARM(env) obj, mechDecl, agentIndex);
            }
        }

		/* Set the agentUUID back in the Java layer.
		 *  RKD: This is only in the V5 or greater Java layer.  We need to catch the exception.
		 */
#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
		setAgentUUID=ENV(env)->GetMethodID(ENVPARM(env) cls, "setAgentUUID", "(Ljava/lang/String;)V");

#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif
		if(setAgentUUID) {
			agentUUID = getnewstrutf(env, agent -> bindingStorage -> agentUUID.data);
			ENV(env)->CallVoidMethod(ENVPARM(env) agent->agent_logger, setAgentUUID, agentUUID);
		}


		#ifdef _DEBUG
		#ifdef MVS                    
		#pragma convlit(suspend)
		#endif
		printf("Log Agent: SetBooleanField\n");
		#ifdef MVS
		#pragma convlit(resume)
		#endif
		#endif
		/* bugzilla 65470 - moved this line here from above because before it was being set
         * even when registration failed.  Here we are sure registration succeeded.
		 *
  		 * Done registering so set the isRegistered flag in the java object */
		ENV(env)->SetBooleanField(ENVPARM(env) obj, isRegisteredDecl, (jboolean)TRUE);
	
	}
}

/*
 * Class:     Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton
 * Method:    deregister0
 * Signature: (Ljava/lang/String;)V
 */
JNIEXPORT void JNICALL
Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton_deregister0(JNIEnv *env,
                                                            jobject obj,
                                                            jstring name) {
	#ifdef _DEBUG2
	#ifdef MVS                    /* 198066 */
	#pragma convlit(suspend)
	#endif
	fprintf(traceFile, "_deregister0: Java code is asking us to deregister the agent\n");
	fflush(traceFile);
	#ifdef MVS                    /* 198066 */
	#pragma convlit(resume)
	#endif
	#endif

	deregisterAgent(env, obj);
}


/** LOGAGENT_LOG_MESSAGE  ******************************************************
  *
  */
/* Bug 74367 */
long logAgent_logMessage_return(logAgent_t *agent, char *messageBuffer, ra_uint_t length, ra_dataFormat_t format) {
	unsigned char *copy;
	long byteSent = 0;

	if(agent->monitored) {
		copy=ra_allocateMessageBlock(length);
		/* Copy the bytes */
		memcpy(copy, messageBuffer, length);
		byteSent = (long)ra_writeMessageBlock(&agent->targetHdl,
							 format,
							 copy,
							 length);
		ra_freeMessageBlock(copy);
	}

#ifdef _DEBUG
	#ifdef MVS
		#pragma convlit(suspend)
	#endif
	printf("logAgent_logMessage: %d byte sent\n", byteSent);
	#ifdef MVS
		#pragma convlit(resume)
	#endif
#endif

	return byteSent;
}

/* Bug 74367 */
void logAgent_logMessage(logAgent_t *agent, char *messageBuffer, ra_uint_t length, ra_dataFormat_t format) {
	logAgent_logMessage_return(agent, messageBuffer, length, format);
}


/*
 * Class:		Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton
 * Method:		logErrorMessage
 * Signature:	(Ljava/lang/String;Ljava/lang/String;I)V
 *
 * Description:	The following JNI function is used to only log error messages to an active
 *				logging agent.
 *
 * @param message	-	The message to be logged
 *		  messageId -	The message ID corresponding to the error message
 *		  severity	-	The level of severity of the message (e.g. default = DEBUG, 1 = INFORMATION, 2 = WARNING, 3 = SEVERE, 4 = MAX ERROR LEVEL)
 */
JNIEXPORT jlong JNICALL
Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton_logErrorMessage(
															JNIEnv *env,
                                                            jobject obj,
															jstring message,
															jstring messageId,
															jint severity) {	
	
	/* The 'mechanism' field of 'obj' will indicate the agent that was used to invoke this
	 * method */
	jlong mech;
	jfieldID mechDecl;
	jclass clazz;
	jlong byteSent;

	/* The error message and its corresponding ID */
	char *errMsg, *msgId;

	/* The severity of the message, which is DEBUG by default */
	RA_ERROR_LEVEL msgSeverity = RA_DEBUG;


	#ifdef _DEBUG
		printf ("Log Agent: Inside of the logErrorMessage function\n");
	#endif
	
	/* Resolve the 'jclass' of 'obj' */
	clazz=ENV(env)->GetObjectClass(ENVPARM(env) obj);


	/* Making JNI calls requires that the mode to be changed */
	#ifdef __OS400__
		#pragma convert(819)
	#endif
		mechDecl=ENV(env)->GetFieldID(ENVPARM(env) clazz, "mechanism", "J");
	#ifdef __OS400__
		#pragma convert(0)
	#endif
	mech=ENV(env)->GetLongField(ENVPARM(env) obj, mechDecl);


    /* Get the appropriate agent and send the message */
	if(JLONG(mech) > -1 && JLONG(mech) < _agent_list.size) {
		agent_list_entry_t *agent;

        agent=_agent_list.entries[JLONG(mech)];
		
		/* Resolve the parameters passed in */
		errMsg = copyJavaStringToNative(env, message);
		msgId = copyJavaStringToNative(env, messageId);
		
		if ((int)severity == 1)
			{msgSeverity = RA_INFORMATION;}
		else if ((int)severity == 2)
			{msgSeverity = RA_WARNING;}
		else if ((int)severity == 3)
			{msgSeverity = RA_SEVERE;}
		else if ((int)severity == 4)
			{msgSeverity = RA_MAX_ERROR_LEVEL;}

		/* Set it to zero first */
		JLONG(byteSent) = 0;
		JLONG(byteSent) = ra_logErrorMessage_return(agent->bindingStorage, msgSeverity, msgId, errMsg);

	}	

#ifdef _DEBUG
	#ifdef MVS
		#pragma convlit(suspend)
	#endif
	printf("JNI_logErrorMessage: %d byte sent\n", byteSent);
	#ifdef MVS
		#pragma convlit(resume)
	#endif
#endif

	return byteSent;
}


/*
 * Class:     Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton
 * Method:    logMessage0
 * Signature: (Ljava/lang/String;[BII)V
 */
JNIEXPORT jlong JNICALL
Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton_logMessage0__Ljava_lang_String_2_3BII(JNIEnv *env,
                                                                                      jobject obj,
                                                                                      jstring name,
                                                                                      jbyteArray msg,
                                                                                      jint offset,
                                                                                      jint length) {
	jlong mech;
	jfieldID mechDecl;
	jclass clazz;
	jlong byteSent;

	/* No need to search, we can just use the _mechanism field in the agent.
	 */

	clazz=ENV(env)->GetObjectClass(ENVPARM(env) obj);
#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
	mechDecl=ENV(env)->GetFieldID(ENVPARM(env) clazz, "mechanism", "J");
#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif
	mech=ENV(env)->GetLongField(ENVPARM(env) obj, mechDecl);


	#ifdef _DEBUG
	#ifdef MVS                    /* 198066 */
	#pragma convlit(suspend)
	#endif
	printf("Logging Binary message\n");
	#ifdef MVS                    /* 198066 */
	#pragma convlit(resume)
	#endif
	#endif

    if(JLONG(mech) >-1 && JLONG(mech)<_agent_list.size) {
		agent_list_entry_t *agent;
        jbyte* bytes;
        agent=_agent_list.entries[JLONG(mech)];
		bytes=ENV(env)->GetByteArrayElements(ENVPARM(env) msg, NULL);

		/* Set it to zero first */
		JLONG(byteSent) = 0;
		JLONG(byteSent) = logAgent_logMessage_return(agent, (char*)bytes, length, RA_BINARY_DATA);
		ENV(env)->ReleaseByteArrayElements(ENVPARM(env) msg, bytes, JNI_ABORT);
	}

#ifdef _DEBUG
	#ifdef MVS
		#pragma convlit(suspend)
	#endif
	printf("JNI_logMessage0: %d byte sent\n", byteSent);
	#ifdef MVS
		#pragma convlit(resume)
	#endif
#endif
	return byteSent;
}

/*
 * Class:     Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton
 * Method:    logMessage0
 * Signature: (Ljava/lang/String;Ljava/lang/String;)V
 */
JNIEXPORT jlong JNICALL
Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton_logMessage0__Ljava_lang_String_2Ljava_lang_String_2(JNIEnv *env,
                                                                                                    jobject obj,
                                                                                                    jstring name,
                                                                                                    jstring msg) {
	jlong mech;
	jfieldID mechDecl;
	jclass clazz;
	jlong byteSent;

	#ifdef _DEBUG
	#ifdef MVS                    
	#pragma convlit(suspend)
	#endif
		printf ("Log Agent: Inside of the logMessage0 function\n");
	#ifdef MVS                    
	#pragma convlit(resume)
	#endif
	#endif
	/* No need to search, we can just use the _mechanism field in the agent.
	 */
	clazz=ENV(env)->GetObjectClass(ENVPARM(env) obj);
#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
	mechDecl=ENV(env)->GetFieldID(ENVPARM(env) clazz, "mechanism", "J");
#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif
	mech=ENV(env)->GetLongField(ENVPARM(env) obj, mechDecl);


    if(JLONG(mech) >-1 && JLONG(mech)<_agent_list.size) {
		agent_list_entry_t *agent;
        ra_uint_t length;
		const jchar *bytes;

        agent=_agent_list.entries[JLONG(mech)];

		length=(ENV(env)->GetStringLength(ENVPARM(env) msg));

	#ifdef _DEBUG
	#ifdef MVS                    
	#pragma convlit(suspend)
	#endif
	printf("Logging String message of length %d\n", length);
	#ifdef MVS                    
	#pragma convlit(resume)
	#endif
	#endif
		bytes=ENV(env)->GetStringChars(ENVPARM(env) msg, NULL);
		/* Set it to zero first */
		JLONG(byteSent) = 0;
		JLONG(byteSent) = logAgent_logMessage_return(agent, (char*)bytes, length*2, RA_UNICODE_STRING_DATA);
		ENV(env)->ReleaseStringChars(ENVPARM(env) msg, bytes);

	}

#ifdef _DEBUG
	#ifdef MVS
		#pragma convlit(suspend)
	#endif
	printf("JNI_logMessage0: %d byte sent\n", byteSent);
	#ifdef MVS
		#pragma convlit(suspend)
	#endif
#endif
	return byteSent;
}

/*
 * Class:     Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton
 * Method:    logMessageUTF80
 * Signature: (Ljava/lang/String;Ljava/lang/String;)V
 */
JNIEXPORT jlong JNICALL
Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton_logMessageUTF80(JNIEnv *env,
                                                                                       jobject obj,
                                                                                       jstring name,
                                                                                       jstring msg) {
	jlong mech;
	jfieldID mechDecl;
	jclass clazz;
	jlong byteSent;

	/* No need to search, we can just use the _mechanism field in the agent.
	 */

	#ifdef _DEBUG
	#ifdef MVS                    
	#pragma convlit(suspend)
	#endif
		printf ("Log Agent: Inside of the logMessageUTF80 function\n");
	#ifdef MVS                    
	#pragma convlit(resume)
	#endif
	#endif
	clazz=ENV(env)->GetObjectClass(ENVPARM(env) obj);
#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
	mechDecl=ENV(env)->GetFieldID(ENVPARM(env) clazz, "mechanism", "J");
#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif
	mech=ENV(env)->GetLongField(ENVPARM(env) obj, mechDecl);

    if(JLONG(mech) >-1 && JLONG(mech)<_agent_list.size) {
		agent_list_entry_t *agent;
        ra_uint_t length;
		const jchar *bytes;
        unsigned char *copy;
		ra_uint_t i;

        agent=_agent_list.entries[JLONG(mech)];

		length=ENV(env)->GetStringLength(ENVPARM(env) msg);

	#ifdef _DEBUG
	#ifdef MVS                    
	#pragma convlit(suspend)
	#endif
	printf("Logging UTF8 String message of length %d\n", length);
	#ifdef MVS                    
	#pragma convlit(resume)
	#endif
	#endif
		bytes=ENV(env)->GetStringChars(ENVPARM(env) msg, NULL);

		/* Make a copy buffer for compression */
		copy=ra_allocateMessageBlock(length);

		for(i=0; i<length; i++) {
			copy[i]=(unsigned char)bytes[i];
		}
		/* Set it to zero first */
		JLONG(byteSent) = 0;
		JLONG(byteSent) = ra_writeMessageBlock(&agent->targetHdl, RA_BINARY_DATA, copy, length);

		ENV(env)->ReleaseStringChars(ENVPARM(env) msg, bytes);
		ra_freeMessageBlock(copy);
	}

#ifdef _DEBUG
	#ifdef MVS
		#pragma convlit(suspend)
	#endif
	printf("JNI_logMessageUTF80: %d byte sent\n", byteSent);
	#ifdef MVS
		#pragma convlit(resume)
	#endif
#endif
	return byteSent;
}

/*
 * Class:     Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton
 * Method:    logMessageUTF80
 * Signature: (Ljava/lang/String;Ljava/lang/String;)V
 */
JNIEXPORT jlong JNICALL
Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton_logMessageUTF81(JNIEnv *env,
                                                                                       jobject obj,
                                                                                       jstring name,
                                                                                       jbyteArray msg) {
	jlong mech;
	jfieldID mechDecl;
	jclass clazz;
	jlong byteSent;

	/* No need to search, we can just use the _mechanism field in the agent.
	 */

	#ifdef _DEBUG
	#ifdef MVS                 
	#pragma convlit(suspend)
	#endif
		printf ("Log Agent: Inside of the logMessageUTF81 function\n");
	#ifdef MVS                    
	#pragma convlit(resume)
	#endif
	#endif
	clazz=ENV(env)->GetObjectClass(ENVPARM(env) obj);
#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
	mechDecl=ENV(env)->GetFieldID(ENVPARM(env) clazz, "mechanism", "J");
#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif
	mech=ENV(env)->GetLongField(ENVPARM(env) obj, mechDecl);

    if(JLONG(mech) >-1 && JLONG(mech)<_agent_list.size) {
		agent_list_entry_t *agent;
        jsize length;
		jbyte *bytes;

        agent=_agent_list.entries[JLONG(mech)];

		length=ENV(env)->GetArrayLength(ENVPARM(env) msg);

	#ifdef _DEBUG
	#ifdef MVS                    /* 198066 */
	#pragma convlit(suspend)
	#endif
	printf("Logging UTF-81 message of length %d\n", length);
	#ifdef MVS                    /* 198066 */
	#pragma convlit(resume)
	#endif
	#endif
		bytes=ENV(env)->GetByteArrayElements(ENVPARM(env) msg, NULL);
/* Reversed in 9434 logAgent_logMessage(agent, as400_atou((char*)bytes), length, RA_UTF8_STRING_DATA);  240091 */
		/* Set it to zero first */
		JLONG(byteSent) = 0;
#if defined(_LP64) && !defined(_SOLARIS) && !defined(_AIX)
        assert(length<=UINT_MAX); /*partial fix 89008: flag any value too large for the uint target*/
#endif        
		JLONG(byteSent) = logAgent_logMessage_return(agent, (char*)bytes, length, RA_UTF8_STRING_DATA);
		ENV(env)->ReleaseByteArrayElements(ENVPARM(env) msg, bytes, JNI_ABORT);
	}

#ifdef _DEBUG
	#ifdef MVS
		#pragma convlit(suspend)
	#endif
	printf("JNI_logMessageUTF81: %d byte sent\n", byteSent);
	#ifdef MVS
		#pragma convlit(resume)
	#endif
#endif
	return byteSent;
}

/*
 * Class:     Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton
 * Method:    sendMessage0
 * Signature: (Ljava/lang/String;J)V
 */
JNIEXPORT jlong JNICALL
Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton_sendMessage0__Ljava_lang_String_2J(JNIEnv *env,
                                                                                    jobject obj,
                                                                                    jstring msg,
                                                                                    jlong contextId) {
	jlong mech;
	jfieldID mechDecl;
	jclass clazz;
	jlong byteSent;

	/* No need to search, we can just use the _mechanism field in the agent.
	 */
	clazz=ENV(env)->GetObjectClass(ENVPARM(env) obj);
#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
	mechDecl=ENV(env)->GetFieldID(ENVPARM(env) clazz, "mechanism", "J");
#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif
	mech=ENV(env)->GetLongField(ENVPARM(env) obj, mechDecl);

	#ifdef _DEBUG2
	#ifdef MVS                    /* 198066 */
	#pragma convlit(suspend)
	#endif
	fprintf(traceFile, "LogAgent: sendMessage0String - agent list size = %d\n", mech);
	fflush(traceFile);
	#ifdef MVS                    /* 198066 */
	#pragma convlit(resume)
	#endif
	#endif

    if(JLONG(mech) >-1 && JLONG(mech)<_agent_list.size) {
		agent_list_entry_t *agent;
        ra_uint_t length;
		char *bytes;
        char *agentName_data;
        int agentName_len;
		ra_message_t *message;
        ra_command_t *command;
		ra_uint_t i;
        agent = _agent_list.entries[JLONG(mech)];

		length = ENV(env)->GetStringLength(ENVPARM(env) msg);
		bytes = (char*)ENV(env)->GetStringUTFChars(ENVPARM(env) msg, NULL);

		agentName_len = unicode2native(&agentName_data, bytes, length);

		/* Create the message to send to the client side */
		message = ra_createMessage(RA_CONTROL_MESSAGE, 0);
		command = ra_addCommandToMessage(message, NULL);

		/* Load the data in the message */
		command->tag = RA_CUSTOM_COMMAND;
		command->info.custom_command.processId = ra_getProcessId();

		command->info.custom_command.context=(unsigned long)JLONG(contextId);

		ra_createRASTRING(&command->info.custom_command.agent, agent->agent_name);
		ra_createRASTRING(&command->info.custom_command.message, (const char *)agentName_data);

		/* RKD:  Why is the context reset to zero here? */
		command->info.custom_command.context=0;

		/* Set it to zero first */
		JLONG(byteSent) = 0;
		JLONG(byteSent) = ra_sendMessage(agent->bindingStorage, message);

		#ifdef _DEBUG2
		#ifdef MVS                    /* 198066 */
		#pragma convlit(suspend)
		#endif
		fprintf(traceFile, "LogAgent: sendMessage0String - sent Custom Command\n");
		fflush(traceFile);
		#ifdef MVS                    /* 198066 */
		#pragma convlit(resume)
		#endif
		#endif

		ra_destroyMessage(message, TRUE);
		ENV(env)->ReleaseStringUTFChars(ENVPARM(env) msg, bytes);
		free(agentName_data);
	}

#ifdef _DEBUG
	#ifdef MVS
		#pragma convlit(suspend)
	#endif
	printf("JNI_sendMessage0: %d byte sent\n", byteSent);
	#ifdef MVS
		#pragma convlit(resume)
	#endif
#endif
	return byteSent;
}

/*
 * Class:     Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton
 * Method:    sendMessage0
 * Signature: ([BIIJ)V
 */
JNIEXPORT jlong JNICALL
Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton_sendMessage0___3BIIJ(JNIEnv *env,
                                                                                            jobject obj,
                                                                                            jbyteArray msg,
                                                                                            jint offset,
                                                                                            jint length,
                                                                                            jlong contextId) {
	jlong mech;
	jfieldID mechDecl;
	jclass clazz;
	jlong byteSent;

	/* No need to search, we can just use the _mechanism field in the agent.  This
	   Could be a problem on some platforms where the address size is not 4 bytes.
	 */
	clazz=ENV(env)->GetObjectClass(ENVPARM(env) obj);
#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
	mechDecl=ENV(env)->GetFieldID(ENVPARM(env) clazz, "mechanism", "J");
#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif
	mech=ENV(env)->GetLongField(ENVPARM(env) obj, mechDecl);

	#ifdef _DEBUG2
	#ifdef MVS                    /* 198066 */
	#pragma convlit(suspend)
	#endif
	fprintf(traceFile, "LogAgent: sendMessage0ByteArray - agent list size = %d\n", mech);
	fflush(traceFile);
	#ifdef MVS                    /* 198066 */
	#pragma convlit(resume)
	#endif
	#endif

    if(JLONG(mech) >-1 && JLONG(mech)<_agent_list.size) {
		agent_list_entry_t *agent;
        jbyte *copy;
		ra_message_t *message;
        ra_command_t *command;
        agent=_agent_list.entries[JLONG(mech)];

		copy=(jbyte*)malloc((length)*sizeof(jbyte));
		ENV(env)->GetByteArrayRegion(ENVPARM(env) msg, offset, length, copy);


		/* Create the message to send to the client side */
		message=ra_createMessage(RA_CONTROL_MESSAGE, 0);
		command=ra_addCommandToMessage(message, NULL);

		/* Load the data in the message */
		command->tag = RA_CUSTOM_COMMAND;
		command->info.custom_command.processId=ra_getProcessId();

		command->info.custom_command.context=(unsigned long)JLONG(contextId);

		ra_createRASTRING(&command->info.custom_command.agent, agent->agent_name);
		ra_createRASTRING3(&command->info.custom_command.message, (const char*)copy, length);

		/* RKD:  Why is the context reset to zero here? */
		command->info.custom_command.context=0;

		/* Set it to zero first */
		JLONG(byteSent) = 0;
		JLONG(byteSent) = ra_sendMessage(agent->bindingStorage, message);

		#ifdef _DEBUG2
		#ifdef MVS                    /* 198066 */
		#pragma convlit(suspend)
		#endif
		fprintf(traceFile, "LogAgent: sendMessage0ByteArray - sent Custom Command\n");
		fflush(traceFile);
		#ifdef MVS                    /* 198066 */
		#pragma convlit(resume)
		#endif
		#endif

		ra_destroyMessage(message, TRUE);
	}

#ifdef _DEBUG
	#ifdef MVS
		#pragma convlit(suspend)
	#endif
	printf("JNI_sendMessage0: %d byte sent\n", byteSent);
	#ifdef MVS
		#pragma convlit(resume)
	#endif
#endif
	return byteSent;
}


/*
 * Class:     org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton
 * Method:    sendMessageBinary0
 * Signature: ([BIIJ)V
 */
JNIEXPORT jlong JNICALL
Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton_sendMessageBinary0(JNIEnv *env,
																							 jobject obj,
																							 jbyteArray msg,
																							 jint offset,
																							 jint length,
																							 jlong contextId) {
	jlong mech;
	jfieldID mechDecl;
	jclass clazz;
	jlong byteSent;

	/* No need to search, we can just use the _mechanism field in the agent.  This
	   Could be a problem on some platforms where the address size is not 4 bytes.
	 */
	clazz=ENV(env)->GetObjectClass(ENVPARM(env) obj);
#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
	mechDecl=ENV(env)->GetFieldID(ENVPARM(env) clazz, "mechanism", "J");
#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif
	mech=ENV(env)->GetLongField(ENVPARM(env) obj, mechDecl);

	#ifdef _DEBUG2
	#ifdef MVS                    /* 198066 */
	#pragma convlit(suspend)
	#endif
	fprintf(traceFile, "LogAgent: sendMessageBinary0 - agent list size = %d\n", mech);
	fflush(traceFile);
	#ifdef MVS                    /* 198066 */
	#pragma convlit(resume)
	#endif
	#endif

    if(JLONG(mech) >-1 && JLONG(mech)<_agent_list.size) {
		agent_list_entry_t *agent;
        jbyte *copy;
		ra_message_t *message;
        ra_command_t *command;
        agent=_agent_list.entries[JLONG(mech)];

		copy=(jbyte*)malloc((length)*sizeof(jbyte));
		ENV(env)->GetByteArrayRegion(ENVPARM(env) msg, offset, length, copy);


		/* Create the message to send to the client side */
		message=ra_createMessage(RA_CONTROL_MESSAGE, 0);
		command=ra_addCommandToMessage(message, NULL);

		/* Load the data in the message */
		command->tag = RA_BINARY_CUSTOM_COMMAND;
		command->info.custom_command.processId=ra_getProcessId();

		command->info.custom_command.context=(unsigned long)JLONG(contextId);

		ra_createRASTRING(&command->info.custom_command.agent, agent->agent_name);
		ra_createRASTRING3(&command->info.custom_command.message, (const char*)copy, length);

		/* RKD:  Why is the context reset to zero here? */
		command->info.custom_command.context=0;

		/* Set it to zero first */
		JLONG(byteSent) = 0;
		JLONG(byteSent) = ra_sendMessage(agent->bindingStorage, message);

		#ifdef _DEBUG2
		#ifdef MVS                    /* 198066 */
		#pragma convlit(suspend)
		#endif
		fprintf(traceFile, "LogAgent: sendMessageBinary0 - sent Binary Custom Command\n");
		fflush(traceFile);
		#ifdef MVS                    /* 198066 */
		#pragma convlit(resume)
		#endif
		#endif
		


		ra_destroyMessage(message, TRUE);
		
		// Free the data copy that we've created
		free(copy);
	}

#ifdef _DEBUG
	#ifdef MVS
		#pragma convlit(suspend)
	#endif
	printf("JNI_sendMessageBinary0: %d byte sent\n", byteSent);
	#ifdef MVS
		#pragma convlit(resume)
	#endif
#endif
	return byteSent;
}

/*
 * Bug 77768
 */
JNIEXPORT void JNICALL
Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton_requestMonitorThroughPeer0___3BJLjava_lang_String_2(JNIEnv *env, jobject obj, jbyteArray ipaddr, jlong pid, jstring agentName) {
#ifdef __OS400__
	jlong port;
	port.ll = 10002;
#else
	jlong port = 10002;
#endif
	Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton_requestMonitorThroughPeer0p___3BJJLjava_lang_String_2(env, obj, ipaddr, port, pid, agentName);
}

/*
 * Class:     Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton
 * Method:    requestMonitorThroughPeer0
 * Signature: ([BJLjava/lang/String;)V
 */
JNIEXPORT void JNICALL
Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton_requestMonitorThroughPeer0p___3BJJLjava_lang_String_2(JNIEnv *env, jobject obj, jbyteArray ipaddr, jlong port, jlong pid, jstring agentName) {
	jlong mech;
	jfieldID mechDecl;
	jclass clazz;

	/* No need to search, we can just use the _mechanism field in the agent.  This
	   Could be a problem on some platforms where the address size is not 4 bytes.
	 */
	clazz=ENV(env)->GetObjectClass(ENVPARM(env) obj);
#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
	mechDecl=ENV(env)->GetFieldID(ENVPARM(env) clazz, "mechanism", "J");
#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif
	mech=ENV(env)->GetLongField(ENVPARM(env) obj, mechDecl);

    if(JLONG(mech) >-1 && JLONG(mech)<_agent_list.size) {
		agent_list_entry_t *agent;
        ra_ipaddr_t addr;
		char *agentName_native;
        agent = _agent_list.entries[JLONG(mech)];

		/* Extract our JNI information */
		addr.addrLength = (unsigned char)ENV(env)->GetArrayLength(ENVPARM(env) ipaddr);
		addr.addr = (unsigned char *)malloc(addr.addrLength * sizeof(unsigned char));
		ENV(env)->GetByteArrayRegion(ENVPARM(env) ipaddr, 0, addr.addrLength, (signed char *)addr.addr);

		/* Convert the Unicode string */
		agentName_native = copyJavaStringToNative(env, agentName);

		ra_requestPeerMonitor_p(agent->bindingStorage, &addr, (unsigned long)JLONG(port), (unsigned long)JLONG(pid), ra_createRASTRING2(agentName_native), 0); /* Bug 77768 */

		/* Cleanup our mess */
		free(addr.addr);
		ra_free(agentName_native); /* Bug 179365 */
	}
}

/*
 * Bug 77768
 */
JNIEXPORT void JNICALL
Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton_requestMonitorThroughPeer0___3BLjava_lang_String_2(JNIEnv *env, jobject obj, jbyteArray ipaddr, jstring agentUUID) {
#ifdef __OS400__
	jlong port;
	port.ll = 10002;
#else
	jlong port = 10002;
#endif
	Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton_requestMonitorThroughPeer0p___3BJLjava_lang_String_2(env, obj, ipaddr, port, agentUUID);
}

/*
 * Class:     Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton
 * Method:    requestMonitorThroughPeer0
 * Signature: ([BLjava/lang/String;)V
 */
JNIEXPORT void JNICALL
Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton_requestMonitorThroughPeer0p___3BJLjava_lang_String_2(JNIEnv *env, jobject obj, jbyteArray ipaddr, jlong port, jstring agentUUID) {
	jlong mech;
	jfieldID mechDecl;
	jclass clazz;

	/* No need to search, we can just use the _mechanism field in the agent.  This
	   Could be a problem on some platforms where the address size is not 4 bytes.
	 */
	clazz=ENV(env)->GetObjectClass(ENVPARM(env) obj);
#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
	mechDecl=ENV(env)->GetFieldID(ENVPARM(env) clazz, "mechanism", "J");
#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif
	mech=ENV(env)->GetLongField(ENVPARM(env) obj, mechDecl);

    if(JLONG(mech) >-1 && JLONG(mech)<_agent_list.size) {
		agent_list_entry_t *agent;
        ra_ipaddr_t addr;
		char *agentUUID_native;
        agent = _agent_list.entries[JLONG(mech)];

		/* Extract our JNI information */
		addr.addrLength=(unsigned char)ENV(env)->GetArrayLength(ENVPARM(env) ipaddr);
		addr.addr=(unsigned char *)malloc(addr.addrLength*sizeof(unsigned char));
		ENV(env)->GetByteArrayRegion(ENVPARM(env) ipaddr, 0, addr.addrLength, (signed char *)addr.addr);

		/* Convert the Unicode string */
		agentUUID_native = copyJavaStringToNative(env, agentUUID);

		ra_requestPeerMonitor2_p(agent->bindingStorage, &addr, (unsigned long)JLONG(port), ra_createRASTRING2(agentUUID_native), 0); /* Bug 77768 */

		/* Cleanup our mess */
		free(addr.addr);
		ra_free(agentUUID_native); /* Bug 179365 */
	}



}


/** JAVA_NOTIFY_MESSAGE  ************************************************************
  * This function is called by the underlying controller mechanism to notify a particular
  * logging agent to either start/stop monitoring or to forward configuration information
  * via the RA_SET_NAME_VALUE_PAIR or RA_CUSTOM_COMMAND commands.
  */
static void _java_notifyMessage(ra_command_t *command) {
	JNIEnv *env;
	jint result;
	agent_list_entry_t *agent;


	#ifdef _DEBUG
	#ifdef MVS                    /* 198066 */
	#pragma convlit(suspend)
	#endif
	printf("Java Log Agent: notifyMessage: Recieving message %d\n", command->tag);
	#ifdef MVS                    /* 198066 */
	#pragma convlit(resume)
	#endif
	#endif
	/* Attach the current thread to the JVM */
#if defined __cplusplus && defined _HPUX
	result=ENV(_agent_vm)->AttachCurrentThread((void**)&env, NULL);
#else
	result=(*_agent_vm)->AttachCurrentThread(_agent_vm,  (void**)&env, NULL);
#endif
	if(!result) {

		#ifdef _DEBUG2
		#ifdef MVS                    /* 198066 */
		#pragma convlit(suspend)
		#endif
		fprintf(traceFile, "Java Log Agent: notifyMessage: Receiving message %d\n", command->tag);
		fflush(traceFile);
		#ifdef MVS                    /* 198066 */
		#pragma convlit(resume)
		#endif
		#endif

		switch(command->tag) {
		case RA_AGENT_CONTROLER_AVAILABLE:
			agent=findAgent(command->info.agentName.data);
			if(agent) {
				jclass cls;
				jmethodID agentControllerActive, setNodeUUID, setProcessUUID;
				jstring nodeUUID, processUUID;
				ra_agentConfigList_t *configuration;

				configuration=ra_getDefaultConfiguration(agent->bindingStorage);

				/* Find the class object */
				cls=ENV(env)->GetObjectClass(ENVPARM(env) agent->agent_logger);

				/* Set the node UUID in the agent
				 * RKD: This is a V5 addition we better catch the exception if the method does not exist.
				 */
#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
				setNodeUUID=ENV(env)->GetMethodID(ENVPARM(env) cls, "setNodeUUID", "(Ljava/lang/String;)V");
#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif
				if(setNodeUUID) {
					nodeUUID = getnewstrutf(env, agent -> bindingStorage -> agentUUID.data);
					ENV(env)->CallVoidMethod(ENVPARM(env) agent->agent_logger, setNodeUUID, nodeUUID);
				}

				/* Set the process UUID in the agent
				 * RKD: This is a V5 addition we better catch the exception if the method does not exist.
				 */
#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
				setProcessUUID=ENV(env)->GetMethodID(ENVPARM(env) cls, "setJVMUUID", "(Ljava/lang/String;)V");
#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif
				if(setProcessUUID) {
					processUUID = getnewstrutf(env, agent -> bindingStorage -> processUUID.data);
					ENV(env)->CallVoidMethod(ENVPARM(env) agent->agent_logger, setProcessUUID, processUUID);
				}

				/* Iterate through the configuration and load the agent with the info. */
				if(configuration) {
					jclass agentClass=ENV(env)->GetObjectClass(ENVPARM(env) agent->agent_logger);

					#ifdef _DEBUG2
					#ifdef MVS                    /* 198066 */
					#pragma convlit(suspend)
					#endif
					fprintf(traceFile, "Java Log Agent: We have a configuration - try to find the agent\n");
					fflush(traceFile);
					#ifdef MVS                    /* 198066 */
					#pragma convlit(resume)
					#endif
					#endif

					if(agentClass) {
#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
						jmethodID factoryMethod=ENV(env)->GetMethodID(ENVPARM(env) agentClass, "createObjectInContextOfClassLoader", "(Ljava/lang/String;)Ljava/lang/Object;");
#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif
						if(factoryMethod) {
#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
							jstring classname=ENV(env)->NewStringUTF(ENVPARM(env) "org.eclipse.hyades.internal.execution.remote.AgentConfigurationEntry"); /* Bug 78628 */
#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif
							jobject agentConfigurationEntryObject=ENV(env)->CallObjectMethod(ENVPARM(env) agent->agent_logger, factoryMethod, classname);
							if(agentConfigurationEntryObject) {
								jclass agentConfigurationEntryClass=ENV(env)->GetObjectClass(ENVPARM(env) agentConfigurationEntryObject);
								jmethodID addEntryToDefaultConfiguration, setName, setType, setValue;
								ra_agentConfigListEntry_t *configListEntry;

#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
								addEntryToDefaultConfiguration=ENV(env)->GetMethodID(ENVPARM(env) cls, "addEntryToDefaultConfiguration", "(Lorg/eclipse/hyades/internal/execution/remote/AgentConfigurationEntry;)V");
								setType=ENV(env)->GetMethodID(ENVPARM(env) agentConfigurationEntryClass, "setType", "(Ljava/lang/String;)V");
								setName=ENV(env)->GetMethodID(ENVPARM(env) agentConfigurationEntryClass, "setName", "(Ljava/lang/String;)V");
								setValue=ENV(env)->GetMethodID(ENVPARM(env) agentConfigurationEntryClass, "setValue", "(Ljava/lang/String;)V");
#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif
								configListEntry=configuration->head;
								while(configListEntry) {
									agentConfigurationEntryObject=ENV(env)->CallObjectMethod(ENVPARM(env) agent->agent_logger, factoryMethod, classname);

									if(agentConfigurationEntryObject) {
										jstring javaName;
										jstring javaType;
										jstring javaValue;
										char *ubName; /* UTF-8 bytes */
										char *ubType; /* UTF-8 bytes */
										char *ubValue; /* UTF-8 bytes */

										native2unicode(&ubName, configListEntry->entry.name.data, configListEntry->entry.name.length);
										native2unicode(&ubType, configListEntry->entry.type.data, configListEntry->entry.type.length);
										native2unicode(&ubValue, configListEntry->entry.value.data, configListEntry->entry.value.length);

										javaName = ENV(env)->NewStringUTF(ENVPARM(env) ubName);
										javaType = ENV(env)->NewStringUTF(ENVPARM(env) ubType);
										javaValue = ENV(env)->NewStringUTF(ENVPARM(env) ubValue);

										ENV(env)->CallVoidMethod(ENVPARM(env) agentConfigurationEntryObject, setName, javaName);
										ENV(env)->CallVoidMethod(ENVPARM(env) agentConfigurationEntryObject, setType, javaType);
										ENV(env)->CallVoidMethod(ENVPARM(env) agentConfigurationEntryObject, setValue, javaValue);

										ENV(env)->CallVoidMethod(ENVPARM(env) agent->agent_logger, addEntryToDefaultConfiguration, agentConfigurationEntryObject);
									}
									configListEntry=configListEntry->next;
								}
							}
						}
					}
				}

				/* If there are any pending exceptions clear them */
#if defined __cplusplus && defined _HPUX
				ENV(env)->ExceptionClear();
#else
				ENV(env)->ExceptionClear(env);
#endif


			    /* Inform that the server is available */
#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
			    agentControllerActive=ENV(env)->GetMethodID(ENVPARM(env) cls, "agentControllerActive", "()V");
#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif
			    ENV(env)->CallVoidMethod(ENVPARM(env) agent->agent_logger, agentControllerActive);

				#ifdef _DEBUG2
				#ifdef MVS                    /* 198066 */
				#pragma convlit(suspend)
				#endif
				fprintf(traceFile, "Java Log Agent: Agent Controller Available processing done and called agentControllerActive method.\n");
				fflush(traceFile);
				#ifdef MVS                    /* 198066 */
				#pragma convlit(resume)
				#endif
				#endif
			}
			break;
		case RA_AGENT_CONTROLER_UNAVAILABLE:
			agent=findAgent(command->info.agentName.data);
			if(agent) {
				jclass cls;
				jmethodID agentControllerInactive;
				/* Find the class object */
			    cls=ENV(env)->GetObjectClass(ENVPARM(env) agent->agent_logger);
				if(cls) {
					/* Inform that the server is available */
#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
					agentControllerInactive=ENV(env)->GetMethodID(ENVPARM(env) cls, "agentControllerInactive", "()V");
#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif
					if(agentControllerInactive) {
						ENV(env)->CallVoidMethod(ENVPARM(env) agent->agent_logger, agentControllerInactive);
					}
				}
			}
			break;
		case RA_DETACH_FROM_AGENT:
			agent=findAgent(command->info.detach.agent.data);
			if(agent) {
				jclass cls;
				jmethodID remoteClientExited;
				/* Find the class object */
			    cls=ENV(env)->GetObjectClass(ENVPARM(env) agent->agent_logger);
				if(cls) {
					/* Inform that the client is no longer available */
#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
					remoteClientExited=ENV(env)->GetMethodID(ENVPARM(env) cls, "remoteClientExited", "()V");
#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif
					if(remoteClientExited) {
						ENV(env)->CallVoidMethod(ENVPARM(env) agent->agent_logger, remoteClientExited);
					}
				}
				
			    /* Close the appropriate data channel implementation if the agent is being monitored */
				if(agent->monitored) {

					if(agent->targetHdl.dtarget == RA_SOCKET) {
						ra_closeSocket(agent->targetHdl.dtargetHdl.socketFD);
					}
					else if(agent->targetHdl.dtarget == RA_SHAREDMEMORY) {
						ra_stopFlushingShm(&agent->targetHdl.dtargetHdl.shmHdl);
					}
				}
				
				agent->monitored = FALSE;
			}
			break;
			
		/* NOTE:  This case is used on platforms that do not support shared memory data channel implementation. */
		
		case RA_START_MONITORING_AGENT_REMOTE: 
		{
			jclass cls;
			jmethodID	agent_setLogging;

			agent=findAgent(command->info.start_monitor_remote.agent.data);
			
			if(agent) {
			
			   if (!agent->monitored) {

					#ifdef _DEBUG
					#ifdef MVS                    /* 198066 */
					#pragma convlit(suspend)
					#endif
					printf("Log Agent: %s connecting to remote server\n", agent->agent_name);
					#ifdef MVS                    /* 198066 */
					#pragma convlit(resume)
					#endif
					#endif

					agent->targetHdl.dtarget = RA_SOCKET;

					ra_connectToTCPServer(command->info.start_monitor_remote.ip,
									  (unsigned short)command->info.start_monitor_remote.port,
									  &agent->targetHdl.dtargetHdl.socketFD);
				}

				cls=ENV(env)->GetObjectClass(ENVPARM(env) agent->agent_logger);

				if(!cls) {
					#ifdef _DEBUG
					#ifdef MVS                    /* 198066 */
					#pragma convlit(suspend)
					#endif
					printf("LogAgent: _agent_notifyMessage - Find class failed\n");
					#ifdef MVS                    /* 198066 */
					#pragma convlit(resume)
					#endif
					#endif
					break;
				}
#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
				agent_setLogging = ENV(env)->GetMethodID(ENVPARM(env)cls, "setLogging", "(Z)V");
#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif

				if(!agent_setLogging) {
					#ifdef _DEBUG
					#ifdef MVS                    /* 198066 */
					#pragma convlit(suspend)
					#endif
					printf("LogAgent: _agent_notifyMessage - GetMethodID failed\n");
					#ifdef MVS                    /* 198066 */
					#pragma convlit(resume)
					#endif
					#endif
					break;
				}
				ENV(env)->CallVoidMethod(ENVPARM(env) agent->agent_logger, agent_setLogging, (jboolean)1 );

				agent->monitored=TRUE;
			}
			#ifdef _DEBUG
			else {
				#ifdef MVS                    /* 198066 */
				#pragma convlit(suspend)
				#endif
				printf("Log Agent: Couldn't find agent %s", agent->agent_name);
				#ifdef MVS                    /* 198066 */
				#pragma convlit(resume)
				#endif
			}
			#endif
			break;
		}
		
		/* NOTE:  This case is used on platforms that support shared memory data channel implementation. */
		
		case RA_START_MONITORING_AGENT_LOCAL:
		{	
			jmethodID	agent_setLogging;
			jclass cls;

			agent=findAgent(command->info.start_monitor_remote.agent.data);
			
			if(agent){

				if(!agent->monitored){
					
					#ifdef _DEBUG
					#ifdef MVS                    /* 198066 */
					#pragma convlit(suspend)
					#endif
					printf("Log Agent: %s connecting to shared memory pipe\n", agent->agent_name);
					#ifdef MVS                    /* 198066 */
					#pragma convlit(resume)
					#endif
					#endif
	
					result = ra_attachToShm(command->info.start_monitor_local.file.data,
									&agent->targetHdl.dtargetHdl.shmHdl);
					if(result != 0) {
						#ifdef MVS                    /* 198066 */
						#pragma convlit(suspend)
						#endif
						printf("Error %d attaching to data channel.\n", result);
						#ifdef MVS                    /* 198066 */
						#pragma convlit(resume)
						#endif
						break;
					}
	
					agent->targetHdl.dtarget = RA_SHAREDMEMORY;
				}
			
				cls=ENV(env)->GetObjectClass(ENVPARM(env) agent->agent_logger);

				if(!cls) {
					#ifdef _DEBUG
					#ifdef MVS                    /* 198066 */
					#pragma convlit(suspend)
					#endif
					printf("LogAgent: _agent_notifyMessage - Find class failed\n");
					#ifdef MVS                    /* 198066 */
					#pragma convlit(resume)
					#endif
					#endif
					break;
				}

#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
				agent_setLogging = ENV(env)->GetMethodID(ENVPARM(env) cls, "setLogging", "(Z)V");
#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif

				if(!agent_setLogging) {
					#ifdef _DEBUG
					#ifdef MVS                    /* 198066 */
					#pragma convlit(suspend)
					#endif
					printf("LogAgent: _agent_notifyMessage - GetMethodID failed\n");
					#ifdef MVS                    /* 198066 */
					#pragma convlit(resume)
					#endif
					#endif
					break;
				}

				agent->monitored=TRUE;

				ENV(env)->CallVoidMethod(ENVPARM(env) agent->agent_logger, agent_setLogging, (jboolean)1 );
			}
			#ifdef _DEBUG
			else {
				#ifdef MVS                    /* 198066 */
				#pragma convlit(suspend)
				#endif
				printf("Log Agent: Couldn't find agent %s", agent->agent_name);
				#ifdef MVS                    /* 198066 */
				#pragma convlit(resume)
				#endif
			}
			#endif
			
			break; 
		}
		
	    /* NOTE:  This case does not set the agent->monitored flag to 'FALSE' or close the data channel. */
	    /*        The agent->monitored flag is used to denote when the data channel is open.  */
	    /*        The data channel is only closed when a client detaches from an agent. */
	    
		case RA_STOP_MONITORING_AGENT:
			agent=findAgent(command->info.stop_monitor.agent.data);
			if(agent && agent->monitored) {
				jclass cls;
				jmethodID	agent_setLogging;
				cls=ENV(env)->GetObjectClass(ENVPARM(env) agent->agent_logger);

				if(!cls) {
					#ifdef _DEBUG
					#ifdef MVS                    /* 198066 */
					#pragma convlit(suspend)
					#endif
					printf("LogAgent: _agent_notifyMessage - Find Class failed\n");
					#ifdef MVS                    /* 198066 */
					#pragma convlit(resume)
					#endif
					#endif
				}
				else {
#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
					agent_setLogging = ENV(env)->GetMethodID(ENVPARM(env) cls, "setLogging", "(Z)V");
#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif
					if(!agent_setLogging) {
						#ifdef _DEBUG
						#ifdef MVS                    /* 198066 */
						#pragma convlit(suspend)
						#endif
						printf("LogAgent: _agent_notifyMessage - GetMethodID failed\n");
						#ifdef MVS                    /* 198066 */
						#pragma convlit(resume)
						#endif
						#endif
					}
					else {
						ENV(env)->CallVoidMethod(ENVPARM(env) agent->agent_logger, agent_setLogging, (jboolean)0 );
					}
				}
			}
			break;
		case RA_CUSTOM_COMMAND:
		case RA_BINARY_CUSTOM_COMMAND:
		{
			BOOL isBinary = FALSE;
			/* Data */
			char *data;
			int length;

			/* String constants, need to perform conversion for EBCDIC systems */
#ifdef __OS400__
	#pragma convert(819)
#endif
			char *className_CustomCommand = "org.eclipse.hyades.internal.execution.local.common.CustomCommand";
			char *className_BinaryCustomCommand = "org.eclipse.hyades.internal.execution.local.common.BinaryCustomCommand";
			char *funcName_createObjectInContextOfClassLoader = "createObjectInContextOfClassLoader";
			char *funcSig_createObjectInContextOfClassLoader = "(Ljava/lang/String;)Ljava/lang/Object;";
			char *funcName_setData = "setData";
			char *funcSig_setData = "([B)V";
			char *funcName_incomingCommand = "incomingCommand";
			char *funcSig_incomingCommand = "(Lorg/eclipse/hyades/internal/execution/local/common/CommandElement;)V";
#ifdef __OS400__
	#pragma convert(0)
#endif
			/* Make sure data is in the correct format, based on the type of the message */
			if(command->tag == RA_CUSTOM_COMMAND) { /* This contains string. Need to perform a conversion */
				isBinary = FALSE;
				length = native2unicode(&data, command->info.custom_command.message.data, command->info.custom_command.message.length);
			}
			else { /* This contains binary data, do not convert */
				isBinary = TRUE;
				length = command->info.custom_command.message.length;
				data = (char*)ra_malloc(sizeof(char*) * length);
				memcpy(data, command->info.custom_command.message.data, length);
			}

			agent = findAgent(command->info.custom_command.agent.data);
			if(agent) {
				jclass agentClass = ENV(env)->GetObjectClass(ENVPARM(env) agent->agent_logger);
				if(agentClass) {
					jmethodID factoryMethod = ENV(env)->GetMethodID(ENVPARM(env) agentClass, funcName_createObjectInContextOfClassLoader, funcSig_createObjectInContextOfClassLoader);
					if(factoryMethod) {
						jstring classname;
						jobject obj;

						if(isBinary) {
							classname = ENV(env)->NewStringUTF(ENVPARM(env) className_BinaryCustomCommand);
						}
						else {
							classname = ENV(env)->NewStringUTF(ENVPARM(env) className_CustomCommand);
						}

						obj = ENV(env)->CallObjectMethod(ENVPARM(env) agent->agent_logger, factoryMethod, classname);
						if(obj) {
							jclass clazz = ENV(env)->GetObjectClass(ENVPARM(env) obj);
							if(clazz) {
								jmethodID setData = ENV(env)->GetMethodID(ENVPARM(env) clazz, funcName_setData, funcSig_setData);
								if(setData) {
									jclass cls;
									jmethodID incomingCommand;
									/* Call the setter on the Command object */
									jbyteArray dataBytes = ENV(env)->NewByteArray(ENVPARM(env) length);
									ENV(env)->SetByteArrayRegion(ENVPARM(env) dataBytes, 0, length, (jbyte*)data);
									ENV(env)->CallVoidMethod(ENVPARM(env) obj, setData, dataBytes);
									/* Invoke incomingCommand on the agent instance */
									cls = ENV(env)->GetObjectClass(ENVPARM(env) agent->agent_logger);
									if(!cls) {
										#ifdef _DEBUG2
										#ifdef MVS
										#pragma convlit(suspend)
										#endif
										fprintf(traceFile, "Java LogAgent: notifyMessage - Find Class failed\n");
										fflush(traceFile);
										#ifdef MVS
										#pragma convlit(resume)
										#endif
										#endif
									}
									else {
										incomingCommand = ENV(env)->GetMethodID(ENVPARM(env) cls, funcName_incomingCommand, funcSig_incomingCommand);
										if(!incomingCommand) {
											#ifdef _DEBUG2
											#ifdef MVS
											#pragma convlit(suspend)
											#endif
											fprintf(traceFile, "Java LogAgent: notifyMessage - GetMethodID failed\n");
											fflush(traceFile);
											#ifdef MVS
											#pragma convlit(resume)
											#endif
											#endif
										}
										else {
											ENV(env)->CallVoidMethod(ENVPARM(env) agent->agent_logger, incomingCommand, obj);
										}
									}
								}
							}
						}
					}
				}
			}
			#ifdef _DEBUG
			/* Note: This call causes the process to end on zOS */
			ENV(env)->ExceptionDescribe(env);
			#endif
			#ifdef _DEBUG2
			#ifdef MVS                    /* 198066 */
			#pragma convlit(suspend)
			#endif
			fprintf(traceFile, "Java LogAgent: notifyMessage - Custom Command processed\n");
			fflush(traceFile);
			#ifdef MVS                    /* 198066 */
			#pragma convlit(resume)
			#endif
			#endif

			/* Free up memory */
			ra_free(data);

			break;
		}
		case RA_SET_NAME_VALUE_PAIR:
		{
			/* The triplets, need conversion */
			char *name_data;
			char *type_data;
			char *value_data;
			int name_len;
			int type_len;
			int value_len;

			/* String constants, need conversion */
#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
			char *className_SetNVPairCommand = "SetNVPairCommand";
			char *funcName_createObjectInContextOfClassLoader = "createObjectInContextOfClassLoader";
			char *funcSig_createObjectInContextOfClassLoader = "(Ljava/lang/String;)Ljava/lang/Object;";
			char *funcName_setType = "setType";
			char *funcSig_setType = "(Ljava/lang/String;)V";
			char *funcName_setName = "setName";
			char *funcSig_setName = "(Ljava/lang/String;)V";
			char *funcName_setValue = "setVaue";
			char *funcSig_setValue = "(Ljava/lang/String;)V";
			char *funcName_incomingCommand = "incomingCommand";
			char *funcSig_incomingCommand = "(Lorg/eclipse/hyades/internal/execution/local/common/CommandElement;)V";
#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif

			name_len = native2unicode(&name_data, command->info.set_nv_pair.name.data, command->info.set_nv_pair.name.length);
			type_len = native2unicode(&type_data, command->info.set_nv_pair.type.data, command->info.set_nv_pair.type.length);
			value_len = native2unicode(&value_data, command->info.set_nv_pair.value.data, command->info.set_nv_pair.value.length);

			agent = findAgent(command->info.set_nv_pair.agent.data);
			if(agent) {
				jclass agentClass = ENV(env)->GetObjectClass(ENVPARM(env) agent->agent_logger);
				if(agentClass) {
					jmethodID factoryMethod = ENV(env)->GetMethodID(ENVPARM(env) agentClass, funcName_createObjectInContextOfClassLoader, funcSig_createObjectInContextOfClassLoader);
					if(factoryMethod) {
						jstring classname = ENV(env)->NewStringUTF(ENVPARM(env) className_SetNVPairCommand);
						jobject obj = ENV(env)->CallObjectMethod(ENVPARM(env) agent->agent_logger, factoryMethod, classname);
						if(obj) {
							jclass clazz = ENV(env)->GetObjectClass(ENVPARM(env) obj);
							if(clazz) {
								jmethodID setType, setName, setValue;
								setName = ENV(env)->GetMethodID(ENVPARM(env) clazz, funcName_setName, funcSig_setName);
								setType = ENV(env)->GetMethodID(ENVPARM(env) clazz, funcName_setType, funcSig_setType);
								setValue = ENV(env)->GetMethodID(ENVPARM(env) clazz, funcName_setValue, funcSig_setValue);
								if(setType && setName && setValue) {
									jclass cls;
									jstring setTypeParam, setNameParam, setValueParam;
									jmethodID incomingCommand;
									char *name, *type, *value;

									/* Bug 83888 */

									/* Verify the name */
									if(name_data == NULL) { /* name cannot be null */
										break;
									}

									/* Verify the type */
									if(type_data == NULL) {
										type_data = "\0";
									}

									/* Verify the value */
									if(value_data == NULL) {
										value = "\0";
									}

									/* Call the setters on the Command object */
									setNameParam = ENV(env)->NewStringUTF(ENVPARM(env) name_data); /* Bug 83888 */
									ENV(env)->CallVoidMethod(ENVPARM(env) obj, setName, setNameParam );
									setTypeParam = ENV(env)->NewStringUTF(ENVPARM(env) type_data); /* Bug 83888 */
									ENV(env)->CallVoidMethod(ENVPARM(env) obj, setType, setTypeParam );
									setValueParam = ENV(env)->NewStringUTF(ENVPARM(env) value_data); /* Bug 83888 */
									ENV(env)->CallVoidMethod(ENVPARM(env) obj, setValue, setValueParam );

									/* Invoke incomingCommand on the agent instance */
									cls = ENV(env)->GetObjectClass(ENVPARM(env) agent->agent_logger);

									if(!cls) {
										#ifdef _DEBUG
										#ifdef MVS                    /* 198066 */
										#pragma convlit(suspend)
										#endif
										printf("LogAgent: _agent_notifyMessage - Find Class failed\n");
										#ifdef MVS                    /* 198066 */
										#pragma convlit(resume)
										#endif
										#endif
									}
									else {
										incomingCommand = ENV(env)->GetMethodID(ENVPARM(env) cls, funcName_incomingCommand, funcSig_incomingCommand);
										if(!incomingCommand) {
											#ifdef _DEBUG
											#ifdef MVS                    /* 198066 */
											#pragma convlit(suspend)
											#endif
											printf("LogAgent: _agent_notifyMessage - GetMethodID failed\n");
											#ifdef MVS                    /* 198066 */
											#pragma convlit(resume)
											#endif
											#endif
										}
										else {
											ENV(env)->CallVoidMethod(ENVPARM(env) agent->agent_logger, incomingCommand, obj);
										}
									}
								}
							}
						}
					}
				}
			}

			ra_free(name_data);
			ra_free(type_data);
			ra_free(value_data);

			break;
		}
		case RA_PEER_UNREACHABLE:
			agent = findAgent(command->info.peer_unreachable.agent.data);
			if(agent) {
					jmethodID peerUnreachable;
					jclass cls;
					/* Find the class object */
					cls = ENV(env)->GetObjectClass(ENVPARM(env) agent->agent_logger);
					/* Inform the calling agent that the remote peer is unreachable
					 * RKD: This is a V5 addition we better catch the exception if the method does not exist.
					 */
#ifdef __OS400__
#pragma convert(819) /* 235033 */
#endif
					peerUnreachable = ENV(env)->GetMethodID(ENVPARM(env) cls, "peerUnreachable", "()V");
#ifdef __OS400__
#pragma convert(0) /* 235033 */
#endif
					if(peerUnreachable) {
						ENV(env)->CallVoidMethod(ENVPARM(env) agent->agent_logger, peerUnreachable, NULL);
					}
				}
			break;
		} /* switch */

		#ifdef _DEBUG2
		#ifdef MVS                    /* 198066 */
		#pragma convlit(suspend)
		#endif
		fprintf(traceFile, "Java Log Agent: notifyMessage:  Completed message handling.\n");
		fflush(traceFile);
		#ifdef MVS                    /* 198066 */
		#pragma convlit(resume)
		#endif
		#endif

#ifdef _DEBUG
		/* Note: This call causes the process to end on zOS */
		ENV(env)->ExceptionDescribe(env);
#endif

		/* If there are any pending exceptions clear them.
		   Detach the current thread from the JVM
		 */
#if defined __cplusplus && defined _HPUX
		ENV(env)->ExceptionClear();
		ENV(_agent_vm)->DetachCurrentThread();
#else
		ENV(env)->ExceptionClear(env);
		(*_agent_vm)->DetachCurrentThread(_agent_vm);
#endif
	}

}


/** NATIVE_NOTIFY_MESSAGE  ************************************************************
  * This function is called by the underlying controller mechanism to notify a particular
  * logging agent to either start/stop monitoring or to forward configuration information
  * via the RA_SET_NAME_VALUE_PAIR or RA_CUSTOM_COMMAND commands.
  */
static void _native_notifyMessage(ra_command_t *command) {
	jint result;
	agent_list_entry_t *agent;

	#ifdef _DEBUG
	#ifdef MVS                    /* 198066 */
	#pragma convlit(suspend)
	#endif
	printf("Native Log Agent: Recieving message 0x%x\n", command->tag);
	#ifdef MVS                    /* 198066 */
	#pragma convlit(resume)
	#endif
	#endif

		switch(command->tag) {
		case RA_AGENT_CONTROLER_AVAILABLE:
			agent=findAgent(command->info.agentName.data);
			if(agent) {
			}
			break;
		case RA_AGENT_CONTROLER_UNAVAILABLE:
			agent=findAgent(command->info.agentName.data);
			if(agent) {
			}
			break;
		case RA_DETACH_FROM_AGENT:
			agent=findAgent(command->info.detach.agent.data);
			if(agent) {
			}
			break;
		case RA_START_MONITORING_AGENT_REMOTE:
			agent=findAgent(command->info.start_monitor_remote.agent.data);
			if(agent && !agent->monitored) {

				#ifdef _DEBUG
				#ifdef MVS                    /* 198066 */
				#pragma convlit(suspend)
				#endif
				printf("Log Agent: %s connecting to remote server\n", agent->agent_name);
				#ifdef MVS                    /* 198066 */
				#pragma convlit(resume)
				#endif
				#endif

				agent->targetHdl.dtarget = RA_SOCKET;

				ra_connectToTCPServer(command->info.start_monitor_remote.ip,
									  (unsigned short)command->info.start_monitor_remote.port,
									  &agent->targetHdl.dtargetHdl.socketFD);

				agent->monitored=TRUE;
			}
			#ifdef _DEBUG
			else {
				#ifdef MVS                    /* 198066 */
				#pragma convlit(suspend)
				#endif
				printf("Log Agent: Couldn't find agent %s", agent->agent_name);
				#ifdef MVS                    /* 198066 */
				#pragma convlit(resume)
				#endif
			}
			#endif
			break;
		case RA_START_MONITORING_AGENT_LOCAL:
			agent=findAgent(command->info.start_monitor_remote.agent.data);
			if(agent && !agent->monitored) {

				#ifdef _DEBUG
				#ifdef MVS                    /* 198066 */
				#pragma convlit(suspend)
				#endif
				printf("Log Agent: %s connecting to shared memory pipe\n", agent->agent_name);
				#ifdef MVS                    /* 198066 */
				#pragma convlit(resume)
				#endif
				#endif

				result = ra_attachToShm(command->info.start_monitor_local.file.data,
								&agent->targetHdl.dtargetHdl.shmHdl);
				if(result != 0) {
					#ifdef MVS                    /* 198066 */
					#pragma convlit(suspend)
					#endif
					printf("Error attaching to shared memory\n");
					#ifdef MVS                    /* 198066 */
					#pragma convlit(resume)
					#endif
				}

				agent->targetHdl.dtarget = RA_SHAREDMEMORY;

				agent->monitored=TRUE;
			}
			#ifdef _DEBUG
			else {
				#ifdef MVS                    /* 198066 */
				#pragma convlit(suspend)
				#endif
				printf("Log Agent: Couldn't find agent %s", command->info.start_monitor_remote.agent.data);
				#ifdef MVS                    /* 198066 */
				#pragma convlit(resume)
				#endif
			}
			#endif
			break;
		case RA_STOP_MONITORING_AGENT:
			agent=findAgent(command->info.stop_monitor.agent.data);
			if(agent && agent->monitored) {
				/* Close the appropriate logging mechanism */
				if(agent->targetHdl.dtarget==RA_SOCKET) {
					ra_closeSocket(agent->targetHdl.dtargetHdl.socketFD);

				}
				else if(agent->targetHdl.dtarget==RA_SHAREDMEMORY) {
					ra_stopFlushingShm(&agent->targetHdl.dtargetHdl.shmHdl);
				}
				agent->monitored=FALSE;
			}
			break;
		case RA_CUSTOM_COMMAND:
			agent=findAgent(command->info.custom_command.agent.data);
			/* create a CustomCommand and forward this to the Agent.incomingCommand() method */
			if(agent) {
			}
			break;
		case RA_SET_NAME_VALUE_PAIR:
			agent=findAgent(command->info.set_nv_pair.agent.data);
			/* Create a CustomCommand and forward this to the Agent.incomingCommand() method */
			if(agent) {
			}
			break;
		}
		/* Forward the command to the agent handler registered with the native agent.  The developer has the option of
		 * registering their own command handler using agent->nativeCommandHandler. */
		if (agent && agent->nativeCommandHandler)
		{
			#ifdef _DEBUG
			#ifdef MVS                    /* 198066 */
			#pragma convlit(suspend)
			#endif
				printf("Log Agent: About to forward command to the registered customized handler\n");
			#ifdef MVS                    /* 198066 */
			#pragma convlit(resume)
			#endif
			#endif
			
			agent->nativeCommandHandler(command);

			#ifdef _DEBUG
			#ifdef MVS                    /* 198066 */
			#pragma convlit(suspend)
			#endif
				printf("Log Agent: Forward of command to customized agent was successful\n");
			#ifdef MVS                    /* 198066 */
			#pragma convlit(resume)
			#endif
			#endif
		}

	#ifdef _DEBUG
	#ifdef MVS                    /* 198066 */
	#pragma convlit(suspend)
	#endif
	printf("Log Agent: Completed message\n");
	#ifdef MVS                    /* 198066 */
	#pragma convlit(resume)
	#endif
	#endif
}

/* Bug 79816 */
JNIEXPORT jlong JNICALL Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton_getPID0(JNIEnv *env, jobject obj) {
	jlong pid;

#ifdef __OS400__
	pid.unsigned_ll = ra_getProcessId();
#else
	pid = ra_getProcessId();
#endif

	return pid;
}

/* Bug 79816 */
JNIEXPORT jstring JNICALL Java_org_eclipse_hyades_internal_execution_remote_RemoteComponentSkeleton_generateUUID0(JNIEnv *env, jobject obj) {
	ra_string_t *uuid;
	jstring juuid;

	uuid = (ra_string_t*)malloc(sizeof(ra_string_t));
	ra_generateUUID(uuid); 

	juuid = ENV(env)->NewStringUTF(ENVPARM(env) uuid->data);
	free(uuid);

	return juuid;
}


/* RKD:  This is not turned on yet and when it is it is Windows explicit.
 */
#if 0
BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
					 )
{
    switch(ul_reason_for_call) {
    case DLL_PROCESS_ATTACH:
        break;
    case DLL_THREAD_ATTACH:
        break;
    case DLL_THREAD_DETACH:
        break;
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
#endif
