platform-core-home/documents/3.1/message_bundles.html

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.5 - (view) (download) (as text)

1 : dj 1.1 <!doctype html public "-//w3c//dtd html 4.0 transitional//en">
2 :     <html>
3 :     <head>
4 :     <title>Eclipse Platform/Core</title>
5 :     <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
6 :     <link rel="stylesheet" href="http://dev.eclipse.org/default_style.css" type="text/css">
7 :     <STYLE TYPE="text/css">
8 :     <!--
9 :     CODE { font-size: 80% }
10 :     -->
11 :     </STYLE>
12 :     </head>
13 :     <body>
14 :     <center>
15 :     <font class=indextop>core</font><br>
16 :     <font class=indexsub>the foundation of the platform</font><p></p>
17 :     <a href="../../main.html">[home]</a>
18 :     <a href="../../documents.html">[documents]</a>
19 :     <a href="../../downloads.html">[downloads]</a>
20 :     <a href="../../resources.html">[resources]</a>
21 :     <a href="../../planning.html">[planning]</a>
22 :     <a href="../../testing.html">[testing]</a>
23 :     </center>
24 :     <br>
25 :     <table BORDER=0 CELLPADDING=2 WIDTH="100%" >
26 :     <tr>
27 :     <td ALIGN=LEFT VALIGN=TOP COLSPAN="2" BGCOLOR="#0080C0"><b><font face="Arial,Helvetica" color="#FFFFFF">Message Bundles</font></b></td>
28 :     </tr>
29 :     <tr>
30 :     <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
31 :    
32 : dj 1.2 <td WIDTH="98%"><b>Description</b> <p>Standard Java ResourceBundles have quite
33 :     inefficient space characteristics. Since a running Eclipse tends to have
34 :     many externalized messages we have implemented a new message bundle story
35 :     to be used in Eclipse. The mechanism is quite simple and completely generic
36 :     - it can be used anywhere.</p>
37 :     <p>Summary of the new approach:</p>
38 : dj 1.1 <ul>
39 : dj 1.2 <li>messages.properties - this file is same as before except all keys
40 :     need to be valid Java identifiers.
41 :     <li>Each message file has a corresponding Java class.
42 :     <li>Each key/value pair in the file has a public static String field whose
43 :     name is the same as the message key.
44 :     <li>When message bundles are loaded, the values of the fields are set
45 :     to be the values from the messages.properties files.
46 :     <li>The message properties files are purged from memory.
47 :     </ul>
48 :     <p>When creating a new message:</p>
49 : dj 1.1 <ul>
50 :     <li>create a field in your Messages.java file</li>
51 : dj 1.2 <li>create a key/value pair in your messages.properties file where the
52 :     key name matches the field name</li>
53 :     <li>to reference the message, simply reference the field (e.g. Messages.my_key)
54 :     rather than the standard lookup</li>
55 : dj 1.1 </ul>
56 :     <p>&nbsp;</p></td>
57 :     </tr>
58 :     <tr>
59 :     <td ALIGN=LEFT VALIGN=TOP COLSPAN="2" BGCOLOR="#0080C0"><b><font face="Arial,Helvetica" color="#FFFFFF">File Formats</font></b></td>
60 :     </tr>
61 :     <tr>
62 :     <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
63 :    
64 :     <td WIDTH="98%"><p><b>Client Code</b></p>
65 :     Old Code:
66 :     <p>
67 :     <pre><code>public class MyClass {
68 :     &nbsp;&nbsp;&nbsp;public void myMethod() {
69 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String message;
70 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...
71 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// no args
72 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message = Messages.getString("key.one"); //$NON-NLS-1$
73 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...
74 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// bind one arg
75 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message = MessageFormat.format(Messages.getString("key.two"), new Object[] {"example usage"}); //$NON-NLS-1$ //$NON-NLS-2$
76 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...
77 :     &nbsp;&nbsp;&nbsp;}
78 :     }</code></pre>
79 :     </p>
80 :    
81 :     New Code:
82 : johna 1.3 <p><pre><code>
83 :     public class MyClass {
84 : dj 1.1 &nbsp;&nbsp;&nbsp;public void myMethod() {
85 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String message;
86 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...
87 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// no args
88 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message = Messages.key_one;
89 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...
90 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// bind one arg
91 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;message = NLS.bind(Messages.key_two, "example usage"); //$NON-NLS-1$
92 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...
93 :     &nbsp;&nbsp;&nbsp;}
94 :     }</code></pre></p>
95 :     <p>&nbsp;</p>
96 :     </td>
97 :     </tr>
98 :     <tr>
99 :     <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
100 :    
101 :     <td WIDTH="98%"><p><b>Messages.java</b></p>
102 :     Old Code:
103 :     <pre><code>public class Messages {
104 :     &nbsp;&nbsp;&nbsp;private static final String BUNDLE_NAME = &quot;org.eclipse.core.utils.messages&quot;; //$NON-NLS-1$
105 :     &nbsp;&nbsp;&nbsp;private static final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_NAME);
106 :     &nbsp;&nbsp;&nbsp;
107 :     &nbsp;&nbsp;&nbsp;public static String getString(String key) {
108 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;try {
109 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return bundle.getString(key);
110 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} catch (MissingResourceException e) {
111 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return key;
112 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}
113 :     &nbsp;&nbsp;&nbsp;}
114 :     }</code></pre>
115 :    
116 :     New Code:
117 : johna 1.3 <pre><code>
118 :     import org.eclipse.osgi.util.NLS;
119 :    
120 :     public class Messages extends NLS {
121 : dj 1.1 &nbsp;&nbsp;&nbsp;private static final String BUNDLE_NAME = &quot;org.eclipse.core.utils.messages&quot;; //$NON-NLS-1$
122 :     &nbsp;&nbsp;&nbsp;
123 :     &nbsp;&nbsp;&nbsp;public static String key_one;
124 :     &nbsp;&nbsp;&nbsp;public static String key_two;
125 :     &nbsp;&nbsp;&nbsp;...
126 :     &nbsp;&nbsp;&nbsp;static {
127 :     &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NLS.initializeMessages(BUNDLE_NAME, Messages.class);
128 :     &nbsp;&nbsp;&nbsp;}
129 :     }</code></pre>
130 :     <p>&nbsp;</p>
131 :     </td>
132 :     </tr>
133 :     <tr>
134 :     <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
135 :    
136 :     <td WIDTH="98%"><p><b>messages.properties</b></p>
137 :     Old Code:
138 :     <pre><code>key.one = Hello world.
139 :     key.two = This is an {0} of binding with one argument.
140 :     </code></pre>
141 :     New Code:
142 :     <pre><code>key_one = Hello world.
143 :     key_two = This is an {0} of binding with one argument.
144 :     </code></pre>
145 :     </p>
146 :     <p>&nbsp; </p></td>
147 :     </td>
148 :     </tr>
149 :     <tr>
150 : dj 1.2 <td ALIGN=LEFT VALIGN=TOP COLSPAN="2" BGCOLOR="#0080C0"><b><font face="Arial,Helvetica" color="#FFFFFF">Performance</font></b></td>
151 :     </tr>
152 :     <tr>
153 :     <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
154 :    
155 :     <td WIDTH="98%"><p><b>Time</b> </p>
156 :     <ul>
157 :     <li>Using a message is marginally faster since it is just a field access
158 :     rather than a lookup in the resource bundle.</li>
159 :     <li>Time to load and initialize a bundle is VM dependant but we have seen
160 :     5% to 46% improvements. </li>
161 :     </ul>
162 :     <p>&nbsp;</p>
163 :     </td>
164 :     </tr>
165 :     <tr>
166 :     <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
167 :    
168 :     <td WIDTH="98%"><p><b>Memory Footprint</b> </p>
169 :     <ul>
170 :     <li>This is very much a scalability play. The more you use, the more you
171 :     save.</li>
172 :     <li>The rough space savings is 88 + 4N bytes per message where N is the
173 :     number of characters in the key.</li>
174 :     <li>The absolute best-case scenerio for the Eclipse SDK, if every property
175 :     file is loaded and every key referenced, is roughly 4.5M of memory.
176 :     (based on the January 11, 2005 integration build)</li>
177 :     <li>Realistic scenarios for the Eclipse IDE should see savings on the
178 :     order of 500KB </li>
179 :     </ul>
180 :     <p>&nbsp;</p>
181 :     </td>
182 :     </tr>
183 :     <tr>
184 :     <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
185 :    
186 :     <td WIDTH="98%"><b>Other benefits</b> <ul>
187 :     <li>Easily catch missing keys - Message lookups are now field accesses
188 :     so you cannot reference a key that doesn't exist or you will get a compile
189 :     error. </li>
190 :     <li>Easily find typos in code when referencing keys - Each key is represented
191 :     by a field in the class so if the referencing code makes a spelling
192 :     error, then you will get a compile error.</li>
193 :     <li>Find unused keys - During the development cycle code is deleted, moved
194 :     and messages are changed. As a result there are keys in the messages.properties
195 :     file which are never referenced.These can easily be found now since
196 :     you can just do a search for references to the field. If there are no
197 :     references, then delete the field from the class and the key/value pair
198 :     from the file.</li>
199 :     </ul>
200 :     <p>&nbsp;</p></td>
201 :     </tr>
202 :     <tr>
203 :     <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
204 :    
205 :     <td WIDTH="98%"><b>Drawbacks</b>
206 :     <ul>
207 :     <li>There are now 2 files to maintain - Now the messages.properties and the java file must be kept in sync. There
208 :     is an opportunity for tooling to help with this; a validation tool could indicate problems with markers. Currently
209 :     there are debug options which log entries which exsit in one file but not the other.</li>
210 :     </ul>
211 :     <p>&nbsp;
212 :     </p>
213 :     </td>
214 :     </tr>
215 :    
216 :    
217 :     <tr>
218 : dj 1.1 <td ALIGN=LEFT VALIGN=TOP COLSPAN="2" BGCOLOR="#0080C0"><b><font face="Arial,Helvetica" color="#FFFFFF">Tools</font></b></td>
219 :     </tr>
220 :     <tr>
221 :     <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td>
222 :    
223 :     <td WIDTH="98%"><b>Conversion</b> <p>We have written a tool which aids in
224 :     converting from the basic Java resource bundle look-up mechanism, to the
225 : dj 1.2 new format. There is no requirement to do this conversion unless you want
226 :     to take advantage of the new mechanism.</p>
227 : dj 1.1 <p><em>Note that the message bundle access class is replaced when the tool
228 :     is run. If you define extra code, constants, etc in that class then please
229 :     read the notes below to ensure that you don't have problems.</em></p>
230 :     <p>Here are the steps to use when converting your code.</p>
231 :     <ul>
232 :     <li>Download <a href="../../downloads/tools/message_bundles/com.example.nls_1.0.0.zip">version 1.0.0</a>
233 :     and install the plug-in.</li>
234 :     <li>Run Eclipse.</li>
235 :     <li>Synchronize with the repository. (you will be using the Synchronize
236 :     view as your compare browser to view changes)</li>
237 :     <li>Select your message bundle access class. (e.g. the class which has
238 :     the <code>#getString(String)</code> method in it)</li>
239 :     <li>From the context menu, choose &quot;Convert Message Bundle&quot;.</li>
240 :     <li>Choose the class's associated .properties file from the resulting
241 :     &quot;Open Resource...&quot; dialog.</li>
242 :     <li>Use the Synchronize view to review the changes.</li>
243 :     <li>Release the new code.</li>
244 :     </ul>
245 :     <p><strong>Notes:</strong> </p>
246 :     <p>When using the NLS tooling from previous Eclipse releases, the java file
247 :     which was created had the format of the &quot;old&quot; Messages.java
248 :     file as described above. (basic class with <code>#getString(String)</code> method) Some plug-in owners have created extra helper
249 :     methods on the class to aid in their message bundle lookup. Since the
250 :     conversion tool has only basic functionality, these plug-in developers
251 :     must perform a couple of extra steps before running the tool.</p>
252 :     <p>Essentially what you want to do is get your java file into the basic
253 :     template form. This is possible via using existing refactorings. For instance,
254 :     if your class defines a method like this:</p>
255 :     <pre><code>public String getString(String key, Object binding) {
256 :     &nbsp;&nbsp;&nbsp;return MessageFormat.format(getString(key), new Object[] {binding});
257 :     }</code></pre>
258 :     <p>Then you want to do the following:</p>
259 :     <ol>
260 :     <li>Change the method body to be: <code>return NLS.bind(getString(key), binding);</code></li>
261 :     <li>Select the method name and from the context menu choose the &quot;Inline&quot;
262 :     refactoring. This will replace calls to this method in your code with
263 :     calls to the code in step 1.</li>
264 :     <li>Run the tool. Since only calls to <code>#getString(String)</code> exist now,
265 :     the tool will run sucessfully.</li>
266 :     </ol>
267 :     </tr>
268 :     </table>
269 :    
270 : johna 1.4 <table width="100%">
271 : johna 1.5 <tr><td style="background:#0080C0"><b><span style="color:white">Eclipse 3.1: Fast and built to last</span></b></td></tr>
272 : johna 1.4 </table>
273 : dj 1.1
274 :     </body>
275 :     </html>