/* * Copyright 1999-2000,2004 The Apache Software Foundation. * * Licensed 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. */ /* * $Id: ICUMsgLoader.cpp 231519 2005-08-11 21:07:26Z amassari $ */ // --------------------------------------------------------------------------- // Includes // --------------------------------------------------------------------------- #include #include #include #include #include #include #include "ICUMsgLoader.hpp" #include "unicode/putil.h" #include "unicode/uloc.h" #include "unicode/udata.h" #include "string.h" #include #include XERCES_CPP_NAMESPACE_BEGIN // --------------------------------------------------------------------------- // Local static methods // --------------------------------------------------------------------------- /* * Resource Data Reference. * * The data is packaged as a dll (or .so or whatever, depending on the platform) that exports a data symbol. * The application (thic *.cpp) references that symbol here, and will pass the data address to ICU, which * will then be able to fetch resources from the data. */ #if defined(_WIN32) || defined(WIN32) extern "C" void U_IMPORT *XercesMessages2_7_dat; #else extern "C" void U_IMPORT *XercesMessages2_7_0_dat; #endif /* * Tell ICU where our resource data is located in memory. The data lives in the XercesMessages dll, and we just * pass the address of an exported symbol from that library to ICU. */ static bool setAppDataOK = false; static void setAppData() { static bool setAppDataDone = false; if (setAppDataDone) { return; } else { setAppDataDone = true; UErrorCode err = U_ZERO_ERROR; #if defined(_WIN32) || defined(WIN32) udata_setAppData("XercesMessages2_7", &XercesMessages2_7_dat, &err); #else udata_setAppData("XercesMessages2_7_0", &XercesMessages2_7_0_dat, &err); #endif if (U_SUCCESS(err)) { setAppDataOK = true; } } } // --------------------------------------------------------------------------- // Public Constructors and Destructor // --------------------------------------------------------------------------- ICUMsgLoader::ICUMsgLoader(const XMLCh* const msgDomain) :fLocaleBundle(0) ,fDomainBundle(0) { /*** Validate msgDomain ***/ if (!XMLString::equals(msgDomain, XMLUni::fgXMLErrDomain) && !XMLString::equals(msgDomain, XMLUni::fgExceptDomain) && !XMLString::equals(msgDomain, XMLUni::fgXMLDOMMsgDomain) && !XMLString::equals(msgDomain, XMLUni::fgValidityDomain) ) { XMLPlatformUtils::panic(PanicHandler::Panic_UnknownMsgDomain); } /*** Resolve domainName ***/ int index = XMLString::lastIndexOf(msgDomain, chForwardSlash); char* domainName = XMLString::transcode(&(msgDomain[index + 1]), XMLPlatformUtils::fgMemoryManager); ArrayJanitor jan1(domainName, XMLPlatformUtils::fgMemoryManager); /*** Location resolution priority 1. XMLMsgLoader::getNLSHome(), set by user through XMLPlatformUtils::Initialize(), which provides user-specified location where the message loader shall retrieve error messages. 2. envrionment var: XERCESC_NLS_HOME 3. path $XERCESCROOT/msg ***/ char locationBuf[1024]; memset(locationBuf, 0, sizeof locationBuf); const char *nlsHome = XMLMsgLoader::getNLSHome(); if (nlsHome) { strcpy(locationBuf, nlsHome); strcat(locationBuf, U_FILE_SEP_STRING); } else { nlsHome = getenv("XERCESC_NLS_HOME"); if (nlsHome) { strcpy(locationBuf, nlsHome); strcat(locationBuf, U_FILE_SEP_STRING); } else { nlsHome = getenv("XERCESCROOT"); if (nlsHome) { strcpy(locationBuf, nlsHome); strcat(locationBuf, U_FILE_SEP_STRING); strcat(locationBuf, "msg"); strcat(locationBuf, U_FILE_SEP_STRING); } else { /*** leave it to ICU to decide where to search for the error message. ***/ setAppData(); } } } /*** Open the locale-specific resource bundle ***/ #if defined(_WIN32) || defined(WIN32) strcat(locationBuf, "XercesMessages2_7"); #else strcat(locationBuf, "XercesMessages2_7_0"); #endif UErrorCode err = U_ZERO_ERROR; uloc_setDefault("en_US", &err); // in case user-specified locale unavailable err = U_ZERO_ERROR; fLocaleBundle = ures_open(locationBuf, XMLMsgLoader::getLocale(), &err); if (!U_SUCCESS(err) || fLocaleBundle == NULL) { /*** in case user specified location does not work try the dll ***/ #if defined(_WIN32) || defined(WIN32) if (strcmp(locationBuf, "XercesMessages2_7") !=0 ) #else if (strcmp(locationBuf, "XercesMessages2_7_0") !=0 ) #endif { setAppData(); err = U_ZERO_ERROR; #if defined(_WIN32) || defined(WIN32) fLocaleBundle = ures_open("XercesMessages2_7", XMLMsgLoader::getLocale(), &err); #else fLocaleBundle = ures_open("XercesMessages2_7_0", XMLMsgLoader::getLocale(), &err); #endif if (!U_SUCCESS(err) || fLocaleBundle == NULL) { XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain); } } else { XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain); } } /*** Open the domain specific resource bundle within the locale-specific resource bundle ***/ err = U_ZERO_ERROR; fDomainBundle = ures_getByKey(fLocaleBundle, domainName, NULL, &err); if (!U_SUCCESS(err) || fDomainBundle == NULL) { XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain); } } ICUMsgLoader::~ICUMsgLoader() { ures_close(fDomainBundle); ures_close(fLocaleBundle); } // --------------------------------------------------------------------------- // Implementation of the virtual message loader API // --------------------------------------------------------------------------- bool ICUMsgLoader::loadMsg( const XMLMsgLoader::XMLMsgId msgToLoad , XMLCh* const toFill , const unsigned int maxChars) { UErrorCode err = U_ZERO_ERROR; int32_t strLen = 0; // Assuming array format const UChar *name = ures_getStringByIndex(fDomainBundle, (int32_t)msgToLoad-1, &strLen, &err); if (!U_SUCCESS(err) || (name == NULL)) { return false; } int retStrLen = strLen > (int32_t)maxChars ? maxChars : strLen; if (sizeof(UChar)==sizeof(XMLCh)) { XMLString::moveChars(toFill, (XMLCh*)name, retStrLen); toFill[retStrLen] = (XMLCh) 0; } else { XMLCh* retStr = toFill; const UChar *srcPtr = name; while (retStrLen--) *retStr++ = *srcPtr++; *retStr = 0; } return true; } bool ICUMsgLoader::loadMsg( const XMLMsgLoader::XMLMsgId msgToLoad , XMLCh* const toFill , const unsigned int maxChars , const XMLCh* const repText1 , const XMLCh* const repText2 , const XMLCh* const repText3 , const XMLCh* const repText4 , MemoryManager* const manager ) { // Call the other version to load up the message if (!loadMsg(msgToLoad, toFill, maxChars)) return false; // And do the token replacement XMLString::replaceTokens(toFill, maxChars, repText1, repText2, repText3, repText4, manager); return true; } bool ICUMsgLoader::loadMsg( const XMLMsgLoader::XMLMsgId msgToLoad , XMLCh* const toFill , const unsigned int maxChars , const char* const repText1 , const char* const repText2 , const char* const repText3 , const char* const repText4 , MemoryManager * const manager) { // // Transcode the provided parameters and call the other version, // which will do the replacement work. // XMLCh* tmp1 = 0; XMLCh* tmp2 = 0; XMLCh* tmp3 = 0; XMLCh* tmp4 = 0; bool bRet = false; if (repText1) tmp1 = XMLString::transcode(repText1, manager); if (repText2) tmp2 = XMLString::transcode(repText2, manager); if (repText3) tmp3 = XMLString::transcode(repText3, manager); if (repText4) tmp4 = XMLString::transcode(repText4, manager); bRet = loadMsg(msgToLoad, toFill, maxChars, tmp1, tmp2, tmp3, tmp4, manager); if (tmp1) manager->deallocate(tmp1);//delete [] tmp1; if (tmp2) manager->deallocate(tmp2);//delete [] tmp2; if (tmp3) manager->deallocate(tmp3);//delete [] tmp3; if (tmp4) manager->deallocate(tmp4);//delete [] tmp4; return bRet; } XERCES_CPP_NAMESPACE_END