/*******************************************************************************
 * 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:
 *    Karla Callaghan,Intel - Initial implementation
 *
 * $Id$ 
 *******************************************************************************/ 

// This header file provides a single location for handler code used by multiple
// locations which do XML parsing (e.g., TPTPConfig, TPTPUtil, MsgParser).
// It relies on the XML  DOM header files being defined by the file which includes this
// header. This header must be placed after XERCES_CPP_NAMESPACE_USE

#ifndef __ParserErrorHandler_H__
#define __ParserErrorHandler_H__
#include <xercesc/dom/DOMErrorHandler.hpp>
#include <time.h>
#include <tptp/TPTPOSCalls.h>

#define TPTP_MAX_MSG_SIZE  8192

#define TPTP_LOG_PARSE_MSG(tptp_log_msg) logParserErrorMsg(tptp_log_msg)

#define TPTP_LOG_PARSE_MSG1(msgFormat, par1)                           \
                                       {	                             \
                                        char tptp_log_msg[TPTP_MAX_MSG_SIZE];      \
                                        sprintf( tptp_log_msg, msgFormat, par1 ); \
                                        logParserErrorMsg(tptp_log_msg);\
                                       }
#define TPTP_LOG_PARSE_MSG2(msgFormat, par1, par2)                     \
                                       {	                             \
                                        char tptp_log_msg[TPTP_MAX_MSG_SIZE];      \
                                        sprintf( tptp_log_msg, msgFormat, par1, par2 ); \
                                        logParserErrorMsg(tptp_log_msg);\
                                       }
#define TPTP_LOG_PARSE_MSG3(msgFormat, par1, par2, par3)               \
                                       {	                             \
                                        char tptp_log_msg[TPTP_MAX_MSG_SIZE];      \
                                        sprintf( tptp_log_msg, msgFormat, par1, par2, par3 ); \
                                        logParserErrorMsg(tptp_log_msg);\
                                       }
#define TPTP_LOG_PARSE_MSG4(msgFormat, par1, par2, par3, par4)         \
                                       {	                             \
                                        char tptp_log_msg[TPTP_MAX_MSG_SIZE];      \
                                        sprintf( tptp_log_msg, msgFormat, par1, par2, par3, par4 ); \
                                        logParserErrorMsg(tptp_log_msg);\
                                       }
#define TPTP_LOG_PARSE_MSG5(msgFormat, par1, par2, par3, par4, par5)   \
                                       {	                             \
                                        char tptp_log_msg[TPTP_MAX_MSG_SIZE];      \
                                        sprintf( tptp_log_msg, msgFormat, par1, par2, par3, par4, par5 ); \
                                        logParserErrorMsg(tptp_log_msg);\
                                       }

// Utility function to open the parser error log file, write a string to it
// and close the file.  This presumes that performance for writing to this
// parsing error log is not an issue as these errors will be infrequent and often
// fatal.
// Note: The log file is created here if it does not exist. However, this log file
// is never deleted (i.e., it must be removed manually). We believe this to be okay since
// the file size is expected to grow infrequently and by small amounts. The messages
// are also being tagged with date/time/executable name info to allow easy determination
// of what messages are appropriate for the current run.
void logParserErrorMsg(char *msgString)
{
	char timeBuf[128] = "00";
	char dateBuf[128] = "00";

#ifndef _WIN32
	struct tm *timeStruct;
	time_t timeSecs;
#endif

#ifdef _WIN32
	tzset();
	_strtime(timeBuf);
	_strdate(dateBuf );
#else
	tzset();
	timeSecs = time(NULL);
	timeStruct = localtime(&timeSecs);
	sprintf(dateBuf,"%02d/%02d/%02d",
	timeStruct->tm_mon,timeStruct->tm_mday,timeStruct->tm_year-100);
	sprintf(timeBuf,"%02d:%02d:%02d",
	timeStruct->tm_hour,timeStruct->tm_min,timeStruct->tm_sec);
#endif
	char *exeName = getExecutableName();

	// What if agent tries to write while AC has file open?
	FILE *hParseLogFile = fopen("tptpParseError.log", "a");
	if (hParseLogFile)
	{
		fprintf(hParseLogFile, "(%s %s %s) %s\n", dateBuf, timeBuf, exeName, msgString);
		fclose(hParseLogFile);
		if (exeName) tptp_free(exeName);
	}
	return;
}


// Provide a handler method to be called if error encountered by the XML/DOM parser.
class TPTPParserErrorHandler : public DOMErrorHandler
{
	public:
	TPTPParserErrorHandler() {}
	bool handleError(const DOMError& domError);
};

bool TPTPParserErrorHandler::handleError(const DOMError& error)
{
	// TODO: Should log this error to the common log file,if the AC has established it.
	// Cannot rely on it being there since parsing must occur before AC knows the log config.
	// Andy proposes to use a pipe that is specific to logging (vs. the pipe used to
	// exchange messages with the AC) to allow common libraries to log error messages
	// (i.e., those libs that currently use NoLog.h).  When this is in place, need
	// to provide a global variable that is Null or set to the name of the logging pipe.
	// If that pipe name is not Null, then these parsing errors should be written to that
	// pipe.
	// In the absence of that common log file, write to a local file with a name we chose.

	if(error.getSeverity() == DOMError::DOM_SEVERITY_FATAL_ERROR)
	{
		char *errMsg = XMLString::transcode(error.getMessage());
		char *errURI = NULL;
		if (error.getLocation()->getURI())
		{
			errURI = XMLString::transcode(error.getLocation()->getURI());
		}
/* Remove after testing on Linux.
TPTP_LOG_PARSE_MSG("Hi");
TPTP_LOG_PARSE_MSG1("%s", "Param1");
TPTP_LOG_PARSE_MSG2("%s, %s", "Param1", "Param2");
TPTP_LOG_PARSE_MSG3("%s, %s, %s", "Param1", "Param2", "Param3");
TPTP_LOG_PARSE_MSG4("%s, %s, %s, %s", "Param1", "Param2", "Param3", "Param4");
TPTP_LOG_PARSE_MSG5("%s, %s, %s, %s, %s", "Param1", "Param2", "Param3", "Param4", "Param5");
*/

		TPTP_LOG_PARSE_MSG4("XML Error: %s (error detected at line:%d, col:%d, in \"%s\")",
							(errMsg?errMsg:"null"),
							error.getLocation()->getLineNumber(),
							error.getLocation()->getColumnNumber(),
							(errURI?errURI:"null"));

		XMLString::release(&errMsg);
		if (errURI) XMLString::release(&errURI);

		return false;
	}
	return true;  //non-fatal error
}


#endif //__ParserErrorHandler_H__

