/*******************************************************************************
 * Copyright (c) 2005, 2009 Intel Corporation.
 * 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
 *
 * Contributors:
 *    Randy D. Smith, Intel - Refactored several instantiations into one
 *
 * $Id: TPTPConfig.cpp,v 1.70 2009/08/26 15:00:00 jwest Exp $
 *******************************************************************************/ 

#include "tptp/TPTPConfig.h"
#include "tptp/ProcCtlUtils.h"
#include "tptp/NoLog.h"

	// This file is the result of a merge of the TPTPConfig.cpp originally found in
	// src/agentController/TPTPConfigBinding with the TPTPConfig.cpp originally found
	// in src/shared/tptpConfig. src/agents/agent/ase/AgentConfig.cpp was also woven
	// in, as it had many of these same functions, along with an overloaded function
	// that was not being called (commented out near the end).

#include <xercesc/util/PlatformUtils.hpp>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/dom/DOMImplementation.hpp>
#include <xercesc/dom/DOMImplementationLS.hpp>
#include <xercesc/dom/DOMWriter.hpp>
#include <xercesc/framework/MemBufInputSource.hpp>
#include <xercesc/framework/Wrapper4InputSource.hpp>
#include <xercesc/framework/XMLFormatter.hpp>
#include <xercesc/framework/MemBufFormatTarget.hpp>

#include <xercesc/framework/StdOutFormatTarget.hpp>
#include <xercesc/framework/LocalFileFormatTarget.hpp>
#include <xercesc/parsers/XercesDOMParser.hpp>


XERCES_CPP_NAMESPACE_USE

#include "tptp/ParserErrorHandler.h"

/*
 * System environment ...these types are taken directly from the RAC.
 */
typedef struct {
	tptp_string *config;
	tptp_string *name;
	tptp_string *value;
} sysEnv_t;

typedef struct _sysEnv_node {
	sysEnv_t *env;
	struct _sysEnv_node *next;
	struct _sysEnv_node *previous;
} sysEnv_list_node_t;

typedef struct {
	sysEnv_list_node_t *head;
	sysEnv_list_node_t *tail;
} sysEnv_list_t;

#define MAX_PLUGINS 1024
static char *loadedPlugin[MAX_PLUGINS];
static int loadedPluginCount = 0;
static char *availablePlugins[MAX_PLUGINS]; /* Plugins available in the "plugins" directory */
static int availablePluginsCount = 0;

void setEnvironmentVariable(char *name, char *value);
int parsePluginConfig(AC_Config_t *ac_config,  char *pluginDirName);
int firstPluginProcessed = 0;
char *applicationAliasPtr = NULL;
static sysEnv_list_t *cacheEnv = NULL;

static AC_Config_t *_ac_config = NULL;

void setEnvironmentVariable(char *name, char *value);
agent_metadata_t* tptp_findAgent(tptp_list_t* agentList, char *agentName);

/* TODO: Replace TPTP_LOG macros with some way to redirect these messages to the AC logging service */

/* Default metadata is used when an agent registers but we don't have       */
/*    metadata corresponding to its agent name                              */
agent_metadata_t  defaultMetadata = {
                                     NULL,         /* No known name         */
                                     { 0, 0, 0, 0, 0}, /* No known interfaces   */
                                     1,            /* Single instance       */
                                     1,            /* Bound (can't launch)  */
                                     -1,           /* Unlimited controllers */
                                     -1,           /* Unlimited observers   */
                                     NULL,         /* No launch info        */
                                     NULL,         /* No client data        */
                                     NULL,         /* No full metadata      */
                                     { 0, 0, 0, 0, 0}, /* options */
				     NULL,	   /* dataChannelSize */
				     NULL,	   /* logFile */
				     NULL,	   /* client */
                                    };


/**
 *********************************************************************
 *                                                       
 * @brief                                  
 *    Format Attr String
 *                                                       
 * @return
 *		0 for success
 *
 *********************************************************************/
static int fmtAttribString(const char *attribName, const char *attribValue, char **attribStr)
{
	*attribStr = 0;
	*attribStr = (char *)tptp_malloc(strlen(SPACE)+strlen(attribName)+strlen(EQUALSIGN)+strlen(DOUBLEQUOTE)+strlen(attribValue)+strlen(DOUBLEQUOTE)+strlen(SPACE)+1);
	sprintf(*attribStr,"%s%s%s%s%s%s"," ",attribName,"=","\"",attribValue,"\"");
	return 0;
}

/**
 *********************************************************************
 *                                                       
 * @brief                                  
 *    Build Attr String
 *                                                       
 * @return
 *		0 for success
 *
 *********************************************************************/
static int buildAttrString(DOMNode *node, char **nodedata)
{
				DOMNamedNodeMap *attributes = node->getAttributes();
		        int attrlen = attributes->getLength();
				for(int i=0;i < attrlen;i++) 
				{
					DOMAttr *attributeNode = (DOMAttr*) attributes->item(i);
					char *attrname = XMLString::transcode(attributeNode->getName());
        			char *attrvalue = XMLString::transcode(attributeNode->getValue());
					char *attvalue;
					int ret = fmtAttribString(attrname, attrvalue, &attvalue);
					strcat(*nodedata, attvalue);
					tptp_free(attvalue);
					XMLString::release(&attrvalue);
					XMLString::release(&attrname);
				} 
	return 0;
}

/**
 *********************************************************************
 *                                                       
 * @brief                                  
 *    Get Attrib Values
 *                                                       
 * @return
 *		0 for success
 *
 *********************************************************************/
int getAttrs(DOMNode *node, char *attrName, char **attrValue)
{
	DOMNamedNodeMap *attributes = node->getAttributes();
    int attrlen = attributes->getLength();
	for(int i=0;i < attrlen;i++) 
	{
		DOMAttr *attributeNode = (DOMAttr*) attributes->item(i);
		char *cattrname = XMLString::transcode(attributeNode->getName());
		
		if(strcmp(cattrname, attrName) == 0) {
			char *cattrvalue = XMLString::transcode(attributeNode->getValue());
			
			*attrValue = (char *) tptp_malloc(strlen(cattrvalue)+1);
			strcpy(*attrValue, cattrvalue);
			
			XMLString::release(&cattrvalue);
		}
		
		XMLString::release(&cattrname);
	} 
	
	return 0;
}

/**
 *********************************************************************
 *                                                       
 * @brief                                  
 *    Get Node Values
 *                                                       
 * @return
 *		void
 *
 *********************************************************************/
void getNodeValue(DOMNode *node, char **input)
{
	if(node->hasChildNodes() && node->getFirstChild()->getNodeType() == DOMNode::TEXT_NODE)
	{
		char *nodevalue = XMLString::transcode(node->getFirstChild()->getNodeValue());
		*input = (char *)tptp_malloc(strlen(nodevalue)+1);
		strcpy(*input, nodevalue);
		//TPTP_LOG_DEBUG_MSG1("GetNodeValue() --> Nodevalue %s",nodevalue);
		XMLString::release(&nodevalue);
	}
}

/**
 *********************************************************************
 *                                                       
 * @brief                                  
 *    Build a DOM Tree Branch Given a node and return the Input
 *                                                       
 * @return
 *		0 for success
 *
 *********************************************************************/
int buildDOMTreeBranch(DOMNode *node, char **input, int bufferLen) 
{
	DOMImplementation   *impl = DOMImplementationRegistry::getDOMImplementation(&chNull);
	DOMWriter           *writer = ((DOMImplementationLS*)impl)->createDOMWriter();
    MemBufFormatTarget  *target = new MemBufFormatTarget;
	int                  targetLen;

	// Set the encoding to EBCDIC from UTF for z-series machines
	#ifdef MVS
		int x = 0;
		writer->setEncoding(XMLUni::fgIBM1047EncodingString);
	#endif

	writer->writeNode( target, *node );
	targetLen = target->getLen();

	if ( targetLen  > bufferLen )
	{
		strncpy( *input, (char *)target->getRawBuffer(), bufferLen );
		(*input)[bufferLen-1] = 0;
		// In the MVS case, the XML parser is having trouble parsing the end-of-line linefeeds (dec 37, 0x25), so we replace them with spaces.
		#ifdef MVS
			for(x = 0 ; x < strlen(*input); x++) {
				if((*input)[x] == 37) {
					(*input)[x] = ' ';
				}
			}
		#endif
		return -1;
	}
	else
	{
		strncpy( *input, (char *)target->getRawBuffer(), targetLen );
		(*input)[targetLen] = 0;
		// In the MVS case, the XML parser is having trouble parsing the end-of-line linefeeds (dec 37, 0x25), so we replace them with spaces.
		#ifdef MVS
			for(x = 0 ; x < strlen(*input); x++) {
				if((*input)[x] == 37) {
					(*input)[x] = ' ';
				}
			}
		#endif
	}

	return 0;
}

/**
 *********************************************************************
 *                                                       
 * @brief                                  
 *    Get InPut Xml File Size
 *                                                       
 * @return
 *		0 for success
 *
 *********************************************************************/
int getXMLFileSize(char *XMLfilename, long *fileSize)
{
	FILE *pFile;
	//unsigned long lSize;
	
	pFile = fopen (XMLfilename, "r" );
	if (pFile==NULL) {return -1; }
	fseek (pFile , 0 , SEEK_END);
	*fileSize = ftell(pFile);
	rewind (pFile);
	fclose(pFile);
	return 0;
}

/**
 *********************************************************************
 *                                                       
 * @brief                                  
 *    Log Service Message (Replace with the Util service function)
 *                                                       
 * @return
 *		0 Success
 *
 *********************************************************************/

void logServiceMessage(char *file,int  line, const char *msg) 
{
	

}

/**
 *********************************************************************
 *                                                       
 * @brief                                  
 *    Utility function to print a list
 *                                                       
 * @return
 *		void
 *
 *********************************************************************/
void printList(tptp_list_t *inputList)
{
	tptp_node_t *listnode;
	for( listnode = inputList->head; listnode != 0; listnode = listnode->next)
	{
		char ret[TPTP_DEFAULT_BUFFER_LENGTH] ;
		//ret = (char *)tptp_malloc(strlen((char *)node->data)+1);
		strcpy(ret, (char *)listnode->data);
		TPTP_LOG_DEBUG_MSG1("ListNode - Data := %s", ret);
		//tptp_free(ret);
	}
}

/*
 * This function return the environment variable (see also java.c)
 *
 */
int ra_getEnvironmentVariable(char* name, char* buffer, int size) {
#ifdef _WIN32
	return GetEnvironmentVariable(name, buffer, size);
#else
	int len;
	char *currentValue = getenv(name);
	if (!currentValue) {
		return 0;
	}

	len = strlen(currentValue) + 1;

	if (size >= len) {
		memcpy(buffer, currentValue, len);
	}

	return len; /* Bug 68919 */
#endif
}

void ra_setServiceEnvironment(char *name, char *value, position_t position) {

	int result,  INITIAL_BUFFER_SIZE=128;
	char *buffer=NULL;
	int bufferSize=INITIAL_BUFFER_SIZE;

	/* Ensure that we have a name and value to start with */
	if(!name || !value) {
		return;
	}

	/* If it doesn't exist or we must replace then just set the value */
	if(position==REPLACE) {
		setEnvironmentVariable(name, value);
		return;
	}

	buffer=(char*)tptp_malloc(bufferSize+strlen(value)+1);

retry:
	if(position==PREPEND)  {
		result=ra_getEnvironmentVariable(name, &buffer[strlen(value)+1], bufferSize);
	}
	else {
		result=ra_getEnvironmentVariable(name, buffer, bufferSize);
	}

	/* Overflow condition */
	if(result>bufferSize) {
		tptp_free(buffer);
		bufferSize=result+1;
		buffer=(char*)tptp_malloc(bufferSize+strlen(value)+1);
		goto retry;
	}
	/* Append */
	else if(position==APPEND){
#ifdef _WIN32
		buffer[result]=PATH_SEPARATOR;
		memcpy(&buffer[result+1], value, strlen(value));
		buffer[result+1+strlen(value)]='\0';
		setEnvironmentVariable(name, buffer);
#else
		//If we are at the start of an item then we don't require
		//a separator... This was causing some linux issues.
		//Linux also required modification of where we inserted the
		//the null character. Nulls should not be embedded in the
		//variable... on the end null is significant.
		if (result > 0) {
			buffer[result-1]=PATH_SEPARATOR;
		}
		memcpy(&buffer[result], value, strlen(value));
		buffer[result+strlen(value)]='\0';
		setEnvironmentVariable(name, buffer);
#endif
	}
	/* Prepend */
	else {
		memcpy(buffer, value, strlen(value));
		buffer[strlen(value)]=PATH_SEPARATOR;
		buffer[result+strlen(value)+1]='\0';
		setEnvironmentVariable(name, buffer);
	}
	tptp_free(buffer);
}

void addEnvVar(sysEnv_list_t *env, char* config, char *name, char *value, position_t pos) {
	sysEnv_list_node_t *node;
	char* buffer;

	if ( env == NULL )
		return;

	node = env->head;
	/* Check for existing env */
	while(node != NULL) {
		if(strcmp(node->env->name, name) == 0) { /* found existing env */
			if(pos == REPLACE) {
				tptp_free(node->env->value);
				node->env->value = (tptp_string*) tptp_malloc(strlen(value) +1);
				strcpy(node->env->value, value);
			}
			else {
				buffer = (char*)tptp_malloc(sizeof(char) * (strlen(node->env->value) + strlen(value) + 1 + 1)); /* separator and NULL */
				BZERO(buffer, strlen(node->env->value) + strlen(value) + 1 + 1);
				if(pos == APPEND) {
					strcpy(buffer, node->env->value);
#ifdef _WIN32
					strcat(buffer, ";");
#else
					strcat(buffer, ":");
#endif
					strcat(buffer, value);
				}
				else if(pos == PREPEND) {
					strcpy(buffer, value);
#ifdef _WIN32
					strcat(buffer, ";");
#else
					strcat(buffer, ":");
#endif
					strcat(buffer, node->env->value);
				}
				tptp_free(node->env->value);
				if (buffer != NULL) {
					node->env->value = (tptp_string*) tptp_malloc(strlen(buffer) +1);
					strcpy(node->env->value, buffer);
					tptp_free(buffer);
				} else {
					node->env->value = NULL;
				}
			}
			break;
		}
		node = node->next;
	}

	if(node == NULL) { /* no existing env */
		node = (sysEnv_list_node_t*)tptp_malloc(sizeof(sysEnv_list_node_t));
		node->env = (sysEnv_t*)tptp_malloc(sizeof(sysEnv_t));

		if (name != NULL) {
			node->env->name = (tptp_string*) tptp_malloc(strlen(name) +1);
			strcpy(node->env->name, name);
		} else {
			node->env->name = NULL;
		}
		if (value != NULL) {
			node->env->value = (tptp_string*) tptp_malloc(strlen(value) +1);
			strcpy(node->env->value, value);
		} else {
			node->env->value = NULL;
		}
		if (config != NULL) {
			node->env->config = (tptp_string*) tptp_malloc(strlen(config) +1);
			strcpy(node->env->config, config);
		} else {
			node->env->config = NULL;
		}
		node->next = NULL;
		node->previous = env->tail;

		if((env->head == NULL) || (env->tail == NULL)) {
			env->head = node;
		}
		else {
			env->tail->next = node;
		}
		env->tail = node;
	}
}


void addCacheEnv(char *config, char *name, char *value, position_t pos) {
	if(cacheEnv == NULL) {
		cacheEnv = (sysEnv_list_t*)tptp_malloc(sizeof(sysEnv_list_t));
		cacheEnv->head = NULL;
		cacheEnv->tail = NULL;
	}

	addEnvVar( cacheEnv, config, name, value, pos );

	ra_setServiceEnvironment(name, value, pos);
}

