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