1 karl 1.23 //%2005////////////////////////////////////////////////////////////////////////
|
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 humberto 1.4 //
12 // Permission is hereby granted, free of charge, to any person obtaining a copy
13 // of this software and associated documentation files (the "Software"), to
14 // deal in the Software without restriction, including without limitation the
15 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
16 // sell copies of the Software, and to permit persons to whom the Software is
17 // furnished to do so, subject to the following conditions:
|
18 chip 1.27 //
|
19 humberto 1.4 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
20 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
21 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
22 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
23 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
25 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 //==============================================================================
|
29 chip 1.27 //
|
30 humberto 1.4 // Author: Humberto Rivero (hurivero@us.ibm.com)
31 //
|
32 joyce.j 1.34 // Modified By: Josephine Eskaline Joyce, IBM (jojustin@in.ibm.com) for Bug#3032
|
33 chip 1.27 //
|
34 humberto 1.4 //%/////////////////////////////////////////////////////////////////////////////
35
36 #include <Pegasus/Common/MessageLoader.h>
37 #include <Pegasus/Common/Thread.h>
38 #include <Pegasus/Common/Tracer.h>
|
39 david 1.15 #include <Pegasus/Common/Constants.h>
|
40 yi.zhou 1.30 #include <Pegasus/Common/CommonUTF.h>
|
41 joyce.j 1.34 #include <Pegasus/Common/FileSystem.h>
|
42 humberto 1.6 #include <iostream>
43 #ifdef PEGASUS_OS_OS400
44 #include "OS400ConvertChar.h"
45 #endif
|
46 chip 1.27 PEGASUS_NAMESPACE_BEGIN
|
47 humberto 1.6 PEGASUS_USING_STD;
|
48 humberto 1.4
49 static const int ID_INVALID = -1;
50 static const String server_resbundl_name = "pegasus/pegasusServer";
|
51 humberto 1.7 String MessageLoader::pegasus_MSG_HOME = String();
|
52 humberto 1.4 Boolean MessageLoader::_useProcessLocale = false;
53 Boolean MessageLoader::_useDefaultMsg = false;
54 AcceptLanguages MessageLoader::_acceptlanguages = AcceptLanguages();
55
56 String MessageLoader::getMessage(MessageLoaderParms &parms){
57 PEG_METHOD_ENTER(TRC_L10N, "MessageLoader::getMessage");
|
58 humberto 1.8 try{
|
59 yi.zhou 1.30 parms.contentlanguages.clear();
60
61 #if defined (PEGASUS_HAS_MESSAGES) && defined (PEGASUS_HAS_ICU)
62 if (InitializeICU::initICUSuccessful())
63 {
64 String msg = loadICUMessage(parms);
65
66 if (msg.size() > 0)
67 {
68 PEG_METHOD_EXIT();
69 return (msg);
70 }
71 }
72
73 #endif
74 // NOTE: the default message is returned if:
75 // Message loading is DIABLED or
76 // A non-ICU message loading function is called that has
77 // non-ICU process locale discovery code and non-ICU
78 // message loading or
79 // InitializeICU::initICUSuccessful() is failed or
80 yi.zhou 1.30 // Did not get a message from ICU
|
81 chip 1.27
|
82 kumpf 1.25 PEG_METHOD_EXIT();
|
83 humberto 1.4 return formatDefaultMessage(parms);
|
84 chip 1.27
|
85 kumpf 1.10 }catch(Exception&){
|
86 kumpf 1.25 PEG_METHOD_EXIT();
|
87 chip 1.27 return String("AN INTERNAL ERROR OCCURED IN MESSAGELOADER: ").append(parms.default_msg);
|
88 carson.hovey 1.24 }
|
89 humberto 1.4 }
|
90 chip 1.27
|
91 chuck 1.22 #ifdef PEGASUS_HAS_ICU
|
92 chip 1.27
|
93 humberto 1.4 String MessageLoader::loadICUMessage(MessageLoaderParms &parms){
|
94 chip 1.27
|
95 humberto 1.4 PEG_METHOD_ENTER(TRC_L10N, "MessageLoader::loadICUMessage");
96 String msg;
97 UResourceBundle* resbundl;
98 UErrorCode status = U_ZERO_ERROR;
|
99 chip 1.27 //String resbundl_path_ICU;
|
100 humberto 1.4 CString resbundl_path_ICU;
|
101 chip 1.27
|
102 humberto 1.4 // the static AcceptLangauges takes precedence over what parms.acceptlangauges has
103 AcceptLanguages acceptlanguages;
104 acceptlanguages = (_acceptlanguages.size() > 0) ? _acceptlanguages : parms.acceptlanguages;
|
105 chip 1.27
|
106 humberto 1.4 // get the correct path to the resource bundles
|
107 humberto 1.6 resbundl_path_ICU = getQualifiedMsgPath(parms.msg_src_path).getCString();
|
108 chuck 1.13
109 // if someone has set the global behaviour to use default messages
110 // Note: this must be after the call to getQualifiedMsgPath
|
111 kumpf 1.25 if (_useDefaultMsg)
112 {
113 PEG_METHOD_EXIT();
|
114 chip 1.27 return formatDefaultMessage(parms);
|
115 kumpf 1.25 }
|
116 chuck 1.13
|
117 humberto 1.6 //cout << "USING PACKAGE PATH: " << endl;
118 //cout << resbundl_path_ICU << endl;
|
119 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, "Using resource bundle path:");
120 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, resbundl_path_ICU);
|
121 chuck 1.22 #ifdef PEGASUS_OS_OS400
|
122 humberto 1.6 const char *atoe = resbundl_path_ICU;
123 AtoE((char*)atoe);
|
124 chuck 1.22 #endif
|
125 chip 1.27
126
127
|
128 humberto 1.4 if(_useProcessLocale || (acceptlanguages.size() == 0 && parms.useProcessLocale)){ // use the system default resource bundle
|
129 chip 1.27
130 resbundl = ures_open((const char*)resbundl_path_ICU, uloc_getDefault() , &status);
131
|
132 humberto 1.4 if(U_SUCCESS(status)) {
133 //cout << "PROCESS_LOCALE: opened resource bundle" << endl;
|
134 humberto 1.17 UErrorCode _status = U_ZERO_ERROR;
135 //cout << "PROCESS_LOCALE = " << ures_getLocale(resbundl, &_status) << endl;
136 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, "Using process locale:");
137 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, ures_getLocale(resbundl, &_status));
|
138 humberto 1.4 if(status == U_USING_FALLBACK_WARNING || status == U_USING_DEFAULT_WARNING){
|
139 chip 1.27 //cout << "PROCESS_LOCALE: using fallback or default" << endl;
|
140 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, "Using process locale fallback or default");
|
141 humberto 1.4 }
142 msg = extractICUMessage(resbundl,parms);
|
143 humberto 1.6
144 String cl_str(ures_getLocale(resbundl,&status));
|
145 chuck 1.22 #ifdef PEGASUS_OS_OS400
|
146 humberto 1.6 CString cstr = cl_str.getCString();
147 const char *etoa = cstr;
148 EtoA((char*)etoa);
149 cl_str = etoa;
|
150 chuck 1.22 #endif
|
151 humberto 1.6 parms.contentlanguages.append(ContentLanguageElement(cl_str));
|
152 chip 1.27 ures_close(resbundl);
|
153 humberto 1.4 } else {
154 //cout << "PROCESS_LOCALE: could not open resouce, formatting default message" << endl;
|
155 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, "Using process locale. Could not open resource, formatting default message.");
|
156 humberto 1.4 msg = formatDefaultMessage(parms);
157 }
|
158 kumpf 1.25 PEG_METHOD_EXIT();
|
159 humberto 1.4 return msg;
160 } else if (acceptlanguages.size() == 0 && parms.useThreadLocale){ // get AcceptLanguages from the current Thread
161 AcceptLanguages *al = Thread::getLanguages();
|
162 chip 1.27 if(al != NULL){
|
163 humberto 1.4 acceptlanguages = *al;
|
164 chip 1.27 //cout << "THREAD_LOCALE: got acceptlanguages from thread" << endl;
|
165 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, "Using thread locale: got AcceptLanguages from thread.");
|
166 chip 1.27 }else {
|
167 humberto 1.4 //cout << "THREAD_LOCALE: thread returned NULL for acceptlanguages" << endl;
|
168 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, "Using thread locale: thread returned NULL for AcceptLanguages.");
|
169 chip 1.27 }
|
170 humberto 1.4 }
|
171 chip 1.27
|
172 humberto 1.4 const int size_locale_ICU = 50;
173 char locale_ICU[size_locale_ICU];
174 AcceptLanguageElement language_element = AcceptLanguageElement::EMPTY;
|
175 chip 1.27
|
176 humberto 1.4 // iterate through AcceptLanguages, use the first resource bundle match
177 acceptlanguages.itrStart();
178 //cout << "LOOPING THROUGH ACCEPTLANGUAGES..." << endl;
|
179 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, "Looping through AcceptLanguages...");
|
180 humberto 1.4 while((language_element = acceptlanguages.itrNext()) != AcceptLanguageElement::EMPTY_REF){
|
181 chuck 1.22 #ifdef PEGASUS_OS_OS400
|
182 humberto 1.6 CString cstr = language_element.getTag().getCString();
183 const char *atoe = cstr;
184 AtoE((char*)atoe);
185 String tag(atoe);
186 uloc_getName((const char*)tag.getCString(), locale_ICU, size_locale_ICU, &status);
|
187 chuck 1.22 #else
|
188 humberto 1.6 uloc_getName((const char*)(language_element.getTag()).getCString(), locale_ICU, size_locale_ICU, &status);
|
189 chuck 1.22 #endif
|
190 chip 1.27 //cout << "locale_ICU = " << locale_ICU << endl;
|
191 humberto 1.4 // TODO: check to see if we have previously cached the resource bundle
|
192 chip 1.27
|
193 humberto 1.4 resbundl = ures_open((const char*)resbundl_path_ICU, locale_ICU, &status);
|
194 chip 1.27
|
195 humberto 1.4 if(U_SUCCESS(status)) {
196 //cout << "ACCEPTLANGUAGES LOOP: opened resource bundle with " << language_element.getTag() << endl;
|
197 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, "ACCEPTLANGUAGES LOOP: opened resource bundle with:");
198 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, language_element.getTag());
|
199 humberto 1.4 if(status == U_USING_FALLBACK_WARNING || status == U_USING_DEFAULT_WARNING){
200 //we want to use the ICU fallback behaviour in the following cases ONLY
201 //cout << "ACCEPTLANGUAGES LOOP: ICU warns using FALLBACK or DEFAULT" << endl;
|
202 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,"ACCEPTLANGUAGES LOOP: ICU warns using FALLBACK or DEFAULT");
|
203 humberto 1.12 if((acceptlanguages.size() == 1) && (!parms.useICUfallback) && (status == U_USING_DEFAULT_WARNING)){
204 // in this case we want to return messages from the root bundle
205 status = U_ZERO_ERROR;
206 //cout << "ML::acceptlang.size =1 && !parms.useICUfallback && U_USING_DEFAULT_WARNING" << endl;
|
207 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,"acceptlang.size =1 && !parms.useICUfallback && U_USING_DEFAULT_WARNING, using root bundle.");
|
208 chuck 1.22
209 // Reopen the bundle in the root locale
210 ures_close(resbundl);
211 resbundl = ures_open((const char*)resbundl_path_ICU, "", &status);
212 if(U_SUCCESS(status)) {
213 msg = extractICUMessage(resbundl,parms);
214 ures_close(resbundl);
215 break;
216 }
|
217 humberto 1.12 }
218 else if(acceptlanguages.size() == 1 || parms.useICUfallback){
|
219 humberto 1.4 //cout << "ACCEPTLANGUAGES LOOP: acceptlanguages.size == 1 or useICUfallback true, using ICU fallback behaviour..." << endl;
|
220 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,"ACCEPTLANGUAGES LOOP: acceptlanguages.size == 1 or useICUfallback true, using ICU fallback behaviour...");
|
221 humberto 1.6 msg = extractICUMessage(resbundl,parms);
222
223 String cl_str(ures_getLocale(resbundl,&status));
|
224 chuck 1.22 #ifdef PEGASUS_OS_OS400
225 CString cstr = cl_str.getCString();
226 const char *etoa = cstr;
227 EtoA((char*)etoa);
228 cl_str = etoa;
229 #endif
|
230 humberto 1.6 parms.contentlanguages.append(ContentLanguageElement(cl_str));
|
231 humberto 1.4 ures_close(resbundl);
232 break;
|
233 chip 1.27 }
|
234 humberto 1.4 }
|
235 chip 1.27 else{ // we found an exact resource bundle match, extract, and set ContentLanguage
|
236 humberto 1.4 //cout << "ACCEPTLANGUAGES LOOP: found an EXACT resource bundle MATCH" << endl;
|
237 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,"ACCEPTLANGUAGES LOOP: found an EXACT resource bundle MATCH:");
238 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,language_element.getTag());
|
239 humberto 1.4 msg = extractICUMessage(resbundl,parms);
|
240 chip 1.27 parms.contentlanguages.append(ContentLanguageElement(language_element.getTag()));
241 ures_close(resbundl);
|
242 humberto 1.4 break;
|
243 chip 1.27 }
|
244 humberto 1.4 } else { // possible errors, ex: message path incorrect
245 // for now do nothing, let the while loop continue
|
246 chip 1.27 //cout << "ACCEPTLANGUAGES LOOP: could NOT open a resource for: " << language_element.getTag() << endl;
|
247 humberto 1.4 }
248 status = U_ZERO_ERROR; // reset status
249 }
|
250 chuck 1.22
|
251 humberto 1.2 // now if we DIDNT get a message, we want to enable ICU fallback for the highest priority language
|
252 humberto 1.4 if(msg.size() == 0 && acceptlanguages.size() > 0){
|
253 humberto 1.3 //cout << "USING ICU FALLBACK" << endl;
|
254 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,"No message was loaded, using ICU fallback behaviour.");
|
255 humberto 1.2 language_element = acceptlanguages.getLanguageElement(0);
|
256 humberto 1.6
|
257 chuck 1.22 #ifdef PEGASUS_OS_OS400
|
258 humberto 1.6 CString cstr = language_element.getTag().getCString();
259 const char *atoe = cstr;
260 AtoE((char*)atoe);
261 String tag(atoe);
|
262 chuck 1.22 uloc_getName((const char*)tag.getCString(), locale_ICU, size_locale_ICU, &status);
263 #else
|
264 humberto 1.6 uloc_getName((const char*)(language_element.getTag()).getCString(), locale_ICU, size_locale_ICU, &status);
|
265 chuck 1.22 #endif
|
266 humberto 1.3 //cout << "locale_ICU in fallback = " << locale_ICU << endl;
|
267 humberto 1.6 status = U_ZERO_ERROR;
|
268 humberto 1.4 resbundl = ures_open((const char*)resbundl_path_ICU, locale_ICU, &status);
|
269 humberto 1.6 String cl_str_;
270 if(U_SUCCESS(status)) {
271 if(status == U_USING_DEFAULT_WARNING){
272 //cout << "PRIORITY ICU FALLBACK: using default resource bundle with " << language_element.getTag() << endl;
|
273 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,"PRIORITY ICU FALLBACK: using default resource bundle with ");
274 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4, language_element.getTag());
|
275 humberto 1.6 status = U_ZERO_ERROR;
|
276 chuck 1.22
277 // Reopen the bundle in the root locale
278 ures_close(resbundl);
|
279 humberto 1.6 resbundl = ures_open((const char*)resbundl_path_ICU, "", &status);
280 if(U_SUCCESS(status)) {
281 msg = extractICUMessage(resbundl,parms);
282 cl_str_ = ures_getLocale(resbundl,&status);
283 }
284 }else{
285 msg = extractICUMessage(resbundl,parms);
286 cl_str_ = ures_getLocale(resbundl,&status);
287 }
|
288 chuck 1.22 #ifdef PEGASUS_OS_OS400
|
289 humberto 1.6 CString cstr_ = cl_str_.getCString();
290 const char *etoa = cstr_;
291 EtoA((char*)etoa);
292 cl_str_ = etoa;
|
293 chuck 1.22 #endif
|
294 humberto 1.6 if(cl_str_ != "root")
|
295 chuck 1.22 parms.contentlanguages.append(ContentLanguageElement(cl_str_));
|
296 humberto 1.6 ures_close(resbundl);
|
297 humberto 1.5 }
|
298 humberto 1.2 }
|
299 chuck 1.22
|
300 humberto 1.6 if(msg.size() == 0){ // else if no message, load message from root bundle explicitly
|
301 humberto 1.4 //cout << "EXHAUSTED ACCEPTLANGUAGES: using root bundle to extract message" << endl;
|
302 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,"EXHAUSTED ACCEPTLANGUAGES: using root bundle to extract message");
|
303 chip 1.27 status = U_ZERO_ERROR;
|
304 humberto 1.4 resbundl = ures_open((const char*)resbundl_path_ICU, "", &status);
305 if(U_SUCCESS(status)){
306 //cout << "EXHAUSTED ACCEPTLANGUAGES: opened root resource bundle" << endl;
|
307 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,"EXHAUSTED ACCEPTLANGUAGES: opened root resource bundle");
|
308 humberto 1.4 msg = extractICUMessage(resbundl,parms);
309 //parms.contentlanguages.append(ContentLanguageElement(String(ures_getLocale(resbundl,&status))));
|
310 chuck 1.22 ures_close(resbundl);
|
311 chip 1.27 }else {
312 //cout << "EXHAUSTED ACCEPTLANGUAGES: could NOT open root resource bundle" << endl;
|
313 humberto 1.17 PEG_TRACE_STRING(TRC_L10N, Tracer::LEVEL4,"EXHAUSTED ACCEPTLANGUAGES: could NOT open root resource bundle");
|
314 humberto 1.4 }
315
316 }
317 PEG_METHOD_EXIT();
|
318 chip 1.27 return msg;
|
319 humberto 1.4 }
|
320 chip 1.27
|
321 humberto 1.4 String MessageLoader::extractICUMessage(UResourceBundle * resbundl, MessageLoaderParms &parms){
|
322 chip 1.27 UErrorCode status = U_ZERO_ERROR;
|
323 humberto 1.4 int32_t msgLen = 0;
|
324 humberto 1.6
|
325 chuck 1.22 #ifdef PEGASUS_OS_OS400
|
326 humberto 1.6 CString cstr = parms.msg_id.getCString();
327 const char *atoe = cstr;
328 AtoE((char*)atoe);
329 const UChar *msg = ures_getStringByKey(resbundl, (const char*)atoe, &msgLen, &status);
|
330 chuck 1.22 #else
|
331 humberto 1.4 const UChar *msg = ures_getStringByKey(resbundl, (const char*)parms.msg_id.getCString(), &msgLen, &status);
|
332 chuck 1.22 #endif
|
333 chip 1.27 if(U_FAILURE(status)) {
|
334 humberto 1.4 //cout << "could not extract ICU Message" << endl;
335 return String::EMPTY;
|
336 chip 1.27 }
|
337 humberto 1.4
338 return formatICUMessage(resbundl, msg, msgLen, parms);
339 }
|
340 chip 1.27
|
341 humberto 1.4 String MessageLoader::uChar2String(UChar * uchar_str){
342 return String((const Char16 *)uchar_str);
|
343 chip 1.27 }
344
|
345 humberto 1.4 String MessageLoader::uChar2String(UChar * uchar_str, int len){
346 return String((const Char16 *)uchar_str, len);
347 }
|
348 chip 1.27
|
349 humberto 1.4 String MessageLoader::formatICUMessage(UResourceBundle * resbundl, const UChar * msg, int msg_len, MessageLoaderParms &parms){
|
350 chip 1.27
|
351 humberto 1.4 // format the message
352 UnicodeString msg_pattern(msg, msg_len);
353 UnicodeString msg_formatted;
354 UErrorCode status = U_ZERO_ERROR;
355 const int arg_count = 10;
|
356 vijay.eli 1.31 const char *locale;
|
357 humberto 1.4 if(resbundl == NULL)
358 locale = ULOC_US;
359 else
|
360 vijay.eli 1.32 locale = ures_getLocale(resbundl, &status);
|
361 chip 1.27
|
362 humberto 1.4 //cout << "FORMAT ICU MESSAGE: using locale = " << locale << endl;
|
363 chip 1.27
364 char lang[4];
|
365 humberto 1.4 char cc[4];
366 char var[arg_count];
367 uloc_getLanguage(locale, lang, 4, &status);
368 uloc_getCountry(locale, cc, 4, &status);
369 uloc_getVariant(locale, var, 10, &status);
370 Locale localeID(lang,cc,var);
|
371 chip 1.27
|
372 humberto 1.4 status = U_ZERO_ERROR;
373 MessageFormat formatter(msg_pattern, localeID, status);
|
374 chuck 1.21
|
375 humberto 1.4 Formattable args[arg_count];
|
376 chuck 1.21
377 if (parms.arg0._type != Formatter::Arg::VOIDT)
378 xferFormattable(parms.arg0, args[0]);
379 if (parms.arg1._type != Formatter::Arg::VOIDT)
380 xferFormattable(parms.arg1, args[1]);
381 if (parms.arg2._type != Formatter::Arg::VOIDT)
382 xferFormattable(parms.arg2, args[2]);
383 if (parms.arg3._type != Formatter::Arg::VOIDT)
384 xferFormattable(parms.arg3, args[3]);
385 if (parms.arg4._type != Formatter::Arg::VOIDT)
386 xferFormattable(parms.arg4, args[4]);
387 if (parms.arg5._type != Formatter::Arg::VOIDT)
388 xferFormattable(parms.arg5, args[5]);
389 if (parms.arg6._type != Formatter::Arg::VOIDT)
390 xferFormattable(parms.arg6, args[6]);
391 if (parms.arg7._type != Formatter::Arg::VOIDT)
392 xferFormattable(parms.arg7, args[7]);
393 if (parms.arg8._type != Formatter::Arg::VOIDT)
394 xferFormattable(parms.arg8, args[8]);
395 if (parms.arg9._type != Formatter::Arg::VOIDT)
396 xferFormattable(parms.arg9, args[9]);
397 chuck 1.21
|
398 humberto 1.4 Formattable args_obj(args,arg_count);
399 status = U_ZERO_ERROR;
400 msg_formatted = formatter.format(args_obj, msg_formatted, status);
|
401 chip 1.27
|
402 humberto 1.4 return uChar2String(const_cast<UChar *>(msg_formatted.getBuffer()), msg_formatted.length());
|
403 chip 1.27 }
404
|
405 chuck 1.21 void MessageLoader::xferFormattable(Formatter::Arg& arg, Formattable &formattable)
406 {
407 //cout << "arg" << " = " << arg.toString() << endl;
408 switch (arg._type)
|
409 humberto 1.4 {
|
410 chuck 1.33 case Formatter::Arg::INTEGER:
411 formattable = (int32_t)arg._integer;
412 break;
413 case Formatter::Arg::UINTEGER:
414 // Note: the ICU Formattable class doesn't support
415 // unsigned 32. Cast to signed 64.
416 formattable = (int64_t)arg._uinteger;
417 break;
418 case Formatter::Arg::BOOLEAN:
419 // Note: the ICU formattable class doesn't support
420 // boolean. Turn it into a string.
421 if (!arg._boolean)
422 formattable = Formattable("false");
423 else
424 formattable = Formattable("true");
425 break;
426 case Formatter::Arg::REAL:
427 formattable = (double)arg._real;
428 break;
429 case Formatter::Arg::LINTEGER:
430 // Note: this uses a Formattable constructor that is
431 chuck 1.33 // labelled ICU 2.8 draft. Assumes that Pegasus uses
432 // at least ICU 2.8.
433 formattable = (int64_t)arg._lInteger;
434 break;
435 case Formatter::Arg::ULINTEGER:
436 // Note: the ICU Formattable class doesn't support
437 // unsigned 64. If the number is too big for signed 64
438 // then turn it into a string. This string will
439 // not be formatted for the locale, but at least the number
440 // will appear in the message.
441 if (arg._lUInteger > PEGASUS_UINT64_LITERAL(0x7FFFFFFFFFFFFFFF))
442 {
443 char buffer[32]; // Should need 21 chars max
444 sprintf(buffer, "%" PEGASUS_64BIT_CONVERSION_WIDTH "u", arg._lUInteger);
445 formattable = Formattable(buffer);
446 }
447 else
448 {
449 formattable = (int64_t)arg._lUInteger;
450 }
451 break;
452 chuck 1.33 case Formatter::Arg::STRING:
453 formattable = Formattable((UChar*)arg._string.getChar16Data());
454 break;
|
455 chip 1.27 case Formatter::Arg::VOIDT:
456 default:
|
457 chuck 1.21 formattable = "";
458 break;
|
459 chip 1.27 }
|
460 chuck 1.21 }
461
462
|
463 chuck 1.22 #endif
|
464 chip 1.27
|
465 humberto 1.4 String MessageLoader::formatDefaultMessage(MessageLoaderParms &parms){
|
466 chip 1.27
|
467 humberto 1.4 PEG_METHOD_ENTER(TRC_L10N, "MessageLoader::formatDefaultMessage");
468 // NOTE TO PROGRAMMERS: using native substitution functions
469 // ie. calling Formatter::format()
|
470 chip 1.27 // can result in incorrect locale handling of substitutions
471
|
472 humberto 1.4 // locale INSENSITIVE formatting code
473 //cout << "using locale INSENSITIVE formatting" << endl;
474 parms.contentlanguages.clear(); // this could have previously been set by ICU
475 //cout << parms.toString() << endl;
476 //cout << "ml:" << parms.default_msg << endl;
|
477 kumpf 1.25 PEG_METHOD_EXIT();
|
478 humberto 1.4 return Formatter::format(parms.default_msg,
479 parms.arg0,
480 parms.arg1,
|
481 chip 1.27 parms.arg2,
|
482 humberto 1.4 parms.arg3,
483 parms.arg4,
484 parms.arg5,
485 parms.arg6,
486 parms.arg7,
487 parms.arg8,
488 parms.arg9);
|
489 chip 1.27
|
490 carson.hovey 1.24
|
491 humberto 1.4 }
|
492 chip 1.27
|
493 humberto 1.4 String MessageLoader::getQualifiedMsgPath(String path){
|
494 kumpf 1.25 PEG_METHOD_ENTER(TRC_L10N, "MessageLoader::getQualifiedMsgPath");
|
495 chip 1.27
|
496 humberto 1.4 if(pegasus_MSG_HOME.size() == 0)
|
497 joyce.j 1.34 initPegasusMsgHome(String::EMPTY);
|
498 chip 1.27
499 if(path.size() == 0)
|
500 kumpf 1.25 {
501 PEG_METHOD_EXIT();
|
502 humberto 1.4 return pegasus_MSG_HOME + server_resbundl_name;
|
503 kumpf 1.25 }
|
504 chip 1.27
|
505 humberto 1.4 Char16 delim = '/'; // NOTE TO PROGRAMMERS: WINDOWS and non-UNIX platforms should redefine delim here
506 Uint32 i;
507 if(( i = path.find(delim)) != PEG_NOT_FOUND && i == 0){ // fully qualified package name
|
508 kumpf 1.25 PEG_METHOD_EXIT();
|
509 humberto 1.4 return path;
510 }
|
511 chip 1.27
|
512 kumpf 1.25 PEG_METHOD_EXIT();
|
513 humberto 1.4 return pegasus_MSG_HOME + path; // relative path and package name
|
514 carson.hovey 1.24
|
515 humberto 1.4 }
|
516 chip 1.27
|
517 humberto 1.4 void MessageLoader::setPegasusMsgHome(String home){
518 PEG_METHOD_ENTER(TRC_L10N, "MessageLoader::setPegasusMsgHome");
519 //cout << "MessageLoader::setPegasusMsgHome()" << endl;
520 pegasus_MSG_HOME = home + "/";
|
521 humberto 1.6 // TODO: remove the next call once test cases are compatible with ICU messages
522 checkDefaultMsgLoading();
|
523 humberto 1.4 PEG_METHOD_EXIT();
|
524 chip 1.27 }
|
525 joyce.j 1.34 void MessageLoader::setPegasusMsgHomeRelative(const String& argv0)
526 {
527 #ifdef PEGASUS_HAS_MESSAGES
528 try
529 {
530 String startingDir, pathDir;
531
532 #ifdef PEGASUS_OS_TYPE_WINDOWS
533 if(PEG_NOT_FOUND == argv0.find('\\'))
534 {
535 char exeDir[_MAX_PATH];
536 HMODULE module = GetModuleHandle(NULL);
537 if(NULL != module )
538 {
539 DWORD filename = GetModuleFileName(module,exeDir ,sizeof(exeDir));
540 if(0 != filename)
541 {
542 String path(exeDir);
543 Uint32 command = path.reverseFind('\\');
544 startingDir = path.subString(0, command+1);
545 }
546 joyce.j 1.34 }
547 }
548 else
549 {
550 Uint32 command = argv0.reverseFind('\\');
551 startingDir = argv0.subString(0, command+1);
552 }
553 #endif
554
555 #ifdef PEGASUS_OS_TYPE_UNIX
556 if(PEG_NOT_FOUND != argv0.find('/'))
557 {
558 Uint32 command = argv0.reverseFind('/');
559 startingDir = argv0.subString(0, command+1);
560 }
561 else
562 {
563 if(FileSystem::existsNoCase(argv0))
564 {
565 FileSystem::getCurrentDirectory(startingDir);
566 startingDir.append("/");
567 joyce.j 1.34 }
568 else
569 {
570 String path;
571 #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
572 #pragma convert(37)
573 const char* env = getenv("PATH");
574 if(env != NULL)
575 EtoA((char*)env);
576 #pragma convert(0)
577 #else
578 const char* env = getenv("PATH");
579 #endif
580 if (env != NULL)
581 path.assign(env);
582 String pathDelim = FileSystem::getPathDelimiter();
583 Uint32 size = path.size();
584 while(path.size() > 0)
585 {
586 try
587 {
588 joyce.j 1.34 Uint32 delim = path.find(pathDelim);
589 if(delim != PEG_NOT_FOUND)
590 {
591 pathDir = path.subString(0,delim);
592 path.remove(0,(delim+1));
593 }
594 else
595 {
596 pathDir = path;
597 path = "";
598 }
599 String commandPath = pathDir.append('/');
600 commandPath = commandPath.append(argv0) ;
601 Boolean dirContent = FileSystem::existsNoCase(commandPath);
602 if(dirContent)
603 {
604 startingDir = pathDir;
605 break;
606 }
607 }
608 catch(Exception &e)
609 joyce.j 1.34 {
610 //Have to do nothing.
611 //Catching the exception if there is any exception while searching in the path variable
612 }
613 }
614 }
615 }
616 #endif
617 initPegasusMsgHome(startingDir);
618 }
619 catch(Exception &e)
620 {
621 //Have to do nothing.
622 //Catching the exception if there is any exception while searching in the path variable
623 }
624 #endif
625 }
626
627
628 void MessageLoader::initPegasusMsgHome(const String & startDir)
629 {
630 joyce.j 1.34 String startingDir = startDir;
631 if (startingDir.size() == 0)
632 {
|
633 david 1.15 #ifdef PEGASUS_PLATFORM_OS400_ISERIES_IBM
634 #pragma convert(37)
|
635 joyce.j 1.34 const char* env = getenv("PEGASUS_MSG_HOME");
636 if(env != NULL)
637 EtoA((char*)env);
|
638 david 1.15 #pragma convert(0)
639 #else
|
640 joyce.j 1.34 const char* env = getenv("PEGASUS_MSG_HOME");
|
641 david 1.15 #endif
|
642 joyce.j 1.34
643 if (env != NULL)
644 startingDir.assign(env);
645 }
646
|
647 david 1.15 #ifdef PEGASUS_DEFAULT_MESSAGE_SOURCE
|
648 joyce.j 1.34 if(System::is_absolute_path(
649 (const char *)PEGASUS_DEFAULT_MESSAGE_SOURCE))
650 {
651 pegasus_MSG_HOME = PEGASUS_DEFAULT_MESSAGE_SOURCE;
652 pegasus_MSG_HOME.append('/');
653 }
654 else
655 {
656 if (startingDir.size() != 0)
657 {
658 pegasus_MSG_HOME = startingDir;
659 pegasus_MSG_HOME.append('/');
660 }
661 pegasus_MSG_HOME.append(PEGASUS_DEFAULT_MESSAGE_SOURCE);
662 pegasus_MSG_HOME.append('/');
663 }
|
664 david 1.15 #else
|
665 joyce.j 1.34 if (startingDir.size() != 0)
666 {
667 pegasus_MSG_HOME = startingDir;
668 pegasus_MSG_HOME.append("/");
669 }
670 else
671 {
672 // Will use current working directory
673 }
|
674 chip 1.27 #endif
|
675 joyce.j 1.34 checkDefaultMsgLoading();
676 }
|
677 chip 1.27
|
678 humberto 1.6 void MessageLoader::checkDefaultMsgLoading(){
|
679 chuck 1.13 // Note: this function is a special hook for the automated tests (poststarttests)
680 // Since the automated tests expect the old hardcoded default messages, an env var
681 // will be used to tell this code to ignore ICU and return the default message.
682 // This will allow poststarttests to run with ICU installed.
683 // TODO: remove this function once test cases are compatible with ICU messages
|
684 chuck 1.14 #ifdef PEGASUS_OS_OS400
685 #pragma convert(37)
686 #endif
|
687 chuck 1.13 const char* env = getenv("PEGASUS_USE_DEFAULT_MESSAGES");
|
688 chuck 1.14 #ifdef PEGASUS_OS_OS400
|
689 chip 1.27 #pragma convert(0)
690 #endif
|
691 chuck 1.13 if (env != NULL)
|
692 chip 1.27 _useDefaultMsg = true;
|
693 humberto 1.4 }
694
|
695 karl 1.20 MessageLoaderParms::MessageLoaderParms()
696 {
697 useProcessLocale = false;
698 useThreadLocale = true;
|
699 chip 1.27
|
700 chuck 1.22 #ifdef PEGASUS_HAS_ICU
|
701 karl 1.20 useICUfallback = false;
|
702 chuck 1.22 #endif
|
703 chip 1.27
|
704 karl 1.20 acceptlanguages = AcceptLanguages();
705 contentlanguages = ContentLanguages();
706 }
707
|
708 chip 1.27 MessageLoaderParms::MessageLoaderParms(
709 const String& id,
710 const String& msg,
711 const Formatter::Arg& arg0,
|
712 karl 1.20 const Formatter::Arg& arg1,
713 const Formatter::Arg& arg2,
714 const Formatter::Arg& arg3,
715 const Formatter::Arg& arg4,
716 const Formatter::Arg& arg5,
717 const Formatter::Arg& arg6,
718 const Formatter::Arg& arg7,
719 const Formatter::Arg& arg8,
720 const Formatter::Arg& arg9)
721 {
722 msg_id = id;
723 default_msg = msg;
724 _init();
725 this->arg0 = arg0;
726 this->arg1 = arg1;
727 this->arg2 = arg2;
728 this->arg3 = arg3;
729 this->arg4 = arg4;
730 this->arg5 = arg5;
731 this->arg6 = arg6;
732 this->arg7 = arg7;
733 karl 1.20 this->arg8 = arg8;
734 this->arg9 = arg9;
|
735 chip 1.27 }
|
736 karl 1.20
|
737 chip 1.27 MessageLoaderParms::MessageLoaderParms(
738 const String& id,
|
739 karl 1.20 const String& msg)
740 {
741 msg_id = id;
742 default_msg = msg;
743 _init();
744 }
745
|
746 chip 1.27 MessageLoaderParms::MessageLoaderParms(
747 const String& id,
748 const String& msg,
|
749 karl 1.20 const Formatter::Arg& arg0)
750 {
751 msg_id = id;
752 default_msg = msg;
753 _init();
754 this->arg0 = arg0;
755 }
756
|
757 chip 1.27 MessageLoaderParms::MessageLoaderParms(
758 const String& id,
759 const String& msg,
|
760 karl 1.20 const Formatter::Arg& arg0,
761 const Formatter::Arg& arg1)
762 {
763 msg_id = id;
764 default_msg = msg;
765 _init();
766 this->arg0 = arg0;
767 this->arg1 = arg1;
768 }
769
|
770 chip 1.27 MessageLoaderParms::MessageLoaderParms(
771 const String& id,
772 const String& msg,
|
773 karl 1.20 const Formatter::Arg& arg0,
774 const Formatter::Arg& arg1,
775 const Formatter::Arg& arg2)
776 {
777 msg_id = id;
778 default_msg = msg;
779 _init();
780 this->arg0 = arg0;
781 this->arg1 = arg1;
782 this->arg2 = arg2;
783 }
784
|
785 chip 1.27 MessageLoaderParms::MessageLoaderParms(
786 const String& id,
787 const String& msg,
|
788 karl 1.20 const Formatter::Arg& arg0,
789 const Formatter::Arg& arg1,
790 const Formatter::Arg& arg2,
791 const Formatter::Arg& arg3)
792 {
793 msg_id = id;
794 default_msg = msg;
795 _init();
796 this->arg0 = arg0;
797 this->arg1 = arg1;
798 this->arg2 = arg2;
799 this->arg3 = arg3;
800 }
801
802 MessageLoaderParms::MessageLoaderParms(
|
803 chip 1.27 const char* id,
|
804 karl 1.20 const char* msg)
805 {
806 msg_id = id;
807 default_msg = msg;
808 _init();
809 }
810
811 MessageLoaderParms::MessageLoaderParms(
|
812 chip 1.27 const char* id,
813 const char* msg,
|
814 karl 1.20 const String& arg0)
815 {
816 msg_id = id;
817 default_msg = msg;
818 _init();
819 this->arg0 = arg0;
820 }
821
822 MessageLoaderParms::MessageLoaderParms(
|
823 chip 1.27 const char* id,
824 const char* msg,
|
825 karl 1.20 const String& arg0,
826 const String& arg1)
827 {
828 msg_id = id;
829 default_msg = msg;
830 _init();
831 this->arg0 = arg0;
832 this->arg1 = arg1;
833 }
834
835 void MessageLoaderParms::_init()
836 {
837 useProcessLocale = false;
838 useThreadLocale = true;
|
839 chip 1.27
|
840 karl 1.20 #ifdef PEGASUS_HAS_ICU
841 useICUfallback = false;
842 #endif
|
843 chip 1.27
|
844 karl 1.20 acceptlanguages = AcceptLanguages::EMPTY;
845 contentlanguages = ContentLanguages::EMPTY;
846
847 this->arg0 = Formatter::DEFAULT_ARG;
848 this->arg1 = Formatter::DEFAULT_ARG;
849 this->arg2 = Formatter::DEFAULT_ARG;
850 this->arg3 = Formatter::DEFAULT_ARG;
851 this->arg4 = Formatter::DEFAULT_ARG;
852 this->arg5 = Formatter::DEFAULT_ARG;
853 this->arg6 = Formatter::DEFAULT_ARG;
854 this->arg7 = Formatter::DEFAULT_ARG;
855 this->arg8 = Formatter::DEFAULT_ARG;
856 this->arg9 = Formatter::DEFAULT_ARG;
857 }
858
859 String MessageLoaderParms::toString()
860 {
861 String s;
862 String processLoc,threadLoc,ICUfallback;
863 processLoc = (useProcessLocale) ? "true" : "false";
864 threadLoc = (useThreadLocale) ? "true" : "false";
|
865 chuck 1.22 #ifdef PEGASUS_HAS_ICU
|
866 karl 1.20 ICUfallback = (useICUfallback) ? "true" : "false";
|
867 chuck 1.22 #endif
|
868 chip 1.27
|
869 karl 1.20 s.append("msg_id = " + msg_id + "\n");
870 s.append("default_msg = " + default_msg + "\n");
871 s.append("msg_src_path = " + msg_src_path + "\n");
872 s.append("acceptlanguages = " + acceptlanguages.toString() + "\n");
873 s.append("contentlanguages = " + contentlanguages.toString() + "\n");
|
874 chip 1.27
|
875 karl 1.20 s.append("useProcessLocale = " + processLoc + "\n");
876 s.append("useThreadLocale = " + threadLoc + "\n");
|
877 chuck 1.22 #ifdef PEGASUS_HAS_ICU
|
878 karl 1.20 s.append("useICUfallback = " + ICUfallback + "\n");
|
879 chuck 1.22 #endif
|
880 chip 1.27 s.append("arg0 = " + arg0.toString() + "\n" + "arg1 = " + arg1.toString() + "\n" + "arg2 = " + arg2.toString() + "\n" + "arg3 = " + arg3.toString() + "\n" +
881 "arg4 = " + arg4.toString() + "\n" + "arg5 = " + arg5.toString() + "\n" + "arg6 = " + arg6.toString() + "\n" + "arg7 = " + arg7.toString() + "\n" +
|
882 karl 1.20 "arg8 = " + arg8.toString() + "\n" + "arg9 = " + arg9.toString() + "\n\n");
|
883 chip 1.27
|
884 karl 1.20 return s;
885 }
|
886 humberto 1.4
|
887 karl 1.20 MessageLoaderParms::~MessageLoaderParms()
888 {
889 }
|
890 humberto 1.4
|
891 karl 1.20 PEGASUS_NAMESPACE_END
|