char* getEnvVar(sysEnv_list_t *env, char *name) {
	sysEnv_list_node_t *node;
	char *sysEnvBuf;
	int result, size; /* Bug 68919 */

	if(env) {
		node = env->head;
		while(node != NULL) {
			if(strcmp(node->env->name, name) == 0) {
				return node->env->value;
			}
			node = node->next;
		}
	}

	/* Bug 62219 begins */
	/* Bug 68919 begins */
	for (size = 1024; ; size <<= 1) {
		/* Make sure there is enough memory. */
		if (!(sysEnvBuf = (char*)tptp_malloc(sizeof(char) * size))) {
			return NULL;
		}

		BZERO(sysEnvBuf, size);
		result = ra_getEnvironmentVariable(name, sysEnvBuf, size);
		if (result <= size) {
			break;
		}

		tptp_free(sysEnvBuf);
        }
	/* Bug 68919 ends */
	/* Bug 62219 ends */

	return sysEnvBuf;
}

char* getCacheEnv(char *config, char *name) {
	return getEnvVar( cacheEnv, name );
}

void freeEnv( sysEnv_list_t* env ) {
	sysEnv_list_node_t *snode1, *snode2;

	if(env) {
		snode1 = env->head;
		while(snode1 != NULL) {
			snode2 = snode1;
			snode1 = snode1->next;
			tptp_free(snode2->env->name); 
			tptp_free(snode2->env->value);
			tptp_free(snode2->env);
			tptp_free(snode2);
		}
		tptp_free(env);
	}
}

void resetCacheEnv() {
	freeEnv( cacheEnv );
	cacheEnv = NULL;
}

void cloneEnv(sysEnv_list_t* env, sysEnv_list_t** cloneEnv ) {
	sysEnv_list_node_t *snode;

	if(env) {
		*cloneEnv = (sysEnv_list_t *)tptp_malloc( sizeof(sysEnv_list_t) );
		if ( *cloneEnv != NULL ) {
			(*cloneEnv)->head = NULL;
			(*cloneEnv)->tail = NULL;
		}
		snode = env->head;
		while(snode != NULL) {
			addEnvVar( *cloneEnv, snode->env->config, snode->env->name, snode->env->value, REPLACE );
			snode = snode->next;
		}
	}
	else
	{
		*cloneEnv = NULL;
	}
}


/* Provide wildcard substitution behaviour during string creation */
void createShellString2(sysEnv_list_t *env, char **result, const char *oldString) {
	char *newString, *begin=NULL, *end=NULL, *current;
	unsigned int offset, oldStringLength, newStringLength;

	static char *emptyString="";
	current=(char*)oldString;


	offset=0;

	/* Initially we will pesimistically assume our string will quadruple in length */
	oldStringLength=strlen(oldString);
	newStringLength=oldStringLength<<2;
	newString=(char*)tptp_malloc(newStringLength);

	do {

		/* Look for a % in the string */
		begin=strchr(current, '%');

		/* Did we find a starting % */
		if(begin) {

			/* find the end of the wildcard */
			end=strchr(begin+1, '%');

			/* Did we find the end of the wildcard */
			if(end) {
				int envLength = end - begin - 1;
				char *envName = (char*)tptp_malloc(sizeof(char) * (envLength + 1)); /* add a null at the end */
				char *envValue = NULL;
				BZERO(envName, envLength + 1);
				strncpy(envName, begin+1, envLength);
				strcat(envName, "\0");

				envValue = getEnvVar(env, envName);
				tptp_free(envName); /* no longer needed */

				if(!envValue) {
					envValue=emptyString;
				}
				envLength = strlen(envValue);

                /* Copy in the data up to the current % */
				memcpy(newString+offset, current, begin-current);
				offset+=begin-current;

				/* determine if our buffer is big enough for the substitution  */
				while(offset+envLength+oldStringLength-(end-begin) >= newStringLength) {
					char *temp;
					newStringLength=newStringLength<<1;
					temp=(char*)malloc(newStringLength);
					memcpy(temp, newString, offset);
					//tptp_free(newString); kevin... this is crashing!
					newString=temp;
				}
			

				/* Copy in the environment variables value */
				strcpy(newString+offset, envValue);
				offset+=envLength;

				/* replace the % in the original string */
				*end='%';

				/* Increment our begin pointer to the next segment of the string */
				current=end+1;
			}
			else {
				/* We didn't find the end of the wildcard, stop processing */
				strcpy(newString+offset, oldString);
				begin=NULL;
			}
		}
		else {
			/* Copy the end of the original string */
			strcpy(newString+offset, current);
		}

	}while(begin);

	*result = newString;
}

void createShellString(char *config, char **result, const char *oldString) {
	createShellString2( cacheEnv, result, oldString );
}

/**
 *********************************************************************
 *                                                       
 * @brief                                  
 *    Set Env Vars
 *                                                       
 * @return
 *		0 for success
 *
 *********************************************************************/
int setEnvAttrs(DOMNode *node, char **attrName)
{
		DOMNamedNodeMap *attributes = node->getAttributes();
        int attrlen = attributes->getLength();
		char *value = NULL, *position = NULL;

		for(int i=0;i < attrlen;i++) 
		{
			DOMAttr *attributeNode = (DOMAttr*) attributes->item(i);
			char *cattrname = XMLString::transcode(attributeNode->getName());
			char *cattrvalue = XMLString::transcode(attributeNode->getValue());
			
			if(strcmp(cattrname, "name") == 0)
			{
				*attrName = (char *)tptp_malloc(strlen(cattrname)+1);
				strcpy(*attrName, cattrname);
			}
			else if(strcmp(cattrname,"value") == 0)
			{
				value = (char *)tptp_malloc(strlen(cattrvalue)+1);
				strcpy(value, cattrvalue);
			}
			else if(strcmp(cattrname,"position") == 0)
			{
				position = (char *)tptp_malloc(strlen(cattrvalue)+1);
				strcpy(position, cattrvalue);
			}
			XMLString::release(&cattrvalue);
			XMLString::release(&cattrname);
		} 
	if(*attrName != NULL && value != NULL && position != NULL)
	{ 
		setEnvironment(*attrName, value, position);
	}
	else
	{
		*attrName = NULL;
	}
	//Possible the Name is used by the caller and hence not freed
	tptp_free(value);
	tptp_free(position);
	return 0;
}

BOOL isVersionChar(char c) { /* return TRUE if it matched any of '0-9', '.' */
	if((c == '.') || ((c >= 0x30) && (c <= 0x39))) {
		return TRUE;
	}
	else {
		return FALSE;
	}
}

BOOL addToAvailablePlugins(char* name) {

	/* If there are already max number of plugins, return falure */
	if(availablePluginsCount == MAX_PLUGINS) {
		return FALSE;
	}

	//printf("add to available plugins %s \n", name);
	availablePlugins[availablePluginsCount] = (char*)tptp_malloc(sizeof(char) * strlen(name) + 1);
	BZERO(availablePlugins[availablePluginsCount], strlen(name) + 1);
	strcpy(availablePlugins[availablePluginsCount], name);
	availablePluginsCount++;

	return TRUE;
}

char* findMatchingPlugin(char *name) {
	char *newName = NULL;
	int nameLen = strlen(name); /* Compare just the plugin name w/o the version numbers */
	int i;
	for(i = 0; i < availablePluginsCount; i++) {
		if(0 == strncmp(name, availablePlugins[i], nameLen)) { /* try to match */
			int len = strlen(availablePlugins[i]);
			if(len == nameLen) { /* if, in a rare case, which the length is the same, do not check the "_n.n.n" part */
				newName = availablePlugins[i]; /* if matched, load this */
				break;
			}
			else if(len > nameLen) {
				if(availablePlugins[i][nameLen] == '_') { /* since we are matching for version, not plugins with the same first-part package name (e.g. "a.b.c.d" vs "a.b.c.d.e" should not match since they are not the same plugin)*/
					newName = availablePlugins[i]; /* if matched, load this */
					break;
				}
			}
			else {
				/* should not reach here... since the length should not be shorter */
				//ra_logServiceMessage(__FILE__, __LINE__, RA_SEVERE, "Cannot match required: (%s) with available: (%s)", name, availablePlugins[i]);
			}
		}
	}
	return newName;
}

int loadAvailablePluginsList(char *Plugin_InstallDir)
{
#ifdef _WIN32
	HANDLE   hlist;
	WIN32_FIND_DATA filedata; //for finding all the agent files first & next
	TCHAR   XMLfilename[_MAX_PATH]; // this is used for the plugin name ... and not the path to the directory.

	sprintf(XMLfilename, "%s\\*",Plugin_InstallDir);
	TPTP_LOG_DEBUG_MSG1("Seeking plugins in %s",XMLfilename);
	hlist = FindFirstFile(XMLfilename, &filedata);
 
	if(hlist == INVALID_HANDLE_VALUE) 
	{ 
		TPTP_LOG_ERROR_MSG("Plugin directory not found");
		return -1;
	}
	else //valid file handle value
	{
	   while (FindNextFile(hlist, &filedata) != 0) //NEED TO Check if have a Dir or File
	   {
		  if((strcmp(filedata.cFileName, "..") != 0) && (strcmp(filedata.cFileName, ".") != 0) ) 
		  {
			  addToAvailablePlugins(filedata.cFileName);
		  }
		 
	   } /*while FindNextFile(hlist, &filedata) loop */

	    if(GetLastError() == ERROR_NO_MORE_FILES) 
		{ 
			TPTP_LOG_DEBUG_MSG("No more plugin files to process");
		} else
		{
			TPTP_LOG_ERROR_MSG("Error getting plugin file.");
		}

	   //close the handle
		FindClose(hlist);

	 return 0;
	}
#else
	DIR			  *dirLkp;
	struct dirent *dirEntry;
	struct stat    statinfo;


	TPTP_LOG_DEBUG_MSG1("Load available plugins in %s",Plugin_InstallDir);
	if ((dirLkp = opendir(Plugin_InstallDir)) == NULL)
	{
		TPTP_LOG_ERROR_MSG("Plugin directory not found");
		return -1;
	}
	else
	{
		char *currentDir;

		/* Backup the current working directory */
		currentDir = (char*)malloc(sizeof(char) * 1024);
		memset(currentDir, 0, 1024);
		getcwd(currentDir, 1024);

		/* Change to the plugin directory for reading all the subdirectories */
		chdir(Plugin_InstallDir);
		while((dirEntry = readdir(dirLkp)) != NULL)
		{
			int rc;
			rc = lstat(dirEntry->d_name, &statinfo);
			if(rc == -1) {
				printf("Error calling lstat() on directory %s, errno = %d\n", dirEntry->d_name, errno);
			}
			else {
				//Test for a directory
				if(S_ISDIR(statinfo.st_mode))
				{
					if( (strcmp(".", dirEntry->d_name) != 0) && (strcmp("..",dirEntry->d_name) != 0) )
					{
						TPTP_LOG_DEBUG_MSG1("Dir name %s",dirEntry->d_name);
						addToAvailablePlugins(dirEntry->d_name);
					} //if dir valid 
				} //if dir
			}
		} //while DirEntry = readdir
		closedir(dirLkp);

		/* Restore to the original working directory */
		chdir(currentDir);
		free(currentDir);
	}
#endif


}

int loadPluginConfig(AC_Config_t *acconfig)
{
	int status = 0;
	char* pluginVar;

	//bug 227779
	pluginVar = (char *) tptp_malloc(strlen(PLUGIN_HOME_VAR_NAME) +1);
	strcpy(pluginVar, PLUGIN_HOME_VAR_NAME);
	//createShellString(acconfig->envConfig, &Plugin_InstallDir, pluginVar);

	//If PLUGINS_HOME is not set then we exit fast!
	if(acconfig->pluginConfigLocation == NULL || strlen(acconfig->pluginConfigLocation) == 0)
	{ 
		TPTP_LOG_ERROR_MSG("No plugin directory specified - no plugin configs will be read."); 
		return -1;
	}

	TPTP_LOG_DEBUG_MSG1("Plugin directory is %s.", acconfig->pluginConfigLocation);
	
	loadAvailablePluginsList(acconfig->pluginConfigLocation);
	//setup a dummy application alias.... if a user has not specified one.
	if (acconfig->applicationAliases == NULL) {
		//allocating a very big string here... it would be better to do this dynamically
		//TODO
		acconfig->applicationAliases = (char *) tptp_malloc(16 * 8096);
		sprintf(acconfig->applicationAliases,  "%s%s", APPLICATION_ALIASES_OPENING_TAG, APPLICATION_ALIASES_CLOSING_TAG );
		
	}
	
	tptp_list_init(&acconfig->options);

#ifdef _WIN32
	HANDLE   hlist;
	WIN32_FIND_DATA filedata; //for finding all the agent files first & next
	TCHAR   XMLfilename[_MAX_PATH]; // this is used for the plugin name ... and not the path to the directory.

	sprintf(XMLfilename, "%s\\*",acconfig->pluginConfigLocation);
	TPTP_LOG_DEBUG_MSG1("Seeking plugins in %s",XMLfilename);
	hlist = FindFirstFile(XMLfilename, &filedata);
 
	if(hlist == INVALID_HANDLE_VALUE) 
	{ 
		TPTP_LOG_ERROR_MSG("Plugin directory not found");
		return -1;
	}
	else //valid file handle value
	{
	   while (FindNextFile(hlist, &filedata) != 0) //NEED TO Check if have a Dir or File
	   {
		  if((strcmp(filedata.cFileName, "..") != 0) && (strcmp(filedata.cFileName, ".") != 0) ) 
		  {
			  int ret =  parsePluginConfig(acconfig, filedata.cFileName);
		  }
		 
	   } /*while FindNextFile(hlist, &filedata) loop */

	    if(GetLastError() == ERROR_NO_MORE_FILES) 
		{ 
			TPTP_LOG_DEBUG_MSG("No more plugin files to process");
		} else
		{
			TPTP_LOG_ERROR_MSG("Error getting plugin file.");
		}

	   //close the handle
		FindClose(hlist);

		//if we processed atleast one plugin then we need to add the tag back to the alias list.
		if (firstPluginProcessed) 
		{
			strcpy(applicationAliasPtr, APPLICATION_ALIASES_CLOSING_TAG);
		}
	 return 0;
	}



#else
	DIR			  *dirLkp;
	struct dirent *dirEntry;
	struct stat    statinfo;
	char		   XMLfilename[AC_MAX_PATH];
	char           inputDir[AC_MAX_PATH];


	TPTP_LOG_DEBUG_MSG1("Seeking plugins in %s",acconfig->pluginConfigLocation);
	if ((dirLkp = opendir(acconfig->pluginConfigLocation)) == NULL)
	{
		TPTP_LOG_ERROR_MSG("Plugin directory not found");
		return -1;
	}
	else
	{
		while((dirEntry = readdir(dirLkp)) != NULL)
		{
			char *checkName = (char*)tptp_malloc(sizeof(char) * (strlen(acconfig->pluginConfigLocation) + 1 + strlen(dirEntry->d_name) +  strlen(PLUGIN_CONFIG_FILE_PATH) + 1));
			sprintf(checkName, "%s/%s%s", acconfig->pluginConfigLocation, dirEntry->d_name,PLUGIN_CONFIG_FILE_PATH );

			FILE *fp = fopen(checkName, "r");
			if(fp == NULL) {
				TPTP_LOG_DEBUG_MSG1("File does not exist: %s", checkName);
			}
			else {
				fclose(fp);
				TPTP_LOG_DEBUG_MSG1("File exists: %s. Start to parse file.", checkName);

			  int ret =  parsePluginConfig(acconfig, dirEntry->d_name);
			}
			tptp_free(checkName);
		} //while DirEntry = readdir
		closedir(dirLkp);
	}
	//if we processed atleast one plugin then we need to add the tag back to the alias list.
	if (firstPluginProcessed) 
	{
		strcpy(applicationAliasPtr, APPLICATION_ALIASES_CLOSING_TAG);
	}
	return 0;
#endif
}

