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 //%/////////////////////////////////////////////////////////////////////////////
33
34 #include <Pegasus/Common/MessageLoader.h>
35 #include <Pegasus/Common/Thread.h>
36 #include <Pegasus/Common/Tracer.h>
|
37 david 1.15 #include <Pegasus/Common/Constants.h>
|
38 yi.zhou 1.30 #include <Pegasus/Common/CommonUTF.h>
|
39 joyce.j 1.34 #include <Pegasus/Common/FileSystem.h>
|
40 kumpf 1.38 #include <Pegasus/Common/LanguageParser.h>
|
41 humberto 1.6 #include <iostream>
42 #ifdef PEGASUS_OS_OS400
|
43 mike 1.44 #include "EBCDIC_OS400.h"
|
44 humberto 1.6 #endif
|
45 chip 1.27 PEGASUS_NAMESPACE_BEGIN
|
46 humberto 1.6 PEGASUS_USING_STD;
|
47 humberto 1.4
48 static const int ID_INVALID = -1;
49 static const String server_resbundl_name = "pegasus/pegasusServer";
|
50 kumpf 1.40 String MessageLoader::pegasus_MSG_HOME;
|
51 humberto 1.4 Boolean MessageLoader::_useProcessLocale = false;
52 Boolean MessageLoader::_useDefaultMsg = false;
|
53 kumpf 1.40 AcceptLanguageList MessageLoader::_acceptlanguages;
|
54 humberto 1.4
|
55 kumpf 1.47 String MessageLoader::getMessage(MessageLoaderParms& parms)
|
56 dave.sudlik 1.46 {
57 PEG_METHOD_ENTER(TRC_L10N, "MessageLoader::getMessage");
58 String msg;
59
60 try
61 {
62 openMessageFile(parms);
63 msg = getMessage2(parms);
64 closeMessageFile(parms);
65 }
|
66 kumpf 1.47 catch (Exception&)
|
67 dave.sudlik 1.46 {
|
68 kumpf 1.47 msg = String("AN INTERNAL ERROR OCCURED IN MESSAGELOADER: ").append(
69 parms.default_msg);
|
70 dave.sudlik 1.46 }
71 PEG_METHOD_EXIT();
72 return msg;
73 }
74
|
75 kumpf 1.47 String MessageLoader::getMessage2(MessageLoaderParms& parms)
|
76 dave.sudlik 1.46 {
77 PEG_METHOD_ENTER(TRC_L10N, "MessageLoader::getMessage2");
78 String msg;
|
79 yi.zhou 1.30
|
80 dave.sudlik 1.46 try
81 {
|
82 yi.zhou 1.30 #if defined (PEGASUS_HAS_MESSAGES) && defined (PEGASUS_HAS_ICU)
|
83 dave.sudlik 1.46 if (!_useDefaultMsg && (parms._resbundl != NO_ICU_MAGIC))
84 {
85 msg = extractICUMessage(parms._resbundl,parms);
86 if (msg.size() > 0)
87 {
88 PEG_METHOD_EXIT();
|
89 kumpf 1.47 return msg;
|
90 dave.sudlik 1.46 }
91 }
92 #endif
93 // NOTE: the default message is returned if:
94 // 1) The previous call to openMessageFile() set _useDefaultMsg
95 // 2) parms._resbundl is set to NO_ICU_MAGIC from a previous
96 // call to openMessageFile() indicating an error
97 // (including InitializeICU::initICUSuccessful() failed)
98 // 3) Message loading is DISABLED
99 // 4) Did not get a message from ICU
100
101 msg = formatDefaultMessage(parms);
|
102 kumpf 1.47 }
103 catch (Exception&)
|
104 dave.sudlik 1.46 {
|
105 kumpf 1.47 msg = String("AN INTERNAL ERROR OCCURED IN MESSAGELOADER: ").append(
106 parms.default_msg);
|
107 dave.sudlik 1.46 }
|
108 chip 1.27
|
109 dave.sudlik 1.46 PEG_METHOD_EXIT();
110 return msg;
111 }
|
112 chip 1.27
|
113 kumpf 1.47 void MessageLoader::openMessageFile(MessageLoaderParms& parms)
|
114 dave.sudlik 1.46 {
115 PEG_METHOD_ENTER(TRC_L10N, "MessageLoader::openMessageFile");
|
116 chip 1.27
|
117 dave.sudlik 1.46 try
118 {
119 parms.contentlanguages.clear();
|
120 dave.sudlik 1.45
121 #if defined (PEGASUS_HAS_MESSAGES) && defined (PEGASUS_HAS_ICU)
|
122 dave.sudlik 1.46 if (InitializeICU::initICUSuccessful())
123 {
124 openICUMessageFile(parms);
125 }
126 // If initICUSuccessful() has returned false, then
127 // _resbundl is still set to NO_ICU_MAGIC and
128 // subsequent calls to getMessage2 will call
129 // formatDefaultMessage() instead of using ICU.
130 #else
|
131 kumpf 1.47 // Set _resbundl to the "magic number" indicating there is no ICU
|
132 dave.sudlik 1.46 // resource bundle to use
|
133 kumpf 1.47 parms._resbundl = NO_ICU_MAGIC;
|
134 dave.sudlik 1.45 #endif
|
135 dave.sudlik 1.46 }
|
136 kumpf 1.47 catch (Exception&)
|
137 dave.sudlik 1.46 {
138 // Set _resbundl to the "magic number" indicating there was trouble
139 // during openICUMessageFile(), so there is no ICU resource bundle
140 // to use.
|
141 kumpf 1.47 parms._resbundl = NO_ICU_MAGIC;
|
142 dave.sudlik 1.46 }
143
144 PEG_METHOD_EXIT();
145 return;
146 }
|
147 dave.sudlik 1.45
|
148 kumpf 1.47 void MessageLoader::closeMessageFile(MessageLoaderParms& parms)
|
149 dave.sudlik 1.46 {
150 PEG_METHOD_ENTER(TRC_L10N, "MessageLoader::closeMessageFile");
|
151 dave.sudlik 1.45
152 #if defined (PEGASUS_HAS_MESSAGES) && defined (PEGASUS_HAS_ICU)
|
153 dave.sudlik 1.46 if (parms._resbundl != NO_ICU_MAGIC)
154 {
155 ures_close(parms._resbundl);
156 }
|
157 dave.sudlik 1.45 #endif
158
|
159 dave.sudlik 1.46 PEG_METHOD_EXIT();
160 return;
161 }
|
162 dave.sudlik 1.45
|
163 chuck 1.22 #ifdef PEGASUS_HAS_ICU
|
164 chip 1.27
|
165 kumpf 1.47 void MessageLoader::openICUMessageFile(MessageLoaderParms &parms)
166 {
167 PEG_METHOD_ENTER(TRC_L10N, "MessageLoader::openICUMessageFile");
168 UErrorCode status = U_ZERO_ERROR;
169 CString resbundl_path_ICU;
170
171 const int size_locale_ICU = 50;
172
173 // the static AcceptLangauges takes precedence over what
174 // parms.acceptlangauges has
175 AcceptLanguageList acceptlanguages;
176 acceptlanguages = (_acceptlanguages.size() > 0) ?
177 _acceptlanguages : parms.acceptlanguages;
178
179 // get the correct path to the resource bundles
180 resbundl_path_ICU = getQualifiedMsgPath(parms.msg_src_path).getCString();
181
182 //cout << "USING PACKAGE PATH: " << endl;
183 //cout << resbundl_path_ICU << endl;
184 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, "Using resource bundle path:");
185 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, resbundl_path_ICU);
|
186 dave.sudlik 1.45 #ifdef PEGASUS_OS_OS400
|
187 kumpf 1.47 const char *atoe = resbundl_path_ICU;
188 AtoE((char*)atoe);
|
189 dave.sudlik 1.45 #endif
190
|
191 kumpf 1.47 if (_useProcessLocale ||
192 (acceptlanguages.size() == 0 && parms.useProcessLocale))
193 {
194 // use the system default resource bundle
|
195 dave.sudlik 1.45
|
196 kumpf 1.47 parms._resbundl = ures_open(
197 (const char*)resbundl_path_ICU, uloc_getDefault(), &status);
|
198 dave.sudlik 1.45
|
199 kumpf 1.47 if (U_SUCCESS(status))
200 {
201 UErrorCode _status = U_ZERO_ERROR;
202 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, "Using process locale:");
203 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,
204 ures_getLocale(parms._resbundl, &_status));
205 if (status == U_USING_FALLBACK_WARNING ||
206 status == U_USING_DEFAULT_WARNING)
207 {
208 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,
209 "Using process locale fallback or default");
210 }
211 const char * _locale = ures_getLocale(parms._resbundl,&status);
|
212 dave.sudlik 1.45 #ifdef PEGASUS_OS_OS400
|
213 kumpf 1.47 char tmplcl[size_locale_ICU];
214 strcpy(tmplcl, _locale);
215 EtoA(tmplcl);
216 String localeStr(tmplcl);
|
217 dave.sudlik 1.45 #else
|
218 kumpf 1.47 String localeStr(_locale);
|
219 dave.sudlik 1.45 #endif
|
220 mateus.baur 1.48 // The "root" locale indicates that an ICU message bundle is not present
221 // for the current locale setting.
222 if (localeStr != "root")
223 {
224 parms.contentlanguages.append(LanguageTag(
225 LanguageParser::convertLocaleIdToLanguageTag(localeStr)));
226 }
|
227 kumpf 1.47 }
228 else
229 {
230 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,
231 "Using process locale. Could not open resource, "
232 "formatting default message.");
233 // magic number to indicate no ICU resource bundle to use
234 parms._resbundl = NO_ICU_MAGIC;
235 }
236 PEG_METHOD_EXIT();
237 return;
238 }
239 else if (acceptlanguages.size() == 0 && parms.useThreadLocale)
240 {
241 // get AcceptLanguageList from the current Thread
242 AcceptLanguageList *al = Thread::getLanguages();
243 if (al != NULL)
244 {
245 acceptlanguages = *al;
246 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,
247 "Using thread locale: got AcceptLanguageList from thread.");
248 kumpf 1.47 }
249 else
250 {
251 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,
252 "Using thread locale: thread returned NULL for "
253 "AcceptLanguageList.");
254 }
255 }
|
256 dave.sudlik 1.45
|
257 kumpf 1.47 char locale_ICU[size_locale_ICU];
258 LanguageTag languageTag;
|
259 dave.sudlik 1.45
|
260 kumpf 1.47 // iterate through AcceptLanguageList, use the first resource bundle match
261 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,
262 "Looping through AcceptLanguageList...");
263 for (Uint32 index = 0; index < acceptlanguages.size(); index++)
264 {
265 languageTag = acceptlanguages.getLanguageTag(index);
|
266 dave.sudlik 1.45 #ifdef PEGASUS_OS_OS400
|
267 kumpf 1.47 CString cstr = languageTag.toString().getCString();
268 const char *atoe = cstr;
269 AtoE((char*)atoe);
270
271 uloc_getName(atoe, locale_ICU, size_locale_ICU, &status);
|
272 dave.sudlik 1.45 #else
|
273 kumpf 1.47 uloc_getName(
274 (const char*)(languageTag.toString()).getCString(),
275 locale_ICU, size_locale_ICU, &status);
|
276 dave.sudlik 1.45 #endif
|
277 kumpf 1.47 // TODO: check to see if we have previously cached the resource bundle
|
278 dave.sudlik 1.45
|
279 kumpf 1.47 parms._resbundl =
280 ures_open((const char*)resbundl_path_ICU, locale_ICU, &status);
281
282 if (U_SUCCESS(status))
283 {
284 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,
285 "ACCEPTLANGUAGES LOOP: opened resource bundle with:");
286 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, languageTag.toString());
287 if (status == U_USING_FALLBACK_WARNING ||
288 status == U_USING_DEFAULT_WARNING)
289 {
290 // we want to use the ICU fallback behaviour in the following
291 // cases ONLY
292 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,
293 "ACCEPTLANGUAGES LOOP: ICU warns using FALLBACK or "
294 "DEFAULT");
295 if ((acceptlanguages.size() == 1) && (!parms.useICUfallback) &&
296 (status == U_USING_DEFAULT_WARNING))
297 {
298 // in this case we want to return messages from the root
299 // bundle
300 kumpf 1.47 status = U_ZERO_ERROR;
301 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,
302 "acceptlang.size =1 && !parms.useICUfallback && "
303 "U_USING_DEFAULT_WARNING, using root bundle.");
304
305 // Reopen the bundle in the root locale
306 ures_close(parms._resbundl);
307 parms._resbundl = ures_open(
308 (const char*)resbundl_path_ICU, "", &status);
309 if (U_SUCCESS(status))
310 {
311 PEG_METHOD_EXIT();
312 return;
313 }
314 }
315 else if (acceptlanguages.size() == 1 || parms.useICUfallback)
316 {
317 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,
318 "ACCEPTLANGUAGES LOOP: acceptlanguages.size == 1 or "
319 "useICUfallback true, using ICU fallback "
320 "behaviour...");
321 kumpf 1.47 const char* _locale =
322 ures_getLocale(parms._resbundl, &status);
|
323 dave.sudlik 1.45
324 #ifdef PEGASUS_OS_OS400
|
325 kumpf 1.47 char tmplcl[size_locale_ICU];
326 strcpy(tmplcl, _locale);
327 EtoA(tmplcl);
328 String localeStr(tmplcl);
|
329 dave.sudlik 1.45 #else
|
330 kumpf 1.47 String localeStr(_locale);
|
331 dave.sudlik 1.45 #endif
332
|
333 mateus.baur 1.48 // The "root" locale indicates that an ICU message bundle is not present
334 // for the current locale setting.
335 if (localeStr != "root")
336 {
337 parms.contentlanguages.append(LanguageTag(
338 LanguageParser::convertLocaleIdToLanguageTag(
339 localeStr)));
340 }
|
341 kumpf 1.47 PEG_METHOD_EXIT();
342 return;
343 }
344 }
345 else
346 {
347 // we found an exact resource bundle match, extract, and set
348 // ContentLanguage
349
350 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,
351 "ACCEPTLANGUAGES LOOP: found an EXACT resource bundle "
352 "MATCH:");
353 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,
354 languageTag.toString());
355 parms.contentlanguages.append(
356 LanguageTag(languageTag.toString()));
357 PEG_METHOD_EXIT();
358 return;
359 }
360 }
361 else
362 kumpf 1.47 {
363 // possible errors, ex: message path incorrect
364 // for now do nothing, let the while loop continue
365 }
366 status = U_ZERO_ERROR; // reset status
367 }
368
369 // now if we DIDN'T open a resource bundle, we want to enable ICU
370 // fallback for the highest priority language
371 if (acceptlanguages.size() > 0)
372 {
373 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,
374 "No message was loaded, using ICU fallback behaviour.");
375 languageTag = acceptlanguages.getLanguageTag(0);
376
377 #ifdef PEGASUS_OS_OS400
378 CString cstr = languageTag.toString().getCString();
379 const char *atoe = cstr;
380 AtoE((char*)atoe);
381
382 uloc_getName(atoe, locale_ICU, size_locale_ICU, &status);
383 kumpf 1.47 #else
384 uloc_getName(
385 (const char*)(languageTag.toString()).getCString(),
386 locale_ICU, size_locale_ICU, &status);
387 #endif
388 status = U_ZERO_ERROR;
389 parms._resbundl =
390 ures_open((const char*)resbundl_path_ICU, locale_ICU, &status);
391 const char* _locale = NULL;
392 if (U_SUCCESS(status))
393 {
394 if (status == U_USING_DEFAULT_WARNING)
395 {
396 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,
397 "PRIORITY ICU FALLBACK: using default resource bundle "
398 "with ");
399 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,
400 languageTag.toString());
401 status = U_ZERO_ERROR;
402
403 // Reopen the bundle in the root locale
404 kumpf 1.47 ures_close(parms._resbundl);
405 parms._resbundl =
406 ures_open((const char*)resbundl_path_ICU, "", &status);
407 if (U_SUCCESS(status))
408 {
409 _locale = ures_getLocale(parms._resbundl,&status);
410 }
411 }
412 else
413 {
414 _locale = ures_getLocale(parms._resbundl,&status);
415 }
416
417 String localeStr;
418
419 if (_locale != NULL)
420 {
|
421 dave.sudlik 1.45 #ifdef PEGASUS_OS_OS400
|
422 kumpf 1.47 char tmplcl[size_locale_ICU];
423 strcpy(tmplcl, _locale);
424 EtoA(tmplcl);
425 localeStr.assign(tmplcl);
|
426 dave.sudlik 1.45 #else
|
427 kumpf 1.47 localeStr.assign(_locale);
|
428 dave.sudlik 1.45 #endif
|
429 kumpf 1.47 }
430
|
431 mateus.baur 1.48 // The "root" locale indicates that an ICU message bundle is not present
432 // for the current locale setting.
|
433 kumpf 1.47 if (localeStr != "root")
434 {
435 parms.contentlanguages.append(LanguageTag(
436 LanguageParser::convertLocaleIdToLanguageTag(
437 localeStr)));
438 }
439
440 if (_locale != NULL)
441 {
442 PEG_METHOD_EXIT();
443 return;
444 }
445 }
446 }
447
448 {
449 // else if no message, load message from root bundle explicitly
450 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,
451 "EXHAUSTED ACCEPTLANGUAGES: using root bundle to extract message");
452 status = U_ZERO_ERROR;
453 parms._resbundl =
454 kumpf 1.47 ures_open((const char*)resbundl_path_ICU, "", &status);
455 if (U_SUCCESS(status))
456 {
457 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,
458 "EXHAUSTED ACCEPTLANGUAGES: opened root resource bundle");
459 }
460 else
461 {
462 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,
463 "EXHAUSTED ACCEPTLANGUAGES: could NOT open root resource "
464 "bundle");
465 parms._resbundl = NO_ICU_MAGIC;
466 }
467 }
468
469 PEG_METHOD_EXIT();
470 return;
471 }
472
473 String MessageLoader::extractICUMessage(
474 UResourceBundle* resbundl,
475 kumpf 1.47 MessageLoaderParms& parms)
476 {
477 UErrorCode status = U_ZERO_ERROR;
478 int32_t msgLen = 0;
|
479 humberto 1.6
|
480 chuck 1.22 #ifdef PEGASUS_OS_OS400
|
481 kumpf 1.47 CString cstr = parms.msg_id.getCString();
482 const char* atoe = cstr;
483 AtoE((char*)atoe);
484 const UChar* msg =
485 ures_getStringByKey(resbundl, (const char*)atoe, &msgLen, &status);
|
486 chuck 1.22 #else
|
487 kumpf 1.47 const UChar* msg = ures_getStringByKey(
488 resbundl, (const char*)parms.msg_id.getCString(), &msgLen, &status);
|
489 chuck 1.22 #endif
|
490 chip 1.27
|
491 kumpf 1.47 if (U_FAILURE(status))
492 {
493 return String::EMPTY;
494 }
495
496 return formatICUMessage(resbundl, msg, msgLen, parms);
497 }
498
499 String MessageLoader::uChar2String(UChar* uchar_str)
500 {
501 return String((const Char16 *)uchar_str);
502 }
503
504 String MessageLoader::uChar2String(UChar* uchar_str, int len)
505 {
506 return String((const Char16 *)uchar_str, len);
507 }
508
509 String MessageLoader::formatICUMessage(
510 UResourceBundle* resbundl,
511 const UChar* msg,
512 kumpf 1.47 int msg_len,
513 MessageLoaderParms& parms)
514 {
515 // format the message
516 UnicodeString msg_pattern(msg, msg_len);
517 UnicodeString msg_formatted;
518 UErrorCode status = U_ZERO_ERROR;
519 const int arg_count = 10;
520 const char *locale;
521 if (resbundl == NULL)
522 locale = ULOC_US;
523 else
524 locale = ures_getLocale(resbundl, &status);
525
526 char lang[4];
527 char cc[4];
528 char var[arg_count];
529 uloc_getLanguage(locale, lang, 4, &status);
530 uloc_getCountry(locale, cc, 4, &status);
531 uloc_getVariant(locale, var, 10, &status);
532 Locale localeID(lang,cc,var);
533 kumpf 1.47
534 status = U_ZERO_ERROR;
535 MessageFormat formatter(msg_pattern, localeID, status);
|
536 chuck 1.21
|
537 kumpf 1.47 Formattable args[arg_count];
|
538 chuck 1.21
|
539 kumpf 1.47 if (parms.arg0._type != Formatter::Arg::VOIDT)
|
540 chuck 1.21 xferFormattable(parms.arg0, args[0]);
|
541 kumpf 1.47 if (parms.arg1._type != Formatter::Arg::VOIDT)
|
542 chuck 1.21 xferFormattable(parms.arg1, args[1]);
|
543 kumpf 1.47 if (parms.arg2._type != Formatter::Arg::VOIDT)
|
544 chuck 1.21 xferFormattable(parms.arg2, args[2]);
|
545 kumpf 1.47 if (parms.arg3._type != Formatter::Arg::VOIDT)
|
546 chuck 1.21 xferFormattable(parms.arg3, args[3]);
|
547 kumpf 1.47 if (parms.arg4._type != Formatter::Arg::VOIDT)
|
548 chuck 1.21 xferFormattable(parms.arg4, args[4]);
|
549 kumpf 1.47 if (parms.arg5._type != Formatter::Arg::VOIDT)
|
550 chuck 1.21 xferFormattable(parms.arg5, args[5]);
|
551 kumpf 1.47 if (parms.arg6._type != Formatter::Arg::VOIDT)
|
552 chuck 1.21 xferFormattable(parms.arg6, args[6]);
|
553 kumpf 1.47 if (parms.arg7._type != Formatter::Arg::VOIDT)
|
554 chuck 1.21 xferFormattable(parms.arg7, args[7]);
|
555 kumpf 1.47 if (parms.arg8._type != Formatter::Arg::VOIDT)
|
556 chuck 1.21 xferFormattable(parms.arg8, args[8]);
|
557 kumpf 1.47 if (parms.arg9._type != Formatter::Arg::VOIDT)
|
558 chuck 1.21 xferFormattable(parms.arg9, args[9]);
559
|
560 kumpf 1.47 Formattable args_obj(args,arg_count);
561 status = U_ZERO_ERROR;
562 msg_formatted = formatter.format(args_obj, msg_formatted, status);
563
564 return uChar2String(
565 const_cast<UChar*>(msg_formatted.getBuffer()), msg_formatted.length());
566 }
567
568 void MessageLoader::xferFormattable(
569 Formatter::Arg &arg,
570 Formattable& formattable)
571 {
572 //cout << "arg" << " = " << arg.toString() << endl;
573 switch (arg._type)
574 {
575 case Formatter::Arg::INTEGER:
576 formattable = (int32_t)arg._integer;
577 break;
578 case Formatter::Arg::UINTEGER:
579 // Note: the ICU Formattable class doesn't support
580 // unsigned 32. Cast to signed 64.
581 kumpf 1.47 formattable = (int64_t)arg._uinteger;
582 break;
583 case Formatter::Arg::BOOLEAN:
584 // Note: the ICU formattable class doesn't support
585 // boolean. Turn it into a string.
586 if (!arg._boolean)
587 formattable = Formattable("false");
588 else
589 formattable = Formattable("true");
590 break;
591 case Formatter::Arg::REAL:
592 formattable = (double)arg._real;
593 break;
594 case Formatter::Arg::LINTEGER:
595 // Note: this uses a Formattable constructor that is
596 // labelled ICU 2.8 draft. Assumes that Pegasus uses
597 // at least ICU 2.8.
598 formattable = (int64_t)arg._lInteger;
599 break;
600 case Formatter::Arg::ULINTEGER:
601 // Note: the ICU Formattable class doesn't support
602 kumpf 1.47 // unsigned 64. If the number is too big for signed 64
603 // then turn it into a string. This string will
604 // not be formatted for the locale, but at least the number
605 // will appear in the message.
606 if (arg._lUInteger > PEGASUS_UINT64_LITERAL(0x7FFFFFFFFFFFFFFF))
607 {
608 char buffer[32]; // Should need 21 chars max
609 sprintf(buffer, "%" PEGASUS_64BIT_CONVERSION_WIDTH "u",
610 arg._lUInteger);
611 formattable = Formattable(buffer);
612 }
613 else
614 {
615 formattable = (int64_t)arg._lUInteger;
616 }
617 break;
618 case Formatter::Arg::STRING:
619 formattable = Formattable((UChar*)arg._string.getChar16Data());
620 break;
621 case Formatter::Arg::VOIDT:
622 default:
623 kumpf 1.47 formattable = "";
624 break;
625 }
626 }
627
628 #endif
629
630 String MessageLoader::formatDefaultMessage(MessageLoaderParms& parms)
631 {
632 PEG_METHOD_ENTER(TRC_L10N, "MessageLoader::formatDefaultMessage");
633
634 // NOTE TO PROGRAMMERS: using native substitution functions
635 // ie. calling Formatter::format()
636 // can result in incorrect locale handling of substitutions
637
638 // locale INSENSITIVE formatting code
639
640 // this could have previously been set by ICU
641 parms.contentlanguages.clear();
642
643 PEG_METHOD_EXIT();
644 kumpf 1.47 return Formatter::format(
645 parms.default_msg,
646 parms.arg0,
647 parms.arg1,
648 parms.arg2,
649 parms.arg3,
650 parms.arg4,
651 parms.arg5,
652 parms.arg6,
653 parms.arg7,
654 parms.arg8,
655 parms.arg9);
656 }
657
658 String MessageLoader::getQualifiedMsgPath(String path)
659 {
660 PEG_METHOD_ENTER(TRC_L10N, "MessageLoader::getQualifiedMsgPath");
661
662 if (pegasus_MSG_HOME.size() == 0)
663 initPegasusMsgHome(String::EMPTY);
664
665 kumpf 1.47 if (path.size() == 0)
666 {
667 PEG_METHOD_EXIT();
668 return pegasus_MSG_HOME + server_resbundl_name;
669 }
670
671 // NOTE TO PROGRAMMERS: WINDOWS and non-UNIX platforms should
672 // redefine delim here
673 Char16 delim = '/';
674 Uint32 i;
675 if ((i = path.find(delim)) != PEG_NOT_FOUND && i == 0)
|
676 joyce.j 1.34 {
|
677 kumpf 1.47 // fully qualified package name
678 PEG_METHOD_EXIT();
679 return path;
680 }
681
682 PEG_METHOD_EXIT();
683 return pegasus_MSG_HOME + path; // relative path and package name
684 }
685
686 void MessageLoader::setPegasusMsgHome(String home)
687 {
688 PEG_METHOD_ENTER(TRC_L10N, "MessageLoader::setPegasusMsgHome");
689 pegasus_MSG_HOME = home + "/";
690
691 // TODO: remove the next call once test cases are compatible with ICU
692 // messages
693 checkDefaultMsgLoading();
694 PEG_METHOD_EXIT();
695 }
696
697 void MessageLoader::setPegasusMsgHomeRelative(const String& argv0)
698 kumpf 1.47 {
|
699 joyce.j 1.34 #ifdef PEGASUS_HAS_MESSAGES
|
700 kumpf 1.47 try
701 {
|
702 joyce.j 1.34 String startingDir, pathDir;
703
704 #ifdef PEGASUS_OS_TYPE_WINDOWS
|
705 kumpf 1.47 if (PEG_NOT_FOUND == argv0.find('\\'))
|
706 joyce.j 1.34 {
|
707 kumpf 1.47 char exeDir[_MAX_PATH];
708 HMODULE module = GetModuleHandle(NULL);
709 if (NULL != module )
710 {
711 DWORD filename =
712 GetModuleFileName(module,exeDir ,sizeof(exeDir));
713 if (0 != filename)
714 {
715 String path(exeDir);
716 Uint32 command = path.reverseFind('\\');
717 startingDir = path.subString(0, command+1);
718 }
719 }
|
720 joyce.j 1.34 }
721 else
722 {
723 Uint32 command = argv0.reverseFind('\\');
724 startingDir = argv0.subString(0, command+1);
725 }
726 #endif
727
728 #ifdef PEGASUS_OS_TYPE_UNIX
|
729 kumpf 1.47 if (PEG_NOT_FOUND != argv0.find('/'))
|
730 joyce.j 1.34 {
731 Uint32 command = argv0.reverseFind('/');
732 startingDir = argv0.subString(0, command+1);
733 }
734 else
735 {
|
736 kumpf 1.47 if (FileSystem::existsNoCase(argv0))
737 {
738 FileSystem::getCurrentDirectory(startingDir);
739 startingDir.append("/");
740 }
741 else
742 {
743 String path;
744 # ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
745 # pragma convert(37)
|
746 joyce.j 1.34 const char* env = getenv("PATH");
|
747 kumpf 1.47 if (env != NULL)
748 EtoA((char*)env);
749 # pragma convert(0)
750 # else
|
751 joyce.j 1.34 const char* env = getenv("PATH");
|
752 kumpf 1.47 # endif
753 if (env != NULL)
754 path.assign(env);
755 String pathDelim = FileSystem::getPathDelimiter();
756 Uint32 size = path.size();
757 while (path.size() > 0)
758 {
759 try
760 {
761 Uint32 delim = path.find(pathDelim);
762 if (delim != PEG_NOT_FOUND)
763 {
764 pathDir = path.subString(0,delim);
765 path.remove(0,(delim+1));
766 }
767 else
768 {
769 pathDir = path;
770 path = "";
771 }
772
773 kumpf 1.47 String commandPath = pathDir.append('/');
774 commandPath = commandPath.append(argv0) ;
775 Boolean dirContent =
776 FileSystem::existsNoCase(commandPath);
777 if (dirContent)
778 {
779 startingDir = pathDir;
780 break;
781 }
782 }
783 catch (Exception& e)
784 {
785 // Have to do nothing.
786 // Catching the exception if there is any exception
787 // while searching in the path variable
788 }
789 }
790 }
791 }
792 #endif
793 initPegasusMsgHome(startingDir);
794 kumpf 1.47 }
795 catch (Exception& e)
796 {
797 // Have to do nothing.
798 // Catching the exception if there is any exception while searching
799 // in the path variable
800 }
|
801 joyce.j 1.34 #endif
802 }
803
804
|
805 kumpf 1.47 void MessageLoader::initPegasusMsgHome(const String& startDir)
|
806 joyce.j 1.34 {
|
807 kumpf 1.47 String startingDir = startDir;
|
808 joyce.j 1.34 if (startingDir.size() == 0)
809 {
|
810 david 1.15 #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
|
811 kumpf 1.47 # pragma convert(37)
812 const char* env = getenv("PEGASUS_MSG_HOME");
813 if (env != NULL)
814 EtoA((char*)env);
815 # pragma convert(0)
|
816 david 1.15 #else
|
817 joyce.j 1.34 const char* env = getenv("PEGASUS_MSG_HOME");
|
818 david 1.15 #endif
|
819 joyce.j 1.34
820 if (env != NULL)
821 startingDir.assign(env);
822 }
823
|
824 david 1.15 #ifdef PEGASUS_DEFAULT_MESSAGE_SOURCE
|
825 kumpf 1.47 if (System::is_absolute_path(
826 (const char *)PEGASUS_DEFAULT_MESSAGE_SOURCE))
827 {
828 pegasus_MSG_HOME = PEGASUS_DEFAULT_MESSAGE_SOURCE;
829 pegasus_MSG_HOME.append('/');
830 }
831 else
832 {
833 if (startingDir.size() != 0)
|
834 joyce.j 1.34 {
|
835 kumpf 1.47 pegasus_MSG_HOME = startingDir;
|
836 joyce.j 1.34 pegasus_MSG_HOME.append('/');
837 }
|
838 kumpf 1.47 pegasus_MSG_HOME.append(PEGASUS_DEFAULT_MESSAGE_SOURCE);
839 pegasus_MSG_HOME.append('/');
840 }
|
841 david 1.15 #else
|
842 kumpf 1.47 if (startingDir.size() != 0)
843 {
844 pegasus_MSG_HOME = startingDir;
845 pegasus_MSG_HOME.append("/");
846 }
847 else
848 {
849 // Will use current working directory
850 }
|
851 chip 1.27 #endif
|
852 kumpf 1.47 checkDefaultMsgLoading();
853 }
|
854 chip 1.27
|
855 kumpf 1.47 void MessageLoader::checkDefaultMsgLoading()
856 {
857 // Note: this function is a special hook for the automated tests
858 // (poststarttests). Since the automated tests expect the old hardcoded
859 // default messages, an env var will be used to tell this code to ignore
860 // ICU and return the default message.
861 // This will allow poststarttests to run with ICU installed.
862 // TODO: remove this function once test cases are compatible with ICU
863 // messages
|
864 chuck 1.14 #ifdef PEGASUS_OS_OS400
|
865 kumpf 1.47 # pragma convert(37)
|
866 chuck 1.14 #endif
|
867 kumpf 1.47 const char* env = getenv("PEGASUS_USE_DEFAULT_MESSAGES");
|
868 chuck 1.14 #ifdef PEGASUS_OS_OS400
|
869 kumpf 1.47 # pragma convert(0)
|
870 chip 1.27 #endif
|
871 kumpf 1.47 if (env != NULL)
872 _useDefaultMsg = true;
873 }
|
874 humberto 1.4
|
875 karl 1.20 MessageLoaderParms::MessageLoaderParms()
876 {
|
877 kumpf 1.47 useProcessLocale = false;
878 useThreadLocale = true;
|
879 chip 1.27
|
880 chuck 1.22 #ifdef PEGASUS_HAS_ICU
|
881 kumpf 1.47 useICUfallback = false;
|
882 chuck 1.22 #endif
|
883 chip 1.27
|
884 kumpf 1.47 acceptlanguages = AcceptLanguageList();
885 contentlanguages = ContentLanguageList();
|
886 dave.sudlik 1.45
|
887 kumpf 1.47 _resbundl = NO_ICU_MAGIC;
|
888 karl 1.20 }
889
|
890 chip 1.27 MessageLoaderParms::MessageLoaderParms(
891 const String& id,
892 const String& msg,
|
893 mike 1.37 const Formatter::Arg& arg0_,
894 const Formatter::Arg& arg1_,
895 const Formatter::Arg& arg2_,
896 const Formatter::Arg& arg3_,
897 const Formatter::Arg& arg4_,
898 const Formatter::Arg& arg5_,
899 const Formatter::Arg& arg6_,
900 const Formatter::Arg& arg7_,
901 const Formatter::Arg& arg8_,
902 const Formatter::Arg& arg9_)
|
903 karl 1.20 {
904 msg_id = id;
905 default_msg = msg;
906 _init();
|
907 mike 1.37 arg0 = arg0_;
908 arg1 = arg1_;
909 arg2 = arg2_;
910 arg3 = arg3_;
911 arg4 = arg4_;
912 arg5 = arg5_;
913 arg6 = arg6_;
914 arg7 = arg7_;
915 arg8 = arg8_;
916 arg9 = arg9_;
|
917 chip 1.27 }
|
918 karl 1.20
|
919 chip 1.27 MessageLoaderParms::MessageLoaderParms(
920 const String& id,
|
921 karl 1.20 const String& msg)
922 {
923 msg_id = id;
924 default_msg = msg;
925 _init();
926 }
927
|
928 chip 1.27 MessageLoaderParms::MessageLoaderParms(
929 const String& id,
930 const String& msg,
|
931 mike 1.37 const Formatter::Arg& arg0_)
|
932 karl 1.20 {
933 msg_id = id;
934 default_msg = msg;
935 _init();
|
936 mike 1.37 arg0 = arg0_;
|
937 karl 1.20 }
938
|
939 chip 1.27 MessageLoaderParms::MessageLoaderParms(
940 const String& id,
941 const String& msg,
|
942 mike 1.37 const Formatter::Arg& arg0_,
943 const Formatter::Arg& arg1_)
|
944 karl 1.20 {
945 msg_id = id;
946 default_msg = msg;
947 _init();
|
948 mike 1.37 arg0 = arg0_;
949 arg1 = arg1_;
|
950 karl 1.20 }
951
|
952 chip 1.27 MessageLoaderParms::MessageLoaderParms(
953 const String& id,
954 const String& msg,
|
955 mike 1.37 const Formatter::Arg& arg0_,
956 const Formatter::Arg& arg1_,
957 const Formatter::Arg& arg2_)
|
958 karl 1.20 {
959 msg_id = id;
960 default_msg = msg;
961 _init();
|
962 mike 1.37 arg0 = arg0_;
963 arg1 = arg1_;
964 arg2 = arg2_;
|
965 karl 1.20 }
966
|
967 chip 1.27 MessageLoaderParms::MessageLoaderParms(
968 const String& id,
969 const String& msg,
|
970 mike 1.37 const Formatter::Arg& arg0_,
971 const Formatter::Arg& arg1_,
972 const Formatter::Arg& arg2_,
973 const Formatter::Arg& arg3_)
|
974 karl 1.20 {
975 msg_id = id;
976 default_msg = msg;
977 _init();
|
978 mike 1.37 arg0 = arg0_;
979 arg1 = arg1_;
980 arg2 = arg2_;
981 arg3 = arg3_;
|
982 karl 1.20 }
983
984 MessageLoaderParms::MessageLoaderParms(
|
985 chip 1.27 const char* id,
|
986 karl 1.20 const char* msg)
987 {
988 msg_id = id;
989 default_msg = msg;
990 _init();
991 }
992
993 MessageLoaderParms::MessageLoaderParms(
|
994 chip 1.27 const char* id,
995 const char* msg,
|
996 mike 1.37 const String& arg0_)
|
997 karl 1.20 {
998 msg_id = id;
999 default_msg = msg;
1000 _init();
|
1001 mike 1.37 arg0 = arg0_;
|
1002 karl 1.20 }
1003
1004 MessageLoaderParms::MessageLoaderParms(
|
1005 chip 1.27 const char* id,
1006 const char* msg,
|
1007 mike 1.37 const String& arg0_,
1008 const String& arg1_)
|
1009 karl 1.20 {
1010 msg_id = id;
1011 default_msg = msg;
1012 _init();
|
1013 mike 1.37 arg0 = arg0_;
1014 arg1 = arg1_;
|
1015 karl 1.20 }
1016
1017 void MessageLoaderParms::_init()
1018 {
1019 useProcessLocale = false;
1020 useThreadLocale = true;
|
1021 chip 1.27
|
1022 karl 1.20 #ifdef PEGASUS_HAS_ICU
1023 useICUfallback = false;
1024 #endif
|
1025 chip 1.27
|
1026 kumpf 1.38 acceptlanguages.clear();
1027 contentlanguages.clear();
|
1028 karl 1.20
|
1029 mike 1.37 arg0 = Formatter::DEFAULT_ARG;
1030 arg1 = Formatter::DEFAULT_ARG;
1031 arg2 = Formatter::DEFAULT_ARG;
1032 arg3 = Formatter::DEFAULT_ARG;
1033 arg4 = Formatter::DEFAULT_ARG;
1034 arg5 = Formatter::DEFAULT_ARG;
1035 arg6 = Formatter::DEFAULT_ARG;
1036 arg7 = Formatter::DEFAULT_ARG;
1037 arg8 = Formatter::DEFAULT_ARG;
1038 arg9 = Formatter::DEFAULT_ARG;
|
1039 dave.sudlik 1.45
1040 _resbundl = NO_ICU_MAGIC;
|
1041 karl 1.20 }
1042
1043 String MessageLoaderParms::toString()
1044 {
1045 String s;
1046 String processLoc,threadLoc,ICUfallback;
1047 processLoc = (useProcessLocale) ? "true" : "false";
1048 threadLoc = (useThreadLocale) ? "true" : "false";
|
1049 chuck 1.22 #ifdef PEGASUS_HAS_ICU
|
1050 karl 1.20 ICUfallback = (useICUfallback) ? "true" : "false";
|
1051 chuck 1.22 #endif
|
1052 chip 1.27
|
1053 karl 1.20 s.append("msg_id = " + msg_id + "\n");
1054 s.append("default_msg = " + default_msg + "\n");
1055 s.append("msg_src_path = " + msg_src_path + "\n");
|
1056 kumpf 1.38 s.append("acceptlanguages = " +
1057 LanguageParser::buildAcceptLanguageHeader(acceptlanguages) + "\n");
1058 s.append("contentlanguages = " +
1059 LanguageParser::buildContentLanguageHeader(contentlanguages) + "\n");
|
1060 chip 1.27
|
1061 karl 1.20 s.append("useProcessLocale = " + processLoc + "\n");
1062 s.append("useThreadLocale = " + threadLoc + "\n");
|
1063 chuck 1.22 #ifdef PEGASUS_HAS_ICU
|
1064 karl 1.20 s.append("useICUfallback = " + ICUfallback + "\n");
|
1065 chuck 1.22 #endif
|
1066 kumpf 1.47 s.append(
1067 "arg0 = " + arg0.toString() + "\n" +
1068 "arg1 = " + arg1.toString() + "\n" +
1069 "arg2 = " + arg2.toString() + "\n" +
1070 "arg3 = " + arg3.toString() + "\n" +
1071 "arg4 = " + arg4.toString() + "\n" +
1072 "arg5 = " + arg5.toString() + "\n" +
1073 "arg6 = " + arg6.toString() + "\n" +
1074 "arg7 = " + arg7.toString() + "\n" +
1075 "arg8 = " + arg8.toString() + "\n" +
1076 "arg9 = " + arg9.toString() + "\n\n");
|
1077 chip 1.27
|
1078 karl 1.20 return s;
1079 }
|
1080 humberto 1.4
|
1081 karl 1.20 MessageLoaderParms::~MessageLoaderParms()
1082 {
1083 }
|
1084 humberto 1.4
|
1085 karl 1.20 PEGASUS_NAMESPACE_END
|