| <!doctype html public "-//w3c//dtd html 4.0 transitional//en"> |
| <html> |
| <head> |
| <title>Eclipse Platform/Core</title> |
| <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> |
| <link rel="stylesheet" href="http://dev.eclipse.org/default_style.css" type="text/css"> |
| <STYLE TYPE="text/css"> |
| <!-- |
| CODE { font-size: 80% } |
| --> |
| </STYLE> |
| </head> |
| <body> |
| <center> |
| <font class=indextop>core</font><br> |
| <font class=indexsub>the foundation of the platform</font><p></p> |
| <a href="../../main.html">[home]</a> |
| <a href="../../documents.html">[documents]</a> |
| <a href="../../downloads.html">[downloads]</a> |
| <a href="../../resources.html">[resources]</a> |
| <a href="../../planning.html">[planning]</a> |
| <a href="../../testing.html">[testing]</a> |
| </center> |
| <br> |
| <table BORDER=0 CELLPADDING=2 WIDTH="100%" > |
| <tr> |
| <td ALIGN=LEFT VALIGN=TOP COLSPAN="2" BGCOLOR="#0080C0"><b><font face="Arial,Helvetica" color="#FFFFFF">Message Bundles</font></b></td> |
| </tr> |
| <tr> |
| <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td> |
| |
| <td WIDTH="98%"><b>Description</b> <p>Standard Java ResourceBundles have quite |
| inefficient space characteristics. Since a running Eclipse tends to have |
| many externalized messages we have implemented a new message bundle story |
| to be used in Eclipse. The mechanism is quite simple and completely generic |
| - it can be used anywhere.</p> |
| <p>Summary of the new approach:</p> |
| <ul> |
| <li>messages.properties - this file is same as before except all keys |
| need to be valid Java identifiers. |
| <li>Each message file has a corresponding Java class. |
| <li>Each key/value pair in the file has a public static String field whose |
| name is the same as the message key. |
| <li>When message bundles are loaded, the values of the fields are set |
| to be the values from the messages.properties files. |
| <li>The message properties files are purged from memory. |
| </ul> |
| <p>When creating a new message:</p> |
| <ul> |
| <li>create a field in your Messages.java file</li> |
| <li>create a key/value pair in your messages.properties file where the |
| key name matches the field name</li> |
| <li>to reference the message, simply reference the field (e.g. Messages.my_key) |
| rather than the standard lookup</li> |
| </ul> |
| <p> </p></td> |
| </tr> |
| <tr> |
| <td ALIGN=LEFT VALIGN=TOP COLSPAN="2" BGCOLOR="#0080C0"><b><font face="Arial,Helvetica" color="#FFFFFF">File Formats</font></b></td> |
| </tr> |
| <tr> |
| <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td> |
| |
| <td WIDTH="98%"><p><b>Client Code</b></p> |
| Old Code: |
| <p> |
| <pre><code>public class MyClass { |
| public void myMethod() { |
| String message; |
| ... |
| // no args |
| message = Messages.getString("key.one"); //$NON-NLS-1$ |
| ... |
| // bind one arg |
| message = MessageFormat.format(Messages.getString("key.two"), new Object[] {"example usage"}); //$NON-NLS-1$ //$NON-NLS-2$ |
| ... |
| } |
| }</code></pre> |
| </p> |
| |
| New Code: |
| <p><pre><code> |
| public class MyClass { |
| public void myMethod() { |
| String message; |
| ... |
| // no args |
| message = Messages.key_one; |
| ... |
| // bind one arg |
| message = NLS.bind(Messages.key_two, "example usage"); //$NON-NLS-1$ |
| ... |
| } |
| }</code></pre></p> |
| <p> </p> |
| </td> |
| </tr> |
| <tr> |
| <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td> |
| |
| <td WIDTH="98%"><p><b>Messages.java</b></p> |
| Old Code: |
| <pre><code>public class Messages { |
| private static final String BUNDLE_NAME = "org.eclipse.core.utils.messages"; //$NON-NLS-1$ |
| private static final ResourceBundle bundle = ResourceBundle.getBundle(BUNDLE_NAME); |
| |
| public static String getString(String key) { |
| try { |
| return bundle.getString(key); |
| } catch (MissingResourceException e) { |
| return key; |
| } |
| } |
| }</code></pre> |
| |
| New Code: |
| <pre><code> |
| import org.eclipse.osgi.util.NLS; |
| |
| public class Messages extends NLS { |
| private static final String BUNDLE_NAME = "org.eclipse.core.utils.messages"; //$NON-NLS-1$ |
| |
| public static String key_one; |
| public static String key_two; |
| ... |
| static { |
| NLS.initializeMessages(BUNDLE_NAME, Messages.class); |
| } |
| }</code></pre> |
| <p> </p> |
| </td> |
| </tr> |
| <tr> |
| <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td> |
| |
| <td WIDTH="98%"><p><b>messages.properties</b></p> |
| Old Code: |
| <pre><code>key.one = Hello world. |
| key.two = This is an {0} of binding with one argument. |
| </code></pre> |
| New Code: |
| <pre><code>key_one = Hello world. |
| key_two = This is an {0} of binding with one argument. |
| </code></pre> |
| </p> |
| <p> </p></td> |
| </td> |
| </tr> |
| <tr> |
| <td ALIGN=LEFT VALIGN=TOP COLSPAN="2" BGCOLOR="#0080C0"><b><font face="Arial,Helvetica" color="#FFFFFF">Performance</font></b></td> |
| </tr> |
| <tr> |
| <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td> |
| |
| <td WIDTH="98%"><p><b>Time</b> </p> |
| <ul> |
| <li>Using a message is marginally faster since it is just a field access |
| rather than a lookup in the resource bundle.</li> |
| <li>Time to load and initialize a bundle is VM dependant but we have seen |
| 5% to 46% improvements. </li> |
| </ul> |
| <p> </p> |
| </td> |
| </tr> |
| <tr> |
| <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td> |
| |
| <td WIDTH="98%"><p><b>Memory Footprint</b> </p> |
| <ul> |
| <li>This is very much a scalability play. The more you use, the more you |
| save.</li> |
| <li>The rough space savings is 88 + 4N bytes per message where N is the |
| number of characters in the key.</li> |
| <li>The absolute best-case scenerio for the Eclipse SDK, if every property |
| file is loaded and every key referenced, is roughly 4.5M of memory. |
| (based on the January 11, 2005 integration build)</li> |
| <li>Realistic scenarios for the Eclipse IDE should see savings on the |
| order of 500KB </li> |
| </ul> |
| <p> </p> |
| </td> |
| </tr> |
| <tr> |
| <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td> |
| |
| <td WIDTH="98%"><b>Other benefits</b> <ul> |
| <li>Easily catch missing keys - Message lookups are now field accesses |
| so you cannot reference a key that doesn't exist or you will get a compile |
| error. </li> |
| <li>Easily find typos in code when referencing keys - Each key is represented |
| by a field in the class so if the referencing code makes a spelling |
| error, then you will get a compile error.</li> |
| <li>Find unused keys - During the development cycle code is deleted, moved |
| and messages are changed. As a result there are keys in the messages.properties |
| file which are never referenced.These can easily be found now since |
| you can just do a search for references to the field. If there are no |
| references, then delete the field from the class and the key/value pair |
| from the file.</li> |
| </ul> |
| <p> </p></td> |
| </tr> |
| <tr> |
| <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td> |
| |
| <td WIDTH="98%"><b>Drawbacks</b> |
| <ul> |
| <li>There are now 2 files to maintain - Now the messages.properties and the java file must be kept in sync. There |
| is an opportunity for tooling to help with this; a validation tool could indicate problems with markers. Currently |
| there are debug options which log entries which exsit in one file but not the other.</li> |
| </ul> |
| <p> |
| </p> |
| </td> |
| </tr> |
| |
| |
| <tr> |
| <td ALIGN=LEFT VALIGN=TOP COLSPAN="2" BGCOLOR="#0080C0"><b><font face="Arial,Helvetica" color="#FFFFFF">Tools</font></b></td> |
| </tr> |
| <tr> |
| <td ALIGN=RIGHT VALIGN=TOP WIDTH="2%"><img SRC="../../images/Adarrow.gif" BORDER=0 height=16 width=16></td> |
| |
| <td WIDTH="98%"><b>Conversion</b> <p>We have written a tool which aids in |
| converting from the basic Java resource bundle look-up mechanism, to the |
| new format. There is no requirement to do this conversion unless you want |
| to take advantage of the new mechanism.</p> |
| <p><em>Note that the message bundle access class is replaced when the tool |
| is run. If you define extra code, constants, etc in that class then please |
| read the notes below to ensure that you don't have problems.</em></p> |
| <p>Here are the steps to use when converting your code.</p> |
| <ul> |
| <li>Download JDT/UI's new <a href="../../downloads/tools/message_bundles/com.ibm.zrh.eclipse.nls_1.0.0.zip">version |
| 1.0.0</a> of the tool and install the plug-in.</li> |
| <li>Run Eclipse.</li> |
| <li>Synchronize with the repository. (you will be using the Synchronize |
| view as your compare browser to view changes)</li> |
| <li>Select your message bundle access class. (e.g. the class which has |
| the <code>#getString(String)</code> method in it)</li> |
| <li>From the context menu, choose "Convert Message Bundle".</li> |
| <li>Choose the class's associated .properties file from the resulting |
| "Open Resource..." dialog.</li> |
| <li>Use the Synchronize view to review the changes.</li> |
| <li>Release the new code.</li> |
| </ul> |
| <p><strong>Notes:</strong> </p> |
| <p>When using the NLS tooling from previous Eclipse releases, the java file |
| which was created had the format of the "old" Messages.java |
| file as described above. (basic class with <code>#getString(String)</code> method) Some plug-in owners have created extra helper |
| methods on the class to aid in their message bundle lookup. Since the |
| conversion tool has only basic functionality, these plug-in developers |
| must perform a couple of extra steps before running the tool.</p> |
| <p>Essentially what you want to do is get your java file into the basic |
| template form. This is possible via using existing refactorings. For instance, |
| if your class defines a method like this:</p> |
| <pre><code>public String getString(String key, Object binding) { |
| return MessageFormat.format(getString(key), new Object[] {binding}); |
| }</code></pre> |
| <p>Then you want to do the following:</p> |
| <ol> |
| <li>Change the method body to be: <code>return NLS.bind(getString(key), binding);</code></li> |
| <li>Select the method name and from the context menu choose the "Inline" |
| refactoring. This will replace calls to this method in your code with |
| calls to the code in step 1.</li> |
| <li>Run the tool. Since only calls to <code>#getString(String)</code> exist now, |
| the tool will run sucessfully.</li> |
| </ol> |
| </tr> |
| </table> |
| <p> |
| Eclipse 3.1: Think Fast! |
| </p> |
| </body> |
| </html> |