1 karl 1.42 //%2006////////////////////////////////////////////////////////////////////////
|
2 humberto 1.4 //
|
3 karl 1.18 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
|
6 karl 1.9 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.18 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
|
9 karl 1.23 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 karl 1.42 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
|
13 humberto 1.4 //
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
15 // of this software and associated documentation files (the "Software"), to
16 // deal in the Software without restriction, including without limitation the
17 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
18 // sell copies of the Software, and to permit persons to whom the Software is
19 // furnished to do so, subject to the following conditions:
|
20 karl 1.42 //
|
21 humberto 1.4 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
22 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
23 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
24 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
25 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 //==============================================================================
|
31 chip 1.27 //
|
32 humberto 1.4 // Author: Humberto Rivero (hurivero@us.ibm.com)
33 //
|
34 joyce.j 1.34 // Modified By: Josephine Eskaline Joyce, IBM (jojustin@in.ibm.com) for Bug#3032
|
35 kumpf 1.38 // Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
|
36 chip 1.27 //
|
37 humberto 1.4 //%/////////////////////////////////////////////////////////////////////////////
38
39 #include <Pegasus/Common/MessageLoader.h>
40 #include <Pegasus/Common/Thread.h>
41 #include <Pegasus/Common/Tracer.h>
|
42 david 1.15 #include <Pegasus/Common/Constants.h>
|
43 yi.zhou 1.30 #include <Pegasus/Common/CommonUTF.h>
|
44 joyce.j 1.34 #include <Pegasus/Common/FileSystem.h>
|
45 kumpf 1.38 #include <Pegasus/Common/LanguageParser.h>
|
46 humberto 1.6 #include <iostream>
47 #ifdef PEGASUS_OS_OS400
|
48 mike 1.44 #include "EBCDIC_OS400.h"
|
49 humberto 1.6 #endif
|
50 chip 1.27 PEGASUS_NAMESPACE_BEGIN
|
51 humberto 1.6 PEGASUS_USING_STD;
|
52 humberto 1.4
53 static const int ID_INVALID = -1;
54 static const String server_resbundl_name = "pegasus/pegasusServer";
|
55 kumpf 1.40 String MessageLoader::pegasus_MSG_HOME;
|
56 humberto 1.4 Boolean MessageLoader::_useProcessLocale = false;
57 Boolean MessageLoader::_useDefaultMsg = false;
|
58 kumpf 1.40 AcceptLanguageList MessageLoader::_acceptlanguages;
|
59 humberto 1.4
60 String MessageLoader::getMessage(MessageLoaderParms &parms){
61 PEG_METHOD_ENTER(TRC_L10N, "MessageLoader::getMessage");
|
62 humberto 1.8 try{
|
63 yi.zhou 1.30 parms.contentlanguages.clear();
64
65 #if defined (PEGASUS_HAS_MESSAGES) && defined (PEGASUS_HAS_ICU)
66 if (InitializeICU::initICUSuccessful())
67 {
68 String msg = loadICUMessage(parms);
69
70 if (msg.size() > 0)
71 {
72 PEG_METHOD_EXIT();
73 return (msg);
74 }
75 }
76
77 #endif
78 // NOTE: the default message is returned if:
79 // Message loading is DIABLED or
80 // A non-ICU message loading function is called that has
81 // non-ICU process locale discovery code and non-ICU
82 // message loading or
83 // InitializeICU::initICUSuccessful() is failed or
84 yi.zhou 1.30 // Did not get a message from ICU
|
85 chip 1.27
|
86 kumpf 1.25 PEG_METHOD_EXIT();
|
87 humberto 1.4 return formatDefaultMessage(parms);
|
88 chip 1.27
|
89 kumpf 1.10 }catch(Exception&){
|
90 kumpf 1.25 PEG_METHOD_EXIT();
|
91 chip 1.27 return String("AN INTERNAL ERROR OCCURED IN MESSAGELOADER: ").append(parms.default_msg);
|
92 carson.hovey 1.24 }
|
93 humberto 1.4 }
|
94 chip 1.27
|
95 chuck 1.22 #ifdef PEGASUS_HAS_ICU
|
96 chip 1.27
|
97 humberto 1.4 String MessageLoader::loadICUMessage(MessageLoaderParms &parms){
|
98 chip 1.27
|
99 humberto 1.4 PEG_METHOD_ENTER(TRC_L10N, "MessageLoader::loadICUMessage");
100 String msg;
101 UResourceBundle* resbundl;
102 UErrorCode status = U_ZERO_ERROR;
|
103 chip 1.27 //String resbundl_path_ICU;
|
104 humberto 1.4 CString resbundl_path_ICU;
|
105 chip 1.27
|
106 david 1.36 const int size_locale_ICU = 50;
107
|
108 humberto 1.4 // the static AcceptLangauges takes precedence over what parms.acceptlangauges has
|
109 kumpf 1.40 AcceptLanguageList acceptlanguages;
|
110 humberto 1.4 acceptlanguages = (_acceptlanguages.size() > 0) ? _acceptlanguages : parms.acceptlanguages;
|
111 chip 1.27
|
112 humberto 1.4 // get the correct path to the resource bundles
|
113 humberto 1.6 resbundl_path_ICU = getQualifiedMsgPath(parms.msg_src_path).getCString();
|
114 chuck 1.13
115 // if someone has set the global behaviour to use default messages
116 // Note: this must be after the call to getQualifiedMsgPath
|
117 kumpf 1.25 if (_useDefaultMsg)
118 {
119 PEG_METHOD_EXIT();
|
120 chip 1.27 return formatDefaultMessage(parms);
|
121 kumpf 1.25 }
|
122 chuck 1.13
|
123 humberto 1.6 //cout << "USING PACKAGE PATH: " << endl;
124 //cout << resbundl_path_ICU << endl;
|
125 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, "Using resource bundle path:");
126 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, resbundl_path_ICU);
|
127 chuck 1.22 #ifdef PEGASUS_OS_OS400
|
128 humberto 1.6 const char *atoe = resbundl_path_ICU;
129 AtoE((char*)atoe);
|
130 chuck 1.22 #endif
|
131 chip 1.27
132
133
|
134 humberto 1.4 if(_useProcessLocale || (acceptlanguages.size() == 0 && parms.useProcessLocale)){ // use the system default resource bundle
|
135 chip 1.27
136 resbundl = ures_open((const char*)resbundl_path_ICU, uloc_getDefault() , &status);
137
|
138 humberto 1.4 if(U_SUCCESS(status)) {
139 //cout << "PROCESS_LOCALE: opened resource bundle" << endl;
|
140 humberto 1.17 UErrorCode _status = U_ZERO_ERROR;
141 //cout << "PROCESS_LOCALE = " << ures_getLocale(resbundl, &_status) << endl;
142 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, "Using process locale:");
143 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, ures_getLocale(resbundl, &_status));
|
144 humberto 1.4 if(status == U_USING_FALLBACK_WARNING || status == U_USING_DEFAULT_WARNING){
|
145 chip 1.27 //cout << "PROCESS_LOCALE: using fallback or default" << endl;
|
146 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, "Using process locale fallback or default");
|
147 humberto 1.4 }
148 msg = extractICUMessage(resbundl,parms);
|
149 humberto 1.6
|
150 david 1.36 const char * _locale = ures_getLocale(resbundl,&status);
|
151 chuck 1.22 #ifdef PEGASUS_OS_OS400
|
152 david 1.36 char tmplcl[size_locale_ICU];
153 strcpy(tmplcl, _locale);
154 EtoA(tmplcl);
155 String localeStr(tmplcl);
156 #else
157 String localeStr(_locale);
|
158 chuck 1.22 #endif
|
159 kumpf 1.41 parms.contentlanguages.append(LanguageTag(
|
160 kumpf 1.43 LanguageParser::convertLocaleIdToLanguageTag(localeStr)));
|
161 chip 1.27 ures_close(resbundl);
|
162 humberto 1.4 } else {
163 //cout << "PROCESS_LOCALE: could not open resouce, formatting default message" << endl;
|
164 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, "Using process locale. Could not open resource, formatting default message.");
|
165 humberto 1.4 msg = formatDefaultMessage(parms);
166 }
|
167 kumpf 1.25 PEG_METHOD_EXIT();
|
168 humberto 1.4 return msg;
|
169 kumpf 1.40 } else if (acceptlanguages.size() == 0 && parms.useThreadLocale){ // get AcceptLanguageList from the current Thread
170 AcceptLanguageList *al = Thread::getLanguages();
|
171 chip 1.27 if(al != NULL){
|
172 humberto 1.4 acceptlanguages = *al;
|
173 chip 1.27 //cout << "THREAD_LOCALE: got acceptlanguages from thread" << endl;
|
174 kumpf 1.40 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, "Using thread locale: got AcceptLanguageList from thread.");
|
175 chip 1.27 }else {
|
176 humberto 1.4 //cout << "THREAD_LOCALE: thread returned NULL for acceptlanguages" << endl;
|
177 kumpf 1.40 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, "Using thread locale: thread returned NULL for AcceptLanguageList.");
|
178 chip 1.27 }
|
179 humberto 1.4 }
|
180 chip 1.27
|
181 david 1.36
|
182 humberto 1.4 char locale_ICU[size_locale_ICU];
|
183 kumpf 1.39 LanguageTag languageTag;
|
184 chip 1.27
|
185 kumpf 1.40 // iterate through AcceptLanguageList, use the first resource bundle match
|
186 humberto 1.4 //cout << "LOOPING THROUGH ACCEPTLANGUAGES..." << endl;
|
187 kumpf 1.40 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, "Looping through AcceptLanguageList...");
|
188 kumpf 1.38 for (Uint32 index = 0; index < acceptlanguages.size(); index++)
189 {
|
190 kumpf 1.39 languageTag = acceptlanguages.getLanguageTag(index);
|
191 chuck 1.22 #ifdef PEGASUS_OS_OS400
|
192 kumpf 1.38 CString cstr = languageTag.toString().getCString();
|
193 humberto 1.6 const char *atoe = cstr;
194 AtoE((char*)atoe);
|
195 david 1.36
196 uloc_getName(atoe, locale_ICU, size_locale_ICU, &status);
|
197 chuck 1.22 #else
|
198 kumpf 1.38 uloc_getName((const char*)(languageTag.toString()).getCString(), locale_ICU, size_locale_ICU, &status);
|
199 chuck 1.22 #endif
|
200 chip 1.27 //cout << "locale_ICU = " << locale_ICU << endl;
|
201 humberto 1.4 // TODO: check to see if we have previously cached the resource bundle
|
202 chip 1.27
|
203 humberto 1.4 resbundl = ures_open((const char*)resbundl_path_ICU, locale_ICU, &status);
|
204 chip 1.27
|
205 humberto 1.4 if(U_SUCCESS(status)) {
|
206 kumpf 1.38 //cout << "ACCEPTLANGUAGES LOOP: opened resource bundle with " << languageTag.toString() << endl;
|
207 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, "ACCEPTLANGUAGES LOOP: opened resource bundle with:");
|
208 kumpf 1.38 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, languageTag.toString());
|
209 humberto 1.4 if(status == U_USING_FALLBACK_WARNING || status == U_USING_DEFAULT_WARNING){
210 //we want to use the ICU fallback behaviour in the following cases ONLY
211 //cout << "ACCEPTLANGUAGES LOOP: ICU warns using FALLBACK or DEFAULT" << endl;
|
212 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,"ACCEPTLANGUAGES LOOP: ICU warns using FALLBACK or DEFAULT");
|
213 humberto 1.12 if((acceptlanguages.size() == 1) && (!parms.useICUfallback) && (status == U_USING_DEFAULT_WARNING)){
214 // in this case we want to return messages from the root bundle
215 status = U_ZERO_ERROR;
216 //cout << "ML::acceptlang.size =1 && !parms.useICUfallback && U_USING_DEFAULT_WARNING" << endl;
|
217 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,"acceptlang.size =1 && !parms.useICUfallback && U_USING_DEFAULT_WARNING, using root bundle.");
|
218 chuck 1.22
219 // Reopen the bundle in the root locale
220 ures_close(resbundl);
221 resbundl = ures_open((const char*)resbundl_path_ICU, "", &status);
222 if(U_SUCCESS(status)) {
223 msg = extractICUMessage(resbundl,parms);
224 ures_close(resbundl);
225 break;
226 }
|
227 humberto 1.12 }
228 else if(acceptlanguages.size() == 1 || parms.useICUfallback){
|
229 humberto 1.4 //cout << "ACCEPTLANGUAGES LOOP: acceptlanguages.size == 1 or useICUfallback true, using ICU fallback behaviour..." << endl;
|
230 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,"ACCEPTLANGUAGES LOOP: acceptlanguages.size == 1 or useICUfallback true, using ICU fallback behaviour...");
|
231 humberto 1.6 msg = extractICUMessage(resbundl,parms);
|
232 david 1.36 const char * _locale = ures_getLocale(resbundl,&status);
233
|
234 chuck 1.22 #ifdef PEGASUS_OS_OS400
|
235 david 1.36 char tmplcl[size_locale_ICU];
236 strcpy(tmplcl, _locale);
237 EtoA(tmplcl);
238 String localeStr(tmplcl);
239 #else
240 String localeStr(_locale);
|
241 chuck 1.22 #endif
|
242 kumpf 1.41
243 parms.contentlanguages.append(LanguageTag(
|
244 kumpf 1.43 LanguageParser::convertLocaleIdToLanguageTag(
245 localeStr)));
|
246 humberto 1.4 ures_close(resbundl);
247 break;
|
248 chip 1.27 }
|
249 humberto 1.4 }
|
250 chip 1.27 else{ // we found an exact resource bundle match, extract, and set ContentLanguage
|
251 humberto 1.4 //cout << "ACCEPTLANGUAGES LOOP: found an EXACT resource bundle MATCH" << endl;
|
252 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,"ACCEPTLANGUAGES LOOP: found an EXACT resource bundle MATCH:");
|
253 kumpf 1.38 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,languageTag.toString());
|
254 humberto 1.4 msg = extractICUMessage(resbundl,parms);
|
255 kumpf 1.38 parms.contentlanguages.append(LanguageTag(languageTag.toString()));
|
256 chip 1.27 ures_close(resbundl);
|
257 humberto 1.4 break;
|
258 chip 1.27 }
|
259 humberto 1.4 } else { // possible errors, ex: message path incorrect
260 // for now do nothing, let the while loop continue
|
261 kumpf 1.38 //cout << "ACCEPTLANGUAGES LOOP: could NOT open a resource for: " << languageTag.toString() << endl;
|
262 humberto 1.4 }
263 status = U_ZERO_ERROR; // reset status
264 }
|
265 chuck 1.22
|
266 humberto 1.2 // now if we DIDNT get a message, we want to enable ICU fallback for the highest priority language
|
267 humberto 1.4 if(msg.size() == 0 && acceptlanguages.size() > 0){
|
268 humberto 1.3 //cout << "USING ICU FALLBACK" << endl;
|
269 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,"No message was loaded, using ICU fallback behaviour.");
|
270 kumpf 1.38 languageTag = acceptlanguages.getLanguageTag(0);
|
271 humberto 1.6
|
272 chuck 1.22 #ifdef PEGASUS_OS_OS400
|
273 kumpf 1.38 CString cstr = languageTag.toString().getCString();
|
274 humberto 1.6 const char *atoe = cstr;
275 AtoE((char*)atoe);
|
276 david 1.36
277 uloc_getName(atoe, locale_ICU, size_locale_ICU, &status);
|
278 chuck 1.22 #else
|
279 kumpf 1.38 uloc_getName((const char*)(languageTag.toString()).getCString(), locale_ICU, size_locale_ICU, &status);
|
280 chuck 1.22 #endif
|
281 humberto 1.3 //cout << "locale_ICU in fallback = " << locale_ICU << endl;
|
282 humberto 1.6 status = U_ZERO_ERROR;
|
283 humberto 1.4 resbundl = ures_open((const char*)resbundl_path_ICU, locale_ICU, &status);
|
284 david 1.36 const char * _locale = NULL;
|
285 humberto 1.6 if(U_SUCCESS(status)) {
286 if(status == U_USING_DEFAULT_WARNING){
|
287 kumpf 1.38 //cout << "PRIORITY ICU FALLBACK: using default resource bundle with " << languageTag.toString() << endl;
|
288 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,"PRIORITY ICU FALLBACK: using default resource bundle with ");
|
289 kumpf 1.38 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, languageTag.toString());
|
290 humberto 1.6 status = U_ZERO_ERROR;
|
291 chuck 1.22
292 // Reopen the bundle in the root locale
293 ures_close(resbundl);
|
294 humberto 1.6 resbundl = ures_open((const char*)resbundl_path_ICU, "", &status);
295 if(U_SUCCESS(status)) {
296 msg = extractICUMessage(resbundl,parms);
|
297 david 1.36 _locale = ures_getLocale(resbundl,&status);
|
298 humberto 1.6 }
299 }else{
300 msg = extractICUMessage(resbundl,parms);
|
301 david 1.36 _locale = ures_getLocale(resbundl,&status);
|
302 humberto 1.6 }
|
303 david 1.36 String localeStr;
304
305 if (_locale != NULL)
306 {
|
307 chuck 1.22 #ifdef PEGASUS_OS_OS400
|
308 david 1.36 char tmplcl[size_locale_ICU];
309 strcpy(tmplcl, _locale);
310 EtoA(tmplcl);
311 localeStr.assign(tmplcl);
312 #else
313 localeStr.assign(_locale);
314 #endif
315 }
316 if(localeStr != "root")
|
317 kumpf 1.41 {
318 parms.contentlanguages.append(LanguageTag(
|
319 kumpf 1.43 LanguageParser::convertLocaleIdToLanguageTag(
320 localeStr)));
|
321 kumpf 1.41 }
|
322 david 1.36 ures_close(resbundl);
|
323 humberto 1.5 }
|
324 humberto 1.2 }
|
325 chuck 1.22
|
326 humberto 1.6 if(msg.size() == 0){ // else if no message, load message from root bundle explicitly
|
327 humberto 1.4 //cout << "EXHAUSTED ACCEPTLANGUAGES: using root bundle to extract message" << endl;
|
328 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,"EXHAUSTED ACCEPTLANGUAGES: using root bundle to extract message");
|
329 chip 1.27 status = U_ZERO_ERROR;
|
330 humberto 1.4 resbundl = ures_open((const char*)resbundl_path_ICU, "", &status);
331 if(U_SUCCESS(status)){
332 //cout << "EXHAUSTED ACCEPTLANGUAGES: opened root resource bundle" << endl;
|
333 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,"EXHAUSTED ACCEPTLANGUAGES: opened root resource bundle");
|
334 humberto 1.4 msg = extractICUMessage(resbundl,parms);
|
335 chuck 1.22 ures_close(resbundl);
|
336 chip 1.27 }else {
337 //cout << "EXHAUSTED ACCEPTLANGUAGES: could NOT open root resource bundle" << endl;
|
338 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,"EXHAUSTED ACCEPTLANGUAGES: could NOT open root resource bundle");
|
339 humberto 1.4 }
340
341 }
342 PEG_METHOD_EXIT();
|
343 chip 1.27 return msg;
|
344 humberto 1.4 }
|
345 chip 1.27
|
346 humberto 1.4 String MessageLoader::extractICUMessage(UResourceBundle * resbundl, MessageLoaderParms &parms){
|
347 chip 1.27 UErrorCode status = U_ZERO_ERROR;
|
348 humberto 1.4 int32_t msgLen = 0;
|
349 humberto 1.6
|
350 chuck 1.22 #ifdef PEGASUS_OS_OS400
|
351 humberto 1.6 CString cstr = parms.msg_id.getCString();
352 const char *atoe = cstr;
353 AtoE((char*)atoe);
354 const UChar *msg = ures_getStringByKey(resbundl, (const char*)atoe, &msgLen, &status);
|
355 chuck 1.22 #else
|
356 humberto 1.4 const UChar *msg = ures_getStringByKey(resbundl, (const char*)parms.msg_id.getCString(), &msgLen, &status);
|
357 chuck 1.22 #endif
|
358 chip 1.27 if(U_FAILURE(status)) {
|
359 humberto 1.4 //cout << "could not extract ICU Message" << endl;
360 return String::EMPTY;
|
361 chip 1.27 }
|
362 humberto 1.4
363 return formatICUMessage(resbundl, msg, msgLen, parms);
364 }
|
365 chip 1.27
|
366 humberto 1.4 String MessageLoader::uChar2String(UChar * uchar_str){
367 return String((const Char16 *)uchar_str);
|
368 chip 1.27 }
369
|
370 humberto 1.4 String MessageLoader::uChar2String(UChar * uchar_str, int len){
371 return String((const Char16 *)uchar_str, len);
372 }
|
373 chip 1.27
|
374 humberto 1.4 String MessageLoader::formatICUMessage(UResourceBundle * resbundl, const UChar * msg, int msg_len, MessageLoaderParms &parms){
|
375 chip 1.27
|
376 humberto 1.4 // format the message
377 UnicodeString msg_pattern(msg, msg_len);
378 UnicodeString msg_formatted;
379 UErrorCode status = U_ZERO_ERROR;
380 const int arg_count = 10;
|
381 vijay.eli 1.31 const char *locale;
|
382 humberto 1.4 if(resbundl == NULL)
383 locale = ULOC_US;
384 else
|
385 vijay.eli 1.32 locale = ures_getLocale(resbundl, &status);
|
386 chip 1.27
|
387 humberto 1.4 //cout << "FORMAT ICU MESSAGE: using locale = " << locale << endl;
|
388 chip 1.27
389 char lang[4];
|
390 humberto 1.4 char cc[4];
391 char var[arg_count];
392 uloc_getLanguage(locale, lang, 4, &status);
393 uloc_getCountry(locale, cc, 4, &status);
394 uloc_getVariant(locale, var, 10, &status);
395 Locale localeID(lang,cc,var);
|
396 chip 1.27
|
397 humberto 1.4 status = U_ZERO_ERROR;
398 MessageFormat formatter(msg_pattern, localeID, status);
|
399 chuck 1.21
|
400 humberto 1.4 Formattable args[arg_count];
|
401 chuck 1.21
402 if (parms.arg0._type != Formatter::Arg::VOIDT)
403 xferFormattable(parms.arg0, args[0]);
404 if (parms.arg1._type != Formatter::Arg::VOIDT)
405 xferFormattable(parms.arg1, args[1]);
406 if (parms.arg2._type != Formatter::Arg::VOIDT)
407 xferFormattable(parms.arg2, args[2]);
408 if (parms.arg3._type != Formatter::Arg::VOIDT)
409 xferFormattable(parms.arg3, args[3]);
410 if (parms.arg4._type != Formatter::Arg::VOIDT)
411 xferFormattable(parms.arg4, args[4]);
412 if (parms.arg5._type != Formatter::Arg::VOIDT)
413 xferFormattable(parms.arg5, args[5]);
414 if (parms.arg6._type != Formatter::Arg::VOIDT)
415 xferFormattable(parms.arg6, args[6]);
416 if (parms.arg7._type != Formatter::Arg::VOIDT)
417 xferFormattable(parms.arg7, args[7]);
418 if (parms.arg8._type != Formatter::Arg::VOIDT)
419 xferFormattable(parms.arg8, args[8]);
420 if (parms.arg9._type != Formatter::Arg::VOIDT)
421 xferFormattable(parms.arg9, args[9]);
422 chuck 1.21
|
423 humberto 1.4 Formattable args_obj(args,arg_count);
424 status = U_ZERO_ERROR;
425 msg_formatted = formatter.format(args_obj, msg_formatted, status);
|
426 chip 1.27
|
427 humberto 1.4 return uChar2String(const_cast<UChar *>(msg_formatted.getBuffer()), msg_formatted.length());
|
428 chip 1.27 }
429
|
430 chuck 1.21 void MessageLoader::xferFormattable(Formatter::Arg& arg, Formattable &formattable)
431 {
432 //cout << "arg" << " = " << arg.toString() << endl;
433 switch (arg._type)
|
434 humberto 1.4 {
|
435 chuck 1.33 case Formatter::Arg::INTEGER:
436 formattable = (int32_t)arg._integer;
437 break;
438 case Formatter::Arg::UINTEGER:
439 // Note: the ICU Formattable class doesn't support
440 // unsigned 32. Cast to signed 64.
441 formattable = (int64_t)arg._uinteger;
442 break;
443 case Formatter::Arg::BOOLEAN:
444 // Note: the ICU formattable class doesn't support
445 // boolean. Turn it into a string.
446 if (!arg._boolean)
447 formattable = Formattable("false");
448 else
449 formattable = Formattable("true");
450 break;
451 case Formatter::Arg::REAL:
452 formattable = (double)arg._real;
453 break;
454 case Formatter::Arg::LINTEGER:
455 // Note: this uses a Formattable constructor that is
456 chuck 1.33 // labelled ICU 2.8 draft. Assumes that Pegasus uses
457 // at least ICU 2.8.
458 formattable = (int64_t)arg._lInteger;
459 break;
460 case Formatter::Arg::ULINTEGER:
461 // Note: the ICU Formattable class doesn't support
462 // unsigned 64. If the number is too big for signed 64
463 // then turn it into a string. This string will
464 // not be formatted for the locale, but at least the number
465 // will appear in the message.
466 if (arg._lUInteger > PEGASUS_UINT64_LITERAL(0x7FFFFFFFFFFFFFFF))
467 {
468 char buffer[32]; // Should need 21 chars max
469 sprintf(buffer, "%" PEGASUS_64BIT_CONVERSION_WIDTH "u", arg._lUInteger);
470 formattable = Formattable(buffer);
471 }
472 else
473 {
474 formattable = (int64_t)arg._lUInteger;
475 }
476 break;
477 chuck 1.33 case Formatter::Arg::STRING:
478 formattable = Formattable((UChar*)arg._string.getChar16Data());
479 break;
|
480 chip 1.27 case Formatter::Arg::VOIDT:
481 default:
|
482 chuck 1.21 formattable = "";
483 break;
|
484 chip 1.27 }
|
485 chuck 1.21 }
486
|
487 chuck 1.22 #endif
|
488 chip 1.27
|
489 humberto 1.4 String MessageLoader::formatDefaultMessage(MessageLoaderParms &parms){
|
490 chip 1.27
|
491 humberto 1.4 PEG_METHOD_ENTER(TRC_L10N, "MessageLoader::formatDefaultMessage");
492 // NOTE TO PROGRAMMERS: using native substitution functions
493 // ie. calling Formatter::format()
|
494 chip 1.27 // can result in incorrect locale handling of substitutions
495
|
496 humberto 1.4 // locale INSENSITIVE formatting code
497 //cout << "using locale INSENSITIVE formatting" << endl;
498 parms.contentlanguages.clear(); // this could have previously been set by ICU
499 //cout << parms.toString() << endl;
500 //cout << "ml:" << parms.default_msg << endl;
|
501 kumpf 1.25 PEG_METHOD_EXIT();
|
502 humberto 1.4 return Formatter::format(parms.default_msg,
503 parms.arg0,
504 parms.arg1,
|
505 chip 1.27 parms.arg2,
|
506 humberto 1.4 parms.arg3,
507 parms.arg4,
508 parms.arg5,
509 parms.arg6,
510 parms.arg7,
511 parms.arg8,
512 parms.arg9);
|
513 chip 1.27
|
514 carson.hovey 1.24
|
515 humberto 1.4 }
|
516 chip 1.27
|
517 humberto 1.4 String MessageLoader::getQualifiedMsgPath(String path){
|
518 kumpf 1.25 PEG_METHOD_ENTER(TRC_L10N, "MessageLoader::getQualifiedMsgPath");
|
519 chip 1.27
|
520 humberto 1.4 if(pegasus_MSG_HOME.size() == 0)
|
521 joyce.j 1.34 initPegasusMsgHome(String::EMPTY);
|
522 chip 1.27
523 if(path.size() == 0)
|
524 kumpf 1.25 {
525 PEG_METHOD_EXIT();
|
526 humberto 1.4 return pegasus_MSG_HOME + server_resbundl_name;
|
527 kumpf 1.25 }
|
528 chip 1.27
|
529 humberto 1.4 Char16 delim = '/'; // NOTE TO PROGRAMMERS: WINDOWS and non-UNIX platforms should redefine delim here
530 Uint32 i;
531 if(( i = path.find(delim)) != PEG_NOT_FOUND && i == 0){ // fully qualified package name
|
532 kumpf 1.25 PEG_METHOD_EXIT();
|
533 humberto 1.4 return path;
534 }
|
535 chip 1.27
|
536 kumpf 1.25 PEG_METHOD_EXIT();
|
537 humberto 1.4 return pegasus_MSG_HOME + path; // relative path and package name
|
538 carson.hovey 1.24
|
539 humberto 1.4 }
|
540 chip 1.27
|
541 humberto 1.4 void MessageLoader::setPegasusMsgHome(String home){
542 PEG_METHOD_ENTER(TRC_L10N, "MessageLoader::setPegasusMsgHome");
543 //cout << "MessageLoader::setPegasusMsgHome()" << endl;
544 pegasus_MSG_HOME = home + "/";
|
545 humberto 1.6 // TODO: remove the next call once test cases are compatible with ICU messages
546 checkDefaultMsgLoading();
|
547 humberto 1.4 PEG_METHOD_EXIT();
|
548 chip 1.27 }
|
549 joyce.j 1.34 void MessageLoader::setPegasusMsgHomeRelative(const String& argv0)
550 {
551 #ifdef PEGASUS_HAS_MESSAGES
552 try
553 {
554 String startingDir, pathDir;
555
556 #ifdef PEGASUS_OS_TYPE_WINDOWS
557 if(PEG_NOT_FOUND == argv0.find('\\'))
558 {
559 char exeDir[_MAX_PATH];
560 HMODULE module = GetModuleHandle(NULL);
561 if(NULL != module )
562 {
563 DWORD filename = GetModuleFileName(module,exeDir ,sizeof(exeDir));
564 if(0 != filename)
565 {
566 String path(exeDir);
567 Uint32 command = path.reverseFind('\\');
568 startingDir = path.subString(0, command+1);
569 }
570 joyce.j 1.34 }
571 }
572 else
573 {
574 Uint32 command = argv0.reverseFind('\\');
575 startingDir = argv0.subString(0, command+1);
576 }
577 #endif
578
579 #ifdef PEGASUS_OS_TYPE_UNIX
580 if(PEG_NOT_FOUND != argv0.find('/'))
581 {
582 Uint32 command = argv0.reverseFind('/');
583 startingDir = argv0.subString(0, command+1);
584 }
585 else
586 {
587 if(FileSystem::existsNoCase(argv0))
588 {
589 FileSystem::getCurrentDirectory(startingDir);
590 startingDir.append("/");
591 joyce.j 1.34 }
592 else
593 {
594 String path;
595 #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
596 #pragma convert(37)
597 const char* env = getenv("PATH");
598 if(env != NULL)
599 EtoA((char*)env);
600 #pragma convert(0)
601 #else
602 const char* env = getenv("PATH");
603 #endif
604 if (env != NULL)
605 path.assign(env);
606 String pathDelim = FileSystem::getPathDelimiter();
607 Uint32 size = path.size();
608 while(path.size() > 0)
609 {
610 try
611 {
612 joyce.j 1.34 Uint32 delim = path.find(pathDelim);
613 if(delim != PEG_NOT_FOUND)
614 {
615 pathDir = path.subString(0,delim);
616 path.remove(0,(delim+1));
617 }
618 else
619 {
620 pathDir = path;
621 path = "";
622 }
623 String commandPath = pathDir.append('/');
624 commandPath = commandPath.append(argv0) ;
625 Boolean dirContent = FileSystem::existsNoCase(commandPath);
626 if(dirContent)
627 {
628 startingDir = pathDir;
629 break;
630 }
631 }
632 catch(Exception &e)
633 joyce.j 1.34 {
634 //Have to do nothing.
635 //Catching the exception if there is any exception while searching in the path variable
636 }
637 }
638 }
639 }
640 #endif
641 initPegasusMsgHome(startingDir);
642 }
643 catch(Exception &e)
644 {
645 //Have to do nothing.
646 //Catching the exception if there is any exception while searching in the path variable
647 }
648 #endif
649 }
650
651
652 void MessageLoader::initPegasusMsgHome(const String & startDir)
653 {
654 joyce.j 1.34 String startingDir = startDir;
655 if (startingDir.size() == 0)
656 {
|
657 david 1.15 #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
658 #pragma convert(37)
|
659 joyce.j 1.34 const char* env = getenv("PEGASUS_MSG_HOME");
660 if(env != NULL)
661 EtoA((char*)env);
|
662 david 1.15 #pragma convert(0)
663 #else
|
664 joyce.j 1.34 const char* env = getenv("PEGASUS_MSG_HOME");
|
665 david 1.15 #endif
|
666 joyce.j 1.34
667 if (env != NULL)
668 startingDir.assign(env);
669 }
670
|
671 david 1.15 #ifdef PEGASUS_DEFAULT_MESSAGE_SOURCE
|
672 joyce.j 1.34 if(System::is_absolute_path(
673 (const char *)PEGASUS_DEFAULT_MESSAGE_SOURCE))
674 {
675 pegasus_MSG_HOME = PEGASUS_DEFAULT_MESSAGE_SOURCE;
676 pegasus_MSG_HOME.append('/');
677 }
678 else
679 {
680 if (startingDir.size() != 0)
681 {
682 pegasus_MSG_HOME = startingDir;
683 pegasus_MSG_HOME.append('/');
684 }
685 pegasus_MSG_HOME.append(PEGASUS_DEFAULT_MESSAGE_SOURCE);
686 pegasus_MSG_HOME.append('/');
687 }
|
688 david 1.15 #else
|
689 joyce.j 1.34 if (startingDir.size() != 0)
690 {
691 pegasus_MSG_HOME = startingDir;
692 pegasus_MSG_HOME.append("/");
693 }
694 else
695 {
696 // Will use current working directory
697 }
|
698 chip 1.27 #endif
|
699 joyce.j 1.34 checkDefaultMsgLoading();
700 }
|
701 chip 1.27
|
702 humberto 1.6 void MessageLoader::checkDefaultMsgLoading(){
|
703 chuck 1.13 // Note: this function is a special hook for the automated tests (poststarttests)
704 // Since the automated tests expect the old hardcoded default messages, an env var
705 // will be used to tell this code to ignore ICU and return the default message.
706 // This will allow poststarttests to run with ICU installed.
707 // TODO: remove this function once test cases are compatible with ICU messages
|
708 chuck 1.14 #ifdef PEGASUS_OS_OS400
709 #pragma convert(37)
710 #endif
|
711 chuck 1.13 const char* env = getenv("PEGASUS_USE_DEFAULT_MESSAGES");
|
712 chuck 1.14 #ifdef PEGASUS_OS_OS400
|
713 chip 1.27 #pragma convert(0)
714 #endif
|
715 chuck 1.13 if (env != NULL)
|
716 chip 1.27 _useDefaultMsg = true;
|
717 humberto 1.4 }
718
|
719 karl 1.20 MessageLoaderParms::MessageLoaderParms()
720 {
721 useProcessLocale = false;
722 useThreadLocale = true;
|
723 chip 1.27
|
724 chuck 1.22 #ifdef PEGASUS_HAS_ICU
|
725 karl 1.20 useICUfallback = false;
|
726 chuck 1.22 #endif
|
727 chip 1.27
|
728 kumpf 1.40 acceptlanguages = AcceptLanguageList();
729 contentlanguages = ContentLanguageList();
|
730 karl 1.20 }
731
|
732 chip 1.27 MessageLoaderParms::MessageLoaderParms(
733 const String& id,
734 const String& msg,
|
735 mike 1.37 const Formatter::Arg& arg0_,
736 const Formatter::Arg& arg1_,
737 const Formatter::Arg& arg2_,
738 const Formatter::Arg& arg3_,
739 const Formatter::Arg& arg4_,
740 const Formatter::Arg& arg5_,
741 const Formatter::Arg& arg6_,
742 const Formatter::Arg& arg7_,
743 const Formatter::Arg& arg8_,
744 const Formatter::Arg& arg9_)
|
745 karl 1.20 {
746 msg_id = id;
747 default_msg = msg;
748 _init();
|
749 mike 1.37 arg0 = arg0_;
750 arg1 = arg1_;
751 arg2 = arg2_;
752 arg3 = arg3_;
753 arg4 = arg4_;
754 arg5 = arg5_;
755 arg6 = arg6_;
756 arg7 = arg7_;
757 arg8 = arg8_;
758 arg9 = arg9_;
|
759 chip 1.27 }
|
760 karl 1.20
|
761 chip 1.27 MessageLoaderParms::MessageLoaderParms(
762 const String& id,
|
763 karl 1.20 const String& msg)
764 {
765 msg_id = id;
766 default_msg = msg;
767 _init();
768 }
769
|
770 chip 1.27 MessageLoaderParms::MessageLoaderParms(
771 const String& id,
772 const String& msg,
|
773 mike 1.37 const Formatter::Arg& arg0_)
|
774 karl 1.20 {
775 msg_id = id;
776 default_msg = msg;
777 _init();
|
778 mike 1.37 arg0 = arg0_;
|
779 karl 1.20 }
780
|
781 chip 1.27 MessageLoaderParms::MessageLoaderParms(
782 const String& id,
783 const String& msg,
|
784 mike 1.37 const Formatter::Arg& arg0_,
785 const Formatter::Arg& arg1_)
|
786 karl 1.20 {
787 msg_id = id;
788 default_msg = msg;
789 _init();
|
790 mike 1.37 arg0 = arg0_;
791 arg1 = arg1_;
|
792 karl 1.20 }
793
|
794 chip 1.27 MessageLoaderParms::MessageLoaderParms(
795 const String& id,
796 const String& msg,
|
797 mike 1.37 const Formatter::Arg& arg0_,
798 const Formatter::Arg& arg1_,
799 const Formatter::Arg& arg2_)
|
800 karl 1.20 {
801 msg_id = id;
802 default_msg = msg;
803 _init();
|
804 mike 1.37 arg0 = arg0_;
805 arg1 = arg1_;
806 arg2 = arg2_;
|
807 karl 1.20 }
808
|
809 chip 1.27 MessageLoaderParms::MessageLoaderParms(
810 const String& id,
811 const String& msg,
|
812 mike 1.37 const Formatter::Arg& arg0_,
813 const Formatter::Arg& arg1_,
814 const Formatter::Arg& arg2_,
815 const Formatter::Arg& arg3_)
|
816 karl 1.20 {
817 msg_id = id;
818 default_msg = msg;
819 _init();
|
820 mike 1.37 arg0 = arg0_;
821 arg1 = arg1_;
822 arg2 = arg2_;
823 arg3 = arg3_;
|
824 karl 1.20 }
825
826 MessageLoaderParms::MessageLoaderParms(
|
827 chip 1.27 const char* id,
|
828 karl 1.20 const char* msg)
829 {
830 msg_id = id;
831 default_msg = msg;
832 _init();
833 }
834
835 MessageLoaderParms::MessageLoaderParms(
|
836 chip 1.27 const char* id,
837 const char* msg,
|
838 mike 1.37 const String& arg0_)
|
839 karl 1.20 {
840 msg_id = id;
841 default_msg = msg;
842 _init();
|
843 mike 1.37 arg0 = arg0_;
|
844 karl 1.20 }
845
846 MessageLoaderParms::MessageLoaderParms(
|
847 chip 1.27 const char* id,
848 const char* msg,
|
849 mike 1.37 const String& arg0_,
850 const String& arg1_)
|
851 karl 1.20 {
852 msg_id = id;
853 default_msg = msg;
854 _init();
|
855 mike 1.37 arg0 = arg0_;
856 arg1 = arg1_;
|
857 karl 1.20 }
858
859 void MessageLoaderParms::_init()
860 {
861 useProcessLocale = false;
862 useThreadLocale = true;
|
863 chip 1.27
|
864 karl 1.20 #ifdef PEGASUS_HAS_ICU
865 useICUfallback = false;
866 #endif
|
867 chip 1.27
|
868 kumpf 1.38 acceptlanguages.clear();
869 contentlanguages.clear();
|
870 karl 1.20
|
871 mike 1.37 arg0 = Formatter::DEFAULT_ARG;
872 arg1 = Formatter::DEFAULT_ARG;
873 arg2 = Formatter::DEFAULT_ARG;
874 arg3 = Formatter::DEFAULT_ARG;
875 arg4 = Formatter::DEFAULT_ARG;
876 arg5 = Formatter::DEFAULT_ARG;
877 arg6 = Formatter::DEFAULT_ARG;
878 arg7 = Formatter::DEFAULT_ARG;
879 arg8 = Formatter::DEFAULT_ARG;
880 arg9 = Formatter::DEFAULT_ARG;
|
881 karl 1.20 }
882
883 String MessageLoaderParms::toString()
884 {
885 String s;
886 String processLoc,threadLoc,ICUfallback;
887 processLoc = (useProcessLocale) ? "true" : "false";
888 threadLoc = (useThreadLocale) ? "true" : "false";
|
889 chuck 1.22 #ifdef PEGASUS_HAS_ICU
|
890 karl 1.20 ICUfallback = (useICUfallback) ? "true" : "false";
|
891 chuck 1.22 #endif
|
892 chip 1.27
|
893 karl 1.20 s.append("msg_id = " + msg_id + "\n");
894 s.append("default_msg = " + default_msg + "\n");
895 s.append("msg_src_path = " + msg_src_path + "\n");
|
896 kumpf 1.38 s.append("acceptlanguages = " +
897 LanguageParser::buildAcceptLanguageHeader(acceptlanguages) + "\n");
898 s.append("contentlanguages = " +
899 LanguageParser::buildContentLanguageHeader(contentlanguages) + "\n");
|
900 chip 1.27
|
901 karl 1.20 s.append("useProcessLocale = " + processLoc + "\n");
902 s.append("useThreadLocale = " + threadLoc + "\n");
|
903 chuck 1.22 #ifdef PEGASUS_HAS_ICU
|
904 karl 1.20 s.append("useICUfallback = " + ICUfallback + "\n");
|
905 chuck 1.22 #endif
|
906 chip 1.27 s.append("arg0 = " + arg0.toString() + "\n" + "arg1 = " + arg1.toString() + "\n" + "arg2 = " + arg2.toString() + "\n" + "arg3 = " + arg3.toString() + "\n" +
907 "arg4 = " + arg4.toString() + "\n" + "arg5 = " + arg5.toString() + "\n" + "arg6 = " + arg6.toString() + "\n" + "arg7 = " + arg7.toString() + "\n" +
|
908 karl 1.20 "arg8 = " + arg8.toString() + "\n" + "arg9 = " + arg9.toString() + "\n\n");
|
909 chip 1.27
|
910 karl 1.20 return s;
911 }
|
912 humberto 1.4
|
913 karl 1.20 MessageLoaderParms::~MessageLoaderParms()
914 {
915 }
|
916 humberto 1.4
|
917 karl 1.20 PEGASUS_NAMESPACE_END
|