1 chuck 1.5 <!DOCTYPE doctype PUBLIC "-//w3c//dtd html 4.0 transitional//en">
|
2 chuck 1.1 <html>
3 <head>
|
4 chuck 1.5 <meta http-equiv="Content-Type"
5 content="text/html; charset=iso-8859-1">
6 <meta name="GENERATOR"
7 content="Mozilla/4.78 [en] (X11; U; Linux 2.4.7-10 i686) [Netscape]">
|
8 chuck 1.1 </head>
|
9 chuck 1.5 <body text="#000000" bgcolor="#ffffff" link="#0000ef" vlink="#55188a"
10 alink="#ff0000">
|
11 chuck 1.6 <center>
12 <p><big><big><big>Globalization HOWTO</big></big></big></p>
|
13 chuck 1.5 <p>Release: Pegasus 2.3 </p>
14 <p>Author: Chuck Carmack (carmack@us.ibm.com) </p>
|
15 chuck 1.6 <p>December 1, 2003</p>
|
16 chuck 1.5 </center>
17 <p><br>
|
18 chuck 1.6 Change History:<br>
19 </p>
20 <table cellpadding="2" cellspacing="2" border="1"
21 style="text-align: left; width: 100%; margin-left: auto; margin-right: auto;">
22 <tbody>
23 <tr>
24 <td style="vertical-align: top;">01/12/03<br>
25 </td>
26 <td style="vertical-align: top;">carmack<br>
27 </td>
28 <td style="vertical-align: top;">Section 2.2.2. Changed how
29 the package name parameter should be used. It should no longer be
30 used as part of the table name inside the bundle.<br>
31 </td>
32 </tr>
|
33 marek 1.7 <tr>
34 <td style="vertical-align: top;">08/04/06<br>
35 </td>
36 <td style="vertical-align: top;">Marek Szermutzky<br>
37 </td>
38 <td style="vertical-align: top;">Section 2.2.5. Added information how to write platform specific messages.<br>
39 </td>
40 </tr>
|
41 sushma.fernandes 1.9 <tr>
42 <td style="vertical-align: top;">01/23/07<br>
43 </td>
44 <td style="vertical-align: top;">Sushma Fernandes<br>
45 </td>
46 <td style="vertical-align: top;">Section 2.2.5. Added information on special considerations while creating a new message.<br>
47 </td>
48 </tr>
|
49 chuck 1.6 </tbody>
50 </table>
51 <p><br>
|
52 chuck 1.5 </p>
53 <h2> 1.0 Introduction</h2>
54 <p><br>
55 As part of the Pegasus 2.3 release, functions were added for
56 globalization support. Globalization involves two major
57 aspects: internationalization and localization. <br>
58 </p>
59 <p>Internationalization is the process of writing a program that is
60 locale-neutral. In other words, the program should be able to run
61 in any locale without change. There are several categories in a
62 locale, including the language of message strings, date format, time
|
63 chuck 1.6 format, etc. For release 2.3, the Pegasus server is concerned with
64 the language of the message strings it returns to its clients. <br>
|
65 chuck 1.5 </p>
66 <p>To support internationalization, a program is designed to do the
67 following: <br>
68 </p>
69 <blockquote> <li> Support character sets that can represent customer
70 data in any language. Typically, the program supports some
71 variation of Unicode for internal data. There is usually some
72 conversion between the supported character sets for external data, and
73 the internal character set. Since Unicode covers all characters,
74 and usually has converters on the platform, it is a good choice for the
75 'normalized' internal character set. The most
76 'interoperable' solution for external data is to support UTF-8 (eg.
|
77 chuck 1.6 network and file system data). The internal data is usually UTF-16
78 (or UCS-2, but that is deprecated).</li>
|
79 chuck 1.5 <br>
80 <li> Extract locale-sensitive resources, such as message
81 strings, from the code to external resource files. Typically, the
82 resources are loaded based on the locale requested by the end-user, and
83 returned to the end-user for display.</li>
|
84 chuck 1.1 </blockquote>
|
85 chuck 1.5 <p><br>
86 Localization is the process of customizing a software product to
87 support particular locales. For example, a product that is
88 internationalized might want to only localize for certain
89 countries. This would mean that the localized resources (eg.
90 message files) would only be translated and shipped for the countries
91 that the product supports. Since the code for the product is
92 locale-neutral, it will be easy to drop in new translations as more
93 countries are supported. <br>
94 </p>
|
95 chuck 1.1 <p>The Pegasus 2.3 release added support for globalization. At a
|
96 chuck 1.5 high-level, the following additions were made to Pegasus 2.3: <br>
97 </p>
|
98 chuck 1.1 <ul>
|
99 chuck 1.5 <li> Support UTF-8 for external data.</li>
100 <br>
101
102 <ul>
103 <li> The CIM-XML documents contained in the HTTP messages</li>
104 <li> The files in the repository</li>
105 <li> Note: Pegasus 2.3 does NOT support UTF-8 in the MOF
106 files</li>
107 <br>
108
109 </ul>
110 <li> Support UTF-16 for internal data.</li>
111 <br>
112 <li> Extract the hardcoded messages from the Pegasus code into
113 message files. An API was added to load messages from the message
114 files.</li>
115 <br>
116 <li> APIs were added for clients to associate a language with
|
117 chuck 1.6 the CIM objects they are sending to Pegasus. Also, APIs were added
118 for clients to determine the language of the error message or CIM
|
119 chuck 1.5 object that Pegasus returns.</li>
120 <br>
121 <li> APIs were added for providers to determine the language of
122 CIM objects sent by the client. Also, APIs were added for
|
123 chuck 1.6 providers to associate a language with the CIM object, or error message,
124 they return to the client.</li>
|
125 chuck 1.1 </ul>
|
126 chuck 1.5 <p><br>
127 Please refer to PEPs 56 and 58 for details about the globalization
128 design in Pegasus 2.3. <br>
129 </p>
130 <p>This document provides a HOWTO guide to be used by developers to
131 globalize code that is being added to Pegasus. The audience for
132 this document are: <br>
133 </p>
|
134 chuck 1.1 <ul>
|
135 chuck 1.5 <li> Provider developers - both CMPI and C++</li>
136 <li> Client developers</li>
137 <li> Pegasus developers</li>
|
138 chuck 1.1 </ul>
|
139 chuck 1.5 <p><br>
140 The quickest way to approach this document is to read the General
141 section, and then the developer section that relates to what you are
142 doing. <br>
143 </p>
144 <h2> 2.0 General</h2>
|
145 chuck 1.1
|
146 chuck 1.5 <h3> 2.1 Unicode Support</h3>
147 <p><br>
148 Pegasus 2.3 supports Unicode throughout the processing of
149 requests. External data to Pegasus is encoded in UTF-8.
150 Internal data is encoded in UTF-16. <br>
151 </p>
|
152 chuck 1.4 <p>UTF-8 support for external data includes the CIM-XML messages passed
|
153 chuck 1.5 over the network, and the repository files. Note: UTF-8
154 support was NOT added to the MOF Compiler for MOF files in release
155 2.3. For the CIM-XML messages, Pegasus follows section 4.8 of
156 the <a
157 href="http://www.dmtf.org/standards/documents/WBEM/DSP200.html">CIM-HTTP
|
158 chuck 1.1 specification</a> Specifically, Pegasus supports the
159 "utf-8" setting for the charset parameter of the Content-Type header and
160 the XML encoding attribute. If no charset is specified, the 7-bit
|
161 chuck 1.5 ASCII is assumed. <br>
162 </p>
|
163 chuck 1.1 <p>The internal support of UTF-16 is encapsulated in the Pegasus String
|
164 chuck 1.5 class. This class has been updated to contain UTF-16
165 characters. Specifically, the Char16 objects inside the String
166 contain UTF-16 characters. Note: a UTF-16 surrogate pair is
167 contained in two consecutive Char16 objects. To keep backwards
168 compatibilty, the methods on the String class have not changed.
169 New methods have been added as needed. The following describes
170 this in more detail: </p>
|
171 chuck 1.1 <ul>
|
172 chuck 1.5 <li> The Pegasus 2.2 methods that take a char *, or return char *, are
173 unchanged. Code written to Pegasus 2.2 may have expected to store
174 8-bit ASCII (ISO-8859-1) characters into String. These methods
|
175 chuck 1.6 will convert the input to UTF-16 from 8-bit ASCII. (This is simple
176 because UTF-16 is a superset of 8-bit ASCII - simply need to prepend
177 '\0' to each char). The Pegasus 2.2 methods that return char data
178 will attempt to convert from the UTF-16 internal representation to
179 8-bit ASCII. Characters that cannot be converted will be replaced
180 with a substitution character.</li>
|
181 chuck 1.5 <br>
182 <li> All methods that take or return Char16 data are
183 unchanged. The String class now supports UTF-16 data in Char16,
184 although surrogate pairs will require two consecutive Char16
|
185 chuck 1.6 objects. The String class does NO checking for unmatched surrogate
186 pairs.</li>
|
187 chuck 1.5 <br>
188 <li> New methods have been added to take and return UTF-8
189 data. The String class will convert between UTF-8 and the UTF-16
|
190 chuck 1.6 internal representation as needed. These new methods will use char
191 * parameters, but will be clearly labelled as UTF-8 methods.</li>
|
192 chuck 1.5 <br>
193
194 </ul>
195 PROGRAMMING NOTE: Putting EBCDIC data into the String class is
196 dangerous. The String class is designed for UTF-16, which is a
197 superset of 8-bit ASCII. Any String object containing EBCDIC data
198 will not work if it is used by Pegasus to read or write data from
199 external sources, such as the network or repository files. In
|
200 chuck 1.6 other words, any String containing EBCDIC data should not leave the code
201 using it. <br>
|
202 chuck 1.5 <br>
203
204 <h3> 2.2 Localization Support</h3>
|
205 chuck 1.1
|
206 chuck 1.5 <h4> 2.2.1 Language Headers</h4>
207 <p><br>
208 Pegasus 2.3 supports clients and providers that wish to localize.
209 There are two areas to be localized: <a
210 href="http://www.dmtf.org/standards/documents/WBEM/DSP201.html#SecERROR">ERROR</a>
211 elements in the CIM-XML; and <a
212 href="http://www.dmtf.org/standards/documents/WBEM/DSP201.html#SecObjectDefinitionElements">Object
213 Definition</a> elements in the CIM-XML. Clients can
214 request the server to return error messages and CIM objects in a
215 set of languages of their choosing. Clients can also tag a
216 language to the CIM objects they are sending to the server.
217 Providers and the server can return error messages and CIM objects that
218 are tagged with one of languages requested by the client. <br>
219 </p>
220 <p>The localization design is based on section 4.8 of the <a
221 href="http://www.dmtf.org/standards/documents/WBEM/DSP200.html">CIM-HTTP
222 specification</a> , which refers to <a
223 href="http://www.ietf.org/rfc/rfc2616.txt?number=2616">RFC 2616</a>.
224 The method used to tag a language to the CIM-XML is through the
225 Accept-Language and Content-Language HTTP headers. These headers
|
226 chuck 1.1 are basically lists of language tags. An HTTP request can contain
|
227 chuck 1.5 an Accept-Language header, which indicates the list of preferred
228 languages that the client wants in the response. This list can be
229 prioritized by using the quality numbers. An HTTP request or
230 response can contain a Content-Language header, which indicates the
231 language(s) of the content in the message. In the Pegasus case,
232 this would be the CIM-XML. Note that the Content-Language header
233 is a list of language tags. This allows the content of an HTTP
234 message to contain more than one translation. However, in the
235 Pegasus case, there is only one CIM-XML document in the HTTP message,
236 and thus one translation. <br>
237 </p>
238 <p>CIM clients may use the Accept-Language HTTP header to specify the
239 languages they wish to be returned in the CIM response message.
|
240 chuck 1.6 CIM clients may also use the Content-Language header to tag the language
241 of any CIM objects they are sending to the server in the CIM request
242 message. The server, and providers, should attempt to return
243 error messages and CIM objects in one of the accept languages requested
244 by the client. The server and providers should set the
245 Content-Language header in the CIM response message to indicate which of
246 the requested languages they are returning. <br>
|
247 chuck 1.5 </p>
|
248 chuck 1.1 <p>NOTE: Localization support was not added for the MOF files and
|
249 chuck 1.5 repository in Pegasus 2.3. The #pragma locale, #pragma
250 instancelocale, and translatable qualifier flavor are not supported in
251 the Pegasus 2.3 MOF compiler. From the client perspective,
252 classes, qualifiers, and instances stored in the repository are not
253 tagged with a language. The Accept-Language and Content-Language
254 headers will be ignored for repository operations. However, since
|
255 chuck 1.6 the repository will support UTF-8, characters for any language may
256 be stored there. <br>
|
257 chuck 1.5 </p>
|
258 chuck 1.1 <p>NOTE: Since the Content-Language header applies to the entire
|
259 chuck 1.5 HTTP message, it applies to the entire CIM-XML document. This
260 includes all the objects in the document, including enumerated objects,
261 and all the values in the objects. This is a limitation that will
262 remain until the CIM standard has been updated to support language tags
263 tied to individual CIM values. From the client perspective, it is
264 possible for Pegasus to send a CIM response with NO Content-Language,
|
265 chuck 1.6 even if the client had sent Accept-Language. This can happen
266 if Pegasus does not know the language of the response. An example
267 is a request that was sent to a Pegasus 2.2 provider. Another
268 example is an enumerated response where each provider returned a
269 different language. Please refer to PEP58 for details on these
|
270 chuck 1.5 provider scenarios. <br>
271 </p>
|
272 kumpf 1.8 <p>
273 The Accept-Language and Content-Language headers are encapsulated
274 in AcceptLanguageList and ContentLanguageList classes, respectively.
275 These classes contain LanguageTag objects. The AcceptLanguageList class
276 keeps its LanguageTags prioritized based on quality,
|
277 chuck 1.5 according to RFC 2616. <br>
278 </p>
|
279 kumpf 1.8 <p>AcceptLanguageList and ContentLanguageList are the objects used by code
|
280 chuck 1.5 throughout the request/response processing, from the client to the
281 server to the providers and back. The server handles the creation
282 of these objects from the HTTP headers. Code at each point in the
283 process will have access to these objects. <br>
284 </p>
|
285 kumpf 1.8 <p>Please refer to the following files for details on the Pegasus
286 language interfaces.<br>
|
287 chuck 1.5 </p>
|
288 chuck 1.1 <ul>
|
289 kumpf 1.8 <li> pegasus/src/Pegasus/Common/AcceptLanguageList.h</li>
290 <li> pegasus/src/Pegasus/Common/ContentLanguageList.h</li>
291 <li> pegasus/src/Pegasus/Common/LanguageTag.h</li>
|
292 chuck 1.1 </ul>
|
293 chuck 1.5 <p><br>
294 See the sections below for details on how to write clients and
295 providers to use these classes. <br>
296 <br>
297 </p>
298 <h4> 2.2.2 Message Bundles</h4>
299 <p><br>
300 One of the goals of globalization for Pegasus 2.3 is the extraction of
301 hardcoded messages into translated message files, loading
302 translated messages from those files, and returning those messages to
303 the client. The topics to be discussed here are: how to
304 create message files, how to compile message files, and how to load
305 messages into Pegasus. <br>
306 </p>
|
307 chuck 1.1 <p>At the time of writing, the message loading function in Pegasus 2.3
|
308 chuck 1.5 used the International Components for Unicode (<a
309 href="http://oss.software.ibm.com/icu">ICU)</a> libraries. This
310 is expected to be the future direction for Pegasus. <a
311 href="http://oss.software.ibm.com/icu">ICU </a>uses a resource bundle
312 format for their message files. In order to load the
313 messages, ICU requires that the resource bundles are compiled into a
314 binary form (.res file) using their genrb tool. <br>
315 </p>
316 <p>Platform Maintainers Note: Please refer to PEP 58 for
317 information about how to build Pegasus to use the ICU libraries. <br>
318 </p>
319 <p>The documentation for ICU resource bundles is in the <a
320 href="http://oss.software.ibm.com/icu/userguide/ResourceManagement.html">Resource
321 Management</a> section of the <a
322 href="http://oss.software.ibm.com/icu/userguide/">ICU User Guide</a>
|
323 chuck 1.6 . This section will tell you how to create and organize your
324 resource bundles for different languages. Note: your
325 resource bundles should be organized in a tree structure similiar to
326 the one shown in the Resource Management section, including the empty
327 bundles in the tree. <br>
328 </p>
329 <p><br>
330 It is recommended that you ship a root resource bundle to be used as
331 the fallback in case the client requests a language that you are not
|
332 chuck 1.5 supporting. The Pegasus make files are set up to automatically
333 create and compile a root resource bundle for you. For Pegasus
334 2.3, the make will use your "en" bundle, upper case all the messages,
335 and then put the uppercased messages into the root bundle. The
336 uppercasing of the messages is necessary to create a "fallback" root
|
337 chuck 1.6 bundle that contains invariant characters across all EBCDIC and
|
338 chuck 1.5 ASCII codepages. <br>
339 </p>
340 <p>NOTE: When creating your resource bundles, the name of the
|
341 chuck 1.6 table resource should <span style="font-style: italic;">not</span>
342 contain the package name. For example, if you <br>
343 have a bundle with a package name of "xyz", then the "en" bundle should
344 start like this: </p>
345 <p><br>
346 en:table { <br>
347 ..... messages here <br>
348
349 }</p>
350 <p><i>not</i> like this:</p>
|
351 chuck 1.5 <p>xyz_en:table { <br>
352 ..... messages here <br>
353
354 } <br>
|
355 chuck 1.6 <br>
356 </p>
357 <p>This is needed because the package name (-p) option is used by the
358 Pegasus make files on the call to genrb. <br>
|
359 chuck 1.5 </p>
|
360 chuck 1.1 <p>NOTE: Pegasus 2.3 only supports simple string resources in the
|
361 chuck 1.5 ICU resource bundles. String resources may only be loaded by
362 key. Tables, arrays, and other complex resource types, are not
363 supported. <br>
364 </p>
|
365 chuck 1.2 <p>In order to compile your resource bundles, support has been added to
|
366 chuck 1.5 the Pegasus make files to run genrb. A new make target,
367 "messages", has been added that will call genrb and put the compiled
368 bundles (.res) in a directory of your choosing. An example of ICU
369 resource bundles and the make files to compile them are located in: <br>
370 </p>
|
371 chuck 1.2 <ul>
|
372 chuck 1.5 <li> pegasus/src/Providers/sample/LocalizedProvider/Makefile (just
373 causes the make to recurse to the msg sub-directory)</li>
374 <li> pegasus/src/Providers/sample/LocalizedProvider/msg/Makefile
375 (compiles the bundles in the msg/ directory)</li>
376 <li> pegasus/src/Providers/sample/LocalizedProvider/msg/*.txt (the
377 resource bundles to compile, using the recommended ICU language tree
378 structure)</li>
|
379 chuck 1.2 </ul>
|
380 chuck 1.5 <p><br>
381 NOTE: At the time of writing, only the Linux make files have been
382 updated to compile ICU resource bundles. <br>
383 </p>
384 <p>It is important to place the compiled resource bundles in a
385 directory where your code can find them . The make files above
386 compile the resource bundles into
387 $PEGASUS_HOME/msg/provider/localizedProvider. The code that loads
388 these messages uses the MessageLoader class (next section) to load
389 messages from this directory. <br>
390 <br>
391 </p>
392 <h4> 2.2.3 Message Loading</h4>
393 <p><br>
394 Code that needs to load a message in Pegasus does not call ICU
395 directly. Two message loading classes were added for Pegasus
|
396 chuck 1.6 2.3: MessageLoader and MessageLoaderParms. These classes are
397 abstractions designed to hide of the actual loader used (but note that
398 at the time of writing, only ICU is supported). The
|
399 chuck 1.5 MessageLoader is used to load a message using a list of preferrred
400 languages. The parameters to MessageLoader are encapsulated in a
401 MessageLoaderParms object. <br>
402 </p>
403 <p>The MessageLoader is the place where the Accept-Language header,
404 Content-Language header, and the ICU resource bundles, join up.
|
405 kumpf 1.8 The MessageLoader class is designed to receive an AcceptLanguageList
|
406 chuck 1.5 object, and a set of parameters indicating the bundle base-name and
|
407 kumpf 1.8 message ID to use. The AcceptLanguageList object contains the list of
|
408 chuck 1.6 requested languages sent by the client. The MessageLoader
409 searches for the message in the set of bundles named with the base-name,
|
410 kumpf 1.8 using the AcceptLanguageList for the list of specific translated bundles
|
411 chuck 1.6 to search. The MessageLoader returns the message that it found,
|
412 kumpf 1.8 along with a ContentLanguageList object indicating the language of the
413 message. The ContentLanguageList object should be used to indicate
|
414 chuck 1.6 the language of the response sent back to the client. <br>
|
415 chuck 1.5 </p>
416 <p>The MessageLoaderParms object contains the parameters to load the
417 message. There are many parameters, but many can be allowed to
418 default. Here is a description of the parameters: <br>
419 <br>
420
421 <table border="1" cols="3" width="100%" nosave="">
422 <tbody>
423 <tr>
424 <td>String msg_id; </td>
425 <td>Input. <br>
426 Required.</td>
427 <td>Message ID of the message to load from the resource
428 bundle. This is the key that ICU will use to load the message.</td>
429 </tr>
430 <tr>
431 <td>String default_msg;</td>
432 <td>Input. <br>
433 Required</td>
434 <td>Message to return if the no message can be loaded for msg_id
435 from any resource bundle. Note: The args parameters below
436 chuck 1.5 are substituted into this string. <br>
437 Note: For the args into this string, use the Pegasus '$'
438 form, as described in pegasus/src/Pegasus/Common/Formatter.h.
439 Don't use the ICU substitution format for the default message string.</td>
440 </tr>
441 <tr>
442 <td>String msg_src_path; </td>
443 <td>Input. <br>
444 Optional <br>
445 Default: $PEGASUS_HOME/msg/pegasus/pegasusServer</td>
|
446 chuck 1.6 <td>Path to the resource bundle file which contains the
|
447 chuck 1.5 msg_id. <br>
448 Note: Only specify the path down to the bundle base-name. Do not
449 append a language tag, such as "_root" or "_en". Do not append a
450 file extension. <br>
451 Note: relative paths start at $PEGASUS_HOME/msg. <br>
452 Note: defaults to the bundle containing the Pegasus server messages.</td>
453 </tr>
454 <tr>
|
455 kumpf 1.8 <td>AcceptLanguageList acceptlanguages;</td>
|
456 chuck 1.5 <td>Input. <br>
457 Optional <br>
|
458 kumpf 1.8 Default: AcceptLanguageList()</td>
|
459 chuck 1.5 <td>Contains the list of preferred languages, in priority
460 order. This is combined with msg_src_path to determine which
|
461 chuck 1.6 resource bundles to search for for the msg_id. If not empty,
462 overrides useThreadLocale and useProcessLocale.</td>
|
463 chuck 1.5 </tr>
464 <tr>
|
465 kumpf 1.8 <td>ContentLanguageList contentlanguages;</td>
|
466 chuck 1.5 <td>Output</td>
467 <td>Contains the language that MessageLoader found for the
468 msg_id. </td>
469 </tr>
470 <tr>
471 <td>Boolean useProcessLocale;</td>
472 <td>Input <br>
473 Optional <br>
474 Default = false</td>
475 <td>If true, MessageLoader will use the default locale of the
476 process. If true, overrides useThreadLocale.</td>
477 </tr>
478 <tr>
479 <td>Boolean useThreadLocale;</td>
480 <td>Input <br>
481 Optional <br>
482 Default = <font color="#ff0000">true</font></td>
|
483 kumpf 1.8 <td>If true, MessageLoader will use the AcceptLanguageList set by
|
484 chuck 1.5 Pegasus into the caller's Thread. See the Note below for
485 details. </td>
486 </tr>
487 <tr>
488 <td>Formatter::Arg arg0; <br>
489 Formatter::Arg arg1; <br>
490 Formatter::Arg arg2; <br>
491 Formatter::Arg arg3; <br>
492 Formatter::Arg arg4; <br>
493 Formatter::Arg arg5; <br>
494 Formatter::Arg arg6; <br>
495 Formatter::Arg arg7; <br>
496 Formatter::Arg arg8; <br>
497 Formatter::Arg arg9;</td>
498 <td>Input <br>
499 Optional <br>
500 Default: Formatter::Arg( ) // empty arg</td>
501 <td>These are the substitution variables, using the Pegasus
502 Formatter::Arg class.</td>
503 </tr>
504 </tbody>
|
505 chuck 1.1 </table>
|
506 chuck 1.5 </p>
507 <p>Notes: <br>
508 </p>
509 <p>The "useThreadLocale" parameter defaults to true. This flag
|
510 kumpf 1.8 indicates to use the AcceptLanguageList object set by Pegasus into the
|
511 chuck 1.5 Pegasus Thread in which the caller's code is running. This
|
512 kumpf 1.8 AcceptLanguageList object reflects the languages requested by the
|
513 chuck 1.5 client. This is useful for code that may not have access to the
|
514 kumpf 1.8 AcceptLanguageList from the client. Pegasus sets this AcceptLanguageList
|
515 chuck 1.6 object into the Thread of providers and internal Pegasus code.
516 For this reason, it is recommended that provider and internal Pegasus
517 code use the "useThreadLocale" flag instead of explicity passing in an
|
518 kumpf 1.8 AcceptLanguageList object. See the Provider Developer and Pegasus
|
519 chuck 1.6 Developer sections for details. <br>
|
520 chuck 1.5 </p>
|
521 chuck 1.2 <p>The "useProcessLocale" flag can be used to tell MessageLoader to use
522 the default locale of the process, as determined by ICU. This is
|
523 chuck 1.5 useful for situations where the caller is not localizing for a client
|
524 chuck 1.6 request. The caller may itself be a client (eg. cimconfig), or may
525 need to log messages to the system log in the locale of the Pegasus
|
526 chuck 1.5 server process. See the CLI Messages and Logger Messages sections
527 below. <br>
528 </p>
529 <p>"Master switch" <br>
530 The MessageLoader class has a public static Boolean variable called
|
531 kumpf 1.8 _useProcessLocale that may be used to override all the AcceptLanguageList
|
532 chuck 1.5 and useThreadLocale settings in the MessageLoaderParms objects passed
533 in. This is useful for CLI code (eg cimconfig) that needs to
534 localize its messages based on the locale of its process, which refects
535 the locale set by the user running the CLI (eg. $LANG on Unix).
536 The CLI code may call Pegasus APIs that are coded to use the Thread's
|
537 kumpf 1.8 AcceptLanguageList, which will not be set in this case. The
|
538 chuck 1.5 _useProcessLocale static variable tells the MessageLoader to ignore the
|
539 kumpf 1.8 AcceptLanguageList, useThreadLocale, and useProcessLocale settings in
|
540 chuck 1.5 MessageLoaderParms that it gets. The MessageLoader will use the
541 default process locale, as determined by ICU, in this case. <br>
542 </p>
|
543 denise.eckstein 1.10 <p><i>Important Note:</i> The MessageLoader does <i>not</i> use
|
544 chuck 1.5 the "fallback" mechanism described in the ICU Resource Management
545 section. This is because the Accept-Language header itself
|
546 kumpf 1.11 describes the fallback that the client wants. If the
|
547 denise.eckstein 1.10 MessageLoader cannot find a message file for any of the languages
|
548 kumpf 1.11 in the AcceptLanguageList, it will try the default process locale.
|
549 denise.eckstein 1.10 If this fails, the ICU root resource bundle will be tried.<br>
|
550 chuck 1.5 </p>
551 <p>Please refer to the following files for details on the new Pegasus
552 classes. <br>
553 </p>
|
554 chuck 1.1 <ul>
|
555 chuck 1.5 <li> pegasus/src/Pegasus/Common/MessageLoader.h</li>
|
556 chuck 1.1 </ul>
|
557 chuck 1.5 <h4> 2.2.4 Message Loading Example</h4>
558 <p><br>
559 The following example shows how a message may be loaded using the
|
560 chuck 1.2 classes described above. Note: this a generic example. Each
|
561 chuck 1.5 of the developer sections below have 'real-life' examples that are
562 better suited to each type of code. </p>
|
563 kumpf 1.8 <p>// Build an AcceptLanguageList with some language elements <br>
564 AcceptLanguageList acceptLangs; <br>
565 acceptLangs.insert(LanguageTag("fr"), 0.5); <br>
566 acceptLangs.insert(LanguageTag("de"), 0.8); <br>
567 acceptLangs.insert(LanguageTag("es"), 0.4); </p>
|
568 chuck 1.5 <p>// Construct a MessageLoaderParms <br>
569 MessageLoaderParms parms("msgID", "default message"); <br>
570 parms. msg_src_path = "/my_msg_dir/my_bundle"; <br>
571 parms.acceptlanguages = acceptLangs; </p>
572 <p>// Note: If you have args, set them into MessageLoaderParms </p>
573 <p>// Load the localized String <br>
574 String localizedMsg = MessageLoader::getMessage(parms); <br>
575 <br>
576 </p>
|
577 marek 1.7 <h4> 2.2.5 Message Writing Guidelines</h4>
|
578 chuck 1.5 <p><br>
579 Here are some basic rules for writing messages: <br>
580 </p>
|
581 chuck 1.1 <ul>
|
582 chuck 1.5 <li> If you want to claim that you are globalized, no hardcoded
583 messages!</li>
|
584 chuck 1.6 <li> Avoid creating a message in the code by combining other
585 messages. When you do this you are assuming that you know the
586 grammar for every language.</li>
|
587 chuck 1.5 <li> String substitutions into messages are generally untranslated,
588 ie. not loaded from the resource bundle. Example: a file
589 name.</li>
590 <li> Avoid jargon, humour, and cultural idioms. Use full
591 sentences. Have your messages reviewed by your globalization
592 team. Your messages need to make sense to the translators, and
593 ultimately the customer.</li>
594 <li> <b>TODO </b>- find a good message writing guide to link to</li>
|
595 chuck 1.1 </ul>
|
596 marek 1.7
597 <p><b>When do I create a new message ?</b></p>
598
599 <p>A new message should be created if a message is needed with a content not
600 described by any existing message.</p>
601
602 <p>A new message should be created if the number or placement of substitution
603 parameters of an existing message would require an update.</p>
604
605 <p>It is not necessary to create a new message if just the text of the message
606 is changed, while the meaning is kept. For instance if the
607 event(error,warning,whatever) is described more precisely by the new message
608 text, it is not necessary to create a new message, but the existing one should
609 be updated.</p>
610
|
611 sushma.fernandes 1.9 <p><b>Are there any special considerations while creating a new message ? </b></p>
612
613 <ul>
614 <li>If a message definition contains text within a single quote
|
615 kumpf 1.11 it is not interpreted in any way.
|
616 sushma.fernandes 1.9
617 <p><i>Example:</i></p>
618 <p> Server.CIMOperationRequestAuthorizer.NOT_IN_AUTHORIZED_GRP:
619 string {"PGS05202: User '{0}' is not authorized to access CIM data."}
620 </p>
621
622 <p><i>Processed message:</i></p>
623 <p> User {0} is not authorized to access CIM data. </p>
624 </li>
625
626 <li> For a single quote to appear in a processed message, it needs to be preceded by
|
627 kumpf 1.11 another single quote.
|
628 sushma.fernandes 1.9
629 <p><i>Example:</i></p>
630 <p> Server.CIMOperationRequestAuthorizer.NOT_IN_AUTHORIZED_GRP:
631 string {"PGS05202: User ''{0}'' is not authorized to access CIM data."}
632 </p>
633
634 <p><i>Processed message:</i></p>
635 <p> User 'wbemuser' is not authorized to access CIM data. </p>
636 </li>
637
638 <li> For a double quote to appear in a processed message, it needs to be preceded by
|
639 kumpf 1.11 a back slash.
|
640 sushma.fernandes 1.9
641 <p><i>Example:</i></p>
642 <p>
643 ControlProviders.ProviderRegistrationProvider.ProviderRegistrationProvider.
|
644 kumpf 1.11 UNSUPPORTED_USERCONTEXT_VALUE:string {"PGS03029: Unsupported UserContext
645 value: \"{0}\"."}
|
646 sushma.fernandes 1.9 </p>
647
648 <p><i>Processed message:</i></p>
649 <p> Unsupported UserContext value: "10". </p>
650 </li>
651 </ul>
652
653 <p> </p>
654
|
655 marek 1.7 <p><b>How do I write a platform specific
656 message ? </b></p>
657
658 <p>Platform specific messages generate in a non-platform specific source file
659 should be formatted with a .<platform> or .STANDARD suffix.</p>
660
661 <p><i>Example:</i></p>
662 <p>Compiler.cmdline.cimmof.cmdline.MENU.PEGASUS_OS_HPUX</p>
663 <p>Compiler.cmdline.cimmof.cmdline.MENU.PEGASUS_OS_OS40</p>
664 <p>Compiler.cmdline.cimmof.cmdline.MENU.STANDARD</p>
665
666 <p> </p>
667
668 <p><b>Where should I place platform specific
669 messages ? </b></p>
670
671 <p>As described in the message bundle file pegasusServer_en.txt messages belong
672 into the section corresponding the file they are created in. This does account
673 the same to platform specific messages.</p>
674 <p>If a message is generated inside a source file not specific to a single
675 platform, the message should be part of the message bundle section of that
676 marek 1.7 source file.</p>
677 <p>If a new platform specific message is generated inside a platform specific
678 source file, the message belongs to the platform specific section of the
679 message bundle file.</p>
680
681 <p><i>Examples:</i></p>
682
683 <p>ProviderManager.ProviderAgent.ProviderAgent.UNINITIALIZED_SECURITY_SETUP.PEGASUS_OS_ZOS
684 - this message is and should be part of the section for the ProviderAgent as it
685 is generated inside the provider agent and not a z/OS platform specific file</p>
686 <p>Common.safCheckzOS_inline.BAD_WBEM_SECURITY_SETUP - this message does and
687 should reside inside the platform specific section as the message is generated
688 in a z/OS platform only file</p>
689
690 <p> </p>
691
|
692 chuck 1.5 <h4> 2.2.5 Localized Exceptions</h4>
693 <p><br>
694 The base Exception class, and derived classes, have been updated to
695 support localization. Constructors have been added that take a
696 MessageLoaderParms object. These constructors will use the
697 MessageLoaderParms object to call the MessageLoader to load the
|
698 chuck 1.6 localized exception message. The localized message is saved in the
|
699 kumpf 1.8 Exception. The ContentLanguageList object returned by MessageLoader
|
700 chuck 1.6 is also saved in the Exception. This indicates the language of
|
701 kumpf 1.8 the message. The ContentLanguageList object is used later to set the
|
702 chuck 1.6 Content-Language header in the HTTP message to the client. <br>
|
703 chuck 1.5 </p>
|
704 chuck 1.2 <p>The old Exception constructors that take a String will remain.
705 These should be used in cases where the code throwing the exception is
|
706 chuck 1.5 not localized, or the String is not localized (for example, a file
707 name). Also, there are several exceptions in Pegasus where the
708 String parameter is meant to be a non-localized substitution in a
709 localized message owned by the Exception (see InternalException.h,
710 ClassNotResolved for an example). The old constructors for these
711 have been kept. <br>
712 <br>
713 </p>
714 <h2> 3.0 Provider Developers</h2>
|
715 chuck 1.1
|
716 chuck 1.5 <h3> 3.1 Design Issues</h3>
717 <p><br>
718 Providers that wish to globalize should consider the following in their
719 design: <br>
720 </p>
|
721 chuck 1.1 <ul>
|
722 chuck 1.5 <li> Are there localized string properties that need to be
723 supported? If so, then the client will use Accept-Language to
|
724 chuck 1.6 request specific languages for these properties. If the properties
725 are read-only, use MessageLoader to load the localized strings for the
726 properties.</li>
|
727 chuck 1.5 <li> If you have a localized read/write string property, then the
728 client will use Content-Language to set the property with an associated
729 language. The client will expect to be able to retrieve the
730 property in that same language later (using Accept-Language).</li>
731 <li> Note: only the string property types in CIM are candidates for
732 localization. The other types, including datetime, are
733 locale-neutral.</li>
734 <li> Are there error messages that need to returned to the client in
735 different languages? The client will use Accept-Language to
736 request specific languages for the error messages.</li>
737 <li> What resource bundle translations, if any, will be shipped with
738 the provider?</li>
739 <li> Do any codepage conversions need to be done between the UTF-16
740 characters in the String objects and the codepage of data stored on the
741 system? This is a concern for EBCDIC platforms. All EBCDIC
742 data needs to be converted to at least 7-bit ASCII before it is passed
743 into the String object.</li>
|
744 chuck 1.1 </ul>
|
745 chuck 1.5 <p><br>
746 To help providers handle the situations described above, Pegasus 2.3
747 will pass the Accept-Language received from the client to the
748 provider. The provider should load strings from its resource
749 bundle based on the client's Accept-Language. The client's
750 Accept-Language is passed to the provider in two ways: <br>
751 </p>
|
752 chuck 1.1 <ul>
|
753 chuck 1.5 <li> Pegasus will set the Accept-Language from the client into the
754 thread in which the provider is running. By using the
|
755 chuck 1.6 useThreadLocale setting in MessageLoaderParms, providers can easily load
756 strings using the client's requested Accept-Language. The
|
757 chuck 1.5 provider does not need to know what the Accept-Language is. This
|
758 chuck 1.6 is the recommended method to load messages based on the client's request.</li>
|
759 chuck 1.5 <br>
|
760 kumpf 1.8 <li> The OperationContext will contain an AcceptLanguageList object
|
761 chuck 1.6 that has the Accept-Language requested by the client. The provider
|
762 kumpf 1.8 can use this AcceptLanguageList object to load strings with MessageLoader.</li>
|
763 chuck 1.1 </ul>
|
764 chuck 1.5 <p><br>
|
765 kumpf 1.8 The OperationContext will also contain a ContentLanguageList object that
|
766 chuck 1.5 is set from the Content-Language in the client request. This is
767 the language of the CIM objects being passed to the provider on that
768 request. A localized provider should store the content language
769 along with the data from the CIM objects. This will allow the
770 client to use Accept-Language later to retreive the data in that
771 language. <br>
772 </p>
773 <p>The provider should indicate the language of CIM objects it is
774 returning by calling setContext( ) on the ResponseHandler. This
775 will be used to set the Content-Language in the CIM response message
776 sent back to the client. If setContext( ) is not called, then no
|
777 chuck 1.6 Content-Language will be returned to the client. The setContext( )
778 function should only be called once per response. <br>
|
779 chuck 1.5 </p>
780 <h3> 3.2 Sample Code</h3>
781 <p><br>
782 The following sample code shows a localized getInstance( ) where the
783 instance returned is localized based on the Accept-Language of the
784 client request. Note that this example also throws a localized
785 exception. <br>
786 </p>
787 <p>void LocalizedProvider::getInstance( <br>
788 const OperationContext & context, <br>
789 const CIMObjectPath & instanceReference, <br>
790 const Boolean includeQualifiers, <br>
791 const Boolean includeClassOrigin, <br>
792 const CIMPropertyList & propertyList, <br>
793 InstanceResponseHandler & handler) <br>
794 { <br>
795 // convert a potential fully qualified
796 reference into a local reference <br>
797 // (class name and keys only). <br>
798 CIMObjectPath localReference = CIMObjectPath( <br>
799 String(), <br>
800 chuck 1.5 String(), <br>
801
802 instanceReference.getClassName(), <br>
803
804 instanceReference.getKeyBindings()); </p>
805 <p> // begin processing the request <br>
806 handler.processing(); </p>
807 <p> // Find the instance to be returned. <br>
808 Uint32 i; <br>
809 Uint32 n = _instances.size(); <br>
810 for (i = 0; i < n; i++) <br>
811 { <br>
812
813 if(localReference == _instanceNames[i]) <br>
814 { <br>
815
816 // We found the instance to return </p>
|
817 chuck 1.1 <p>
|
818 chuck 1.5 // Build the parameters for loading the localized string property. <br>
819
820 // We are going to let the message loader parameters default to use the <br>
821
|
822 kumpf 1.8 // AcceptLanguageList that Pegasus set into our thread. <br>
|
823 chuck 1.5
|
824 kumpf 1.8 // (this equals the AcceptLanguageList requested by the client) <br>
|
825 chuck 1.5
826 // Note: This parms object could be constructed once and <br>
827
828 // reused. <br>
829
830 MessageLoaderParms parms("myMsgID", "myDefaultString"); <br>
831
832 parms.msg_src_path = "/myprovider/msg/myResourceBundle"; </p>
|
833 chuck 1.1 <p>
|
834 chuck 1.5 // Load the string for the localized property from the resource bundle <br>
835
836 String localizedString = MessageLoader::getMessage(parms); </p>
|
837 chuck 1.1 <p>
|
838 chuck 1.5 // Remove the old property from the instance to be returned <br>
839
840 Uint32 index = instances[i].findProperty("myProperty"); <br>
841
842 if (index != PEG_NOT_FOUND) <br>
843
844 { <br>
845
846 _instances[i].removeProperty(index); <br>
847
848 } </p>
|
849 chuck 1.1 <p>
|
850 chuck 1.5 // Add the localized string property to the instance <br>
851
852 instances[i].addProperty(CIMProperty("myProperty", localizedString)); </p>
|
853 chuck 1.1 <p>
|
854 chuck 1.5 // The MessageLoader set the contentlanguages member <br>
855
856 // of parms to the language that it found for the message. <br>
857
|
858 kumpf 1.8 ContentLanguageList rtnLangs = parms.contentlanguages; </p>
|
859 chuck 1.1 <p>
|
860 chuck 1.5 // We need to tag the instance we are returning with the <br>
861 // the
862 content language. <br>
863
864 OperationContext context;<br>
865
866 context.insert(ContentLanguageListContainer(rtnLangs));<br>
867
868 handler.setContext(context);<br>
869 </p>
870
871 // deliver requested instance<br>
872
|
873 chuck 1.1 handler.deliver(_instances[i]);
874 <p>
|
875 chuck 1.5 break; <br>
876
877 } // end if <br>
878
879 } //
880 end for </p>
|
881 chuck 1.1 <p> // throw an exception if
|
882 chuck 1.5 the instance wasn't found <br>
883 if (i == n) <br>
884 { <br>
885
886 // Build the parameters for loading the localized error message. <br>
887
888 // We are going to let the message loader parameters default to use the <br>
889
|
890 kumpf 1.8 // AcceptLanguageList that Pegasus set into our thread. <br>
|
891 chuck 1.5
|
892 kumpf 1.8 // (this equals the AcceptLanguageList requested by the client) <br>
|
893 chuck 1.5
894 // Note: This parms object could be constructed once and <br>
895
896 // reused. <br>
897
898 MessageLoaderParms errParms("myErrorMsgID", "myErrorDefaultString"); <br>
899
900 errParms.msg_src_path = "/myprovider/msg/myResourceBundle"; </p>
|
901 chuck 1.1 <p>
|
902 chuck 1.5 // Note: the exception calls MessageLoader::getMessage( ) <br>
903
904 // Note: no need to call handler.setContext( ) in this case <br>
905
906 throw CIMObjectNotFoundException(errParms); <br>
907 } <br>
908 </p>
909 <p> // complete processing
910 the request <br>
911 handler.complete(); <br>
912 } <br>
913 </p>
|
914 chuck 1.1 <p>NOTE: A sample provider has been written that fully demonstates the
|
915 chuck 1.5 design issues described above. This provider is located at: <br>
916 </p>
|
917 chuck 1.1 <ul>
|
918 chuck 1.5 <li> pegasus/src/Providers/sample/LocalizedProvider/</li>
|
919 chuck 1.1 </ul>
|
920 chuck 1.5 <p><br>
921 This sample provider also demonstrates how some of the special issues
922 can be handled. The special issues are caused by having a
923 read/only localized property and a read/write localized property.
924 What happens if the client sets the read/write property with a
925 Content-Language that is not one of the supported languages for the
926 read/only property? This provider allows the client to set any
|
927 chuck 1.6 language into the read/write property, and get that property back in the
928 same language. This becomes an issue when the client does a
|
929 chuck 1.5 getInstance( ) later, because the Content-Language on the returned
|
930 chuck 1.6 instance applies to all the properties. A related issue is what to
931 return for Content-Language when the client does enumerateInstances,
|
932 chuck 1.5 but the instances have different languages. Recall that
|
933 chuck 1.6 Content-Language applies to the entire response (a limitation in the CIM
934 specification). <br>
|
935 chuck 1.5 </p>
936 <p>NOTE: Indication Providers have other special considerations
937 for language support. Please refer to PEP58. <br>
938 </p>
939 <p>NOTE: The CMPI interface has been updated for language
940 support. Please refer to the CMPI documentation for details. <br>
941 </p>
942 <p>NOTE: SPECIAL ISSUES FOR OS/400 PROVIDERS: </p>
|
943 chuck 1.1 <ul>
|
944 chuck 1.5 <li> Convert between UTF-16 in the String objects and EBCDIC system
945 data as needed. The converters in
946 Pegasus/Common/OS400ConvertChar.h may be used to convert between EBCDIC
947 CCSID 37 and ASCII CCSID 819 (a subset of UTF-16).</li>
948 <li> The Pegasus program, and all bound service programs, will
949 run in a UTF-8 locale even though the job CCSID is 37. The
950 C-runtime library (printf, fopen, isalpha, strcmp, etc) will expect
951 UTF-8, or at least 7-bit ASCII, characters.</li>
952 <li> Consideration should be given to the codepage for the compiled
953 string literals. Use #pragma convert as needed. But,
954 remember that the C-runtime will expect UTF-8.</li>
955 <li> For more details, refer to "Unicode support" in chapter 3 of the <u>ILE
|
956 chuck 1.1 C/C++ for iSeries Run-Time Functions, Version 5</u> publication for V5R3
957 (SC41-5607-02). The Pegasus string literals will be compiled with
|
958 chuck 1.5 the UTF-8 compile switch described in this section. OS/400
959 provider developers should strongly consider using the same compile
|
960 chuck 1.6 switch for their string literals. This would allow the literals to
961 match the UTF-8 encoding expected by the C-runtime.</li>
|
962 chuck 1.1 </ul>
|
963 chuck 1.5 <h2> 4. 0 Client Developers</h2>
964 <p><br>
965 Methods have been added to CIMClient to set the Accept-Language and
966 Content-Language on the request, and retrieve Content-Language on the
967 response. The language tags in the Accept-Language header must
968 meet the ISO-639 and ISO-3166 standards. <br>
969 </p>
970 <p>Please refer to <br>
971 </p>
|
972 chuck 1.1 <ul>
|
973 chuck 1.5 <li> pegasus/src/Pegasus/Client/CIMClient.h</li>
974 <br>
975
976 </ul>
977 for the new methods on CIMClient. <br>
978
979 <p>Here is a code fragment that uses the new methods on CIMClient </p>
980 <p> // <br>
981 // Get a localized instance in French <br>
982 // </p>
983 <p> // Language priority is martian, pig-latin, and
984 french. We should <br>
985 // get french back, even though its the lowest priority <br>
|
986 kumpf 1.8 AcceptLanguageList acceptLangs; <br>
987 acceptLangs.insert(LanguageTag("x-martian"), 1.0); <br>
988 acceptLangs.insert(LanguageTag("fr"), 0.1); <br>
989 acceptLangs.insert(LanguageTag("x-pig-latin"), 0.4); </p>
|
990 chuck 1.5 <p> // Set the requested languages into the CIMClient <br>
991 client.setRequestAcceptLanguages(acceptLangs); </p>
992 <p> // Get the instance <br>
993 CIMInstance instance = client.getInstance( <br>
994 NAMESPACE, <br>
995 cimNInstances[0].buildPath(sampleClass), <br>
996 localOnly, <br>
997 includeQualifiers, <br>
998 includeClassOrigin); </p>
999 <p> // Get the string property that should be french <br>
1000 String returnedString; <br>
1001 instance.getProperty ( <br>
1002 instance.findProperty("myProp")). <br>
1003
1004 getValue(). <br>
1005
1006 get(returnedString); </p>
1007 <p> // Check that we got back french <br>
|
1008 kumpf 1.8 ContentLanguageList CL_FR(); <br>
1009 CL_FR.append(LanguageTag("fr")); <br>
|
1010 chuck 1.5 String expectedFRString = "oui"; <br>
1011 PEGASUS_ASSERT(CL_FR == client.getResponseContentLanguages()); <br>
1012 PEGASUS_ASSERT(expectedFRString == returnedString); </p>
1013 <p> // <br>
1014 // Create an instance in French <br>
1015 // </p>
1016 <p> String oui = "Oui"; <br>
1017 CIMInstance frInstance(CLASSNAME); <br>
1018 frInstance.addProperty(CIMProperty( <br>
1019
1020 CIMName("myProp"), <br>
1021
1022 oui)); </p>
1023 <p> CIMObjectPath frInstanceName =
1024 frInstance.buildPath(sampleClass); </p>
1025 <p> client.setRequestContentLanguages(CL_FR); </p>
1026 <p> client.createInstance(NAMESPACE, frInstance); <br>
1027 <br>
1028 <br>
1029 </p>
1030 <p>Also, refer to </p>
|
1031 chuck 1.1 <ul>
|
1032 chuck 1.5 <li> pegasus/src/Clients/g11ntest/</li>
|
1033 chuck 1.1 </ul>
|
1034 chuck 1.5 for more examples of a client that uses Accept-Language and
1035 Content-Language. <br>
1036
|
1037 chuck 1.1 <p>NOTE: Consideration should be given for converting the UTF-16
1038 characters in the String objects passed over the CIMClient interface to
|
1039 chuck 1.5 a platform codepage. This is especially needed for EBCDIC
1040 platforms. See the Provider developer section for details of the
1041 EBCDIC considerations. <br>
1042 <br>
1043 </p>
1044 <h3> 4.1 Default Process Locale</h3>
1045 <p><br>
1046 A method has been added to CIMClient to set the Accept-Language for the
1047 requests based on the default locale of the process, as determined by
1048 ICU. If ICU is installed on the client system then CIMClient will
1049 set the Accept-Language from the default ICU process locale. If
1050 ICU is not installed then the caller is required to set an
|
1051 kumpf 1.8 AcceptLanguageList into CIMClient that meets the ISO-639 and IS0-3166
|
1052 chuck 1.5 standards. Note: this is useful for local clients, such as
1053 the Pegasus CLIs, where ICU would be installed on both the client and
1054 server sides. <br>
1055 <br>
1056 </p>
1057 <h2> 5. 0 Pegasus Developers</h2>
1058 <p><br>
1059 The design for Pegasus releases beyond 2.3 is to avoid using hardcoded
1060 messages. All new messages should be loaded from a Pegasus
1061 resource bundle. This section describes the process to follow if
1062 you are creating a new message. The process depends on where you
1063 are in the code. <br>
1064 <br>
1065 </p>
1066 <h3> <b>5.1 Pegasus Resource Bundles</b></h3>
1067 <p><br>
1068 Place any new Pegasus messages into one of the following resource
1069 bundles: <br>
1070 </p>
|
1071 chuck 1.1 <ul>
|
1072 chuck 1.5 <li> pegasus/src/Pegasus/msg/Server/pegasusServer_*.txt for
1073 server and MOF compiler (cimmof, cimmofl) messages</li>
1074 <li> pegasus/src/Pegasus/msg/CLI/pegasusCLI_*.txt for all CLI messages
1075 (except the MOF compiler)</li>
|
1076 chuck 1.1 </ul>
|
1077 chuck 1.5 <p><br>
1078 The make messages target will compile these resource bundles. </p>
1079 <p>Note: As described above, the resource bundle path in
|
1080 chuck 1.6 MessageLoaderParms defaults to the server resource bundle. For CLI
1081 messages, you will need to specify the bundle for your CLI. <br>
|
1082 chuck 1.5 </p>
1083 <h3> 5.2 Server Messages</h3>
1084 <p><br>
1085 For messages returned from one of the services in the Pegasus server
|
1086 chuck 1.1 (eg. CIMOperationRequestDispatcher, or ProviderManagerService), the goal
1087 is to make it easy for any code in the call chain to throw an exception
|
1088 chuck 1.5 with a localized error string. The code throwing the exception
1089 will not need to know the Accept-Language that the client
1090 requested. To understand how this works, some design points need
1091 to described: <br>
1092 </p>
1093 <p><b>Server Design Points:</b> <br>
1094 </p>
1095 <p>The CIMMessage object has been expanded to include an
|
1096 kumpf 1.8 AcceptLanguageList object and a ContentLanguageList object in its
1097 OperationContext member. For
|
1098 chuck 1.5 CIMRequestMessage, these objects contain the Accept-Language and
1099 Content-Language headers that were built from the client request.
|
1100 kumpf 1.8 For CIMResponseMessage, the ContentLanguageList object is used to build the
|
1101 chuck 1.6 Content-Language header associated with the CIM <i>objects </i>in the
|
1102 kumpf 1.8 response message. The AcceptLanguageList object in the
|
1103 chuck 1.5 CIMResponseMessage is ignored. <br>
1104 </p>
1105 <p>The localization of the cimException object in the
|
1106 chuck 1.6 CIMResponseMessage is handled separately from the CIM objects. The
1107 message string in the cimException object is assumed to have been
|
1108 chuck 1.5 localized by the time it is built into the XML. For this reason,
1109 the localization of the exception is the responsibility of the code
1110 throwing the exception. (The goal of the design is to make that
|
1111 kumpf 1.8 easy - see below). The ContentLanguageList object in the
|
1112 chuck 1.5 CIMResponseMessage has NO relation to this exception. The
1113 cimException object keeps its own localization information once it is
1114 created. <br>
1115 </p>
|
1116 chuck 1.1 <p>To enable exceptions to be localized, the ability was added to set a
|
1117 chuck 1.5 global language for all the code running from a Pegasus Thread
1118 object. The top level code for a Thread can set a global
|
1119 kumpf 1.8 AcceptLanguageList object that can be accessed by all the low-level
|
1120 chuck 1.5 functions that it calls. This will allow an exception thrown by
1121 the low-level function to be localized based on this global
|
1122 kumpf 1.8 AcceptLanguageList object. Note: This applies only to Threads
|
1123 chuck 1.5 that are managed by a ThreadPool. <br>
1124 </p>
1125 <p>Each service in the request path of the Pegasus server sets the
|
1126 kumpf 1.8 AcceptLanguageList into its Thread from the AcceptLanguageList in the
|
1127 chuck 1.5 CIMRequestMessage object that it dequeues. This sets the global
1128 langauge for all the functions in the same thread that are called below
|
1129 chuck 1.6 handleEnqueue. <i>If you are writing a new service that processes
1130 requests, or discover a request service that was missed, please do
1131 this. </i> The CIMOperationRequestDispatcher service is an example. <br>
|
1132 chuck 1.5 </p>
1133 <p><b>How to Throw a Localized Exception from Server code:</b> <br>
1134 </p>
1135 <p>With all that background, here is how code running in a Pegasus
1136 service can throw a localized exception: <br>
1137 This example assumes that the top-level code in the service had set the
|
1138 kumpf 1.8 global thread AcceptLanguageList beforehand. As described above,
|
1139 chuck 1.5 every service in Pegasus should do that. The code here may be
1140 buried several layers deep in the call chain, but does not need to know
|
1141 kumpf 1.8 the AcceptLanguagList of the current client request. </p>
|
1142 chuck 1.5 <p>// First, construct a MessageLoaderParms <br>
1143 // <br>
1144 // Notes: <br>
1145 // 1) The errorMessageID must be in the Pegasus server resource
1146 bundle. <br>
1147 // 2) The default message is the old "hardcoded" message. <br>
1148 // 3) The MessageLoaderParms will default to use the Pegasus
1149 server resource bundle <br>
1150 // 4) The MessageLoaderParms will default to use the
|
1151 kumpf 1.8 AcceptLanguageList set into the current Thread. Don't change this! <br>
|
1152 chuck 1.5 // 5) You might need to set the arguments for the message into
1153 the MessageLoaderParms <br>
1154 MessageLoaderParms parms("errorMessageID", "default message"); </p>
1155 <p>// Second, throw the Exception <br>
1156 // Note: this applies to all the derived classes from Exception,
1157 including the CIMException's <br>
1158 throw new Exception(parms); <br>
1159 </p>
|
1160 chuck 1.1 <p>NOTE: If you are throwing an Exception with un-localized data,
1161 use the constructor that takes a String. An example of this would
1162 be an Exception where you are passing in a file name. Most of the
1163 "non-CIM" exceptions defined in Exception.h and InternalException.h take
|
1164 chuck 1.5 un-localized data. <br>
1165 </p>
1166 <p><b>The Exception Macros</b> <br>
1167 </p>
1168 <p>There are many spots in the server code that use the
1169 PEGASUS_CIM_EXCEPTION macro to throw a TraceableCIMException. The
1170 use of this macro in the code like the following example presented a
1171 design problem: </p>
1172 <p>.... <br>
1173 } catch (Exception & e) <br>
1174 { <br>
1175 throw PEGASUS_CIM_EXCEPTION(CIM_ERR_FAILED,
1176 e.getMessage()); <br>
1177 } <br>
1178 </p>
|
1179 kumpf 1.8 <p>This type of code would have lost the ContentLanguageList saved in "e",
|
1180 chuck 1.5 so that the Content-Language would not be set in HTTP response to the
1181 client. <br>
1182 </p>
1183 <p>For Pegasus 2.3, these types of macro calls can stay. The
|
1184 chuck 1.6 TraceableCIMException constructed by the macro will "re-localize".
1185 That is, the "CIM" part of the message (the part based on the error
|
1186 kumpf 1.8 code) will be localized at throw time, and the ContentLanguageList
|
1187 chuck 1.6 re-established. A key is to avoid a "language mismatch" problem
1188 between the CIM part of the message and the extra part of the
1189 message. The design point here is that all internal exceptions
|
1190 kumpf 1.8 thrown by Pegasus code are localized using the global AcceptLanguageList
|
1191 chuck 1.6 of the Thread...see above. <br>
|
1192 chuck 1.5 </p>
1193 <p>In the future, it will be safer and more maintainable to use of
1194 the new "localized" flavors of the macro. For example: <br>
1195 </p>
1196 <p>When the message from a caught Exception needs to be become
1197 the extra message in a thrown CIMException: </p>
1198 <p>.... <br>
1199 } catch (Exception & e) <br>
1200 { <br>
1201 throw
1202 PEGASUS_CIM_EXCEPTION_LANG(e.getContentLanguages( ), <br>
1203
1204 CIM_ERR_FAILED, <br>
1205
1206 e.getMessage( )); <br>
1207 } <br>
1208 </p>
|
1209 kumpf 1.8 <p>This guarantees that the ContentLanguageList in "e" is copied to the
|
1210 chuck 1.5 newly created TraceableCIMException. <br>
1211 </p>
1212 <p>In the case where the extra message for the CIMException is
1213 determined by the throwing code: <br>
1214 </p>
1215 <p>throw PEGASUS_CIM_EXCEPTION_L(CIM_ERR_FAILED, <br>
1216
1217 MessageLoaderParms("Repository.CIMRepository.COMPACT_FAILED",
1218 "compact failed")); <br>
1219 </p>
1220 <p>(example from CIMRepository.cpp) <br>
1221 This uses a MessageLoaderParms object to localize the extra message in
1222 the newly created TraceableCIMException. <br>
1223 </p>
1224 <h3> 5.2 Logger Messages</h3>
1225 <p><br>
1226 New methods have been added to Logger to take a message ID of a message
1227 to be loaded from the Pegasus server resource bundle. The caller
|
1228 chuck 1.6 is only required to pass in the message ID, the old "hardcoded" message,
1229 and the args. The Logger will use MessageLoader to load the
1230 message in the locale of the Pegasus server <i>process</i>, using the
1231 hardcoded message as the default string. Please refer to
|
1232 chuck 1.5 pegasus/src/Pegasus/Logger.h. </p>
|
1233 chuck 1.2 <p>Note: Messages sent to the "logs", whether the system logs or
|
1234 chuck 1.5 the Pegasus log file, are converted to UTF-8 before being sent. <br>
1235 </p>
1236 <h3> 5.3 CLI Messages</h3>
1237 <p><br>
1238 The goal for messages returned by the Pegasus CLIs is to localize in
1239 the locale of the user running the CLI. This should be automatic
1240 -- the user should not be required to tell the CLI what the locale
1241 is. For the CLIs that are CIM clients (cimconfing,
1242 cimprovider) there are two sets of messages to localize --
|
1243 chuck 1.6 messages generated in the CLI process itself, and messages returned from
1244 the Pegasus server . For CLIs that are directly linked into
|
1245 chuck 1.5 Pegasus (cimmofl), all the messages are generated in the CLI's process,
1246 but the CLI may call Pegasus APIs that are coded to localize based on a
1247 client's requested languages. <br>
1248 </p>
1249 <p>Code in the client side of the client/server CLIs (eg. cimconfig,
1250 cimmof), or in directly linked CLIs (cimmofl), should use the
1251 _useProcessLocale "master switch" described in the Message Loading
|
1252 chuck 1.6 section. This will cause all messages, including exceptions thrown
1253 by Pegasus APIs, to be loaded in the locale based on the
|
1254 chuck 1.5 environment in which the program is running. This locale can be
1255 set by the user before running the program. <br>
1256 </p>
1257 <p>Code in the client side of the client/server CLIs need to send an
1258 Accept-Language to the Pegasus server that reflects the default locale
1259 of the CLI's process. See the Client Developer section for
1260 details. <br>
1261 </p>
1262 <p>An example of these considerations can be seen in the source code
1263 for cimconfig. <br>
1264 </p>
1265 <p> </p>
|
1266 chuck 1.1 <hr>
|
1267 marek 1.7 <p><i>
1268 Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
1269 Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
1270 Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
1271 IBM Corp.; EMC Corporation, The Open Group.
1272 Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
1273 IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
1274 Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
1275 EMC Corporation; VERITAS Software Corporation; The Open Group.
1276 Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
1277 EMC Corporation; Symantec Corporation; The Open Group.
1278 </i> </p>
1279
1280 <p><i>
1281 Permission is hereby granted, free of charge, to any person obtaining a copy
1282 of this software and associated documentation files (the "Software"), to
1283 deal in the Software without restriction, including without limitation the
1284 rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
1285 sell copies of the Software, and to permit persons to whom the Software is
1286 furnished to do so, subject to the following conditions:
1287 </i> </p>
1288 marek 1.7
1289 <p><i>
1290 THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
1291 ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
1292 "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
1293 LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
1294 PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
1295 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
1296 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
1297 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1298 </i> <br>
1299 <br>
1300 </p>
|
1301 chuck 1.1 </body>
1302 </html>
|