(file) Return to MessageLoader.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

  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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2