//add a plugin's application to our global alias list.
//applicationAliasPtr is a global ptr to the end of our list.
//when we our done we re-add the closing element.
int pluginAddApplication(char *appAlias, char *application)
{
	if (firstPluginProcessed == 0) {
		firstPluginProcessed = 1;
		//this this is the first plugin we need remove the closing element.
		// remove end tag from application aliases list.
		applicationAliasPtr = appAlias + strlen(appAlias) - strlen(APPLICATION_ALIASES_CLOSING_TAG);
	} 
	strcpy(applicationAliasPtr, application);
	applicationAliasPtr+=strlen(application);

	return 0;
}

#define PLUGIN_CONFIG_LOADED 0
#define PLUGIN_CONFIG_NOT_FOUND -1
#define PLUGIN_DIR_NOT_FOUND -2
#define PLUGIN_CONFIG_FAILED -3

int loadPluginRequires(AC_Config_t *ac_config, DOMNamedNodeMap *attributes)
{
	int attrlen = attributes->getLength();
	char *_requires =NULL;


	for (int j=0;j < attrlen;j++) 
	{
		DOMAttr *attributeNode = (DOMAttr*) attributes->item(j);
		char *cAttrName = XMLString::transcode(attributeNode->getName());
		char *cAttrValue = XMLString::transcode(attributeNode->getValue());

		if (strcmp(cAttrName, "requires") == 0) 
		{
			_requires = (char *) tptp_malloc(strlen(cAttrValue) + 1);
			strcpy(_requires, cAttrValue);
		}
	}

	if (_requires) { /* Bug 59802 */
		char *tok[256]; /* list of plugins */
		int i;

		/* Initialize the list of requires */
		for(i = 0; i < 256; i++) {
			tok[i] = NULL; /* initialize each of them to NULL */
		}

		/* Read all requires since we cannot use strtok() recursively */
		i = 0;
		tok[i] = strtok(_requires, " ,");
		while((tok[i] != NULL) && (i < 255)) {
			i++;
			tok[i] = strtok(NULL, " ,"); /* get next require */
		}

		/* Load each of the requires */
		i = 0;
		while((tok[i] != NULL) && (i < 256)) {
			int rc;
			char *name = tok[i];
			  
			rc = parsePluginConfig(ac_config, name);
			if(rc == PLUGIN_CONFIG_NOT_FOUND) 
			{
				BOOL isVersion = FALSE;
				int index = strlen(name) - 1; /* last index of the string's char array */

				while((index > 0) && isVersionChar(name[index])) {
					index--;
					if(name[index] == '_') {
						isVersion = TRUE; /* assume all version in the format "_n.n.n" */
						break;
					}
				}

				/* If version number exist, we are not trying to load since there should be an exact match */
				if(isVersion){
					TPTP_LOG_DEBUG_MSG1("Recovery: Failed to load dependent plugin: %s since we need an exact version match", name);
				}
				/* If no version number, since there wasn't a match, will try to search for available plugins by trimming the version */
				else {
					char *newName = findMatchingPlugin(name);

					if(newName != NULL) {
						TPTP_LOG_DEBUG_MSG1("Recovery: since there is no version requirement, trying to load plugin instead: %s", newName);
						//printf("load plugin requires %s \n", newName);
						rc = parsePluginConfig(ac_config, newName);
						switch(rc) {
						case PLUGIN_CONFIG_LOADED:
							TPTP_LOG_DEBUG_MSG("Recovery: succeeded");
							break;
						case PLUGIN_CONFIG_NOT_FOUND:
							TPTP_LOG_DEBUG_MSG("Recovery: failed");
							break;
						case PLUGIN_DIR_NOT_FOUND:
							TPTP_LOG_DEBUG_MSG("Recovery: failed");
							break;
						case PLUGIN_CONFIG_FAILED:
							TPTP_LOG_DEBUG_MSG("Recovery: failed");
							break;
						default:
							break;
						}
					}
					else {
						TPTP_LOG_DEBUG_MSG1( "Recovery: failed to find a match to: %s", name);
					}
				}
			}
			else if(rc == PLUGIN_CONFIG_FAILED) {
				TPTP_LOG_DEBUG_MSG1("Failed to load dependent plugin: %s. Please make sure the config is valid", name);
			}
			else {
				TPTP_LOG_DEBUG_MSG1("Sucessfully loaded dependent pluign: %s", name);
			}
			i++;
		}
		tptp_free(_requires);
	}
	return 0;
}

int parsePluginConfig(AC_Config_t *ac_config, char *pluginDirName)
{
	int ret = -1;
	long fileSize = 0;
	int i;
#ifdef _WIN32
	TCHAR  *XMLfilename;

	//Do not load the plugin if it has been loaded already.
	for(i = 0; i < loadedPluginCount; i++) {
		if(strcmp(loadedPlugin[i], pluginDirName) == 0) {
			return TRUE;
		}
	}

	XMLfilename = (TCHAR *) tptp_malloc(strlen(ac_config->pluginConfigLocation) + strlen(pluginDirName) + strlen(PLUGIN_CONFIG_FILE_PATH) + 2); //add 1 for null term and 1 for file path separators.

	sprintf(XMLfilename,"%s%c%s%s",ac_config->pluginConfigLocation, FILE_SEPARATOR, pluginDirName, PLUGIN_CONFIG_FILE_PATH);

#else
	char   XMLfilename[AC_MAX_PATH];

	//this code section should be reworked when linux is fully ported... I think we 
	//could remove this whole section of ifdef.
	//Do not load the plugin if it has been loaded already.
	TPTP_LOG_DEBUG_MSG("Check for loaded plugin ");
	for(i = 0; i < loadedPluginCount; i++) {
		if(strcmp(loadedPlugin[i], pluginDirName) == 0) {
			return TRUE;
		}
	}

	sprintf(XMLfilename,"%s%c%s%s",ac_config->pluginConfigLocation,FILE_SEPARATOR, pluginDirName,PLUGIN_CONFIG_FILE_PATH);
#endif
	TPTP_LOG_DEBUG_MSG1("Processing config file :: %s",XMLfilename);

	try {
		if ( ac_config == NULL ) {
			return -1; /* TODO: Return a more specific error code */
		}

		ret = getXMLFileSize(XMLfilename, &fileSize);
		if ( ret != 0 )
		{
			/* TODO: Log an error */
			return ret;
		}

		if ( fileSize == 0 ) {
			return -1; /* TODO: Return a more specific error code */
		}

		bool	isValidRoot = false;
		DOMImplementation *impl		= DOMImplementationRegistry::getDOMImplementation(&chNull);
		DOMBuilder        *parser	= ((DOMImplementationLS*)impl)->createDOMBuilder(DOMImplementationLS::MODE_SYNCHRONOUS, 0);
			
		parser->setFeature(XMLUni::fgDOMWhitespaceInElementContent,false);
		parser->setFeature(XMLUni::fgDOMValidation,true);

		TPTPParserErrorHandler* tptp_dom_err = new TPTPParserErrorHandler();
		parser->setErrorHandler(tptp_dom_err);

		//Parse the input file name
		XERCES_CPP_NAMESPACE::DOMDocument *doc = parser->parseURI(XMLfilename);

		DOMTreeWalker* iter = doc->createTreeWalker(doc->getDocumentElement(),DOMNodeFilter::SHOW_ELEMENT,NULL,true);
        
		char *roottag = XMLString::transcode(iter->getCurrentNode()->getNodeName());

		if(strcmp(roottag, "PluginConfiguration")==0)
		{
			DOMNamedNodeMap *attributes = iter->getCurrentNode()->getAttributes();

			loadPluginRequires(ac_config,attributes);
			isValidRoot = true;
		}
		else
		{ 
			//logServiceMessage();
			return -1;
		}

		XMLString::release(&roottag);
		DOMNode *node; // = iter->firstChild();
		if(isValidRoot){node = iter->firstChild();}

		DOMNode *curr = iter->getCurrentNode();

		while(curr)
		{
			char *tempnodename = XMLString::transcode(iter->getCurrentNode()->getNodeName());
			TPTP_LOG_DEBUG_MSG1("NodeName %s",tempnodename);

			if(strcmp(tempnodename, ELEMENT_NAME_AGENT_CONTROLLER_ENVIRONMENT) == 0)
			{
				tptp_list_t varList; //storage for Variable tags until they are combined into an env string
				tptp_list_init(&varList);
				tptp_list_setNodeDestructor(&varList, destroyVariableNode);
				tptp_list_setNodeCopier(&varList, copyVariableNode);

				DOMNodeList *node = iter->getCurrentNode()->getChildNodes();
				int varNodeLength = node->getLength();

				for (int k=0; k<varNodeLength; k++) 
				{
					variable_t *envVariable = NULL;
					char *name = NULL;
					char *value = NULL; 
					char* newValue = NULL;
					position_t position = APPEND; //Default to append if position not specified

					char *nodeName = XMLString::transcode(node->item(k)->getNodeName());
					if(strcmp(nodeName, "Variable") == 0)
					{
						DOMNamedNodeMap *attributes = node->item(k)->getAttributes();
						int attrlen = attributes->getLength();

						for(int j=0;j < attrlen;j++) 
						{
							DOMAttr *attributeNode = (DOMAttr*) attributes->item(j);
							char *cAttrName = XMLString::transcode(attributeNode->getName());
							char *cAttrValue = XMLString::transcode(attributeNode->getValue());

							if(strcmp(cAttrName, "name") == 0)
							{
								name = cAttrValue;
							}
							else if(strcmp(cAttrName,"value") == 0)
							{
								value = cAttrValue;
							}
							else if(strcmp(cAttrName,"position") == 0)
							{
								if(strcmp("append", cAttrValue)==0)
									position = APPEND;
								else if(strcmp("prepend", cAttrValue)==0)
									position = PREPEND;
								else if(strcmp("replace", cAttrValue)==0)
									position = REPLACE;
								else
									position = APPEND;	//Default to append if unrecognized value

								XMLString::release(&cAttrValue);
							}

							XMLString::release(&cAttrName);
						} 

						// Create & fill the variable_t, then add it to the list.
						createShellString(ac_config->envConfig, &newValue, value);
						//printf("old %s new %s \n", value, newValue);
						envVariable = initVariableT(name, newValue, position);
						tptp_list_add(&varList, envVariable);
						addCacheEnv(ac_config->envConfig, name, newValue, position);

						// Now free the cAttrValues we saved until we copied it into the Variable struct.
						// Note: We have a memory leak here if the Variable tag had multiple name or value
						// attributes found in the for loop above (should only be one each, but no guarantee),
						// because we only have the ptr of the last one.
						XMLString::release(&name);
						XMLString::release(&value);
						//tptp_free(newValue);
					}
					
					XMLString::release(&nodeName);
				}

				// Combine the env vars from the config file that are stored in the varList, with
				// the current env var settings to create the base env used in launching the
				// process controller.
				// kevin is this working
				ac_config->envConfig = (char *) modifyApplicationEnvironment(&varList, ac_config->envConfig); 
				tptp_list_clear(&varList); 
			}
			else if(strcmp(tempnodename, ELEMENT_NAME_APPLICATION) == 0)
			{
				char *application;
				application= (char *)tptp_malloc(fileSize);  // why malloc such a big size.
				strcpy(application,"");
				buildDOMTreeBranch(curr, &application, fileSize);

				pluginAddApplication(ac_config->applicationAliases, application);
			}
			else if(strcmp(tempnodename, "Option") == 0)
			{
				DOMNamedNodeMap *attributes = curr->getAttributes();
				int attrlen = attributes->getLength();
				tptp_option_t* option;
				char *name = NULL;
				char *value = NULL; 
				char *type = NULL; 

				for(int j=0;j < attrlen;j++) 
				{
					DOMAttr *attributeNode = (DOMAttr*) attributes->item(j);
					char *cAttrName = XMLString::transcode(attributeNode->getName());
					char *cAttrValue = XMLString::transcode(attributeNode->getValue());

					if(strcmp(cAttrName, "name") == 0)
					{
						name = cAttrValue;
					}
					else if(strcmp(cAttrName,"value") == 0)
					{
						value = cAttrValue;
					}
					else if(strcmp(cAttrName,"type") == 0)
					{
						type = cAttrValue;
					}
				
					XMLString::release(&cAttrName);
				}
				//printf("Parsing plugin global option %s %s %s \n", name, value, type);

				option = initOptionT(ac_config->envConfig, name, value, type);
				tptp_list_add(&ac_config->options, option);

				XMLString::release(&name);
				XMLString::release(&value);
				XMLString::release(&type);
			}
			else if(strcmp(tempnodename, ELEMENT_NAME_AGENT) == 0)
			{
				//printf("Parsing plugin agent \n");
		
				agent_metadata_t		*agentmetadata;
				agentmetadata = (agent_metadata_t *)tptp_malloc(sizeof(agent_metadata_t));
				tptp_string* extends = NULL;

				if ( agentmetadata == 0 )
				{
					/* TODO: log error */
					return -1;
				}
				memcpy( agentmetadata, &defaultMetadata, sizeof(agent_metadata_t) );
				tptp_list_init( &agentmetadata->options );

				DOMNamedNodeMap *attributes = curr->getAttributes();
				int attrlen = attributes->getLength();
				DOMNodeList *node = iter->getCurrentNode()->getChildNodes();
				int varNodeLength = node->getLength();


				for(int j=0;j < attrlen;j++) 
				{
					DOMAttr *attributeNode = (DOMAttr*) attributes->item(j);
					char *cAttrName = XMLString::transcode(attributeNode->getName());
					char *cAttrValue = XMLString::transcode(attributeNode->getValue());

					if(strcmp(cAttrName, "name") == 0)
					{
						agentmetadata->agentName = (char *) tptp_malloc(strlen(cAttrValue) +1 
								+ strlen(PLUGIN_LEGACY_PREFIX));
						strcpy(agentmetadata->agentName, PLUGIN_LEGACY_PREFIX);
						strcat(agentmetadata->agentName, cAttrValue);
					}
					else if(strcmp(cAttrName,"client") == 0)
					{
						agentmetadata->client = (char *) tptp_malloc(strlen(cAttrValue) +1);
						strcpy(agentmetadata->client, cAttrValue);
					}
					else if(strcmp(cAttrName,"dataChannelSize") == 0)
					{
						agentmetadata->dataChannelSize = (char *) tptp_malloc(strlen(cAttrValue) +1);
						strcpy(agentmetadata->dataChannelSize, cAttrValue);
					}
					else if(strcmp(cAttrName,"logFile") == 0)
					{
						agentmetadata->logFile = (char *) tptp_malloc(strlen(cAttrValue) +1);
						strcpy(agentmetadata->logFile, cAttrValue);
					}
					else if(strcmp(cAttrName,"extends") == 0)
					{
						extends = (char *) tptp_malloc(strlen(cAttrName) +1);
						strcpy(extends, cAttrValue);
					}

					XMLString::release(&cAttrValue);
					XMLString::release(&cAttrName);
				}

				if (agentmetadata->logFile == NULL) {
					agentmetadata->logFile = (char *) tptp_malloc(strlen(EMPTY_DATA_CHANNEL) +1);
					strcpy(agentmetadata->logFile, EMPTY_DATA_CHANNEL);
				}
				if (agentmetadata->dataChannelSize == NULL) {
					agentmetadata->dataChannelSize = (char *) tptp_malloc(strlen(EMPTY_DATA_CHANNEL) +1);
					strcpy(agentmetadata->dataChannelSize, EMPTY_DATA_CHANNEL);
				}
				if (agentmetadata->client == NULL) {
					agentmetadata->client = (char *) tptp_malloc(strlen(EMPTY_DATA_CHANNEL) +1);
					strcpy(agentmetadata->client, EMPTY_DATA_CHANNEL);
				}
				for (int k=0; k<varNodeLength; k++) 
				{
					char *nodeName = XMLString::transcode(node->item(k)->getNodeName());
					if(strcmp(nodeName, "Option") == 0) 
					{
						DOMNamedNodeMap *attributes = node->item(k)->getAttributes();
						int attrlen = attributes->getLength();
						tptp_option_t* option;
						char *name = NULL;
						char *value = NULL; 
						char *type = NULL; 

						for(int j=0;j < attrlen;j++) 
						{
							DOMAttr *attributeNode = (DOMAttr*) attributes->item(j);
							char *cAttrName = XMLString::transcode(attributeNode->getName());
							char *cAttrValue = XMLString::transcode(attributeNode->getValue());

							if(strcmp(cAttrName, "name") == 0)
							{
								name = cAttrValue;
							}
							else if(strcmp(cAttrName,"value") == 0)
							{
								value = cAttrValue;
							}
							else if(strcmp(cAttrName,"type") == 0)
							{
								type = cAttrValue;
							}
							
							XMLString::release(&cAttrName);
						}

						option = initOptionT(ac_config->envConfig, name, value, type);
						tptp_list_add(&agentmetadata->options, option);

						XMLString::release(&name);
						XMLString::release(&value);
						XMLString::release(&type);
					}
					
					XMLString::release(&nodeName);
				}
				if (extends) {
					agent_metadata_t *baseAgent=NULL;;
					tptp_node_t* listNode=NULL;

					baseAgent = tptp_findAgent(&ac_config->agentList, agentmetadata->agentName);
					if (baseAgent == NULL) {
						TPTP_LOG_DEBUG_MSG1("Cannot find agent %s to extend ", agentmetadata->agentName);
					} else {
						
						//preserve all attributes.
						//just allow adding of options.
						for (listNode = agentmetadata->options.head; listNode != 0; listNode = listNode->next)
						{
							tptp_option_t* option = (tptp_option_t*)listNode->data;

							tptp_list_add(&baseAgent->options, (void *) option);
						}
					}
				} else {
					tptp_list_add(&ac_config->agentList, (void *) agentmetadata);
				}

			}
			curr = iter->nextSibling();
			XMLString::release(&tempnodename);
		}

		//Add this plugin to the list of plugins that have been loaded.
		int len = strlen(pluginDirName);
		loadedPlugin[loadedPluginCount] = (char*)tptp_malloc(sizeof(char) * (len + 1)); /* include trailing null */
		strcpy(loadedPlugin[loadedPluginCount], pluginDirName); /* Bug 66584 */
		loadedPluginCount++;

		//printf("loaded plugin %s %d \n", pluginDirName, loadedPluginCount);

		delete tptp_dom_err;
		parser->release();

		return 0;
	} //end try

	catch (const DOMException& error)
	{
		if ( error.msg != 0 )
		{
			char *errmesg = XMLString::transcode(error.msg);
			TPTP_LOG_PARSE_MSG1("XML/DOM Exception: %s", errmesg);
			XMLString::release(&errmesg);
		}
		else
		{
			// Can't get the msg string so print the error code.
			TPTP_LOG_PARSE_MSG1("XML/DOM Exception: error code %d", error.code);

		}

		TPTP_LOG_PARSE_MSG1("XML/DOM Exception occurred while parsing plugin config file \"%s\"", (XMLfilename?XMLfilename:"null"));
		return -1;
	}
	catch (const XMLException& error)
	{
		char *errmesg = XMLString::transcode(error.getMessage());
		TPTP_LOG_PARSE_MSG2("XML Exception: %s (at line %d)", errmesg, error.getSrcLine());
		XMLString::release(&errmesg);
		TPTP_LOG_PARSE_MSG1("XML Exception occurred while parsing plugin config file \"%s\"", (XMLfilename?XMLfilename:"null"));
		return -1;
	}
	catch(...)
	{ 
		TPTP_LOG_PARSE_MSG1("Unexpected exception occurred while parsing plugin config file \"%s\"", (XMLfilename?XMLfilename:"null"));
		return -1;
	}
}

