ICU4J is a set of Java libraries that provides more comprehensive support for Unicode, software globalization, and internationalization. In order to provide this functionality to the Eclipse community, ICU4J was added to the Eclipse platform build in 3.2. You will see it in the build as a plugin named com.ibm.icu.
Updating the Execution Environment for ICU4J
In Indigo (Eclipse SDK 3.7) Eclipse will remove the Foundation-1.0/J2SE-1.4 restriction on our consumption of ICU4J and move com.ibm.icu up to J2SE-1.5.
Rational: ICU4J has been using J2SE-1.5 for a while now. In Eclipse SDK 3.6, the ICU project provided us a specially compiled version of ICU4J 4.2.1 (conditional compilation code back to Foundation-1.0). But with ICU4J 4.4 the ICU project moved up to using java 1.5 libraries in the implementation and java 1.5 syntax in the API, and can no longer provide a back-compiled version of ICU4J.
By moving the BREE of com.ibm.icu up to J2SE-1.5 we will be able to consume the ICU4J releases without a special compile step. This will allow us to move up version more easily:
- ICU4J 4.4 includes Unicode 5.2 support.
- ICU4J 4.8 is planned to include Unicode 6.0 support.
Comments welcome on Bug 324782 - Workbench: Move up to ICU4J 4.6 with J2SE-1.5
Effects on Consumers
The Eclipse SDK 3.7 and RCP apps built against it as a target platform will only run on a Java 1.5 and higher.
This will not require *consumers* of com.ibm.icu to change their BREEs unless they need to use new 1.5 APIs (ex: org.eclipse.ui.workbench still has a BREE of J2SE-1.4).
The requirement that no one specifies a maximum version range for com.ibm.icu still applies, and plug-ins should specify the minimum version that satisfies their use of ICU4J API. That will be com.ibm.icu 3.8, for the most common cases (use of com.ibm.icu.text and com.ibm.icu.util).
RCP applications that require themselves to run on Java 1.4 can use com.ibm.icu 4.2.1, the last version to run on Java 1.4. This is available from Orbit.
Migration from java.text/java.util to com.ibm.icu.text/com.ibm.icu.util
This section describes how to adopt ICU4J into your application.
Migration of application code can be done incrementally, meaning full adoption of all ICU4J function is not necessary to reap the benefits of using ICU4J. Migration can be done in the following five sequential steps:
1. Remove use of affected classes
Take a careful look at your use of the java.text, java.util, and java.lang classes mentioned below. In some cases, dependency on these classes can be removed entirely. For example, if you are just using MessageFormat for binding parameters to a translated string, consider using org.eclipse.osgi.util.NLS#bind instead. Or, if you were using these classes to format dates and messages for printing in a context that does not require translation (such as the log file), consider using a simpler format that does not require these APIs. Avoiding the classes listed below will prevent the need to add any unnecessary dependency on the ICU4J packages. In the case of RCP applications where size is critical, you may want to avoid the large ICU4J bundle if it's not really needed.
2. Import changes
Some classes need only be replaced with the ICU equivalent class by changing the import statement (i.e. change java.* with com.ibm.icu.*).
Example: change references of java.text.Collator to com.ibm.icu.text.Collator
This should be done for the following classes:
Note: java.util.StringTokenizer should be included in this list but the equivalent class in ICU4J (versions up to and including 3.4.4) can potentially cause a performance degradation versus the default Java implementation. Therefore, the Eclipse SDK did not adopt ICU's version of StringTokenizer for Eclipse 3.2.
3. Parallel APIs
In this case, you will want to use the corresponding classes and API’s in place of the ones that are included in the JDK (in the java.* packages).
Example: replace references of java.lang.Character with class com.ibm.icu.lang.UCharacter
The conversion of java.* classes to com.ibm.icu.* classes should be done as follows:
- java.util.Currency -> com.ibm.icu.util.Currency
- java.util.GregorianCalendar -> com.ibm.icu.util.GregorianCalendar
- java.util.SimpleTimeZone -> com.ibm.icu.util.SimpleTimeZone
- java.lang.Character -> com.ibm.icu.lang.UCharacter
- java.lang.Character$UnicodeBlock -> com.ibm.icu.lang.UCharacter$UnicodeBlock"
- java.text.Format -> com.ibm.icu.text.UFormat
- java.util.Locale -> com.ibm.icu.util.ULocale
- java.util.ResourceBundle -> com.ibm.icu.util.UResourceBundle
Note: classes UCharacter, UResourceBundle, and UFormat are not implemented in the replacement plug-in (see below) so if your application’s code needs to work with both the replacement plug-in and the real ICU4J plug-in then you will not be able to adopt these classes at this time.
Some code needs to be re-written to take utilize ICU function. Discovering code that needs to be re-structured in this manner will not be as systematic as in the previous two steps.
Example: use com.ibm.icu.text.BreakIterator to locate boundaries in text instead of iterating over a string and using java.lang.Character.isLetterOrDigit(string.charAt(idx)).
5. Utilize New Features
ICU adds additional function in some areas that is not provided by the JDK. In this case, new code would need to be written to take advantage of these new features.
Example: the class com.ibm.icu.text.Transliterator
The Eclipse SDK will be adopting the ICU4J APIs for Eclipse 3.2. The addition of the ICU4J plug-in adds on the order of 3MB worth of code. Some applications may not want to absorb ICU4J if the priority is size over adopting the ICU4J function. If this is the case for your application, you can download the replacement plug-in (com.ibm.icu.base) from the build page from which you obtained your Eclipse build, remove the com.ibm.icu plug-in and its source counterpart, and drop in the replacement plug-in. This is required because the Platform adopted the ICU APIs for 3.2 and so just removing the ICU plug-in will result in compilation errors. The replacement plug-in is about 100KB in size and simply calls through to the java.* packages (default JDK implementation) of the most commonly used classes and APIs in ICU4J. The classes that are implemented in the replacement plug-in are as follows:
If your application needs to be compatible between both the ICU4J plug-in and the replacement plug-in (most often for size reasons), we recommend you only use the API in the classes from this list. If ICU4J is guaranteed to always be present in the application then you can safely use any of the ICU4J APIs. The replacement plug-in will be built separately and available as a download on the build pages, but this is still work in progress. You can however, start using the ICU4J APIs since the ICU4J plug-in is currently in the SDK build as of M4 (and beyond).
If you choose to adopt ICU4J, it is recommended that, in your plug-in manifest file, instead of using the Require-Bundle header to specify the dependency on ICU4J (e.g.)
you use the Import-Package header to specify your plug-in's dependency on ICU4J (e.g.).
Import-Package: com.ibm.icu.text, com.ibm.icu.util
This is to ensure you will not encounter compile or runtime errors if you decide to use the replacement plug-in instead of the full ICU4J plug-in, or vice-versa.
Effect on JFace - ViewerSorter and StructuredViewer
In order to support ICU4J in JFace, some creative API additions were made without actually referencing classes in the ICU4J plug-in in the API. This resulted in the addition of:
1. a new class called org.eclipse.jface.viewers.ViewerComparator, of which org.eclipse.jface.viewers.Viewer Sorter is now a subclass
2. two new methods to StructuredViewer, to support the addition of the ViewerComparator class
The ViewerSorter class has a public method getCollator() that returns a java.text.Collator. Since this method is API it could not simply be changed to use an ICU Collator. Also, ICU classes cannot be part of the API (signatures) as a direct plug-in dependency on ICU would prevent JFace from being used standalone (with SWT). To accomodate these constraints, the ViewerComparator class that uses a java.util.Comparator, rather than an ICU Collator, was added. This was done because ICU's Collator class implements java.util.Comparator, so StructuredViewers now have the option to use ICU's Collator rather than the java.text.Collator, but JFace doesn't have to add a dependency on the ICU4J plug-in.
The two new methods added to StructuredViewer support using ICU's Collator to sort the contents of the Viewer via a ViewerComparator, rather than a ViewerSorter. It is recommended that StructuredViewers now use these methods to get/set the viewer's sorter, instead of the getSorter() and setSorter(ViewerSorter) methods.
/** * Return this viewer's comparator used to sort elements. * This method should be used instead of <code>getSorter()</code>. * * @return a viewer comparator, or <code>null</code> if none * * @since 3.2 */ public ViewerComparator getComparator() /** * Sets this viewer's comparator to be used for sorting elements, and triggers refiltering and * resorting of this viewer's element. <code>null</code> turns sorting off. * To get the viewer's comparator, call <code>getComparator()</code>. * <p> * IMPORTANT: This method was introduced in 3.2. If a reference to this viewer object * is passed to clients who call <code>getSorter()<code>, null may be returned from * from that method even though the viewer is sorting its elements using the * viewer's comparator. * </p> * * @param comparator a viewer comparator, or <code>null</code> if none * * @since 3.2 */ public void setComparator(ViewerComparator comparator)
Bugs in ICU4J
Bugs that are found in ICU4J should not be logged against Eclipse products or components, they should be logged against the ICU project at:
Be sure to include the version of ICU4J you are using and mention that you are using ICU4J in Eclipse.
ICU4J Usage in Eclipse
Link to a table that lists all the plugins in the Eclipse SDK that have a dependency on ICU4J.
For more information about ICU4J visit the official home page: