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

  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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2