/**
 *********************************************************************
 *                                                       
 * @brief                                  
 *    Load TPTP AC Config
 *                                                       
 * @return
 *		0 for success
 *
 *********************************************************************/
int loadTPTPConfig(char *acConfigFile, AC_Config_t *ac_config, BOOL calledByAC )
{
	// When this file was created via merge, the TPTPConfig.cpp originally found in
	// src/agentController/TPTPConfigBinding had a couple of special areas of handling
	// elements distinct from the TPTPConfig.cpp originally found in src/shared/tptpConfig.
	// To distinguish between these behaviors, the calledByAC boolean was introduced.
	// The call to here from the connection manager (based on the original call to the
	// one in src/agentController/TPTPConfigBinding) is dealt with via "calledByAC" set
	// to TRUE, and the other call to here from BaseAgentImpl has it set to FALSE.
	try {
		int ret = -1;
		long fileSize = 0;

		if ( (ac_config == NULL) || (acConfigFile == NULL) )
			return -1; /* TODO: Return a more specific error code */

		ret = getXMLFileSize(acConfigFile, &fileSize);
		if ( ret != 0 )
		{
			/* TODO: Log an error */
			TPTP_LOG_SEVERE_MSG1("Error: Failed to open configuration file \"%s\"", acConfigFile);
			return ret;
		}

		if (fileSize == 0)
		{
			printf("Empty serviceconfig.xml file  \n");
			printf("Make sure you have created a valid serviceconfig.xml file by running the SetConfig script. \n");

			return -1;
		}

		bool	isValidRoot = false;
		DOMImplementation *impl		= DOMImplementationRegistry::getDOMImplementation(&chNull);
		DOMBuilder        *parser	= ((DOMImplementationLS*)impl)->createDOMBuilder(DOMImplementationLS::MODE_SYNCHRONOUS, 0);
			
		parser->setFeature(XMLUni::fgDOMWhitespaceInElementContent,false);
		parser->setFeature(XMLUni::fgDOMValidation,true);

		TPTPParserErrorHandler* tptp_dom_err = new TPTPParserErrorHandler();
		parser->setErrorHandler(tptp_dom_err);

		//Parse the input file name
		XERCES_CPP_NAMESPACE::DOMDocument *doc = parser->parseURI(acConfigFile);
		
		DOMTreeWalker* iter = doc->createTreeWalker(doc->getDocumentElement(),DOMNodeFilter::SHOW_ELEMENT,NULL,true);
        
		char *roottag = XMLString::transcode(iter->getCurrentNode()->getNodeName());
		if(strcmp(roottag, ELEMENT_NAME_AGENT_CONTROLLER_CONFIGURATION)==0)
		{
			isValidRoot = true;
		}
		else
		{ 
			//logServiceMessage();
			TPTP_LOG_SEVERE_MSG1("Error: Missing <AgentControllerConfiguration> in file \"%s\"", acConfigFile);
			return -1;
		}

		if(isValidRoot)
		{
			ret = getAttrs(iter->getCurrentNode(), ATTRB_NAME_AC_VERSION, &ac_config->version);
		}

		XMLString::release(&roottag);
		DOMNode *node; // = iter->firstChild();
		if(isValidRoot){node = iter->firstChild();}

		//Initialize the lists here after ensuring the file is valid and the root is found

		tptp_list_init( &ac_config->msgPipelineList );
		
		tptp_list_t	connectionList;
		tptp_list_init(&connectionList);
		
		agent_metadata_t		*agentmetadata;
		agentmetadata = (agent_metadata_t *)tptp_malloc(sizeof(agent_metadata_t));
		if ( agentmetadata == 0 )
		{
			/* TODO: log error */
			return -1;
		}

		memcpy( agentmetadata, &defaultMetadata, sizeof(agent_metadata_t) );
		tptp_list_init( &agentmetadata->options );

		// Get the <Variable> tags located in the <AgentControllerEnvironment> tag.
		// These are global environment variables to be used in launching processes.
		DOMNode *curr = iter->getCurrentNode();
		while(curr)
		{
			char *tempnodename = XMLString::transcode(iter->getCurrentNode()->getNodeName());
			TPTP_LOG_DEBUG_MSG1("NodeName %s",tempnodename);

			if(strcmp(tempnodename, ELEMENT_NAME_AGENT_CONTROLLER_ENVIRONMENT) == 0)
			{
				if (!calledByAC) {
					ret = getAttrs(curr, ATTRB_NAME_AC_ENV_CONFIG, &ac_config->envConfig);
					//Loop through Variables and do the set setEnvAttrs
				} else {
					tptp_list_t varList; //storage for Variable tags until they are combined into an env string
					tptp_list_init(&varList);
					tptp_list_setNodeDestructor(&varList, destroyVariableNode);
					tptp_list_setNodeCopier(&varList, copyVariableNode);

					DOMNodeList *node = iter->getCurrentNode()->getChildNodes();
					int varNodeLength = node->getLength();

					for (int k=0; k<varNodeLength; k++) 
					{
						variable_t *envVariable = NULL;
						char *name = NULL;
						char *value = NULL; 
						char *newValue = NULL; 
						position_t position = APPEND; //Default to append if position not specified

						char *nodeName = XMLString::transcode(node->item(k)->getNodeName());
						if(strcmp(nodeName, "Variable") == 0)
						{
							DOMNamedNodeMap *attributes = node->item(k)->getAttributes();
							int attrlen = attributes->getLength();

							for(int j=0;j < attrlen;j++) 
							{
								DOMAttr *attributeNode = (DOMAttr*) attributes->item(j);
								char *cAttrName = XMLString::transcode(attributeNode->getName());
								char *cAttrValue = XMLString::transcode(attributeNode->getValue());

								if(strcmp(cAttrName, "name") == 0)
								{
									name = cAttrValue;
								}
								else if(strcmp(cAttrName,"value") == 0)
								{
									value = cAttrValue;
								}
								else if(strcmp(cAttrName,"position") == 0)
								{
									if(strcmp("append", cAttrValue)==0)
										position = APPEND;
									else if(strcmp("prepend", cAttrValue)==0)
										position = PREPEND;
									else if(strcmp("replace", cAttrValue)==0)
										position = REPLACE;
									else
										position = APPEND;	//Default to append if unrecognized value

									XMLString::release(&cAttrValue);
								}

								XMLString::release(&cAttrName);
							} 

							// Create & fill the variable_t, then add it to the list.
							createShellString(ac_config->envConfig, &newValue, value);
							//printf("old %s new %s \n", value, newValue);
							envVariable = initVariableT(name, newValue, position);
							tptp_list_add(&varList, envVariable);
							addCacheEnv(ac_config->envConfig, name, newValue, position);

							// Now free the cAttrValues we saved until we copied it into the Variable struct.
							// Note: We have a memory leak here if the Variable tag had multiple name or value
							// attributes found in the for loop above (should only be one each, but no guarantee),
							// because we only have the ptr of the last one.
							XMLString::release(&name);
							XMLString::release(&value);
							//tptp_free(newValue);
						}
						
						XMLString::release(&nodeName);
					}

					// Combine the env vars from the config file that are stored in the varList, with
					// the current env var settings to create the base env used in launching the
					// process controller.
					//
					char *tmpEnv = (char *)getEnvironmentStrings();
					ac_config->envConfig = (char *) modifyApplicationEnvironment(&varList, tmpEnv);
					freeEnvironmentStrings(tmpEnv);
					tptp_list_clear(&varList);
				}
			}
			else if(strcmp(tempnodename, ELEMENT_NAME_APPLICATION) == 0)
			{
				// The serviceconfig file does not expect Application tags outside
				// of an ApplicationAliases tag.
				// Ignore them.
			}
			else if(strcmp(tempnodename, ELEMENT_NAME_PROCESS_CONTROLLER_AGENT_NAME) == 0)
			{
				char *tmpPCexeName=NULL;
				ac_config->procCntlrAgent  = NULL;
		
				getNodeValue(curr,&tmpPCexeName);
				if(tmpPCexeName == NULL)
				{
					TPTP_LOG_SEVERE_MSG1("Error: Missing <ProcessController> in file \"%s\"", acConfigFile);
					return -1;
				}
				createShellString(ac_config->envConfig, &ac_config->procCntlrAgent, tmpPCexeName);
				TPTP_LOG_DEBUG_MSG1("Process Controller exe %s",ac_config->procCntlrAgent);
			
			}
			else if(strcmp(tempnodename, ELEMENT_NAME_JVM) == 0) {
				if (!getAttrs(iter->getCurrentNode(), "location", &ac_config->jvmLibPath)) {
					TPTP_LOG_DEBUG_MSG1("JVM location is %s", ac_config->jvmLibPath);
				}
			}				
			else if(strcmp(tempnodename, ELEMENT_NAME_AGENT) == 0)
			{
				char *tmpAgentDirName=NULL;
				
				ret = getAttrs(iter->getCurrentNode(), "path", &tmpAgentDirName);
				createShellString(ac_config->envConfig, &ac_config->agentConfigLocation, tmpAgentDirName);
				TPTP_LOG_DEBUG_MSG1("Agent Path %s",ac_config->agentConfigLocation);
			}
			else if(strcmp(tempnodename, "Plugin") == 0)
			{
				char *tmpPluginDirName=NULL;
				
				ret = getAttrs(iter->getCurrentNode(), "path", &tmpPluginDirName);
				createShellString(ac_config->envConfig, &ac_config->pluginConfigLocation, tmpPluginDirName);
				TPTP_LOG_DEBUG_MSG1("Agent Path %s",ac_config->pluginConfigLocation);
			}
			else if (strcmp(tempnodename, ELEMENT_NAME_APPL_ALIASES) == 0)
			{
				if (calledByAC) {
					// Application tags found in an ApplicationAliases tag are not parsed here.
					// We just take the entire contents as a string. This string can be requested
					// and the recipient would have to do the parsing.
					// allocating a very big string here.
					// TODO allocate dynamically
					ac_config->applicationAliases = (char *)tptp_malloc(8096*16);
					//ac_config->applicationAliases = (char *)tptp_malloc(fileSize);
					strcpy(ac_config->applicationAliases,"");
					buildDOMTreeBranch(curr, &ac_config->applicationAliases, 8096*16);
				}
			}
			else if (strcmp(tempnodename, ELEMENT_NAME_PM_TRANSPORT) == 0)
			{
				// PeerConnectionTransport tag
				// This element gives us the type of the transport layer to be 
				// used for peer monitoring operations
				char *tmpPMT = NULL;
				ac_config->peerConnectionTransport = NULL;
		
				getNodeValue(curr,&tmpPMT);
				if(tmpPMT != NULL)
				{
					createShellString(ac_config->envConfig, &ac_config->peerConnectionTransport, tmpPMT);
					TPTP_LOG_DEBUG_MSG1("Peer connection transport is %s",ac_config->peerConnectionTransport);
				}

			}
			else if (strcmp(tempnodename, ELEMENT_NAME_LOGGING) == 0)
			{
				char *format;
				char *level;
				char *tmpLogFileDir=NULL;
				
				ret = getAttrs(iter->getCurrentNode(), ATTRB_NAME_LOGGING_FORMAT, &format);
				if ( ret == 0 )
				{
					if (strcmp(format, "Simple") == 0)
					{
						ac_config->loggingFormat = TPTP_LOGFORMAT_SIMPLE;
					}
					else
					{
						ac_config->loggingFormat = TPTP_LOGFORMAT_CBE;
					}
					tptp_free( format );
				}
				
				ret = getAttrs(iter->getCurrentNode(), ATTRB_NAME_LOGGING_LEVEL, &level);
				if ( ret == 0 )
				{
					if ( strcmp(level, "DEBUG") == 0 )
					{
						ac_config->loggingLevel = TPTP_DEBUG;
					}
					else if (strcmp(level, "INFORMATION") == 0 )
					{
						ac_config->loggingLevel = TPTP_INFORMATION;
					}
					else if (strcmp(level, "WARNING") == 0 )
					{
						ac_config->loggingLevel = TPTP_WARNING;
					}
					else if (strcmp(level, "SEVERE") == 0 )
					{
						ac_config->loggingLevel = TPTP_SEVERE;
					}
					else /* default is "CRITICAL" */
					{
						ac_config->loggingLevel = TPTP_CRITICAL;
					}
					
					tptp_free(level);
				}

				ret = getAttrs(iter->getCurrentNode(), ATTRB_NAME_LOGGING_DIR, &tmpLogFileDir);
				createShellString(ac_config->envConfig, &ac_config->loggingDirectory, tmpLogFileDir);
			}
			else if(strcmp(tempnodename, ELEMENT_NAME_CONNECTION) == 0)
			{
				char *conninput;
				conninput = (char *)tptp_malloc(fileSize);
				strcpy(conninput, "");
				buildDOMTreeBranch(curr, &conninput, fileSize);
				tptp_list_add(&connectionList, (void *)conninput);
				
				DOMNodeList *nodelist = curr->getChildNodes();
				int	nodelistlen = nodelist->getLength();
			
				for(int i = 0; i < nodelistlen; i++)
				{
					char *childnodename = XMLString::transcode(nodelist->item(i)->getNodeName());		
					bool isElemNode = false;
					if(nodelist->item(i)->getNodeType() == DOMNode::ELEMENT_NODE)
					{ isElemNode = true; }
					
					if(isElemNode)
					{
						if(strcmp(childnodename, ELEMENT_TRANS_LYR_VARIABLE) == 0)
						{	
							message_pipeline_config_t* mp;
							
							mp = (message_pipeline_config_t*)tptp_malloc( sizeof(message_pipeline_config_t) );
							BZERO( mp, sizeof(message_pipeline_config_t) );
							DOMNamedNodeMap *attributes = nodelist->item(i)->getAttributes();
							int attrlen = attributes->getLength();

							for ( int k = attrlen-1; k >= 0; k-- ) 
							{
								DOMAttr *attributeNode = (DOMAttr*) attributes->item(k);
								char *attrname = XMLString::transcode(attributeNode->getName());

								if (strcmp(attrname, ATTRB_TL_LIBNAME) == 0)
								{
									char *attrval  = XMLString::transcode(attributeNode->getValue());

									/* Save the transport layer library name */
									mp->transportLayerLib = (char*)tptp_malloc(strlen(attrval)+1);
									strcpy(mp->transportLayerLib, attrval);

									XMLString::release(&attrval);
								}
								else if (strcmp(attrname, ATTRB_TRANSTYPE_VARIABLE) == 0)
								{
									char *attrval  = XMLString::transcode(attributeNode->getValue());

									/* Save the transport layer type */
									mp->transportType = (char*)tptp_malloc(strlen(attrval)+1);
									strcpy(mp->transportType, attrval);

									XMLString::release(&attrval);
								}

								XMLString::release(&attrname);
							}
			
							/* TODO: Check for payload normalizers */

							DOMNodeList *gnodelist = nodelist->item(i)->getChildNodes();
							int	nlistlen = gnodelist->getLength();
							for(int nl = 0; nl < nlistlen; nl++)
							{
								char *gchnodename = XMLString::transcode(gnodelist->item(nl)->getNodeName());		

								if(strcmp(gchnodename, ELEMENT_CMD_EXTR_VARIABLE) == 0)
								{
									mp->commandExtractorLib = NULL;
									getNodeValue( gnodelist->item(nl), &mp->commandExtractorLib );
								}
								else if (strcmp(gchnodename, ELEMENT_CONFIGURATION_VARIABLE) == 0)
								{
									mp->transportLayerConfig = (char *)tptp_malloc(fileSize);
									strcpy(mp->transportLayerConfig,"");
									buildDOMTreeBranch(gnodelist->item(nl), &mp->transportLayerConfig, fileSize);
								}
									
								XMLString::release(&gchnodename);
							}

							tptp_list_add(&ac_config->msgPipelineList, (void *)mp);
						}	
					}
					XMLString::release(&childnodename);
				}
			}		

			curr = iter->nextSibling();
			XMLString::release(&tempnodename);
		}
		
		if (calledByAC) {
			ret = loadAgentConfig(ac_config);
			ret = loadPluginConfig(ac_config);
		}

		delete tptp_dom_err;
		parser->release();
		
		_ac_config = ac_config;
		
		return 0;
	} //end try

	catch (const DOMException& error)
	{
		if ( error.msg != 0 )
		{
			char *errmesg = XMLString::transcode(error.msg);
			TPTP_LOG_PARSE_MSG1("XML/DOM Exception: %s", errmesg);
			XMLString::release(&errmesg);
		}
		else
		{
			// Can't get the msg string so print the error code.
			TPTP_LOG_PARSE_MSG1("XML/DOM Exception: error code %d", error.code);

		}

		TPTP_LOG_PARSE_MSG1("XML/DOM Exception occurred while parsing AC config file \"%s\"", (acConfigFile?acConfigFile:"null"));
		return -1;
	}
	catch (const XMLException& error)
	{
		char *errmesg = XMLString::transcode(error.getMessage());
		TPTP_LOG_PARSE_MSG2("XML Exception: %s (at line %d)", errmesg, error.getSrcLine());
		XMLString::release(&errmesg);
		printf("XML Exception occurred while parsing AC config file \"%s\"\n", (acConfigFile?acConfigFile:"null"));
		return -1;
	}
	catch(...)
	{ 
		TPTP_LOG_PARSE_MSG1("Unexpected exception occurred while parsing AC config file \"%s\"", (acConfigFile?acConfigFile:"null"));
		return -1;
	}
}


