blob: c1a566a5f9b0671c05aaf62e100f4ad6293f0094 [file] [log] [blame]
/** @name resmgr.cpp
-----------------------------------------------------------------------------
* 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.
-----------------------------------------------------------------------------
Description: This file contains class {\tt ResourceManager}.
Note: code parts which should be made thread-safe
are marked with "mutex" (suhre)
-----------------------------------------------------------------------------
-------------------------------------------------------------------------- */
/* ----------------------------------------------------------------------- */
/* Interface dependencies */
/* ----------------------------------------------------------------------- */
//#define DEBUG_VERBOSE
#include "uima/resmgr.hpp"
#include "apr.h"
/* ----------------------------------------------------------------------- */
/* Implementation dependencies */
/* ----------------------------------------------------------------------- */
#if (__GNUC__ < 3)
#include <clocale>
#else
#include <locale>
#endif
#if defined(_MSC_VER)
int rc = _CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
// Send all reports to STDOUT
int rc1 = _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
_HFILE h1 = _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT );
int rc3 = _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
_HFILE h2 = _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT );
int rc5 = _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
_HFILE h3 = _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT );
#endif
#include <jni.h>
#include "uima/envvar.hpp"
#include "uima/trace.hpp"
#include "uima/dirwalk.hpp"
#include "uima/dllfile.hpp"
#include "uima/macros.h"
#include "uima/comp_ids.h"
#include "uima/res_abase.hpp"
#include "uima/res_annotator.hpp"
#include "uima/envvars.h"
#include "uima/exceptions.hpp"
#include "uima/language.hpp"
#include "uima/msg.h"
#include "uima/msgstrtab.h"
#include "uima/casexception.hpp"
#include "xercesc/util/PlatformUtils.hpp"
#include "unicode/uclean.h"
#include "uima/stltools.hpp"
/* ----------------------------------------------------------------------- */
/* Constants */
/* ----------------------------------------------------------------------- */
#define JAVA_PROXY "org/apache/uima/uimacpp/UimacppAnalysisComponent"
#ifndef UIMA_VERSION
#error UIMA_VERSION must be defined in the compilation environment
#endif
/* max. number of characters in a valid filename for shipment */
const size_t UIMA_MAX_VALID_FILENAME_SIZE = 8; /* DOS 8+3 */
XERCES_CPP_NAMESPACE_USE
/* ----------------------------------------------------------------------- */
/* Types / Classes */
/* ----------------------------------------------------------------------- */
using namespace std;
namespace uima {
/*
* The class ResourceManagerAutomaticInstanceDestructor is used to call method
* ResourceManager::deleteInstance().
* There needs to be one instance of ResourceManagerAutomaticInstanceDestructor
* for which the destructor will be called whenever the DLL goes out of scope.
* This destructor will then call ResourceManager::deleteInstance()
* automatically shutting down the resource manager.
*/
class ResourceManagerAutomaticInstanceDestructor {
public:
ResourceManagerAutomaticInstanceDestructor(void) {
; /* do nothing */
UIMA_TPRINT(_TEXT("INIT ..."));
}
~ResourceManagerAutomaticInstanceDestructor(void) {
UIMA_TPRINT(_TEXT("deleting ResourceManagerInstance ..."));
ResourceManager::deleteInstance();
}
}
; /* ResourceManagerAutomaticInstanceDestructor */
/* ----------------------------------------------------------------------- */
/* Globals */
/* ----------------------------------------------------------------------- */
ResourceManager * ResourceManager::cv_pclSingletonInstance = 0;
TyProcedure iv_traceProc;
/* see docu for class ResourceManagerAutomaticInstanceDestructor above */
static ResourceManagerAutomaticInstanceDestructor gs_clResourceManagerAutomaticInstanceDestructor;
/* ----------------------------------------------------------------------- */
/* Function declarations */
/* ----------------------------------------------------------------------- */
/* ----------------------------------------------------------------------- */
/* Macro definitions */
/* ----------------------------------------------------------------------- */
/* ----------------------------------------------------------------------- */
/* Private implementation */
/* ----------------------------------------------------------------------- */
ResourceManager::ResourceManager(const TCHAR * cpszInstance, const TCHAR * cpszProductPrefix) :
iv_utLastErrorId(UIMA_ERR_NONE),
iv_locationWork("."),
iv_locationData("."),
iv_frameworkLogger(NULL),
iv_logLevel(LogStream::EnMessage),
iv_fileLogger(NULL),
iv_loggers()
/* ----------------------------------------------------------------------- */
{
string str;
assert(EXISTS(cpszInstance));
UIMA_TPRINT(_TEXT("instance: ") << cpszInstance);
/* set the product prefix -- dropped this code */
/* after the trace instance has been created and enabled,
we may instantiate a first trace object */
util::Trace clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_RESOURCE_MGR);
clTrace.dump(_TEXT("UIMACPP Instance"), cpszInstance);
/* determine xsd path ... use $UIMACPP_HOME/data instead of iv_locationData
(which defaults to $UIMACPP_DATAPATH) as the latter is for user data. */
bDoSchemaValidation=true;
str = UIMA_ENVVAR_HOME;
util::EnvironmentVariableQueryOnly clEnvVarSchemaPath(str.c_str());
UIMA_TPRINT(_TEXT("querying envvar: ") << str.c_str());
schemaInfo[0] = '\0'; // Play safe
if (clEnvVarSchemaPath.hasValue()) {
string schemaloc = clEnvVarSchemaPath.getValue();
UIMA_TPRINT(_TEXT("value: ") << schemaloc);
schemaloc += "/data";
// Create full name & transform path to absolute s.t. the XML parser can handle it
util::Filename schemaFilename(schemaloc.c_str(),UIMA_XSD_FILENAME);
schemaFilename.normalizeAbsolute();
bIsSchemaAvailable = schemaFilename.isExistent();
// schema filename must not contain blanks as the parser schemaLocation
// attribute is a blank-separated pair of strings
if (bIsSchemaAvailable) {
icu::UnicodeString schemaPath(schemaFilename.getAsCString());
schemaPath.findAndReplace(" ", "%20");
int len = strlen(UIMA_XML_NAMESPACE);
memcpy(schemaInfo, UIMA_XML_NAMESPACE, len);
schemaInfo[len] = ' ';
schemaPath.extract(0, schemaPath.length(), schemaInfo+len+1, "UTF-8");
}
} else {
bIsSchemaAvailable = false;
}
/* determine data path */
str = UIMA_ENVVAR_SUFFIX_DATAPATH;
util::EnvironmentVariableQueryOnly clEnvVarDataPath(str.c_str());
UIMA_TPRINT(_TEXT("querying envvar: ") << str.c_str());
if (clEnvVarDataPath.hasValue()) {
iv_locationData = util::Location(clEnvVarDataPath.getValue());
} else {
iv_locationData = util::Location(".");
}
assert(EXISTS(iv_locationData));
UIMA_TPRINT(_TEXT("value: ") << iv_locationData);
/* determine work path */
str = UIMA_ENVVAR_SUFFIX_WORKPATH;
util::EnvironmentVariableQueryOnly clEnvVarWorkPath(str.c_str());
UIMA_TPRINT(_TEXT("querying envvar: ") << str.c_str());
if (clEnvVarWorkPath.hasValue()) {
iv_locationWork = util::Location(clEnvVarWorkPath.getValue());
} else {
iv_locationWork = util::Location(); // TMP directory
}
assert(EXISTS(iv_locationWork));
UIMA_TPRINT(_TEXT("value: ") << iv_locationWork);
/* determine iv_bIgnoreAnnotatorPathSpec flag */ // ** Dropped this
// we must make sure real values our ini files are read with . (e.g. "0.5")
setlocale(LC_NUMERIC, "C");
UIMA_TPRINT(_TEXT("workpath: ") << (const char*)iv_locationWork);
UIMA_TPRINT(_TEXT("datapath: ") << (const char*)iv_locationData);
clTrace.dump(_TEXT("Work path"), iv_locationWork.getAsCString());
clTrace.dump(_TEXT("Data path"), iv_locationData.getAsCString());
#ifndef NDEBUG
/* check whether the message string table apepars correct and consistent */
ErrorMessage clMsgSig1(UIMA_MSG_ID_SIGNATURE_BEGIN);
ErrorMessage clMsgSig2(UIMA_MSG_ID_SIGNATURE_END);
/* the signatures at the start and end must match! */
if (strcmp(clMsgSig1.asString().c_str(), clMsgSig2.asString().c_str()) != 0) {
cerr << "Internal build error"
<< "String table in uima/msgstrtab.h is inconsistent!" << endl
<< "Signature Id BEGIN: " << clMsgSig1.getMessageID() << endl
<< " Found message: " << clMsgSig1 << endl
<< "Signature Id END: " << clMsgSig2.getMessageID() << endl
<< " Found message:" << clMsgSig2 << endl;
assert(false);
}
#endif
//read environement setting to register Sofa Stream handlers
//mappings are specified as:
// UIMACPP_STREAMHANDLERS=urischeme:dllfilename urischeme2:dllfilename2
str = UIMA_ENVVAR_SOFA_STREAM_HANDLERS;
util::EnvironmentVariableQueryOnly clEnvVarStreamHandlers(str.c_str());
UIMA_TPRINT(_TEXT("querying envvar: ") << str.c_str());
TCHAR * cpszURIToStreamHandlerMap=0;
if (clEnvVarStreamHandlers.hasValue()) {
cpszURIToStreamHandlerMap = (TCHAR*) clEnvVarStreamHandlers.getValue();
assert(EXISTS(cpszURIToStreamHandlerMap));
UIMA_TPRINT(_TEXT("value: ") << cpszURIToStreamHandlerMap);
TCHAR * urischeme =0;
TCHAR * handlerdllfilename=0;
TCHAR * curptr = cpszURIToStreamHandlerMap;
TCHAR * chptr = 0;
//parse string to get each uri:dllfilename pair ... separated by one or more spaces
while (curptr != NULL) {
while (*curptr == ' ')
++curptr;
chptr = strchr(curptr, ':');
int len = chptr - curptr;
if (len > 0) {
//get the uri scheme
urischeme = new char[len+1];
strncpy(urischeme, curptr, len);
urischeme[len]='\0';
curptr = chptr+1;
chptr = strchr(curptr, ' ');
if (chptr == NULL)
len = strlen(curptr);
else
len = chptr - curptr;
//get dll and register
if (len > 0) {
handlerdllfilename = new char[len+1];
strncpy(handlerdllfilename,curptr, len);
handlerdllfilename[len]='\0';
registerStreamHandlerForURIScheme(urischeme, handlerdllfilename);
delete [] handlerdllfilename;
}
delete [] urischeme;
}
//move ptr
if (chptr==NULL)
curptr=chptr;
else
curptr = chptr+1;
} //while
} //if
//register the Sofa Data Stream Handler for the 'file' URI scheme
//registerStreamHandlerForURIScheme("file", "sofafilestreamhandler");
}
void ResourceManager::deleteResourceList( TyResourceList & rResList) {
int i;
for (i=rResList.size()-1; i>=0 ;--i) {
ResourceABase * rResource = rResList[i];
UIMA_TPRINT(" deleting resource " << i << ": " << rResource);
assert( EXISTS(rResource) );
UIMA_TPRINT(" key: " << rResource->getKey() );
UIMA_TPRINT(" de-initing resource");
rResource->deInit();
assert( EXISTS(rResource) );
delete rResource;
rResList[i] = NULL;
UIMA_TPRINT(" done");
}
}
/* ----------------------------------------------------------------------- */
/* Protected implementation */
/* ----------------------------------------------------------------------- */
/* ----------------------------------------------------------------------- */
/* Public implementation */
/* ----------------------------------------------------------------------- */
ResourceManager::~ResourceManager(void)
/* ----------------------------------------------------------------------- */
{
UIMA_TPRINT("Searching...");
// it is important that annotators are deInited (unloaded)
// last due to the following scenario:
// a annotator p derives a class from ResourceABase, the class definition
// is thus only valid during the lifetime in p. However, all resources
// are handled by the resource manager. After the annotator is unloaded
// the virtual function table of the resource is destroyed
// (MS .NET and MSVC++6), thus the deInit() call fails.
// use this factory just to get the kind string
internal::ResourceAnnotatorFileFactory annotatorFactory;
icu::UnicodeString const & crAnnotatorKind = annotatorFactory.getKind();
TyResourceList * pAnnotators = NULL;
TyResources::iterator it;
for (it = iv_resources.begin(); it != iv_resources.end(); ++it) {
TyResourceList & rResList = (*it).second;
UIMA_TPRINT("Deleting all resources with kind: " << (*it).first);
if ( (*it).first == crAnnotatorKind ) {
assert( pAnnotators == NULL );
pAnnotators = & rResList;
} else {
deleteResourceList( rResList );
}
}
TyURIStreamHandlers::iterator ite;
for (ite = iv_streamhandlers.begin(); ite != iv_streamhandlers.end(); ++ite) {
util::Filename * pDllFile = (util::Filename *) (*ite).second;
UIMA_TPRINT("Deleting stream handler dll file for uri scheme: " << (*ite).first);
delete pDllFile;
}
// unload annotators at last, if any
if (pAnnotators != NULL) {
deleteResourceList( *pAnnotators );
}
iv_resources.clear();
UIMA_TPRINT(" ...seek and destroy!");
}
const util::Location & ResourceManager::getLocationWork(void) const
/* ----------------------------------------------------------------------- */
{
assert(iv_utLastErrorId != UIMA_ERR_RESMGR_OUT_OF_MEMORY );
return iv_locationWork;
}
const util::Location & ResourceManager::getLocationData(void) const
/* ----------------------------------------------------------------------- */
{
assert(iv_utLastErrorId != UIMA_ERR_RESMGR_OUT_OF_MEMORY );
return iv_locationData;
}
void ResourceManager::setNewLocationWork(const util::Location & crclLocation)
/* ----------------------------------------------------------------------- */
{
util::Trace clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_RESOURCE_MGR);
assert(iv_utLastErrorId != UIMA_ERR_RESMGR_OUT_OF_MEMORY );
clTrace.dump(_TEXT("New work path"), crclLocation.getAsCString());
iv_locationWork = crclLocation;
}
void ResourceManager::setNewLocationData(const util::Location & crclLocation)
/* ----------------------------------------------------------------------- */
{
util::Trace clTrace(util::enTraceDetailLow, UIMA_TRACE_ORIGIN, UIMA_TRACE_COMPID_RESOURCE_MGR);
assert(iv_utLastErrorId != UIMA_ERR_RESMGR_OUT_OF_MEMORY );
clTrace.dump(_TEXT("New data path"), crclLocation.getAsCString());
iv_locationData = crclLocation;
}
util::DllProcLoaderFile * ResourceManager::requestAnnotatorFile(const util::Filename & crclFilename)
/* ----------------------------------------------------------------------- */
{
internal::ResourceAnnotatorFileFactory factory;
icu::UnicodeString us( crclFilename.getAsCString() );
uima::ErrorInfo errInfo;
internal::ResourceAnnotatorFile const * cpResAnnotatorFile = (internal::ResourceAnnotatorFile const *) getResource( us, factory, errInfo);
if (errInfo.getErrorId()==UIMA_ERR_NONE && EXISTS(cpResAnnotatorFile)) {
return cpResAnnotatorFile->getAnnotatorFile();
} else {
std::string err = "ResourceManager::requestAnnotatorFile() failed to find ";
err += crclFilename;
ResourceManager::getInstance().getLogger().logError(err);
UIMA_EXC_THROW_NEW(Uima_runtime_error,
errInfo.getErrorId(),
errInfo.getMessage(),
errInfo.getMessage().getMessageID(),
ErrorInfo::unrecoverable);
}
}
ResourceABase const * ResourceManager::getResource(uima::Language const & crLang,
ResourceFactoryABase const & crFactory,
ErrorInfo & rErrInfo) {
icu::UnicodeString us( crLang.asString().c_str() );
return getResource(us, crFactory, rErrInfo);
}
ResourceABase const * ResourceManager::getResource(icu::UnicodeString const & crKey,
ResourceFactoryABase const & crFactory,
uima::ErrorInfo & rErrInfo) {
// assertWithMsg(false, "Implement caching functionality");
icu::UnicodeString const & crKind = crFactory.getKind();
UIMA_TPRINT("Creating resource with kind " << crKind << " and key " << crKey);
// acquire mutex lock
TyResourceList & rResList = iv_resources[crKind];
ResourceABase * pResource = NULL;
TyResourceList::const_iterator cit;
for (cit = rResList.begin(); cit != rResList.end(); ++cit) {
if ( (*cit)->getKey() == crKey ) {
pResource = *cit;
break;
}
}
// if the resource was not found
if (pResource == NULL) {
pResource = crFactory.createResource( crKey );
pResource->init(rErrInfo);
if (rErrInfo.getErrorId() != UIMA_ERR_NONE) {
delete pResource;
return NULL;
}
rResList.push_back(pResource);
}
// release mutex lock
UIMA_TPRINT("...resource created: " << pResource);
assert( EXISTS( pResource ) );
return pResource;
}
void ResourceManager::enableSchemaValidation(bool aEnable) {
bDoSchemaValidation=aEnable;
}
bool ResourceManager::doSchemaValidation() {
return bDoSchemaValidation;
}
bool ResourceManager::isSchemaAvailable() {
return bIsSchemaAvailable;
}
LogStream::EnEntryType ResourceManager::getLoggingLevel() {
return iv_logLevel;
}
void ResourceManager::setLoggingLevel(LogStream::EnEntryType level) {
iv_logLevel=level;
}
TCHAR const * ResourceManager::getSchemaInfo() {
return schemaInfo;
}
void ResourceManager::registerLogger(Logger * pLogger) {
iv_loggers.push_back(pLogger);
}
vector<Logger*> & ResourceManager::getLoggers() {
return iv_loggers;
}
void ResourceManager::unregisterLogger(Logger * pLogger) {
vector<Logger*>::iterator iter;
for (iter=iv_loggers.begin(); iter != iv_loggers.end();iter++) {
if (*iter == pLogger) {
iv_loggers.erase(iter);
return;
}
}
string str = "Logger not found. Could not unregister.";
UIMA_EXC_THROW_NEW(Uima_runtime_error,
UIMA_MSG_ID_LITERAL_STRING,
UIMA_MSG_ID_LITERAL_STRING,
ErrorMessage(UIMA_MSG_ID_LITERAL_STRING, str.c_str()),
ErrorInfo::unrecoverable);
}
void ResourceManager::registerFactory(icu::UnicodeString const & crKind, ResourceFactoryABase & crFactory) {
iv_resourceFactories.insert(TyResourceFactories::value_type(crKind, &crFactory));
}
void ResourceManager::deRegisterFactory(icu::UnicodeString const & crKind, ResourceFactoryABase & crFactory) {
TyResourceFactories::iterator it = iv_resourceFactories.find(crKind);
if (it != iv_resourceFactories.end()) {
assert( (*it).second == &crFactory );
iv_resourceFactories.erase(it);
}
}
ResourceABase const * ResourceManager::getResource(
icu::UnicodeString const & crKey,
icu::UnicodeString const & crKind,
ErrorInfo & errorInfo) {
TyResourceFactories::iterator it = iv_resourceFactories.find(crKind);
if (it == iv_resourceFactories.end()) {
errorInfo.setErrorId(UIMA_ERR_RESMGR_NO_RESOURCE_FACTORY_FOR_KIND);
return NULL;
}
assert(it->first == crKind);
assert(EXISTS(it->second));
return getResource(crKey, *(it->second), errorInfo);
}
/**
* Register a stream handler dll filename for a given URI scheme.
* A URI scheme may be registered only once in an application.
*/
util::Filename const * ResourceManager::registerStreamHandlerForURIScheme(TCHAR const * uriScheme,
TCHAR const * dllFilename) {
std::string uriSchemeStr(uriScheme);
TyURIStreamHandlers::iterator ite;
ite = iv_streamhandlers.find(uriSchemeStr);
if (ite != iv_streamhandlers.end() ) {
ErrorMessage errMsg = ErrorMessage(UIMA_MSG_ID_EXC_SCHEMEHANDLER_DUPLICATE);
errMsg.addParam(dllFilename);
errMsg.addParam(uriScheme);
UIMA_EXC_THROW_NEW(SofaDataStreamException,
UIMA_ERR_SOFADATASTREAM,
errMsg,
UIMA_MSG_ID_EXCON_SOFADATASTREAM,
ErrorInfo::unrecoverable);
}
util::Filename * pDllFile = new util::Filename(dllFilename);
if (pDllFile == NULL) {
ErrorMessage errMsg = ErrorMessage(UIMA_MSG_ID_EXC_SCHEMEHANDLER_LOAD);
errMsg.addParam(dllFilename);
errMsg.addParam(uriScheme);
UIMA_EXC_THROW_NEW(SofaDataStreamException,
UIMA_ERR_SOFADATASTREAM,
errMsg,
UIMA_MSG_ID_EXCON_SOFADATASTREAM,
ErrorInfo::unrecoverable);
}
iv_streamhandlers.insert(TyURIStreamHandlers::value_type(uriSchemeStr, pDllFile));
return(util::Filename*)pDllFile;
}
/**
* Return the dll file registered for the specified uri scheme if found.
* Otherwise, returns null.
*/
util::Filename const * ResourceManager::getStreamHandlerForURIScheme(std::string uriScheme) {
TyURIStreamHandlers::iterator ite = iv_streamhandlers.find(uriScheme);
if (ite == iv_streamhandlers.end() ) {
return NULL;
} else {
return(util::Filename *) ite->second;
}
}
/* ----------------------------------------------------------------------- */
/* Static implementation */
/* ----------------------------------------------------------------------- */
/* static */ ResourceManager & ResourceManager::createInstance(const TCHAR * cpszInstance, const TCHAR * cpszProductPrefix)
/* ----------------------------------------------------------------------- */
{
// acquire mutex
if (NOTEXISTS(cv_pclSingletonInstance)) {
// First must initialize apr (re-init is OK)
apr_status_t rv = apr_initialize();
if (rv != APR_SUCCESS) {
char errBuf[256];
apr_strerror(rv, errBuf, sizeof(errBuf));
UIMA_EXC_THROW_NEW(AprFailureException,
UIMA_ERR_APR_FAILURE,
ErrorMessage(UIMA_MSG_ID_EXC_APR_ERROR,errBuf),
ErrorMessage(UIMA_MSG_ID_EXCON_APR_FUNCTION,"apr_initialize"),
ErrorInfo::unrecoverable);
}
cv_pclSingletonInstance = new ResourceManager(cpszInstance, cpszProductPrefix);
assert(EXISTS(cv_pclSingletonInstance));
// Initialize the ICU
UErrorCode status = U_ZERO_ERROR;
u_init(&status);
if (status != U_ZERO_ERROR) {
char buffer[100];
sprintf(buffer, "ICU init failed with %d", status);
UIMA_EXC_THROW_NEW(Uima_runtime_error,
UIMA_MSG_ID_LITERAL_STRING,
UIMA_MSG_ID_LITERAL_STRING,
ErrorMessage(UIMA_MSG_ID_LITERAL_STRING, buffer),
ErrorInfo::unrecoverable);
}
try {
// initialize XML4C stuff
XMLPlatformUtils::Initialize();
} catch (XMLException& ) {
cv_pclSingletonInstance->iv_utLastErrorId = UIMA_ERR_RESMGR_COULD_NOT_INITIALIZE_XML4C;
assertWithMsg(false, "XML4C initialization failed");
}
//create the fileLogger if UIMACPP_LOGFILE env variable is set
/* determine log file name */
string str = UIMA_ENVVAR_LOG_FILE;
util::EnvironmentVariableQueryOnly clEnvVarLogFilePath(str.c_str());
UIMA_TPRINT(_TEXT("querying envvar: ") << str.c_str());
if (clEnvVarLogFilePath.hasValue()) {
const TCHAR * cpszLogFile = clEnvVarLogFilePath.getValue();
UIMA_TPRINT(_TEXT("value: ") << cpszLogFile);
/* create an instance of FileLogger and register it. */
cv_pclSingletonInstance->iv_fileLogger = new FileLogger(cpszLogFile);
if (cv_pclSingletonInstance->iv_fileLogger == NULL) { //Need to handle this better
//cerr << "Could not open the log file " << cpszLogFile << endl;
str = "Could not create FileLogger";
str += cpszLogFile;
UIMA_EXC_THROW_NEW(Uima_runtime_error,
UIMA_MSG_ID_LITERAL_STRING,
UIMA_MSG_ID_LITERAL_STRING,
ErrorMessage(UIMA_MSG_ID_LITERAL_STRING, str.c_str()),
ErrorInfo::unrecoverable);
} else {
cv_pclSingletonInstance->registerLogger(cv_pclSingletonInstance->iv_fileLogger);
}
}
//instantiate framework logger
cv_pclSingletonInstance->iv_frameworkLogger = new LogFacility(UnicodeString("org.apache.uima.cpp"), cv_pclSingletonInstance->iv_logLevel);
cv_pclSingletonInstance->iv_frameworkLogger->logMessage("ResourceManager Instance created.");
} // release mutex
UIMA_TPRINT("ResourceManager instance created");
return(*cv_pclSingletonInstance);
}
/* static */ ResourceManager & ResourceManager::getInstance(void)
/* ----------------------------------------------------------------------- */
{
assert(EXISTS(cv_pclSingletonInstance));
return(*cv_pclSingletonInstance);
}
/* static */ bool ResourceManager::hasInstance(void)
/* ----------------------------------------------------------------------- */
{
return((bool) EXISTS(cv_pclSingletonInstance));
}
/* ----------------------------------------------------------------------- */
void ResourceManager::deleteInstance(void) {
UIMA_TPRINT(_TEXT("deleting..."));
// acquire mutex
if (cv_pclSingletonInstance != 0 ) {
try {
XMLPlatformUtils::Terminate();
}
catch (const XMLException& ) {
cv_pclSingletonInstance->iv_utLastErrorId = UIMA_ERR_RESMGR_COULD_NOT_TERMINATE_XML4C;
assertWithMsg(false, "XML4C termination failed");
}
if (cv_pclSingletonInstance->iv_frameworkLogger != NULL) {
delete cv_pclSingletonInstance->iv_frameworkLogger;
}
if (cv_pclSingletonInstance->iv_fileLogger != NULL) {
delete cv_pclSingletonInstance->iv_fileLogger;
}
assert(EXISTS(cv_pclSingletonInstance));
delete cv_pclSingletonInstance;
cv_pclSingletonInstance = 0;
// Terminate apr (undo matching apr_initialize)
apr_terminate();
//#if !defined( NDEBUG ) && defined(_MSC_VER) && defined(_CRTDBG_MAP_ALLOC)
// int iRetVal = _CrtDumpMemoryLeaks();
//#endif
UIMA_TPRINT("ResMgr instance deleted");
}
assert( cv_pclSingletonInstance == 0 );
// release mutex
}
bool
ResourceManager::createFilenameForLanguage(Language & rclLanguage,
const TCHAR * cpszExtension,
bool bUseAlternateTerritories,
const util::Location & crclDirToUse,
util::Filename & rclFilename) {
string str(rclLanguage.asString());
assert(EXISTS(cpszExtension));
assert(*cpszExtension == _TEXT('.')); /* extension starts with a dot */
/* we need to restrict ourselves to DOS 8+3 filenames */
if (str.length() > UIMA_MAX_VALID_FILENAME_SIZE) {
str.resize(UIMA_MAX_VALID_FILENAME_SIZE);
}
/* create a filename based on the complete language name
e.g. language is en-us and file is en-us.tsw */
util::Filename clFilename(crclDirToUse, str.c_str(), cpszExtension);
UIMA_TPRINT(_TEXT("1st Filename: '") << clFilename.getAsCString() << _TEXT("' existent: ") << clFilename.isExistent());
if (clFilename.isExistent()) {
rclFilename = clFilename;
return(true); /* done! */
} else {
/* if the user did specify a territory, we could look a little bit further... */
if (rclLanguage.hasTerritory()) {
/* give it another try using just the language name without the territory
e.g. language is en-us and file is en.tsw */
clFilename.setNew( crclDirToUse,rclLanguage.getLanguageCode(),cpszExtension );
UIMA_TPRINT(_TEXT("2nd Filename: '") << clFilename.getAsCString() << _TEXT("' existent: ") << clFilename.isExistent());
}
}
if (bUseAlternateTerritories && !clFilename.isExistent()) {
/* give it another try using just the language name without the territory
e.g. language is en and file is en-us.tsw
this means a little bit more effort - we need to walk the directory */
util::DirectoryWalk clDirWalk(crclDirToUse.getAsCString());
string strSearchPattern(rclLanguage.getLanguageCode());
strSearchPattern += _TEXT("*");
strSearchPattern += cpszExtension;
UIMA_TPRINT(_TEXT("Search pattern: '") << strSearchPattern.c_str() << _TEXT("'"));
while (clDirWalk.isValid()) {
if (clDirWalk.isFile() && clDirWalk.matchesWildcardPattern(strSearchPattern.c_str())) {
clFilename.setNewName(clDirWalk.getNameWithoutPath());
break;
}
clDirWalk.setToNext();
}
UIMA_TPRINT(_TEXT("3rd Filename: '") << clFilename.getAsCString() << _TEXT("' existent: ") << clFilename.isExistent());
}
rclFilename = clFilename;
return(clFilename.isExistent());
}
LogFacility & ResourceManager::getLogger() {
return *iv_frameworkLogger;
}
icu::UnicodeString ResourceManager::resolveFilename(icu::UnicodeString const & filename, icu::UnicodeString const & lastFilename) {
auto_array<char> filename_cstr( new char[filename.length() + 1] );
filename.extract(0, filename.length(), filename_cstr.get());
auto_array<char> lastFilename_cstr( new char[lastFilename.length() + 1] );
lastFilename.extract(0, lastFilename.length(), lastFilename_cstr.get());
//build the filename
util::Filename fileLoc(filename_cstr.get());
// don't try our search mimic for absolute paths
if (fileLoc.isAbsolute()) {
return filename;
}
// relative path to the current directory
if (fileLoc.isExistent()) {
return filename;
}
// try in the same directory as lastFilename
util::Filename locSameDirAsLast(lastFilename_cstr.get());
locSameDirAsLast.setNewName(filename_cstr.get());
if (locSameDirAsLast.isExistent()) {
return locSameDirAsLast.getAsCString();
}
// try in the UIMACPP data directory
util::Location const & fallbackLoc = ResourceManager::getInstance().getLocationData();
std::string nameInDataDir( fallbackLoc.getAsCString() );
nameInDataDir += filename_cstr.get();
util::Filename fileInDataDir( nameInDataDir.c_str() );
fileInDataDir.normalizeAbsolute(); // Normalize to native / or \ separators
if (fileInDataDir.isExistent()) {
return icu::UnicodeString(fileInDataDir.getAsCString());
}
nameInDataDir.clear();
nameInDataDir = fallbackLoc.getAsCString();
nameInDataDir += "descriptors/";
nameInDataDir += filename_cstr.get();
fileInDataDir.setNew(nameInDataDir.c_str());
fileInDataDir.normalizeAbsolute();
if (fileInDataDir.isExistent()) {
return icu::UnicodeString(fileInDataDir.getAsCString());
}
nameInDataDir.clear();
nameInDataDir = fallbackLoc.getAsCString();
nameInDataDir += "specifiers/";
nameInDataDir += filename_cstr.get();
fileInDataDir.setNew(nameInDataDir.c_str());
fileInDataDir.normalizeAbsolute();
if (fileInDataDir.isExistent()) {
return icu::UnicodeString(fileInDataDir.getAsCString());
}
// return the original filename here, will trigger an XML exception since
// it couldn't be found anywhere
return filename;
}
}
/* <EOF> */