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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2