AC_Config_t* getTPTPConfig() {
	return _ac_config; 
}

/**
 *********************************************************************
 *                                                       
 * @brief                                  
 *    Load Agent Config
 *                                                       
 * @return
 *		0 Success
 *
 *********************************************************************/
int loadAgentConfig(AC_Config_t *acconfig)
{
	char   *Agent_InstallDir;

	if(acconfig->agentConfigLocation == NULL) 
	{ 
		TPTP_LOG_ERROR_MSG("No agent directory specified"); 
		return -1;
	}

	Agent_InstallDir = (char *)tptp_malloc(strlen(acconfig->agentConfigLocation)+1);
	strcpy(Agent_InstallDir, acconfig->agentConfigLocation);
	
	tptp_list_t			agentList;
	tptp_list_init(&agentList);
#ifdef _WIN32
	HANDLE   hlist;
	WIN32_FIND_DATA filedata; //for finding all the agent files first & next
	TCHAR   XMLfilename[_MAX_PATH]; /* "C:\\hyades\\agentcontroller 3.0\\plugins\\*";*/

	if(Agent_InstallDir == NULL) 
	{ 
		TPTP_LOG_ERROR_MSG("No agent directory specified"); 
		return -1;
	}
	else
	{
		sprintf(XMLfilename, "%s\\*",Agent_InstallDir);
		TPTP_LOG_DEBUG_MSG1("Seeking agents in %s",XMLfilename);
	}
	hlist = FindFirstFile(XMLfilename, &filedata);
 
	if(hlist == INVALID_HANDLE_VALUE) 
	{ 
		TPTP_LOG_ERROR_MSG("Agent directory not found");
		return -1;
	}
	else //valid file handle value
	{
	   while (FindNextFile(hlist, &filedata) != 0) 
	   {
		  if((strcmp(filedata.cFileName, "..") != 0) && (strcmp(filedata.cFileName, ".") != 0) ) 
		  {
			  agent_metadata_t *metadata;
			  metadata = (agent_metadata_t *)tptp_malloc(sizeof(agent_metadata_t));			  
			  if(metadata == 0) 
			  {	
				  TPTP_LOG_ERROR_MSG("Failed to alloc memory:: AgentInfo");
				  return	-1;
			  }
			  tptp_list_init( &metadata->options );
			  sprintf(XMLfilename,"%s\\%s\\%s",Agent_InstallDir,filedata.cFileName,AGENT_FILE);
			  TPTP_LOG_DEBUG_MSG1("Processing file :: %s",XMLfilename);
			  int ret =  parseAgentMetaData(metadata,XMLfilename);
			  if ( ret == 0 )
			  {
				  tptp_list_add(&agentList, (void *)metadata);
			  }
			  else
			  {
				  tptp_free( metadata );
			  }

		  } /* if(strcmp fiename is not cur dir and you have obtained the first file now */
		 
	   } /*while FindNextFile(hlist, &filedata) loop */

	    if(GetLastError() == ERROR_NO_MORE_FILES) 
		{ 
			TPTP_LOG_DEBUG_MSG("No more agent files to process");
		} else
		{
			TPTP_LOG_ERROR_MSG("Error getting agent file.");
		}

	   //close the handle
		FindClose(hlist);

		//Add it to the AC_Config List
		acconfig->agentList = agentList;

	 return 0;
	}

#else

	DIR			  *dirLkp;
	struct dirent *dirEntry;
	struct stat    statinfo;
	char		   XMLfilename[AC_MAX_PATH];
	char           inputDir[AC_MAX_PATH];
	if(Agent_InstallDir == NULL) 
	{ 
		TPTP_LOG_ERROR_MSG("No agent directory specified"); 
		return -1;
	}
	else
	{
		sprintf(XMLfilename, "%s/*",Agent_InstallDir);
		sprintf(inputDir, "%s",Agent_InstallDir);
		TPTP_LOG_DEBUG_MSG1("Seeking agents in %s",XMLfilename);
	}

	if ((dirLkp = opendir(inputDir)) == NULL)
	{
		TPTP_LOG_ERROR_MSG("Agent directory not found");
		return -1;
	}
	else
	{
		while((dirEntry = readdir(dirLkp)) != NULL)
		{
			strcpy(inputDir, Agent_InstallDir);
			strcat(inputDir, "/");
			strcat(inputDir, dirEntry->d_name);
			lstat(inputDir, &statinfo);
	
			//Test for a directory
			if(S_ISDIR(statinfo.st_mode))
			{
				if( (strcmp(".", dirEntry->d_name) != 0) && (strcmp("..",dirEntry->d_name) != 0) )
				{
					agent_metadata_t *metadata;
					metadata = (agent_metadata_t *)tptp_malloc(sizeof(agent_metadata_t));
					if(metadata == 0) 
					{	
					  TPTP_LOG_ERROR_MSG("Failed to alloc memory:: AgentInfo");
					  return	-1;
					}
					tptp_list_init( &metadata->options );
					TPTP_LOG_DEBUG_MSG1("Dir name %s",dirEntry->d_name);
					sprintf(XMLfilename,"%s/%s/%s",Agent_InstallDir,dirEntry->d_name,AGENT_FILE);
					TPTP_LOG_DEBUG_MSG1("Processing file :: %s",XMLfilename);
					int ret =  parseAgentMetaData(metadata,XMLfilename);
				    if ( ret == 0 )
				    {
					   tptp_list_add(&agentList, (void *)metadata);
				    }
				    else
				    {
					   tptp_free( metadata );
				    }
		  
				} //if dir valid 
			} //if dir
		} //while DirEntry = readdir
		closedir(dirLkp);
	}
	
	acconfig->agentList = agentList;
	return 0;
#endif
}
/**
 *********************************************************************
 *                                                       
 * @brief                                  
 *    Parse Agent Meta Data
 *                                                       
 * @return
 *		0 Success
 *
 *********************************************************************/
int parseAgentMetaData(agent_metadata_t *metadata, char *agentConfigFileName)
{
	bool	isValidRoot = false;
	tptp_list_t			interfaceList;
	tptp_list_init(&interfaceList);
	int ret = -1;
	long fileSize = 0;
	
	try {
		ret = getXMLFileSize(agentConfigFileName, &fileSize);

		memcpy( metadata, &defaultMetadata, sizeof(agent_metadata_t) );

		if(ret == 0) 
		{
			metadata->launchInfo	= (char *)tptp_malloc(fileSize+1);
			strcpy(metadata->launchInfo,"");
			metadata->clientData	= (char *)tptp_malloc(fileSize+1);
			strcpy(metadata->clientData,"");
			metadata->fullMetadata	= (char *)tptp_malloc(fileSize+1);
			strcpy(metadata->fullMetadata,"");
		}
		else 
		{
			//TO DO 
			//log_serviceMessage(file, Message,..);
			return -1; /* The file is empty or is not-valid */	
		}
			
		DOMImplementation *impl		= DOMImplementationRegistry::getDOMImplementation(&chNull);
		DOMBuilder        *parser	= ((DOMImplementationLS*)impl)->createDOMBuilder(DOMImplementationLS::MODE_SYNCHRONOUS, 0);
			
		//Create the DOM Document
		parser->setFeature(XMLUni::fgDOMWhitespaceInElementContent,false);
		parser->setFeature(XMLUni::fgDOMValidation,true);

		TPTPParserErrorHandler* tptp_dom_err = new TPTPParserErrorHandler();
		parser->setErrorHandler(tptp_dom_err);
		
		XERCES_CPP_NAMESPACE::DOMDocument* doc = parser->parseURI(agentConfigFileName);
		
		DOMTreeWalker* iter = doc->createTreeWalker(doc->getDocumentElement(),DOMNodeFilter::SHOW_ELEMENT,NULL,true);
    
		char *roottag = XMLString::transcode(iter->getCurrentNode()->getNodeName());
		TPTP_LOG_DEBUG_MSG1("Root Tag %s", roottag);
		if(strcmp(roottag, ELEMENT_NAME_AGENT)==0) {isValidRoot = true;}
		if(isValidRoot)
		{
			ret = getAttrs(iter->getCurrentNode(), ATTRB_AGENT_NAME, &metadata->agentName);
			buildDOMTreeBranch(iter->getCurrentNode(),&metadata->fullMetadata, fileSize);
			iter->firstChild();
		}
		XMLString::release(&roottag);
		
		DOMNode *curr = iter->getCurrentNode();
		while(curr)
		{
			char *tempnodename = XMLString::transcode(iter->getCurrentNode()->getNodeName());
			TPTP_LOG_DEBUG_MSG1("NodeName %s",tempnodename);
			if(strcmp(tempnodename, ELEMENT_NAME_AGENT) == 0)
			{
				ret = getAttrs(iter->getCurrentNode(), ATTRB_AGENT_NAME, &metadata->agentName);
				//This node is used to build the full metadata set
				buildDOMTreeBranch(curr,&metadata->fullMetadata, fileSize);
			}
			else if(strcmp(tempnodename, ELEMENT_NAME_AGENT_INTRF) == 0)
			{
				char *interfaceName;
				getNodeValue(curr,&interfaceName);
				tptp_list_add(&interfaceList, (void *)interfaceName);
			}
			else if(strcmp(tempnodename, ELEMENT_NAME_AGENT_BOUND) == 0)
			{
				char *temp;
				getNodeValue(curr,&temp);
				metadata->bound = atoi(temp);
				tptp_free(temp);
			}
			else if(strcmp(tempnodename, ELEMENT_NAME_AGENT_INST) == 0)
			{
				char *temp;
				getNodeValue(curr,&temp);
				metadata->singleInstance = atoi(temp);
				tptp_free(temp);
			}
			else if(strcmp(tempnodename, ELEMENT_NAME_AGENT_CNTLR) == 0)
			{
				char *temp;
				getNodeValue(curr,&temp);
				metadata->maxControllers = atoi(temp);
				tptp_free(temp);			
			}
			else if(strcmp(tempnodename, ELEMENT_NAME_AGENT_OBSR) == 0)
			{
				char *temp;
				getNodeValue(curr,&temp);
				metadata->maxObservers = atoi(temp);
				tptp_free(temp);			
			}
			else if(strcmp(tempnodename, ELEMENT_NAME_AGENT_LNCH) == 0)
			{
				DOMNodeList *nodelist = curr->getChildNodes();
				int	nodelistlen = nodelist->getLength();
			
				strcpy( metadata->launchInfo, "" );
				for(int i = 0; i < nodelistlen; i++)
				{
					if(nodelist->item(i)->getNodeType() == DOMNode::ELEMENT_NODE)
					{
						buildDOMTreeBranch(nodelist->item(i),&metadata->launchInfo, fileSize);
					}
				}
				TPTP_LOG_DEBUG_MSG1("Agent Launch Config %s", metadata->launchInfo);

			}
			else if(strcmp(tempnodename, ELEMENT_NAME_AGENT_CLDATA) == 0)
			{
				buildDOMTreeBranch(curr,&metadata->clientData, fileSize);
				TPTP_LOG_DEBUG_MSG1("Client Data %s", metadata->clientData);
			}
			else if(strcmp(tempnodename, ELEMENT_NAME_AGENT_CFGFILE) == 0)
			{
				/*
				char *temp;
				getNodeValue(curr,&temp);
				metadata->configFile = (char*)tptp_malloc( strlen(temp)+1 );
				strcpy( metadata->configFile, temp );
				tptp_free(temp);
				TPTP_LOG_DEBUG_MSG1("Config file %s", metadata->configFile);
				*/
			}

			curr = iter->nextSibling();
			XMLString::release(&tempnodename);
		}
		//Add to the userAppList
		metadata->interfaces = interfaceList;

		delete tptp_dom_err;
		parser->release();
		
		return 0;
	} //end try

	catch (const DOMException& error)
	{
		if ( error.msg != 0 )
		{
			char *errmesg = XMLString::transcode(error.msg);
			TPTP_LOG_PARSE_MSG1("XML/DOM Exception: %s", errmesg);
			XMLString::release(&errmesg);
		}
		else
		{
			// Can't get the msg string so print the error code.
			TPTP_LOG_PARSE_MSG1("XML/DOM Exception: error code %d", error.code);

		}

		TPTP_LOG_PARSE_MSG1("XML/DOM Exception occurred while parsing agent metadata in file \"%s\"", (agentConfigFileName?agentConfigFileName:"null"));
		return -1;
	}
	catch (const XMLException& error)
	{
		char *errmesg = XMLString::transcode(error.getMessage());
		TPTP_LOG_PARSE_MSG2("XML Exception: %s (at line %d)", errmesg, error.getSrcLine());
		XMLString::release(&errmesg);
		TPTP_LOG_PARSE_MSG1("XML Exception occurred while parsing agent metadata in file \"%s\"", (agentConfigFileName?agentConfigFileName:"null"));
		return -1;
	}
	catch(...)
	{ 
		TPTP_LOG_PARSE_MSG1("Unexpected exception occurred while parsing agent metadata in file \"%s\"", (agentConfigFileName?agentConfigFileName:"null"));
		return -1;
	}
}

