source: icXML/icXML-devel/src/xercesc/util/MsgLoaders/ICU/ICUMsgLoader.cpp @ 2722

Last change on this file since 2722 was 2722, checked in by cameron, 6 years ago

Original Xerces files with import mods for icxercesc

File size: 9.6 KB
Line 
1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *      http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18/*
19 * $Id: ICUMsgLoader.cpp 883612 2009-11-24 07:24:53Z borisk $
20 */
21
22
23// ---------------------------------------------------------------------------
24//  Includes
25// ---------------------------------------------------------------------------
26#include <xercesc/util/XercesDefs.hpp>
27#include <icxercesc/util/PlatformUtils.hpp>
28#include <xercesc/util/XMLMsgLoader.hpp>
29#include <icxercesc/util/XMLString.hpp>
30#include <xercesc/util/XMLUniDefs.hpp>
31#include <xercesc/util/Janitor.hpp>
32#include "ICUMsgLoader.hpp"
33#include "unicode/putil.h"
34#include "unicode/uloc.h"
35#include "unicode/udata.h"
36
37#include "string.h"
38#include <stdio.h>
39#include <stdlib.h>
40
41XERCES_CPP_NAMESPACE_BEGIN
42
43// ---------------------------------------------------------------------------
44//  Local static methods
45// ---------------------------------------------------------------------------
46
47/*
48 *  Resource Data Reference.
49 *
50 *  The data is packaged as a dll (or .so or whatever, depending on the platform) that exports a data symbol.
51 *  The application (this *.cpp) references that symbol here, and will pass the data address to ICU, which
52 *  will then  be able to fetch resources from the data.
53 */
54#define ENTRY_POINT xercesc_messages_3_1_dat
55#define BUNDLE_NAME "xercesc_messages_3_1"
56
57extern "C" void U_IMPORT *ENTRY_POINT;
58
59/*
60 *  Tell ICU where our resource data is located in memory. The data lives in the xercesc_nessages dll, and we just
61 *  pass the address of an exported symbol from that library to ICU.
62 */
63static bool setAppDataOK = false;
64
65static void setAppData()
66{
67    static bool setAppDataDone = false;
68
69    if (setAppDataDone)
70    {
71        return;
72    }
73    else
74    {
75        setAppDataDone = true;
76        UErrorCode err = U_ZERO_ERROR;
77        udata_setAppData(BUNDLE_NAME, &ENTRY_POINT, &err);
78        if (U_SUCCESS(err))
79        {
80            setAppDataOK = true;
81        }
82    }
83
84}
85
86// ---------------------------------------------------------------------------
87//  Public Constructors and Destructor
88// ---------------------------------------------------------------------------
89ICUMsgLoader::ICUMsgLoader(const XMLCh* const  msgDomain)
90:fLocaleBundle(0)
91,fDomainBundle(0)
92{
93    /***
94            Validate msgDomain
95    ***/
96    if (!XMLString::equals(msgDomain, XMLUni::fgXMLErrDomain)    &&
97        !XMLString::equals(msgDomain, XMLUni::fgExceptDomain)    &&
98        !XMLString::equals(msgDomain, XMLUni::fgXMLDOMMsgDomain) &&
99        !XMLString::equals(msgDomain, XMLUni::fgValidityDomain)   )
100    {
101        XMLPlatformUtils::panic(PanicHandler::Panic_UnknownMsgDomain);
102    }
103
104    /***
105        Resolve domainName
106    ***/
107    int     index = XMLString::lastIndexOf(msgDomain, chForwardSlash);
108    char*   domainName = XMLString::transcode(&(msgDomain[index + 1]), XMLPlatformUtils::fgMemoryManager);
109    ArrayJanitor<char> jan1(domainName, XMLPlatformUtils::fgMemoryManager);
110
111    /***
112        Location resolution priority
113
114         1. XMLMsgLoader::getNLSHome(), set by user through
115            XMLPlatformUtils::Initialize(), which provides user-specified
116            location where the message loader shall retrieve error messages.
117
118         2. environment var: XERCESC_NLS_HOME
119
120         3. path $XERCESCROOT/msg
121    ***/
122
123    char locationBuf[1024];
124    memset(locationBuf, 0, sizeof locationBuf);
125    const char *nlsHome = XMLMsgLoader::getNLSHome();
126
127    if (nlsHome)
128    {
129        strcpy(locationBuf, nlsHome);
130        strcat(locationBuf, U_FILE_SEP_STRING);
131    }
132    else
133    {
134        nlsHome = getenv("XERCESC_NLS_HOME");
135        if (nlsHome)
136        {
137            strcpy(locationBuf, nlsHome);
138            strcat(locationBuf, U_FILE_SEP_STRING);
139        }
140        else
141        {
142            nlsHome = getenv("XERCESCROOT");
143            if (nlsHome)
144            {
145                strcpy(locationBuf, nlsHome);
146                strcat(locationBuf, U_FILE_SEP_STRING);
147                strcat(locationBuf, "msg");
148                strcat(locationBuf, U_FILE_SEP_STRING);
149            }
150            else
151            {
152                /***
153                 leave it to ICU to decide where to search
154                 for the error message.
155                 ***/
156                 setAppData();
157            }
158        }
159    }
160
161    /***
162        Open the locale-specific resource bundle
163    ***/
164    strcat(locationBuf, BUNDLE_NAME);
165    UErrorCode err = U_ZERO_ERROR;
166    uloc_setDefault("root", &err);   // in case user-specified locale unavailable
167    err = U_ZERO_ERROR;
168    fLocaleBundle = ures_open(locationBuf, XMLMsgLoader::getLocale(), &err);
169    if (!U_SUCCESS(err) || fLocaleBundle == NULL)
170    {
171        /***
172           in case user specified location does not work
173           try the dll
174        ***/
175
176        if (strcmp(locationBuf, BUNDLE_NAME) !=0 )
177        {
178            setAppData();
179            err = U_ZERO_ERROR;
180            fLocaleBundle = ures_open(BUNDLE_NAME, XMLMsgLoader::getLocale(), &err);
181            if (!U_SUCCESS(err) || fLocaleBundle == NULL)
182            {
183                 XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain);
184            }
185        }
186        else
187        {
188            XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain);
189        }
190    }
191
192    /***
193        Open the domain specific resource bundle within
194        the locale-specific resource bundle
195    ***/
196    err = U_ZERO_ERROR;
197    fDomainBundle = ures_getByKey(fLocaleBundle, domainName, NULL, &err);
198    if (!U_SUCCESS(err) || fDomainBundle == NULL)
199    {
200        XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain);
201    }
202}
203
204ICUMsgLoader::~ICUMsgLoader()
205{
206    ures_close(fDomainBundle);
207    ures_close(fLocaleBundle);
208}
209
210
211// ---------------------------------------------------------------------------
212//  Implementation of the virtual message loader API
213// ---------------------------------------------------------------------------
214bool ICUMsgLoader::loadMsg( const   XMLMsgLoader::XMLMsgId  msgToLoad
215                          ,         XMLCh* const            toFill
216                          , const   XMLSize_t               maxChars)
217{
218    UErrorCode   err = U_ZERO_ERROR;
219    int32_t      strLen = 0;
220
221    // Assuming array format
222    const UChar *name = ures_getStringByIndex(fDomainBundle, (int32_t)msgToLoad-1, &strLen, &err);
223
224    if (!U_SUCCESS(err) || (name == NULL))
225    {
226        return false;
227    }
228
229    int retStrLen = strLen > (int32_t)maxChars ? maxChars : strLen;
230
231    if (sizeof(UChar)==sizeof(XMLCh))
232    {
233        XMLString::moveChars(toFill, (XMLCh*)name, retStrLen);
234        toFill[retStrLen] = (XMLCh) 0;
235    }
236    else
237    {
238        XMLCh* retStr = toFill;
239        const UChar *srcPtr = name;
240
241        while (retStrLen--)
242           *retStr++ = *srcPtr++;
243
244        *retStr = 0;
245    }
246
247    return true;
248}
249
250
251bool ICUMsgLoader::loadMsg( const   XMLMsgLoader::XMLMsgId  msgToLoad
252                            ,       XMLCh* const            toFill
253                            , const XMLSize_t               maxChars
254                            , const XMLCh* const            repText1
255                            , const XMLCh* const            repText2
256                            , const XMLCh* const            repText3
257                            , const XMLCh* const            repText4
258                            , MemoryManager* const          manager   )
259{
260    // Call the other version to load up the message
261    if (!loadMsg(msgToLoad, toFill, maxChars))
262        return false;
263
264    // And do the token replacement
265    XMLString::replaceTokens(toFill, maxChars, repText1, repText2, repText3, repText4, manager);
266    return true;
267}
268
269
270bool ICUMsgLoader::loadMsg( const   XMLMsgLoader::XMLMsgId  msgToLoad
271                            ,       XMLCh* const            toFill
272                            , const XMLSize_t               maxChars
273                            , const char* const             repText1
274                            , const char* const             repText2
275                            , const char* const             repText3
276                            , const char* const             repText4
277                            , MemoryManager * const         manager)
278{
279    //
280    //  Transcode the provided parameters and call the other version,
281    //  which will do the replacement work.
282    //
283    XMLCh* tmp1 = 0;
284    XMLCh* tmp2 = 0;
285    XMLCh* tmp3 = 0;
286    XMLCh* tmp4 = 0;
287
288    bool bRet = false;
289    if (repText1)
290        tmp1 = XMLString::transcode(repText1, manager);
291    if (repText2)
292        tmp2 = XMLString::transcode(repText2, manager);
293    if (repText3)
294        tmp3 = XMLString::transcode(repText3, manager);
295    if (repText4)
296        tmp4 = XMLString::transcode(repText4, manager);
297
298    bRet = loadMsg(msgToLoad, toFill, maxChars, tmp1, tmp2, tmp3, tmp4, manager);
299
300    if (tmp1)
301        manager->deallocate(tmp1);//delete [] tmp1;
302    if (tmp2)
303        manager->deallocate(tmp2);//delete [] tmp2;
304    if (tmp3)
305        manager->deallocate(tmp3);//delete [] tmp3;
306    if (tmp4)
307        manager->deallocate(tmp4);//delete [] tmp4;
308
309    return bRet;
310}
311
312XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.