GME
13
|
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