/**
 *********************************************************************
 *                                                       
 * @brief                                  
 *    Set Env Variable
 *                                                       
 * @return
 *		void
 *
 *********************************************************************/
void setEnvironmentVariable(char *name, char *value) 
{
	//printf("ra_setservice %s %s \n", name, value);
#ifdef _WIN32
	SetEnvironmentVariable(name, value);
#else
	char *newEnv;
	int nameLen, valueLen;
	nameLen=strlen(name);
	valueLen=strlen(value);
	newEnv=(char*)tptp_malloc(nameLen+valueLen+2);
	memcpy(newEnv, name, nameLen);
	newEnv[nameLen]='=';
	memcpy(&newEnv[nameLen+1], value, valueLen+1);
	putenv(newEnv);
#endif
}
/**
 *********************************************************************
 *                                                       
 * @brief                                  
 *    Set Env Variable
 *                                                       
 * @return
 *		void
 *
 *********************************************************************/
void setEnvironment(char *name, char *value, char *position) 
{

	int result,  INITIAL_BUFFER_SIZE=128;
	char *buffer=NULL;
	int bufferSize=INITIAL_BUFFER_SIZE;

	/* Ensure that we have a name and value to start with */
	if(!name || !value) {
		return;
	}

	/* If it doesn't exist or we must replace then just set the value */
	if(strcmp(position,"replace")==0) {
		setEnvironmentVariable(name, value);
		return;
	}

	buffer=(char*)tptp_malloc(bufferSize+strlen(value)+1);

retry:
	if(strcmp(position,"prepend")==0)  
	{
		result=getEnvironmentVariable(name, &buffer[strlen(value)+1], bufferSize);
	}
	else 
	{
		result=getEnvironmentVariable(name, buffer, bufferSize);
	}

	/* Overflow condition */
	if(result>bufferSize) {
		tptp_free(buffer);
		bufferSize=result+1;
		buffer=(char*)tptp_malloc(bufferSize+strlen(value)+1);
		goto retry;
	}
	/* Append */
	else if(strcmp(position,"append")==0){
		buffer[result]=PATH_SEPARATOR;
		memcpy(&buffer[result+1], value, strlen(value));
		buffer[result+1+strlen(value)]='\0';
		setEnvironmentVariable(name, buffer);
	}
	/* Prepend */
	else {
		memcpy(buffer, value, strlen(value));
		buffer[strlen(value)]=PATH_SEPARATOR;
		buffer[result+strlen(value)+1]='\0';
		setEnvironmentVariable(name, buffer);
	}
	tptp_free(buffer);
}
/**
 *********************************************************************
 *                                                       
 * @brief                                  
 *    Get Env Variable
 *                                                       
 * @return
 *		0 success
 *
 *********************************************************************/
int getEnvironmentVariable(char* name, char* buffer, int size) 
{
#ifdef _WIN32
	return GetEnvironmentVariable(name, buffer, size);
#else
	int len;
	char *currentValue = getenv(name);
	if (!currentValue) {
		return 0;
	}

	len = strlen(currentValue) + 1;

	if (size >= len) {
		memcpy(buffer, currentValue, len);
	}

	return len;
#endif
}
/**
 *********************************************************************
 *                                                       
 * @brief                                  
 *    Append Env
 *                                                       
 * @return
 *		void
 *
 *********************************************************************/
void appendEnvironment(char *name, char *value) 
{
	int   len;
	char* env = (char*)tptp_malloc(sizeof(char) * ENV_SIZE);

	BZERO(env, ENV_SIZE);
	getEnvironmentVariable(name, env, ENV_SIZE);
	len=strlen(env);
	if ( len+strlen(value)+1 < ENV_SIZE )
		return;
	env[len]=PATH_SEPARATOR;
	env[len+1]='\0';
	strcat(env, value);

	setEnvironmentVariable(name, env);
	tptp_free(env);
}


int test()
{
	//tptp_list_t temp;
	AC_Config_t	 *ac;
	ac = (AC_Config_t *)tptp_malloc(sizeof(AC_Config_t));
	//Pass the location of the ServiceConfig file for the AC and the AC
	//The Service Config file has to be defined in the TPTPCommon.h
	int x =  loadTPTPConfig("C:\\Documents and Settings\\gnagaraj\\My Documents\\hyades\\AC_ServiceConfig.xml",ac, FALSE);

	return 0;
}

// Takes an XML-formatted character string containing an Application tag.
// It parses the string placing the attributes and elements into an App_Label_t
// structure.  The structure is allocated here and returned to the caller.  The caller is
// responsible for freeing it.
int parseApplication(char *applicationString, App_Label_t **pLabel)
{
	int ret;

	try {
		//Build a MemBuf Input source 
		MemBufInputSource *is = new MemBufInputSource((const XMLByte*)applicationString,strlen(applicationString),"parseApplication()",false);

		// Set the encoding to EBCDIC from UTF for z-series machines
		#ifdef MVS
			is->setEncoding(XMLUni::fgIBM1047EncodingString);
		#endif

		//Wrap the MemBufInputSource
		Wrapper4InputSource* domBufIS = NULL; 
		domBufIS = new Wrapper4InputSource(is);

		//Get the DOM document by passing the input string to the parser
		DOMImplementation *impl		= DOMImplementationRegistry::getDOMImplementation(&chNull);
		DOMBuilder        *parser	= ((DOMImplementationLS*)impl)->createDOMBuilder(DOMImplementationLS::MODE_SYNCHRONOUS, 0);
		App_Label_t *appLabel=NULL;;
		char* executable=NULL;
		char* path=NULL;
		char* location=NULL;
		char* extends=NULL;

		TPTPParserErrorHandler* tptp_dom_err = new TPTPParserErrorHandler();
		parser->setErrorHandler(tptp_dom_err);

		XERCES_CPP_NAMESPACE::DOMDocument *doc = parser->parse(*domBufIS);
		
		//Get all the tags into the LnList
		DOMNodeList *node = doc->getElementsByTagName(XMLString::transcode(ELEMENT_NAME_APPLICATION));
		char *tempnodename = XMLString::transcode(node->item(0)->getNodeName());

		if(strcmp(tempnodename, ELEMENT_NAME_APPLICATION) != 0)
		{
			return -1; // return fast if we cannot parse an application
		}

		// First get the attributes exec, path and location.
		ret = getAttrs(node->item(0), ATTRB_NAME_APP_EXEC, &executable);
		ret = getAttrs(node->item(0), ATTRB_NAME_APP_PATH, &path);
		ret = getAttrs(node->item(0), ATTRB_NAME_APP_LOCATION, &location);
		ret = getAttrs(node->item(0), "extends", &extends);

		appLabel = initAppLabelT(executable, path, location, extends);
		if (!appLabel)
		{
			//TODO: report error
			return -1;
		}
		//TODO: Need to free executable, path, location because init made its own copy

		// Next get any env vars (Variable) and cmd line args (Parameter) elements,
		// these are stored as child nodes of application.

		DOMNodeList *varNode = node->item(0)->getChildNodes();
		int varNodeLength = varNode->getLength();

		for (int k=0; k<varNodeLength; k++) 
		{
			char *nodeName = XMLString::transcode(varNode->item(k)->getNodeName());
			if(strcmp(nodeName, "Variable") == 0)
			{
				DOMNamedNodeMap *attributes = varNode->item(k)->getAttributes();
				int attrlen = attributes->getLength();
				variable_t *envVariable=NULL;
				char *name = NULL;
				char *value = NULL;
				position_t position=APPEND; //Default is to append

				for(int j=0;j < attrlen;j++) 
				{
					DOMAttr *attributeNode = (DOMAttr*) attributes->item(j);
					char *cAttrName = XMLString::transcode(attributeNode->getName());
					char *cAttrValue = XMLString::transcode(attributeNode->getValue());
				
					if(strcmp(cAttrName, "name") == 0)
					{
						name = cAttrValue;
					}
					else if(strcmp(cAttrName,"value") == 0)
					{
						value = cAttrValue;
					}
					else if(strcmp(cAttrName,"position") == 0)
					{
						if(strcmp("append", cAttrValue)==0)
							position = APPEND;
						else if(strcmp("prepend", cAttrValue)==0)
							position = PREPEND;
						else if(strcmp("replace", cAttrValue)==0)
							position = REPLACE;
						else
							position = APPEND; //Default to append if unknown value.

						XMLString::release(&cAttrValue);
					}

					XMLString::release(&cAttrName);
				}

				// Create & fill the variable_t, then add it to the list for this appLabel.
				if (name)
				{
					// Must have a name at the very least or don't put it in the list
					//TODO: Log/report error if no name or if initVariableT fails
					envVariable = initVariableT(name, value, position);
					if (envVariable)
					{
						tptp_list_add(appLabel->variables, envVariable);
					}
				}			
				
				// Now free the cAttrValues we saved until we copied it into the Variable struct.
				// Note: We have a memory leak here if the Variable tag had multiple name or value
				// attributes found in the for loop above (should only be one each, but no guarantee),
				// because we only have the ptr of the last one.
				if (name) XMLString::release(&name);
				if (value) XMLString::release(&value);
			} else if(strcmp(nodeName, "Parameter") == 0)
			{
				DOMNamedNodeMap *attributes = varNode->item(k)->getAttributes();
				int attrlen = attributes->getLength();
				parameter_t *cmdLineParam=NULL;
				char *value = NULL;
				position_t position=APPEND; //Default is to append

				for(int j=0;j < attrlen;j++) 
				{
					DOMAttr *attributeNode = (DOMAttr*) attributes->item(j);
					char *cAttrName = XMLString::transcode(attributeNode->getName());
					char *cAttrValue = XMLString::transcode(attributeNode->getValue());
				
					if(strcmp(cAttrName,"value") == 0)
					{
						value = cAttrValue;
					}
					else if(strcmp(cAttrName,"position") == 0)
					{
						if(strcmp("append", cAttrValue)==0)
							position = APPEND;
						else if(strcmp("prepend", cAttrValue)==0)
							position = PREPEND;
						else if(strcmp("replace", cAttrValue)==0)
							position = REPLACE;
						else
							position = APPEND; //Default to append if unknown value.

						XMLString::release(&cAttrValue);
					}

					XMLString::release(&cAttrName);
				}

				if (value == NULL) {
					DOMNodeList *pnodes = varNode->item(k)->getChildNodes();
					if (pnodes != NULL && pnodes->getLength() > 0) {
						DOMNode *dn = pnodes->item(0);
			 			if (dn->getNodeType() == DOMNode::TEXT_NODE) {
							value = XMLString::transcode(dn->getNodeValue());
			 			}
					}
				}

				// Create & fill the parameter_t, then add it to the list for this appLabel.
				if (value)
				{
					// Must have a value at the very least or don't put it in the list
					//TODO: Log/report error if no value or if initParameterT fails
					cmdLineParam = initParameterT(value, position);
					if (cmdLineParam)
					{
						tptp_list_add(appLabel->parameters, cmdLineParam);
					}
				}
				
				// Now free the cAttrValue we saved until we copied it into the Parameter struct.
				// Note: We have a memory leak here if the Parameter tag had multiple name or value
				// attributes found in the for loop above (should only be one each, but no guarantee),
				// because we only have the ptr of the last one.
				if (value) XMLString::release(&value);
			}
			
			XMLString::release(&nodeName);
		}
		
		delete tptp_dom_err;		
		parser->release();
		delete domBufIS;
		

		*pLabel = appLabel;
		return 0;
	} //end try

	catch (const DOMException& error)
	{
		if ( error.msg != 0 )
		{
			char *errmesg = XMLString::transcode(error.msg);
			TPTP_LOG_PARSE_MSG1("XML/DOM Exception: %s", errmesg);
			XMLString::release(&errmesg);
		}
		else
		{
			// Can't get the msg string so print the error code.
			TPTP_LOG_PARSE_MSG1("XML/DOM Exception: error code %d", error.code);

		}

		TPTP_LOG_PARSE_MSG1("XML/DOM Exception occurred while parsing Application string \"%s\"", (applicationString?applicationString:"null"));
		return -1;
	}
	catch (const XMLException& error)
	{
		char *errmesg = XMLString::transcode(error.getMessage());
		TPTP_LOG_PARSE_MSG2("XML Exception: %s (at line %d)", errmesg, error.getSrcLine());
		XMLString::release(&errmesg);
		TPTP_LOG_PARSE_MSG1("XML Exception occurred while parsing Application string \"%s\"", (applicationString?applicationString:"null"));
		return -1;
	}
	catch(...)
	{ 
		TPTP_LOG_PARSE_MSG1("Unexpected exception occurred while parsing Application string \"%s\"", (applicationString?applicationString:"null"));
		return -1;
	}
}

//Find a given executable in the application list.
//Returns NULL if not found.
App_Label_t* tptp_findApplication(tptp_list_t* appAliasesList, char *executable)
{
	tptp_node_t* node=NULL;
	App_Label_t* appAlias=NULL;

	for (node = appAliasesList->head; node != 0; node = node->next)
	{
		appAlias = (App_Label_t*)node->data;

		if (!appAlias) continue;  //empty data field, skip this node

		if ( isEqualString(appAlias->executable, executable) )
		{
			return appAlias;
		}
	}
	return NULL;
}

