1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the  "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 
19 #if defined XALAN_ICU_MSG_LOADER
20 
21 
22 // Class header file.
23 #include "XalanICUMessageLoader.hpp"
24 
25 #include "PlatformSupportInit.hpp"
26 
27 #include "DOMStringHelper.hpp"
28 
29 #include "unicode/uloc.h"
30 
31 #include "unicode/udata.h"
32 
33 #include <xercesc/util/XMLMsgLoader.hpp>
34 
35 #include <xercesc/util/XMLString.hpp>
36 
37 #include "xalanc/Include/XalanVersion.hpp"
38 
39 #if defined(XALAN_WINDOWS)
40 #define XALAN_MESSAGES_NAME XalanMessages
41 #else
42 #define XALAN_MESSAGES_NAME xalanMsg
43 #endif
44 
45 #define XALAN_MESSAGES_NAME_W_UNDERSCORE INVK_CAT2_RAW_NUMERIC(XALAN_MESSAGES_NAME,_)
46 
47 #define MAKE_STRING(a) #a
48 #define INVK_MAKE_STRING(a) MAKE_STRING(a)
49 
50 #if defined(XALAN_WINDOWS)
51 
52 #if _MSC_VER >= 1400
53 
54 #define ENTRY_POINT_SUFFIX _dat
55 #define PACKAGE_NAME_SUFFIX
56 
57 #else
58 #ifdef  NDEBUG_SYMBOLS // release with symbols
59 
60 #define ENTRY_POINT_SUFFIX S_dat
61 #define PACKAGE_NAME_SUFFIX S
62 
63 #elif NDEBUG // release
64 
65 #define ENTRY_POINT_SUFFIX _dat
66 #define PACKAGE_NAME_SUFFIX
67 
68 #elif _DEBUG // debug only
69 
70 #define ENTRY_POINT_SUFFIX D_dat
71 #define PACKAGE_NAME_SUFFIX D
72 
73 #endif // NDEBUG_SYMBOLS
74 #endif // _MSC_VER >= 1400
75 
76 #define PACKAGE_NAME INVK_CAT3_RAW_NUMERIC(XALAN_MESSAGES_NAME_W_UNDERSCORE,\
77                                     INVK_CAT2_RAW_NUMERIC_SEP_UNDERSCORE(XALAN_VERSION_MAJOR,XALAN_VERSION_MINOR),\
78                                     PACKAGE_NAME_SUFFIX)
79 
80 #define ICUDLL_ENTRYPOINT_NAME INVK_CAT3_RAW_NUMERIC(XALAN_MESSAGES_NAME_W_UNDERSCORE,\
81                                     INVK_CAT2_RAW_NUMERIC_SEP_UNDERSCORE(XALAN_VERSION_MAJOR,XALAN_VERSION_MINOR),\
82                                     ENTRY_POINT_SUFFIX)
83 
84 #else // NON-WINDOWS systems
85 
86 #define ICUDLL_ENTRYPOINT_NAME INVK_CAT2_RAW_NUMERIC(XALAN_MESSAGES_NAME_W_UNDERSCORE,dat)
87 
88 #define PACKAGE_NAME XALAN_MESSAGES_NAME
89 
90 #endif // XALAN_WINDOWS
91 
92 static const char* const    sPackageName=INVK_MAKE_STRING(PACKAGE_NAME);
93 
94 extern "C" const char U_IMPORT  ICUDLL_ENTRYPOINT_NAME [];
95 
96 
97 namespace XALAN_CPP_NAMESPACE {
98 
99 using xercesc::XMLMsgLoader;
100 
101 using xercesc::XMLString;
102 
103 
104 
105 // ---------------------------------------------------------------------------
106 //  Local static methods
107 // ---------------------------------------------------------------------------
108 
109 /*
110  *  Resource Data Reference.
111  *
112  *  The data is packaged as a dll (or .so or whatever, depending on the platform) that exports a data symbol.
113  *  The application (thic *.cpp) references that symbol here, and will pass the data address to ICU, which
114  *  will then  be able to fetch resources from the data.
115  */
116 
117 
118 static const char* domainName = INVK_MAKE_STRING(XALAN_PRODUCT);
119 
120 
121 
XalanICUMessageLoader(MemoryManager & theManager)122 XalanICUMessageLoader::XalanICUMessageLoader(MemoryManager &theManager):
123     m_localeBundle(0),
124     m_domainBundle(0),
125     m_unknownMessage("The message was not found in the ICU resource bundle.", theManager)
126 {
127     UErrorCode err = U_ZERO_ERROR;
128 
129     udata_setAppData(sPackageName, &ICUDLL_ENTRYPOINT_NAME, &err);
130 
131     if (! U_SUCCESS(err))
132     {
133         assert( 0 );
134     }
135     const char* szLocal = XMLMsgLoader::getLocale();
136     if ( szLocal == 0 )
137     {
138         // We failed to get local from Xerces, let's try our own default.
139         szLocal="en_US";
140     }
141 
142     m_localeBundle = ures_open(sPackageName, szLocal , &err);
143     if (!U_SUCCESS(err) || m_localeBundle == 0)
144     {
145         assert( 0 );
146     }
147 
148     err = U_ZERO_ERROR;
149     m_domainBundle = ures_getByKey(m_localeBundle, domainName, 0, &err);
150     if (!U_SUCCESS(err) || m_domainBundle == 0)
151     {
152         assert( 0 );
153     }
154 }
155 
156 
157 
~XalanICUMessageLoader()158 XalanICUMessageLoader::~XalanICUMessageLoader()
159 {
160     ures_close(m_domainBundle);
161     ures_close(m_localeBundle);
162 }
163 
164 
165 
loadMsg(XalanMessages::Codes msgToLoad,XalanDOMChar * toFill,XalanSize_t maxChars)166 bool XalanICUMessageLoader::loadMsg(
167             XalanMessages::Codes    msgToLoad,
168             XalanDOMChar*           toFill,
169             XalanSize_t             maxChars)
170 {
171    bool bResult = true;
172    UErrorCode   err = U_ZERO_ERROR;
173    int32_t      strLen = 0;
174 
175    // Assuming array format
176    const UChar * const  name = ures_getStringByIndex(m_domainBundle, (int32_t)msgToLoad+1, &strLen, &err);
177 
178    if (!U_SUCCESS(err) || (name == 0))
179    {
180        XalanCopy(m_unknownMessage.c_str(), m_unknownMessage.c_str() + m_unknownMessage.length() + 1, toFill);
181 
182        return false;
183    }
184 
185    const XalanSize_t    retStrLen =
186        static_cast<XalanSize_t>(strLen + 1 ) > maxChars ? maxChars : static_cast<XalanSize_t>(strLen + 1);
187 
188    XalanCopy(name, name + retStrLen, toFill);
189 
190    return bResult;
191 }
192 
193 }
194 
195 #endif // defined (XALAN_ICU_MSG_LOADER)
196 
197 
198 
199