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