agent_metadata_t* tptp_findAgent(tptp_list_t* agentList, char *agentName)
{
	tptp_node_t* node=NULL;
	agent_metadata_t* agent=NULL;

	for (node = agentList->head; node != 0; node = node->next)
	{
		agent = (agent_metadata_t*)node->data;

		if (!agent) continue;  //empty data field, skip this node

		if ( isEqualString(agent->agentName, agentName) )
		{
			return agent;
		}
	}
	return NULL;
}

#define APPLICATION_ALIASES "ApplicationAliases" 
// Takes an XML-formatted character string containing an ApplicationAliases tag which encompasses
// a list of Application tags.
// It parses the string to separate each Application specification into a list of App_Label_t
// structures.  The list is allocated here and returned to the caller.  The caller is
// responsible for freeing the list.
int parseApplicationAliases(char *applicationString, tptp_list_t **pAppAliasList, int *launchAliasesOnly)
{
	int ret;
	tptp_list_t *appList;
	char *booleanBuffer = NULL;
	char* tmpEnv;
	sysEnv_list_t* appEnv = NULL;

	try {
		//printf("App alias %s \n", applicationString);
		tmpEnv = (char *)getEnvironmentStrings();  // used to resolve wildcards.

		/* Copy the global environment for variable lookup */
		cloneEnv( cacheEnv, &appEnv );
		if ( appEnv == NULL ) {
			appEnv = (sysEnv_list_t*)tptp_malloc(sizeof(sysEnv_list_t));
			appEnv->head = NULL;
			appEnv->tail = NULL;
		}

		// Initialize the list we will eventually return.
		appList = (tptp_list_t *) tptp_malloc(sizeof(tptp_list_t));
		tptp_list_init(appList);
		tptp_list_setNodeDestructor(appList, destroyAppLabelNode);
		tptp_list_setNodeCopier(appList, copyAppLabelNode);

		//Build a MemBuf Input source 
		MemBufInputSource *is = new MemBufInputSource((const XMLByte*)applicationString,strlen(applicationString),"parseApplicationAliases()",false);

		// Set the encoding to EBCDIC from UTF for z-series machines
		#ifdef MVS
			is->setEncoding(XMLUni::fgIBM1047EncodingString);
		#endif

		//Wrap the MemBufInputSource
		Wrapper4InputSource* domBufIS = NULL; 
		domBufIS = new Wrapper4InputSource(is);

		//Get the DOM document by passing the input string to the parser
		DOMImplementation *impl		= DOMImplementationRegistry::getDOMImplementation(&chNull);
		DOMBuilder        *parser	= ((DOMImplementationLS*)impl)->createDOMBuilder(DOMImplementationLS::MODE_SYNCHRONOUS, 0);

		TPTPParserErrorHandler* tptp_dom_err = new TPTPParserErrorHandler();
		parser->setErrorHandler(tptp_dom_err);
		
		XERCES_CPP_NAMESPACE::DOMDocument *doc = parser->parse(*domBufIS);
		
		//Find the ApplicationAliases tag and get all its elements into the LnList
		DOMNodeList *nodelist = doc->getElementsByTagName(XMLString::transcode(APPLICATION_ALIASES));
		int nodelength = nodelist->getLength();

		if(nodelength == 0) { return -1;} 

		DOMNodeList *applicationAliasesNodeList = nodelist->item(0)->getChildNodes();

		/* Get the launchAliasesOnly attribute from ApplicationAliases */
		/* If it's not there then default to false */
		ret = getAttrs(nodelist->item(0), "launchAliasesOnly", &booleanBuffer);
		if (booleanBuffer == NULL) {
			*launchAliasesOnly = FALSE;
		} else if (strcmp(booleanBuffer, "true") == 0) {
			*launchAliasesOnly = TRUE;
		} else {
			*launchAliasesOnly = FALSE;
		}
		tptp_free(booleanBuffer);

		int appnodelength = applicationAliasesNodeList->getLength();

		// Find each Application element and extract its fields and elements, placing them
		// in a App_Label_t structure.
		for(int i = 0; i < appnodelength; i++)
		{
			char *tempnodename = XMLString::transcode(applicationAliasesNodeList->item(i)->getNodeName());

			if(strcmp(tempnodename, ELEMENT_NAME_APPLICATION) == 0)
			{
				App_Label_t *appLabel=NULL;;
				char* executable=NULL;
				char* path=NULL;
				char* location=NULL;
				char* extends=NULL;
				char* newExecutable=NULL;
				char* newPath=NULL;
				char* newLocation=NULL;

				int envCount = 0;

				// Retrieve the attributes for tag Application
				ret = getAttrs(applicationAliasesNodeList->item(i), ATTRB_NAME_APP_EXEC, &executable);

				ret = getAttrs(applicationAliasesNodeList->item(i), ATTRB_NAME_APP_PATH, &path);
				ret = getAttrs(applicationAliasesNodeList->item(i), ATTRB_NAME_APP_LOCATION, &location);
				ret = getAttrs(applicationAliasesNodeList->item(i), "extends", &extends);
				createShellString(tmpEnv, &newPath, path);
				createShellString(tmpEnv, &newLocation, location);

				appLabel = initAppLabelT(executable, newPath, newLocation, extends);
				if (!appLabel)
				{
					//TODO: report error
					return -1;
				}
				//TODO: Need to free executable, path, location because init made its own copy

				DOMNodeList *node = applicationAliasesNodeList->item(i)->getChildNodes();
				int varNodeLength = node->getLength();

				// Find any Parameter and Variable elements within the Application
				// and store them in the corresponding lists within the appLabel.
				for (int k=0; k<varNodeLength; k++) 
				{
					char *name = NULL;
					char *value = NULL;
					char *newValue = NULL;
					position_t position=APPEND; //Default is to append

					char *nodeName = XMLString::transcode(node->item(k)->getNodeName());
					if(strcmp(nodeName, "Variable") == 0)
					{
						DOMNamedNodeMap *attributes = node->item(k)->getAttributes();
						int attrlen = attributes->getLength();
						variable_t *envVariable = NULL;

						for(int j=0;j < attrlen;j++) 
						{
							DOMAttr *attributeNode = (DOMAttr*) attributes->item(j);
							char *cAttrName = XMLString::transcode(attributeNode->getName());
							char *cAttrValue = XMLString::transcode(attributeNode->getValue());
				
							if(strcmp(cAttrName, "name") == 0)
							{
								name = cAttrValue;
							}
							else if(strcmp(cAttrName,"value") == 0)
							{
								value = cAttrValue;
							}
							else if(strcmp(cAttrName,"position") == 0)
							{
								if(strcmp("append", cAttrValue)==0)
									position = APPEND;
								else if(strcmp("prepend", cAttrValue)==0)
									position = PREPEND;
								else if(strcmp("replace", cAttrValue)==0)
									position = REPLACE;
								else
									position = APPEND; // Default for unrecognized value

								XMLString::release(&cAttrValue);
							}

							XMLString::release(&cAttrName);
						} 

						// Create & fill the variable_t, then add it to the list for this appLabel.
						if (name)
						{
							// Must have a name at the very least or don't put it in the list
							//TODO: Log/report error if no name or if initVariableT fails
							createShellString2(appEnv, &newValue, value);
							//printf("old %s new %s \n", value, newValue);
							envVariable = initVariableT(name, newValue, position);
							if (envVariable)
							{
								tptp_list_add(appLabel->variables, envVariable);
							}

							addEnvVar( appEnv, NULL, name, newValue, position );

						}

						// Now free the cAttrValues we saved until we copied it into the Variable struct.
						// Note: We have a memory leak here if the Variable tag had multiple name or value
						// attributes found in the for loop above (should only be one each, but no guarantee),
						// because we only have the ptr of the last one.
						if (name) XMLString::release(&name);
						if (value) XMLString::release(&value);

					}
					else if(strcmp(nodeName, "Parameter") == 0)
					{
						DOMNamedNodeMap *attributes = node->item(k)->getAttributes();
						int attrlen = attributes->getLength();
						parameter_t *cmdLineParam = NULL;
						char *newValue = NULL;

						for(int j=0;j < attrlen;j++) 
						{
							DOMAttr *attributeNode = (DOMAttr*) attributes->item(j);
							char *cAttrName = XMLString::transcode(attributeNode->getName());
							char *cAttrValue = XMLString::transcode(attributeNode->getValue());
				
							if(strcmp(cAttrName,"value") == 0)
							{
								value = cAttrValue;
							}
							else if(strcmp(cAttrName,"position") == 0)
							{
								if(strcmp("append", cAttrValue)==0)
									position = APPEND;
								else if(strcmp("prepend", cAttrValue)==0)
									position = PREPEND;
								else if(strcmp("replace", cAttrValue)==0)
									position = REPLACE;
								else
									position = APPEND; // Default for unrecognized value

								XMLString::release(&cAttrValue);
							}

							XMLString::release(&cAttrName);
						} 

						// Create & fill the parameter_t, then add it to the list for this appLabel.					
						if (value)
						{
							// Must have a value at the very least or don't put it in the list
							//TODO: Log/report error if no value or if initParameterT fails
							createShellString2(appEnv, &newValue, value);
							cmdLineParam = initParameterT(newValue, position);
							if (cmdLineParam)
							{
								tptp_list_add(appLabel->parameters, cmdLineParam);
							}
						}

						// Now free the cAttrValue we saved until we copied it into the Parameter struct.
						// Note: We have a memory leak here if the Parameter tag had multiple name or value
						// attributes found in the for loop above (should only be one each, but no guarantee),
						// because we only have the ptr of the last one.
						if (value) XMLString::release(&value);
					}
					
					XMLString::release(&nodeName);
				}

				//If we have an extends specified then try to find the base application.
				//The extends specified will modify this base application.
				if (appLabel->extends) {
					App_Label_t *baseApp=NULL;;
					tptp_node_t* listNode=NULL;

					baseApp = tptp_findApplication(appList, appLabel->executable);
					if (baseApp == NULL) {
						TPTP_LOG_DEBUG_MSG1("Cannot find application %s to extend ", appLabel->executable);
					} else {
						//Free the current location... allocate new space and copy the extended location.
						tptp_free(baseApp->location);
						baseApp->location = (char *) tptp_malloc(strlen(appLabel->location) + 1);
						strcpy(baseApp->location, appLabel->location);
						//Add the new Variables and Parameters to their respective lists.
						for (listNode = appLabel->variables->head; listNode != 0; listNode = listNode->next)
						{
							variable_t* Variable = (variable_t*)listNode->data;

							tptp_list_add(baseApp->variables, Variable);
						}

						for (listNode = appLabel->parameters->head; listNode != 0; listNode = listNode->next)
						{
							parameter_t* Parameter = (parameter_t*)listNode->data;

							tptp_list_add(baseApp->parameters, Parameter);
						}
					}
				} else {
					tptp_list_add(appList, (void *)appLabel);
				}
			}
		
			XMLString::release(&tempnodename);
		}
		
		parser->release();
		delete tptp_dom_err;
		delete domBufIS;
		
		*pAppAliasList = appList;

		freeEnv( appEnv );

		freeEnvironmentStrings(tmpEnv); //Free the system allocated space.
		return 0;
	} //end try

	catch (const DOMException& error)
	{
		if ( error.msg != 0 )
		{
			char *errmesg = XMLString::transcode(error.msg);
			TPTP_LOG_PARSE_MSG1("XML/DOM Exception: %s", errmesg);
			XMLString::release(&errmesg);
		}
		else
		{
			// Can't get the msg string so print the error code.
			TPTP_LOG_PARSE_MSG1("XML/DOM Exception: error code %d", error.code);

		}

		TPTP_LOG_PARSE_MSG1("XML/DOM Exception occurred while parsing ApplicationAliases string \"%s\"", (applicationString?applicationString:"null"));
		return -1;
	}
	catch (const XMLException& error)
	{
		char *errmesg = XMLString::transcode(error.getMessage());
		TPTP_LOG_PARSE_MSG2("XML Exception: %s (at line %d)", errmesg, error.getSrcLine());
		XMLString::release(&errmesg);
		TPTP_LOG_PARSE_MSG1("XML Exception occurred while parsing ApplicationAliases string \"%s\"", (applicationString?applicationString:"null"));
		return -1;
	}
	catch(...)
	{ 
		TPTP_LOG_PARSE_MSG1("Unexpected exception occurred while parsing ApplicationAliases string \"%s\"", (applicationString?applicationString:"null"));
		return -1;
	}
}

/* ============  parameter_t structure functions ========================== */
/*
 * Allocate and initialize a parameter_t structure.
 *
 * Returns:
 * Pointer to parameter_t if successful.
 * Null if error occurred.
 */
parameter_t* initParameterT(const char* value, position_t position)
{
	parameter_t* param = NULL;

	param = (parameter_t*)tptp_malloc( sizeof(parameter_t) );
	if ( param == NULL )
	{
		// Report internal memory error.
		return NULL;
	}

	if (value)
	{
		int len = strlen(value) + 1;
		param->value = (char*) tptp_malloc(len);
		memcpy(param->value, value, len);
	}
	else
		param->value = NULL;

	param->position = position;

	return param;
}

/*
 * Allocate a new parameter_t structure and copy contents of
 * the param arg into it.
 *
 * Returns:
 * Pointer to clone's parameter_t if successful.
 * Null if error occurred.
 */
parameter_t* cloneParameterT(const parameter_t* param)
{
	parameter_t* cloneParam = NULL;

	cloneParam = (parameter_t*)tptp_malloc( sizeof(parameter_t) );
	if ( cloneParam == NULL )
	{
		return NULL;
	}

	if (param->value)
	{
		int len = strlen(param->value) + 1;
		cloneParam->value = (char*) tptp_malloc(len);
		memcpy(cloneParam->value, param->value, len);
	}
	else
		cloneParam->value = NULL;

	cloneParam->position = param->position;

	return cloneParam;
}

/*
 * Used by the tptp_list utility to get a copy of a parameter_t node.
 */
int copyParameterNode(const tptp_node_t* node, tptp_node_t* nodeCopy)
{
	parameter_t* param = (parameter_t*)node->data;
	nodeCopy->data = cloneParameterT(param);
	return 0;
}

/*
 * Free any allocated members of a parameter_t structure.
 */
void destroyParameterT(parameter_t* param)
{
	if (param == NULL)
		return;

	if (param->value)
	{
		tptp_free(param->value);
		param->value = NULL;
	}

	param->position = APPEND; //Don't have a non-initialized state, so this is the default.

	return;
}

/*
 * Used by the tptp_list utility to free contents of a parameter_t node in a list.
 */
int destroyParameterNode(tptp_node_t* node)
{
	parameter_t* param = (parameter_t*)node->data;
	destroyParameterT(param);
	return 0;
}

tptp_option_t* initOptionT(char* config, const char* name, const char* value, const char* type)
{
	tptp_option_t* opt = NULL;

	opt = (tptp_option_t*)tptp_malloc( sizeof(tptp_option_t) );
	if ( opt == NULL )
	{
		// Report internal memory error.
		return NULL;
	}

	if (name)
	{
		createShellString( config, &opt->name, name );
	}
	else
		opt->name = NULL;  

	if (value)
	{
		createShellString( config, &opt->value, value );
	}
	else
		opt->value = NULL;

	if (type)
	{
		createShellString( config, &opt->type, type );
	}
	else
		opt->type = NULL;


	return opt;
}

tptp_option_t* cloneOptionT(const tptp_option_t* option)
{
	tptp_option_t* cloneOption = NULL;

	cloneOption = (tptp_option_t*)tptp_malloc( sizeof(tptp_option_t) );
	if ( cloneOption == NULL )
	{
		return NULL;
	}

	if (option->name)
	{
		int len = strlen(option->name) + 1;
		cloneOption->name = (char*) tptp_malloc(len);
		memcpy(cloneOption->name, option->name, len);
	}
	else
		cloneOption->name = NULL;

	if (option->value)
	{
		int len = strlen(option->value) + 1;
		cloneOption->value = (char*) tptp_malloc(len);
		memcpy(cloneOption->value, option->value, len);
	}
	else
		cloneOption->value = NULL;

	if (option->type)
	{
		int len = strlen(option->type) + 1;
		cloneOption->type = (char*) tptp_malloc(len);
		memcpy(cloneOption->type, option->type, len);
	}
	else
		cloneOption->type = NULL;

	return cloneOption;
}

