blob: e85ece1db76f1a0a564bb1fddaf57b777e5d9563 [file] [log] [blame]
/*
-------------------------------------------------------------------------------
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
*/
#if defined(_MSC_VER)
#include <stdio.h>
#include <eh.h>
#include <windows.h>
#include <winbase.h>
#endif
#include "uima/pragmas.hpp" //must be included first to disable warnings
#include "uima/msg.h"
#include <string>
#include <sstream>
#include "uima/macros.h"
#include "uima/trace.hpp"
#include "uima/strconvert.hpp"
#include "uima/unistrref.hpp"
#include "uima/comp_ids.h"
#include "uima/exceptions.hpp"
#include "uima/msgstrtab.h"
using namespace std;
namespace uima {
///Constructor with just the message id
ErrorMessage::ErrorMessage(
TyMessageId utMsgId
) :
iv_utMsgId(utMsgId) {
if ( iv_utMsgId == 0) {
iv_utMsgId = UIMA_MSG_ID_NO_MESSAGE_AVAILABLE;
}
}
///Constructor with a single char * parameter
ErrorMessage::ErrorMessage(
TyMessageId utMsgId,
const char * cpszParam1
) :
iv_utMsgId(utMsgId) {
assert( iv_utMsgId != 0 );
iv_vecParams.push_back((string)cpszParam1);
}
///Constructor with a single string parameter
ErrorMessage::ErrorMessage(
TyMessageId utMsgId,
const string & crstrParam1
) :
iv_utMsgId(utMsgId) {
assert( iv_utMsgId != 0 );
iv_vecParams.push_back(crstrParam1);
}
///Constructor with a single UChar * parameter
ErrorMessage::ErrorMessage(
TyMessageId utMsgId,
const UChar * cpuszParam1
) :
iv_utMsgId(utMsgId) {
assert( iv_utMsgId != 0 );
string s;
UnicodeStringRef(cpuszParam1).extract(s); // Convert to default encoding for platform
iv_vecParams.push_back(s);
}
///Constructor with a single UnicodeString parameter
ErrorMessage::ErrorMessage(
TyMessageId utMsgId,
const icu::UnicodeString & crustrParam1
) :
iv_utMsgId(utMsgId) {
assert( iv_utMsgId != 0 );
string s;
UnicodeStringRef(crustrParam1).extract(s); // Convert to default encoding for platform
iv_vecParams.push_back(s);
}
///Constructor with a single int parameter
ErrorMessage::ErrorMessage(
TyMessageId utMsgId,
int iParam1
) :
iv_utMsgId(utMsgId) {
assert( iv_utMsgId != 0 );
string s;
iv_vecParams.push_back(long2String(iParam1, s));
}
///Constructor with a single unsigned int parameter
ErrorMessage::ErrorMessage(
TyMessageId utMsgId,
unsigned int uiParam1
) :
iv_utMsgId(utMsgId) {
assert( iv_utMsgId != 0 );
string s;
iv_vecParams.push_back(long2String((int) uiParam1, s));
}
///Constructor with a single long parameter
ErrorMessage::ErrorMessage(
TyMessageId utMsgId,
long lParam1
) :
iv_utMsgId(utMsgId) {
assert( iv_utMsgId != 0 );
string s;
iv_vecParams.push_back(long2String(lParam1, s));
}
///Constructor with a single unsigned long parameter
ErrorMessage::ErrorMessage(
TyMessageId utMsgId,
unsigned long ulParam1
) :
iv_utMsgId(utMsgId) {
assert( iv_utMsgId != 0 );
string s;
iv_vecParams.push_back(long2String((long) ulParam1, s));
}
///Constructor with a single double parameter
ErrorMessage::ErrorMessage(
TyMessageId utMsgId,
const double dParam1
) :
iv_utMsgId(utMsgId) {
assert( iv_utMsgId != 0 );
string s;
iv_vecParams.push_back(double2String(dParam1, s));
}
///Constructor with a full parameter vector
ErrorMessage::ErrorMessage(
TyMessageId utMsgId,
const vector<string> & crvecParams
) :
iv_utMsgId(utMsgId),
iv_vecParams(crvecParams) {
assert( iv_utMsgId != 0 );
}
///add parameter to message id
void
ErrorMessage::addParam(const char * cpsz) {
iv_vecParams.push_back(cpsz);
}
///add parameter to message id
void
ErrorMessage::addParam(const string & str) {
iv_vecParams.push_back(str);
}
///add parameter to message id
void
ErrorMessage::addParam(const UChar * cpuszParam) {
string s;
UnicodeStringRef(cpuszParam).extract(s); // Convert to default encoding for platform
iv_vecParams.push_back(s);
}
///add parameter to message id
void
ErrorMessage::addParam(const icu::UnicodeString & crustrParam) {
string s;
UnicodeStringRef(crustrParam).extract(s); // Convert to default encoding for platform
iv_vecParams.push_back(s);
}
void ErrorMessage::addParam(uima::UnicodeStringRef const & crParam) {
icu::UnicodeString str(crParam.getBuffer(), crParam.length() );
addParam(str);
}
///add parameter to message id
void
ErrorMessage::addParam(long l) {
string str;
convertToString(l, str);
iv_vecParams.push_back(str);
}
///add parameter to message id
void
ErrorMessage::addParam(unsigned long ul) {
string str;
convertToString(ul, str);
iv_vecParams.push_back(str);
}
///add parameter to message id
void
ErrorMessage::addParam(int i) {
string str;
convertToString(i, str);
iv_vecParams.push_back(str);
}
///add parameter to message id
void
ErrorMessage::addParam(unsigned int ui) {
string str;
convertToString(ui, str);
iv_vecParams.push_back(str);
}
///add parameter to message id
void
ErrorMessage::addParam(double d) {
string str;
convertToString(d, str);
iv_vecParams.push_back(str);
}
/*------------------------------- Constructors -------------------------------*/
ErrorContext::ErrorContext(
const ErrorMessage & crclMessage,
const char* pszFilename,
const char* pszFunction,
unsigned long ulLineNumber
):
iv_clMessage(crclMessage),
iv_pszFilename(pszFilename),
iv_pszFunction(pszFunction),
iv_ulLineNo(ulLineNumber) {}
#ifdef OS_STL
Exception::~Exception()
#else
Exception::~Exception() UIMA_THROW0()
#endif
{}
/*------------------------------ Output Support ------------------------------*/
string
ErrorMessage::asString() const {
size_t numparams = getMessageParams().size();
// Check for unknown message id
if (iv_utMsgId < 0 || iv_utMsgId > UIMA_MSG_ID_SIGNATURE_END) {
return string("Unknown message id " + iv_utMsgId);
}
//parameter substitution
//locate message in message table
const TCHAR ** messages = gs_aszMessageStringTable;
const TCHAR * msg = messages[iv_utMsgId];
TCHAR * buf = new TCHAR[UIMA_MSG_MAX_STR_LEN];
memset(buf,'\0',UIMA_MSG_MAX_STR_LEN);
int numwritten=0;
TCHAR * trg = buf;
while (*msg) {
if (numwritten > UIMA_MSG_MAX_STR_LEN) {
break;
}
if (*msg == UIMA_MSG_REPLACE_CHAR) {
msg = msg+1;
if (*msg == UIMA_MSG_REPLACE_CHAR) {
*trg = *msg;
trg = trg +1;
;
msg = msg+1;
numwritten++;
} else { //replace %n with the corresponding param
unsigned long index;
int len;
string arg;
// determine the number of the specified argument ...
index = (unsigned long) atol(msg);
if (index > numparams) // param not defined
{
arg = "???"; // replace it by "dont-know"
} else {
// ... the indexed argument ...
arg = iv_vecParams[index - 1]; // zero-based array!
//assert(arg.length() > 0);
}
len = arg.length();
// ... and then copy the argument
if (UIMA_MSG_MAX_STR_LEN-numwritten < len) {
len = UIMA_MSG_MAX_STR_LEN - numwritten;
}
if (len > 0) {
strncpy(trg, arg.c_str(), len);
trg = trg+len;
}
msg = msg+1;
while ( isdigit(*msg) ) { //handle arg number 10 or more
msg = msg+1;
}
}
} else {
*trg = *msg;
trg = trg+1;
msg = msg+1;
}
}
//cout << buf << endl;
string target(buf);
delete[] buf ;
return target;
//string target;
//target.assign(buf, UIMA_MSG_MAX_STR_LEN); // Copy the result to the string
//delete buf;
//return target;
}
ostream &
operator << (
ostream & os,
const ErrorMessage & errorMsg
) {
os << errorMsg.asString();
return(os);
}
string
ErrorContext::asString() const {
string s;
s += getMessage().asString();
if (getFileName() != NULL) {
s += string("\n") + ErrorInfo::getGlobalErrorInfoIndent() + " File : " + getFileName();
}
if (getFunctionName() != NULL) {
s += string("\n") + ErrorInfo::getGlobalErrorInfoIndent() + " Function : " + getFunctionName();
}
if (getLineNumber() != 0) {
string sNum;
long2String(getLineNumber(), sNum);
s += string("\n") + ErrorInfo::getGlobalErrorInfoIndent() + " Line : " + sNum;
}
return(s);
}
ostream &
operator << (
ostream & os,
const ErrorContext & errContext
) {
os << errContext.asString();
return (os);
}
void ErrorMessage::reset(void) {
iv_utMsgId = UIMA_MSG_ID_NO_MESSAGE_AVAILABLE;
iv_vecParams.clear();
}
/* ----------------------------------------------------------------------- */
/* ErrorInfo */
/* ----------------------------------------------------------------------- */
/*------------------------------- Statics -----------------------------------*/
//initialize static member var to an initial value
const char * ErrorInfo::cv_cpszContextPrefix = " While : ";
const char * ErrorInfo::cv_cpszIndent = "";
/*------------------------------- Constructors -------------------------------*/
ErrorInfo::ErrorInfo(
const ErrorMessage & rclMessage,
TyErrorId ulErrorId,
ErrorInfo::EnSeverity enSeverity
) :
iv_clErrorMsg(rclMessage),
iv_ulErrorId(ulErrorId),
iv_enSeverity(enSeverity),
iv_vecContexts() {}
ErrorInfo::ErrorInfo( void ) :
iv_clErrorMsg(),
iv_ulErrorId(UIMA_ERR_NONE),
iv_enSeverity(recoverable),
iv_vecContexts() {}
ErrorInfo::~ErrorInfo() {}
//constructor (copy)
//? Exception::Exception(
//? const Exception& rclException
//? )
//? {
//? }
/*---------------------------- Exception Context ----------------------------*/
void
ErrorInfo::addContext( const ErrorContext & crclContext ) {
iv_vecContexts.push_back(crclContext);
}
const ErrorContext *
ErrorInfo::contextPtrAtIndex( size_t uiContextIndex ) const {
if (uiContextIndex >= iv_vecContexts.size()) {
return(NULL);
}
return(&iv_vecContexts[uiContextIndex]);
}
/*------------------------------ Output Support ------------------------------*/
string
ErrorInfo::asString() const {
string s;
if (getErrorId() == UIMA_ERR_NONE) {
s += string("No Error\n");
return (s);
}
if (getErrorId() != UIMA_ERR_NONE) {
s += string("\n") + ErrorInfo::getGlobalErrorInfoIndent() + "Error number : ";
string sErr;
long2String( getErrorId(), sErr);
s += sErr;
}
s += string("\n") + ErrorInfo::getGlobalErrorInfoIndent() + "Recoverable : " + (isRecoverable() ? "Yes" : "No");
s += string("\n") + ErrorInfo::getGlobalErrorInfoIndent() + "Error : " + getMessage().asString();
for (size_t i = 0; i < contextCount(); ++i) {
s += string("\n") + ErrorInfo::getGlobalErrorInfoIndent() + ErrorInfo::getGlobalErrorInfoContextPrefix();
assert(EXISTS(contextPtrAtIndex(i))); //lint !e666: Expression with side effects passed to repeated parameter 1 in macro EXISTS
s += contextPtrAtIndex(i)->asString();
}
s += string("\n");
return (s);
}
///output support for streams
ostream &
operator << (
ostream & os,
const ErrorInfo & errInfo
) {
os << errInfo.asString();
return(os);
}
void ErrorInfo::reset(void) {
iv_clErrorMsg.reset();
iv_ulErrorId = UIMA_ERR_NONE;
iv_enSeverity = recoverable;
iv_vecContexts.clear();
}
/* ----------------------------------------------------------------------- */
/* Exception */
/* ----------------------------------------------------------------------- */
Exception::Exception(
const ErrorMessage & rclMessage,
TyErrorId ulErrorId,
ErrorInfo::EnSeverity enSeverity
) :
EXCEPTION_BASE_CLASS(),
iv_clErrorInfo(rclMessage, ulErrorId, enSeverity) {}
Exception::Exception(
const ErrorInfo & crclErrorInfo
) :
EXCEPTION_BASE_CLASS(),
iv_clErrorInfo(crclErrorInfo) {}
/*------------------------------ Exception Type ------------------------------*/
const char * Exception::getName() const {
return(_TEXT("unspecified exception"));
}
/*------------------------- Application Termination --------------------------*/
void Exception::terminate() {
exit(iv_clErrorInfo.getErrorId()); //lint !e713: Loss of precision (arg. no. 1) (unsigned long to int)
}
/*------------------------------ Throw Support -------------------------------*/
void Exception::assertParameter(
const char* /*exceptionText*/,
ErrorContext /*context*/ ) {
assert(false);
//not tested yet (and not used anywhere!)
}
/*------------------------- Logging Support ----------------------------------*/
void Exception::logExceptionData() {
util::Trace clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_EXCEPTIONS);
clTrace.dump(_TEXT("Exception occured"), asString().c_str());
//not implemented yet
}
/*------------------------------ Output Support ------------------------------*/
string
Exception::asString() const {
//output the (class) name of the exception and its error info after it.
return string("\n") +
ErrorInfo::getGlobalErrorInfoIndent() +
"Exception : " +
getName() +
"\n" +
getErrorInfo().asString() +
"\n";
}
ostream &
operator << (
ostream & os,
const Exception & exception
) {
//output the (class) name of the exception and its error info after it.
os << exception.asString();
return(os);
}
/*------------------------------ Static Method -------------------------------*/
// Release contents of string container allocated by asString method
void
Exception::release(std::string & msg) {
msg.clear(); // Empty string
msg.reserve(1); // Reduce capacity so will use internal buffer & free external one
}
//private:
/*----------------------------- Hidden Functions -----------------------------*/
Exception& Exception::operator=( const Exception& /*exc*/ ) {
assert(false);
return(*this); //lint !e527 unreachable
} //lint !e1745: member not assigned by private assignment operator
/* ----------------------------------------------------------------------- */
/* Implementations of predefined exceptions */
/* ----------------------------------------------------------------------- */
/*
The following classes reimplement the ANSI standard exception hierarchy from
stdexcept.h as UIMACPP exceptions with context and message id support
*/
UIMA_EXC_CLASSIMPLEMENT(Uima_logic_error ,Exception);
UIMA_EXC_CLASSIMPLEMENT(Uima_runtime_error ,Exception);
UIMA_EXC_CLASSIMPLEMENT(Uima_domain_error ,Uima_logic_error);
UIMA_EXC_CLASSIMPLEMENT(Uima_invalid_argument ,Uima_logic_error);
UIMA_EXC_CLASSIMPLEMENT(Uima_length_error ,Uima_logic_error);
UIMA_EXC_CLASSIMPLEMENT(Uima_out_of_range ,Uima_logic_error);
UIMA_EXC_CLASSIMPLEMENT(Uima_range_error ,Uima_runtime_error);
UIMA_EXC_CLASSIMPLEMENT(Uima_overflow_error ,Uima_runtime_error);
UIMA_EXC_CLASSIMPLEMENT(Uima_underflow_error ,Uima_runtime_error);
/**
The following exceptions are used by helper test classes that are no longer in the UIMACPP library:
CommandLineDriver DocBuffer ParseHandlers
*/
UIMA_EXC_CLASSIMPLEMENT(ConsoleAbortExc ,Exception);
UIMA_EXC_CLASSIMPLEMENT(ParseHandlerExc ,Exception);
UIMA_EXC_CLASSIMPLEMENT(ExcDocBuffer ,Uima_out_of_range);
/** code page conversion errors */
UIMA_EXC_CLASSIMPLEMENT(CodePageConversionException, uima::Exception);
/**
The following exception is used to report failures from APR functions
*/
UIMA_EXC_CLASSIMPLEMENT(AprFailureException, Exception);
/*
The following classes provide a starting point for an exception hierarchy
*/
//? UIMA_EXC_CLASSIMPLEMENT(ExcAssertionFailure, Exception);
UIMA_EXC_CLASSIMPLEMENT(ExcIllFormedInputError , Uima_runtime_error);
UIMA_EXC_CLASSIMPLEMENT(ExcInvalidParameter , Uima_invalid_argument);
UIMA_EXC_CLASSIMPLEMENT(ExcIndexOutOfRange , Uima_out_of_range);
//? UIMA_EXC_CLASSIMPLEMENT(ExcDeviceError ,Uima_runtime_error);
UIMA_EXC_CLASSIMPLEMENT(ExcInvalidRequest , Uima_runtime_error);
UIMA_EXC_CLASSIMPLEMENT(ExcResourceExhausted , Uima_runtime_error);
UIMA_EXC_CLASSIMPLEMENT(ExcOutOfMemory , ExcResourceExhausted);
//? UIMA_EXC_CLASSIMPLEMENT(ExcOutOfSystemResource, ResourceExhausted);
//? UIMA_EXC_CLASSIMPLEMENT(ExcOutOfWindowResource, ResourceExhausted);
UIMA_EXC_CLASSIMPLEMENT(ExcFileNotFoundError , Uima_runtime_error);
// Windows specific CException
ExcWinCException::ExcWinCException(
ErrorMessage clMessage,
TyErrorId ulErrorId,
ErrorInfo::EnSeverity enSeverity
)
: Uima_runtime_error (clMessage, ulErrorId, enSeverity) {
;
}
const char*
ExcWinCException :: getName() const {
return( "ExcWinCException" );
}
ExcWinCException::~ExcWinCException () CHILD_DESTRUCT_THROW0() {
;
}
ExcWinCException::ExcWinCException (const ExcWinCException & a) : Uima_runtime_error (a) {
;
}
// Windows exceptions can be mapped only when compiled with MS VC++
#if defined(_MSC_VER)
void translation_func( unsigned int u, _EXCEPTION_POINTERS* pExp ) {
const char * cpszMsg = NULL;
switch (u) {
case EXCEPTION_ACCESS_VIOLATION:
cpszMsg ="\"ACCESS VIOLATION\"";
break;
case EXCEPTION_DATATYPE_MISALIGNMENT:
cpszMsg ="\"DATATYPE MISALIGNMENT\"";
break;
case EXCEPTION_BREAKPOINT:
cpszMsg ="\"BREAKPOINT\"";
break;
case EXCEPTION_SINGLE_STEP:
cpszMsg ="\"SINGLE STEP\"";
break;
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
cpszMsg ="\"ARRAY BOUNDS EXCEEDED\"";
break;
case EXCEPTION_FLT_DENORMAL_OPERAND:
cpszMsg ="\"FLT DENORMAL OPERAND\"";
break;
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
cpszMsg ="\"FLT DIVIDE_BY ZERO\"";
break;
case EXCEPTION_FLT_INEXACT_RESULT:
cpszMsg ="\"FLT INEXACT_RESULT\"";
break;
case EXCEPTION_FLT_INVALID_OPERATION:
cpszMsg ="\"FLT INVALID OPERATION\"";
break;
case EXCEPTION_FLT_OVERFLOW:
cpszMsg ="\"FLT OVERFLOW\"";
break;
case EXCEPTION_FLT_STACK_CHECK:
cpszMsg ="\"FLT STACK_CHECK\"";
break;
case EXCEPTION_FLT_UNDERFLOW:
cpszMsg ="\"FLT UNDERFLOW\"";
break;
case EXCEPTION_INT_DIVIDE_BY_ZERO:
cpszMsg ="\"INT DIVIDE BY ZERO\"";
break;
case EXCEPTION_INT_OVERFLOW:
cpszMsg ="\"INT OVERFLOW\"";
break;
case EXCEPTION_PRIV_INSTRUCTION:
cpszMsg ="\"PRIV INSTRUCTION\"";
break;
case EXCEPTION_IN_PAGE_ERROR:
cpszMsg ="\"IN PAGE_ERROR\"";
break;
case EXCEPTION_ILLEGAL_INSTRUCTION:
cpszMsg ="\"ILLEGAL INSTRUCTION\"";
break;
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
cpszMsg ="\"NONCONTINUABLE EXCEPTION\"";
break;
case EXCEPTION_STACK_OVERFLOW:
cpszMsg ="\"STACK OVERFLOW\"";
break;
case EXCEPTION_INVALID_DISPOSITION:
cpszMsg ="\"INVALID DISPOSITION\"";
break;
case EXCEPTION_GUARD_PAGE:
cpszMsg ="\"GUARD PAGE\"";
break;
case EXCEPTION_INVALID_HANDLE:
cpszMsg ="\"INVALID HANDLE\"";
break;
case CONTROL_C_EXIT:
cpszMsg ="\"CONTROL C EXIT\"";
break;
default:
cpszMsg = "Unknows Windows C Exception";
break;
}
// throw our own type of exception so we know at least what was going on
// instead of just getting an unknown ... C++ excepition
throw ExcWinCException( ErrorMessage(UIMA_MSG_ID_EXC_WINDOWS_EXCEPTION, cpszMsg),
(TyErrorId)UIMA_ERR_ENGINE_WINDOWS_EXCEPTION,
ErrorInfo::unrecoverable);
}
#define UIMA_ENVVAR_DONT_MAP_WINDOWS_EXCEPTIONS "UIMA_DONT_MAP_WINDOWS_EXCEPTIONS"
// _set_se_translator should be called at the beginning of main
// since we have no access to main here, we declare a static var of a dummy
// type which does the _set_se_translator call in it's constructor
// Note: this only works if the compiler properly executes the ctors of
// such static vars in DLLs
class Dummy {
public:
Dummy( void ) {
if ( getenv(UIMA_ENVVAR_DONT_MAP_WINDOWS_EXCEPTIONS) == NULL) {
_set_se_translator( translation_func );
}
}
};
// static var of our dummy type
Dummy clDummy;
#endif
}