platform-core-home/documents/3.1/message_bundles.html
Parent Directory
|
Revision Log
Revision 1.6 - (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> </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 : | public void myMethod() { | ||
| 69 : | String message; | ||
| 70 : | ... | ||
| 71 : | // no args | ||
| 72 : | message = Messages.getString("key.one"); //$NON-NLS-1$ | ||
| 73 : | ... | ||
| 74 : | // bind one arg | ||
| 75 : | message = MessageFormat.format(Messages.getString("key.two"), new Object[] {"example usage"}); //$NON-NLS-1$ //$NON-NLS-2$ | ||
| 76 : | ... | ||
| 77 : | } | ||
| 78 : | }</code></pre> | ||
| 79 : | </p> | ||
| 80 : | |||
| 81 : | New Code: | ||
| 82 : | johna | 1.3 | <p><pre><code> |
| 83 : | public class MyClass { | ||
| 84 : | dj | 1.1 | public void myMethod() { |
| 85 : | String message; | ||
| 86 : | ... | ||
| 87 : | // no args | ||
| 88 : | message = Messages.key_one; | ||
| 89 : | ... | ||
| 90 : | // bind one arg | ||
| 91 : | message = NLS.bind(Messages.key_two, "example usage"); //$NON-NLS-1$ | ||
| 92 : | ... | ||
| 93 : | } | ||
| 94 : | }</code></pre></p> | ||
| 95 : | <p> </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 : | private static final String BUNDLE_NAME = "org.eclipse.core.utils.messages"; //$NON-NLS-1$ | ||
| 105 : | private static final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_NAME); | ||
| 106 : | | ||
| 107 : | public static String getString(String key) { | ||
| 108 : | try { | ||
| 109 : | return bundle.getString(key); | ||
| 110 : | } catch (MissingResourceException e) { | ||
| 111 : | return key; | ||
| 112 : | } | ||
| 113 : | } | ||
| 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 | private static final String BUNDLE_NAME = "org.eclipse.core.utils.messages"; //$NON-NLS-1$ |
| 122 : | | ||
| 123 : | public static String key_one; | ||
| 124 : | public static String key_two; | ||
| 125 : | ... | ||
| 126 : | static { | ||
| 127 : | NLS.initializeMessages(BUNDLE_NAME, Messages.class); | ||
| 128 : | } | ||
| 129 : | }</code></pre> | ||
| 130 : | <p> </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> </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> </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> </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> </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> | ||
| 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 "Convert Message Bundle".</li> | ||
| 240 : | <li>Choose the class's associated .properties file from the resulting | ||
| 241 : | "Open Resource..." 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 "old" 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 : | 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 "Inline" | ||
| 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.6 | <tr><td style="background:#0080C0"><b><span style="color:white">Eclipse 3.1: Think Fast!</span></b></td></tr> |
| 272 : | johna | 1.4 | </table> |
| 273 : | dj | 1.1 | |
| 274 : | </body> | ||
| 275 : | </html> |
| help@eclipse.org | ViewVC Help |
| Powered by ViewVC 1.0.3 |