/*
 * Used by the tptp_list utility to get a copy of a variable_t node.
 */
int copyOptionNode(const tptp_node_t* node, tptp_node_t* nodeCopy)
{
	tptp_option_t* option = (tptp_option_t*)node->data;
	nodeCopy->data = cloneOptionT(option);
	return 0;
}

void destroyOptionT(tptp_option_t* opt)
{
	if (opt == NULL)
		return;

	if (opt->name)
	{
		tptp_free(opt->name);
		opt->name = NULL;
	}

	if (opt->value)
	{
		tptp_free(opt->value);
		opt->value = NULL;
	}

	if (opt->type)
	{
		tptp_free(opt->type);
		opt->type = NULL;
	}

	return;
}
 

/* ============  variable_t structure functions ========================== */
/*
 * Allocate and initialize a variable_t structure.
 *
 * Returns:
 * Pointer to variable_t if successful.
 * Null if error occurred.
 */
variable_t* initVariableT(const char* name, const char* value, position_t position)
{
	variable_t* var = NULL;

	var = (variable_t*)tptp_malloc( sizeof(variable_t) );
	if ( var == NULL )
	{
		// Report internal memory error.
		return NULL;
	}

	if (name)
	{
		int len = strlen(name) + 1;
		var->name = (char*) tptp_malloc(len);
		memcpy(var->name, name, len);
	}
	else
		var->name = NULL;

	if (value)
	{
		int len = strlen(value) + 1;
		var->value = (char*) tptp_malloc(len);
		memcpy(var->value, value, len);
	}
	else
		var->value = NULL;

	var->position = position;

	return var;
}

/*
 * Allocate a new variable_t structure and copy contents of
 * the variable arg into it.
 *
 * Returns:
 * Pointer to clone's variable_t if successful.
 * Null if error occurred.
 */
variable_t* cloneVariableT(const variable_t* variable)
{
	variable_t* cloneVariable = NULL;

	cloneVariable = (variable_t*)tptp_malloc( sizeof(variable_t) );
	if ( cloneVariable == NULL )
	{
		return NULL;
	}

	if (variable->name)
	{
		int len = strlen(variable->name) + 1;
		cloneVariable->name = (char*) tptp_malloc(len);
		memcpy(cloneVariable->name, variable->name, len);
	}
	else
		cloneVariable->name = NULL;

	if (variable->value)
	{
		int len = strlen(variable->value) + 1;
		cloneVariable->value = (char*) tptp_malloc(len);
		memcpy(cloneVariable->value, variable->value, len);
	}
	else
		cloneVariable->value = NULL;

	cloneVariable->position = variable->position;

	return cloneVariable;
}

/*
 * Used by the tptp_list utility to get a copy of a variable_t node.
 */
int copyVariableNode(const tptp_node_t* node, tptp_node_t* nodeCopy)
{
	variable_t* var = (variable_t*)node->data;
	nodeCopy->data = cloneVariableT(var);
	return 0;
}

/*
 * Free any allocated members of a variable_t structure.
 */
void destroyVariableT(variable_t* var)
{
	if (var == NULL)
		return;

	if (var->name)
	{
		tptp_free(var->name);
		var->name = NULL;
	}

	if (var->value)
	{
		tptp_free(var->value);
		var->value = NULL;
	}

	var->position = APPEND; //Don't have a non-initialized state, so this is the default.

	return;
}

/*
 * Used by the tptp_list utility to free contents of a tptp_listener_t node in a list.
 */
int destroyVariableNode(tptp_node_t* node)
{
	variable_t* var = (variable_t*)node->data;
	destroyVariableT(var);
	return 0;
}
 

/* ============  App_Label_t structure functions ========================== */
/*
 * Allocate and initialize App_Label_t structure.
 *
 * Returns:
 * Pointer to App_Label_t if successful.
 * Null if error occurred.
 */
App_Label_t* initAppLabelT(const char* exe, const char* path, const char* loc, const char* extends)
{
	App_Label_t* appLabel = NULL;

	appLabel = (App_Label_t*)tptp_malloc( sizeof(App_Label_t) );
	if ( appLabel == NULL )
	{
		// Report internal memory error.
		return NULL;
	}

	if (exe)
	{
		int len = strlen(exe) + 1;
		appLabel->executable = (char*) tptp_malloc(len);
		memcpy(appLabel->executable, exe, len);
	}
	else
		appLabel->executable = NULL;

	if (path)
	{
		int len = strlen(path) + 1;
		appLabel->path = (char*) tptp_malloc(len);
		memcpy(appLabel->path, path, len);
	}
	else
		appLabel->path = NULL;

	if (loc)
	{
		int len = strlen(loc) + 1;
		appLabel->location = (char*) tptp_malloc(len);
		memcpy(appLabel->location, loc, len);
	}
	else
		appLabel->location = NULL;

	if (extends)
	{
		int len = strlen(extends) + 1;
		appLabel->extends = (char*) tptp_malloc(len);
		memcpy(appLabel->extends, extends, len);
	}
	else
		appLabel->extends = NULL;

	// Create empty lists for env variables and cmd line parameters.
	appLabel->variables = (tptp_list_t*)tptp_malloc( sizeof(tptp_list_t) );
	if ( appLabel->variables == NULL )
	{
		return NULL;
	}
	tptp_list_init(appLabel->variables);
	tptp_list_setNodeDestructor(appLabel->variables, destroyVariableNode);
	tptp_list_setNodeCopier(appLabel->variables, copyVariableNode);

	appLabel->parameters = (tptp_list_t*)tptp_malloc( sizeof(tptp_list_t) );
	if ( appLabel->parameters == NULL )
	{
		return NULL;
	}
	tptp_list_init(appLabel->parameters);
	tptp_list_setNodeDestructor(appLabel->parameters, destroyParameterNode);
	tptp_list_setNodeCopier(appLabel->parameters, copyParameterNode);

	return appLabel;
}


/*
 * Allocate a new App_Label_t structure and copy contents of
 * the appLabel arg into it.
 *
 * Returns:
 * Pointer to clone's App_Label_t if successful.
 * Null if error occurred.
 */
App_Label_t* cloneAppLabelT(const App_Label_t* appLabel)
{
	App_Label_t* cloneAppLabel = NULL;

	cloneAppLabel = (App_Label_t*)tptp_malloc( sizeof(App_Label_t) );
	if ( cloneAppLabel == NULL )
	{
		return NULL;
	}

	if (appLabel->executable)
	{
		int len = strlen(appLabel->executable) + 1;
		cloneAppLabel->executable = (char*) tptp_malloc(len);
		memcpy(cloneAppLabel->executable, appLabel->executable, len);
	}
	else
		cloneAppLabel->executable = NULL;

	if (appLabel->path)
	{
		int len = strlen(appLabel->path) + 1;
		cloneAppLabel->path = (char*) tptp_malloc(len);
		memcpy(cloneAppLabel->path, appLabel->path, len);
	}
	else
		cloneAppLabel->path = NULL;

	if (appLabel->location)
	{
		int len = strlen(appLabel->location) + 1;
		cloneAppLabel->location = (char*) tptp_malloc(len);
		memcpy(cloneAppLabel->location, appLabel->location, len);
	}
	else
		cloneAppLabel->location = NULL;

	if (appLabel->extends)
	{
		int len = strlen(appLabel->extends) + 1;
		cloneAppLabel->extends = (char*) tptp_malloc(len);
		memcpy(cloneAppLabel->extends, appLabel->extends, len);
	}
	else
		cloneAppLabel->extends = NULL;

	//Copy list of variables and list of parameters if any.
	cloneAppLabel->variables = (tptp_list_t*)tptp_malloc( sizeof(tptp_list_t) );
	if ( cloneAppLabel->variables == NULL )
	{
		return NULL;
	}
	tptp_list_clone(cloneAppLabel->variables, appLabel->variables);

	cloneAppLabel->parameters = (tptp_list_t*)tptp_malloc( sizeof(tptp_list_t) );
	if ( cloneAppLabel->parameters == NULL )
	{
		return NULL;
	}
	tptp_list_clone(cloneAppLabel->parameters, appLabel->parameters);

	return cloneAppLabel;
}

/*
 * Used by the tptp_list utility to get a copy of a App_Label_t node.
 */
int copyAppLabelNode(const tptp_node_t* node, tptp_node_t* nodeCopy)
{
	App_Label_t* appLabel = (App_Label_t*)node->data;
	nodeCopy->data = cloneAppLabelT(appLabel);
	return 0;
}


/*
 * Free any allocated members of a App_Label_t structure.
 */
void destroyAppLabelT(App_Label_t* appLabel)
{
	if (appLabel == NULL)
		return;

	if (appLabel->executable)
	{
		tptp_free(appLabel->executable);
		appLabel->executable = NULL;
	}

	if (appLabel->path)
	{
		tptp_free(appLabel->path);
		appLabel->path = NULL;
	}

	if (appLabel->location)
	{
		tptp_free(appLabel->location);
		appLabel->location = NULL;
	}

	if (appLabel->extends)
	{
		tptp_free(appLabel->extends);
		appLabel->extends = NULL;
	}

	//Free list of variables and parameters if any.
	tptp_list_clear(appLabel->variables);
	tptp_free(appLabel->variables);
	appLabel->variables = NULL;

	tptp_list_clear(appLabel->parameters);
	tptp_free(appLabel->parameters);
	appLabel->parameters = NULL;

	return;
}

/*
 * Used by the tptp_list utility to free contents of a App_Label_t node in a list.
 */
int destroyAppLabelNode(tptp_node_t* node)
{
	App_Label_t* appLabel = (App_Label_t*)node->data;
	destroyAppLabelT(appLabel);
	return 0;
}

/**
 *********************************************************************
 *                                                       
 * @brief                                  
 *    Parse Agent Config Data
 *                                                       
 * @return
 *		0 Success
 *
 *********************************************************************/
//This filename is built in the calling 
/*int loadAgentConfig(BaseAgentImpl* pAgentIn, char *agentConfigFileName, agent_config_t* agentConfig)
{
	bool	isValidRoot = false;
	
	int ret = -1;
	long fileSize = 0;

	try {
		// Store the agent as a global so we can use it to log events everwhere
		//	pAgent = pAgentIn;
		
		ret = getXMLFileSize(agentConfigFileName, &fileSize);

			
		DOMImplementation *impl		= DOMImplementationRegistry::getDOMImplementation(&chNull);
		DOMBuilder        *parser	= ((DOMImplementationLS*)impl)->createDOMBuilder(DOMImplementationLS::MODE_SYNCHRONOUS, 0);
			
		//Create the DOM Document
		parser->setFeature(XMLUni::fgDOMWhitespaceInElementContent,false);
		parser->setFeature(XMLUni::fgDOMValidation,true);

		DOMErrorHandler* tptp_dom_err = new TPTPParserErrorHandler();
		parser->setErrorHandler(tptp_dom_err);
		
		XERCES_CPP_NAMESPACE::DOMDocument* doc = parser->parseURI(agentConfigFileName);
		
		DOMTreeWalker* iter = doc->createTreeWalker(doc->getDocumentElement(),DOMNodeFilter::SHOW_ELEMENT,NULL,true);
    
		char *roottag = XMLString::transcode(iter->getCurrentNode()->getNodeName());
	//	TPTP_LOG_DEBUG_MSG1(pAgent, "Root Tag %s", roottag);
		if(strcmp(roottag, ELEMENT_NAME_ROOT)==0) {isValidRoot = true;}
		if(!isValidRoot)
		{
	//		TPTP_LOG_DEBUG_MSG(pAgent, "The Agent Config XML is not valid");
			XMLString::release(&roottag);
			return -1;
		}
		XMLString::release(&roottag);
		
		DOMNode *curr = iter->getCurrentNode();
		while(curr)
		{
			char *tempnodename = XMLString::transcode(iter->getCurrentNode()->getNodeName());
	//		TPTP_LOG_DEBUG_MSG1(pAgent, "NodeName %s",tempnodename);
			
			if(strcmp(tempnodename, ELEMENT_NAME_LOG_LEVEL) == 0)
			{
				char *temp;
				getNodeValue(curr,&temp);
				agentConfig->loggingLevel = temp;
			}
			else if(strcmp(tempnodename, ELEMENT_NAME_AC_NAMED_PIPE) == 0)
			{
				char *temp;
				getNodeValue(curr,&temp);
				agentConfig->acNamedPipeName = temp;
			}
			else if(strcmp(tempnodename, ELEMENT_NAME_AC_SHARED_MEM) == 0)
			{
				char *temp;
				getNodeValue(curr,&temp);
				agentConfig->acSharedMemName = temp;
			}		
			else if(strcmp(tempnodename, ELEMENT_NAME_AGENT_CUSTOM_DATA) == 0)
			{			
				tptp_list_t			agentCustomDataList;
				tptp_list_init(&agentCustomDataList);			
				DOMNodeList *gnodelist = curr->getChildNodes();			
				int	nlistlen = gnodelist->getLength();
				for(int nl = 0; nl < nlistlen; nl++)
				{
					bool isElemNode = false;
					if(gnodelist->item(nl)->getNodeType() == DOMNode::ELEMENT_NODE)
					{ 
						isElemNode = true; 
					}
					if (isElemNode)
					{
						char *gchnodename = XMLString::transcode(gnodelist->item(nl)->getNodeName());		
						char *temp = 0;
						agent_custom_data_t* customData = (agent_custom_data_t *)tptp_malloc(sizeof(agent_custom_data_t));
						getNodeValue(gnodelist->item(nl),&temp);
						customData->name = (char*)tptp_malloc(sizeof(strlen(gchnodename)));
						strcpy(customData->name, gchnodename);
						customData->value = temp;
						tptp_list_add(&agentCustomDataList, (void *)customData);
						TPTP_LOG_DEBUG_MSG1(pAgent, "Custom Node Name - %s", customData->name);
						TPTP_LOG_DEBUG_MSG1(pAgent, "Custom Node Value - %s", customData->value);
					
						XMLString::release(&gchnodename);
					}
				}
				agentConfig->agentCustomData = agentCustomDataList;
			}


			curr = iter->nextNode();
			XMLString::release(&tempnodename);
		}
		

		parser->release();
		delete tptp_dom_err;
		
		return 0;
	} //end try

	catch (const DOMException& error)
	{
		if ( error.msg != 0 )
		{
			char *errmesg = XMLString::transcode(error.msg);
			TPTP_LOG_PARSE_MSG1("XML/DOM Exception: %s", errmesg);
			XMLString::release(&errmesg);
		}
		else
		{
			// Can't get the msg string so print the error code.
			TPTP_LOG_PARSE_MSG1("XML/DOM Exception: error code %d", error.code);

		}

		TPTP_LOG_PARSE_MSG1("XML/DOM Exception occurred while parsing AgentConfig file \"%s\"\n", (agentConfigFileName?agentConfigFileName:"null"));
		return -1;
	}
	catch (const XMLException& error)
	{
		char *errmesg = XMLString::transcode(error.getMessage());
		TPTP_LOG_PARSE_MSG2("XML Exception: %s (at line %d)", errmesg, error.getSrcLine());
		XMLString::release(&errmesg);
		TPTP_LOG_PARSE_MSG1("XML Exception occurred while parsing AgentConfig file \"%s\"", (agentConfigFileName?agentConfigFileName:"null"));
		return -1;
	}
	catch(...)
	{ 
		TPTP_LOG_PARSE_MSG1("Unexpected exception occurred while parsing AgentConfig file \"%s\"", (agentConfigFileName?agentConfigFileName:"null"));
		return -1;
	}
}*/

