GME  13
ICUMsgLoader.cpp
Go to the documentation of this file.
00001 /*
00002  * Licensed to the Apache Software Foundation (ASF) under one or more
00003  * contributor license agreements.  See the NOTICE file distributed with
00004  * this work for additional information regarding copyright ownership.
00005  * The ASF licenses this file to You under the Apache License, Version 2.0
00006  * (the "License"); you may not use this file except in compliance with
00007  * the License.  You may obtain a copy of the License at
00008  *
00009  *      http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 /*
00019  * $Id: ICUMsgLoader.cpp 883612 2009-11-24 07:24:53Z borisk $
00020  */
00021 
00022 
00023 // ---------------------------------------------------------------------------
00024 //  Includes
00025 // ---------------------------------------------------------------------------
00026 #include <xercesc/util/XercesDefs.hpp>
00027 #include <xercesc/util/PlatformUtils.hpp>
00028 #include <xercesc/util/XMLMsgLoader.hpp>
00029 #include <xercesc/util/XMLString.hpp>
00030 #include <xercesc/util/XMLUniDefs.hpp>
00031 #include <xercesc/util/Janitor.hpp>
00032 #include "ICUMsgLoader.hpp"
00033 #include "unicode/putil.h"
00034 #include "unicode/uloc.h"
00035 #include "unicode/udata.h"
00036 
00037 #include "string.h"
00038 #include <stdio.h>
00039 #include <stdlib.h>
00040 
00041 XERCES_CPP_NAMESPACE_BEGIN
00042 
00043 // ---------------------------------------------------------------------------
00044 //  Local static methods
00045 // ---------------------------------------------------------------------------
00046 
00047 /*
00048  *  Resource Data Reference.
00049  *
00050  *  The data is packaged as a dll (or .so or whatever, depending on the platform) that exports a data symbol.
00051  *  The application (this *.cpp) references that symbol here, and will pass the data address to ICU, which
00052  *  will then  be able to fetch resources from the data.
00053  */
00054 #define ENTRY_POINT xercesc_messages_3_1_dat
00055 #define BUNDLE_NAME "xercesc_messages_3_1"
00056 
00057 extern "C" void U_IMPORT *ENTRY_POINT;
00058 
00059 /*
00060  *  Tell ICU where our resource data is located in memory. The data lives in the xercesc_nessages dll, and we just
00061  *  pass the address of an exported symbol from that library to ICU.
00062  */
00063 static bool setAppDataOK = false;
00064 
00065 static void setAppData()
00066 {
00067     static bool setAppDataDone = false;
00068 
00069     if (setAppDataDone)
00070     {
00071         return;
00072     }
00073     else
00074     {
00075         setAppDataDone = true;
00076         UErrorCode err = U_ZERO_ERROR;
00077         udata_setAppData(BUNDLE_NAME, &ENTRY_POINT, &err);
00078         if (U_SUCCESS(err))
00079         {
00080             setAppDataOK = true;
00081         }
00082     }
00083 
00084 }
00085 
00086 // ---------------------------------------------------------------------------
00087 //  Public Constructors and Destructor
00088 // ---------------------------------------------------------------------------
00089 ICUMsgLoader::ICUMsgLoader(const XMLCh* const  msgDomain)
00090 :fLocaleBundle(0)
00091 ,fDomainBundle(0)
00092 {
00093     /***
00094             Validate msgDomain
00095     ***/
00096     if (!XMLString::equals(msgDomain, XMLUni::fgXMLErrDomain)    &&
00097         !XMLString::equals(msgDomain, XMLUni::fgExceptDomain)    &&
00098         !XMLString::equals(msgDomain, XMLUni::fgXMLDOMMsgDomain) &&
00099         !XMLString::equals(msgDomain, XMLUni::fgValidityDomain)   )
00100     {
00101         XMLPlatformUtils::panic(PanicHandler::Panic_UnknownMsgDomain);
00102     }
00103 
00104     /***
00105         Resolve domainName
00106     ***/
00107     int     index = XMLString::lastIndexOf(msgDomain, chForwardSlash);
00108     char*   domainName = XMLString::transcode(&(msgDomain[index + 1]), XMLPlatformUtils::fgMemoryManager);
00109     ArrayJanitor<char> jan1(domainName, XMLPlatformUtils::fgMemoryManager);
00110 
00111     /***
00112         Location resolution priority
00113 
00114          1. XMLMsgLoader::getNLSHome(), set by user through
00115             XMLPlatformUtils::Initialize(), which provides user-specified
00116             location where the message loader shall retrieve error messages.
00117 
00118          2. environment var: XERCESC_NLS_HOME
00119 
00120          3. path $XERCESCROOT/msg
00121     ***/
00122 
00123     char locationBuf[1024];
00124     memset(locationBuf, 0, sizeof locationBuf);
00125     const char *nlsHome = XMLMsgLoader::getNLSHome();
00126 
00127     if (nlsHome)
00128     {
00129         strcpy(locationBuf, nlsHome);
00130         strcat(locationBuf, U_FILE_SEP_STRING);
00131     }
00132     else
00133     {
00134         nlsHome = getenv("XERCESC_NLS_HOME");
00135         if (nlsHome)
00136         {
00137             strcpy(locationBuf, nlsHome);
00138             strcat(locationBuf, U_FILE_SEP_STRING);
00139         }
00140         else
00141         {
00142             nlsHome = getenv("XERCESCROOT");
00143             if (nlsHome)
00144             {
00145                 strcpy(locationBuf, nlsHome);
00146                 strcat(locationBuf, U_FILE_SEP_STRING);
00147                 strcat(locationBuf, "msg");
00148                 strcat(locationBuf, U_FILE_SEP_STRING);
00149             }
00150             else
00151             {
00152                 /***
00153                  leave it to ICU to decide where to search
00154                  for the error message.
00155                  ***/
00156                  setAppData();
00157             }
00158         }
00159     }
00160 
00161     /***
00162         Open the locale-specific resource bundle
00163     ***/
00164     strcat(locationBuf, BUNDLE_NAME);
00165     UErrorCode err = U_ZERO_ERROR;
00166     uloc_setDefault("root", &err);   // in case user-specified locale unavailable
00167     err = U_ZERO_ERROR;
00168     fLocaleBundle = ures_open(locationBuf, XMLMsgLoader::getLocale(), &err);
00169     if (!U_SUCCESS(err) || fLocaleBundle == NULL)
00170     {
00171         /***
00172            in case user specified location does not work
00173            try the dll
00174         ***/
00175 
00176         if (strcmp(locationBuf, BUNDLE_NAME) !=0 )
00177         {
00178             setAppData();
00179             err = U_ZERO_ERROR;
00180             fLocaleBundle = ures_open(BUNDLE_NAME, XMLMsgLoader::getLocale(), &err);
00181             if (!U_SUCCESS(err) || fLocaleBundle == NULL)
00182             {
00183                  XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain);
00184             }
00185         }
00186         else
00187         {
00188             XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain);
00189         }
00190     }
00191 
00192     /***
00193         Open the domain specific resource bundle within
00194         the locale-specific resource bundle
00195     ***/
00196     err = U_ZERO_ERROR;
00197     fDomainBundle = ures_getByKey(fLocaleBundle, domainName, NULL, &err);
00198     if (!U_SUCCESS(err) || fDomainBundle == NULL)
00199     {
00200         XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain);
00201     }
00202 }
00203 
00204 ICUMsgLoader::~ICUMsgLoader()
00205 {
00206     ures_close(fDomainBundle);
00207     ures_close(fLocaleBundle);
00208 }
00209 
00210 
00211 // ---------------------------------------------------------------------------
00212 //  Implementation of the virtual message loader API
00213 // ---------------------------------------------------------------------------
00214 bool ICUMsgLoader::loadMsg( const   XMLMsgLoader::XMLMsgId  msgToLoad
00215                           ,         XMLCh* const            toFill
00216                           , const   XMLSize_t               maxChars)
00217 {
00218     UErrorCode   err = U_ZERO_ERROR;
00219     int32_t      strLen = 0;
00220 
00221     // Assuming array format
00222     const UChar *name = ures_getStringByIndex(fDomainBundle, (int32_t)msgToLoad-1, &strLen, &err);
00223 
00224     if (!U_SUCCESS(err) || (name == NULL))
00225     {
00226         return false;
00227     }
00228 
00229     int retStrLen = strLen > (int32_t)maxChars ? maxChars : strLen;
00230 
00231     if (sizeof(UChar)==sizeof(XMLCh))
00232     {
00233         XMLString::moveChars(toFill, (XMLCh*)name, retStrLen);
00234         toFill[retStrLen] = (XMLCh) 0;
00235     }
00236     else
00237     {
00238         XMLCh* retStr = toFill;
00239         const UChar *srcPtr = name;
00240 
00241         while (retStrLen--)
00242            *retStr++ = *srcPtr++;
00243 
00244         *retStr = 0;
00245     }
00246 
00247     return true;
00248 }
00249 
00250 
00251 bool ICUMsgLoader::loadMsg( const   XMLMsgLoader::XMLMsgId  msgToLoad
00252                             ,       XMLCh* const            toFill
00253                             , const XMLSize_t               maxChars
00254                             , const XMLCh* const            repText1
00255                             , const XMLCh* const            repText2
00256                             , const XMLCh* const            repText3
00257                             , const XMLCh* const            repText4
00258                             , MemoryManager* const          manager   )
00259 {
00260     // Call the other version to load up the message
00261     if (!loadMsg(msgToLoad, toFill, maxChars))
00262         return false;
00263 
00264     // And do the token replacement
00265     XMLString::replaceTokens(toFill, maxChars, repText1, repText2, repText3, repText4, manager);
00266     return true;
00267 }
00268 
00269 
00270 bool ICUMsgLoader::loadMsg( const   XMLMsgLoader::XMLMsgId  msgToLoad
00271                             ,       XMLCh* const            toFill
00272                             , const XMLSize_t               maxChars
00273                             , const char* const             repText1
00274                             , const char* const             repText2
00275                             , const char* const             repText3
00276                             , const char* const             repText4
00277                             , MemoryManager * const         manager)
00278 {
00279     //
00280     //  Transcode the provided parameters and call the other version,
00281     //  which will do the replacement work.
00282     //
00283     XMLCh* tmp1 = 0;
00284     XMLCh* tmp2 = 0;
00285     XMLCh* tmp3 = 0;
00286     XMLCh* tmp4 = 0;
00287 
00288     bool bRet = false;
00289     if (repText1)
00290         tmp1 = XMLString::transcode(repText1, manager);
00291     if (repText2)
00292         tmp2 = XMLString::transcode(repText2, manager);
00293     if (repText3)
00294         tmp3 = XMLString::transcode(repText3, manager);
00295     if (repText4)
00296         tmp4 = XMLString::transcode(repText4, manager);
00297 
00298     bRet = loadMsg(msgToLoad, toFill, maxChars, tmp1, tmp2, tmp3, tmp4, manager);
00299 
00300     if (tmp1)
00301         manager->deallocate(tmp1);//delete [] tmp1;
00302     if (tmp2)
00303         manager->deallocate(tmp2);//delete [] tmp2;
00304     if (tmp3)
00305         manager->deallocate(tmp3);//delete [] tmp3;
00306     if (tmp4)
00307         manager->deallocate(tmp4);//delete [] tmp4;
00308 
00309     return bRet;
00310 }
00311 
00312 XERCES_CPP_NAMESPACE_END