src/share/jaxws_classes/com/sun/xml/internal/dtdparser/MessageCatalog.java

Fri, 23 Aug 2013 09:57:21 +0100

author
mkos
date
Fri, 23 Aug 2013 09:57:21 +0100
changeset 397
b99d7e355d4b
parent 286
f50545b5e2f1
child 637
9c07ef4934dd
permissions
-rw-r--r--

8022885: Update JAX-WS RI integration to 2.2.9-b14140
8013016: Rebase 8009009 against the latest jdk8/jaxws
Reviewed-by: alanb, chegar

ohair@286 1 /*
mkos@397 2 * Copyright (c) 2009, Oracle and/or its affiliates. All rights reserved.
ohair@286 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ohair@286 4 *
ohair@286 5 * This code is free software; you can redistribute it and/or modify it
ohair@286 6 * under the terms of the GNU General Public License version 2 only, as
ohair@286 7 * published by the Free Software Foundation. Oracle designates this
ohair@286 8 * particular file as subject to the "Classpath" exception as provided
ohair@286 9 * by Oracle in the LICENSE file that accompanied this code.
ohair@286 10 *
ohair@286 11 * This code is distributed in the hope that it will be useful, but WITHOUT
ohair@286 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ohair@286 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
ohair@286 14 * version 2 for more details (a copy is included in the LICENSE file that
ohair@286 15 * accompanied this code).
ohair@286 16 *
ohair@286 17 * You should have received a copy of the GNU General Public License version
ohair@286 18 * 2 along with this work; if not, write to the Free Software Foundation,
ohair@286 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ohair@286 20 *
ohair@286 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohair@286 22 * or visit www.oracle.com if you need additional information or have any
ohair@286 23 * questions.
ohair@286 24 */
ohair@286 25
ohair@286 26 package com.sun.xml.internal.dtdparser;
ohair@286 27
ohair@286 28 import java.io.InputStream;
ohair@286 29 import java.text.FieldPosition;
ohair@286 30 import java.text.MessageFormat;
ohair@286 31 import java.util.Hashtable;
ohair@286 32 import java.util.Locale;
ohair@286 33 import java.util.MissingResourceException;
ohair@286 34 import java.util.ResourceBundle;
ohair@286 35
ohair@286 36
ohair@286 37 /**
ohair@286 38 * This class provides support for multi-language string lookup, as needed
ohair@286 39 * to localize messages from applications supporting multiple languages
ohair@286 40 * at the same time. One class of such applications is network services,
ohair@286 41 * such as HTTP servers, which talk to clients who may not be from the
ohair@286 42 * same locale as the server. This class supports a form of negotiation
ohair@286 43 * for the language used in presenting a message from some package, where
ohair@286 44 * both user (client) preferences and application (server) support are
ohair@286 45 * accounted for when choosing locales and formatting messages.
ohair@286 46 * <p/>
ohair@286 47 * <P> Each package should have a singleton package-private message catalog
ohair@286 48 * class. This ensures that the correct class loader will always be used to
ohair@286 49 * access message resources, and minimizes use of memory: <PRE>
ohair@286 50 * package <em>some.package</em>;
ohair@286 51 * <p/>
ohair@286 52 * // "foo" might be public
ohair@286 53 * class foo {
ohair@286 54 * ...
ohair@286 55 * // package private
ohair@286 56 * static final Catalog messages = new Catalog ();
ohair@286 57 * static final class Catalog extends MessageCatalog {
ohair@286 58 * Catalog () { super (Catalog.class); }
ohair@286 59 * }
ohair@286 60 * ...
ohair@286 61 * }
ohair@286 62 * </PRE>
ohair@286 63 * <p/>
ohair@286 64 * <P> Messages for a known client could be generated using code
ohair@286 65 * something like this: <PRE>
ohair@286 66 * String clientLanguages [];
ohair@286 67 * Locale clientLocale;
ohair@286 68 * String clientMessage;
ohair@286 69 * <p/>
ohair@286 70 * // client languages will probably be provided by client,
ohair@286 71 * // e.g. by an HTTP/1.1 "Accept-Language" header.
ohair@286 72 * clientLanguages = new String [] { "en-ca", "fr-ca", "ja", "zh" };
ohair@286 73 * clientLocale = foo.messages.chooseLocale (clientLanguages);
ohair@286 74 * clientMessage = foo.messages.getMessage (clientLocale,
ohair@286 75 * "fileCount",
ohair@286 76 * new Object [] { new Integer (numberOfFiles) }
ohair@286 77 * );
ohair@286 78 * </PRE>
ohair@286 79 * <p/>
ohair@286 80 * <P> At this time, this class does not include functionality permitting
ohair@286 81 * messages to be passed around and localized after-the-fact. The consequence
ohair@286 82 * of this is that the locale for messages must be passed down through layers
ohair@286 83 * which have no normal reason to support such passdown, or else the system
ohair@286 84 * default locale must be used instead of the one the client needs.
ohair@286 85 * <p/>
ohair@286 86 * <P> <hr> The following guidelines should be used when constructiong
ohair@286 87 * multi-language applications: <OL>
ohair@286 88 * <p/>
ohair@286 89 * <LI> Always use <a href=#chooseLocale>chooseLocale</a> to select the
ohair@286 90 * locale you pass to your <code>getMessage</code> call. This lets your
ohair@286 91 * applications use IETF standard locale names, and avoids needless
ohair@286 92 * use of system defaults.
ohair@286 93 * <p/>
ohair@286 94 * <LI> The localized messages for a given package should always go in
ohair@286 95 * a separate <em>resources</em> sub-package. There are security
ohair@286 96 * implications; see below.
ohair@286 97 * <p/>
ohair@286 98 * <LI> Make sure that a language name is included in each bundle name,
ohair@286 99 * so that the developer's locale will not be inadvertently used. That
ohair@286 100 * is, don't create defaults like <em>resources/Messages.properties</em>
ohair@286 101 * or <em>resources/Messages.class</em>, since ResourceBundle will choose
ohair@286 102 * such defaults rather than giving software a chance to choose a more
ohair@286 103 * appropriate language for its messages. Your message bundles should
ohair@286 104 * have names like <em>Messages_en.properties</em> (for the "en", or
ohair@286 105 * English, language) or <em>Messages_ja.class</em> ("ja" indicates the
ohair@286 106 * Japanese language).
ohair@286 107 * <p/>
ohair@286 108 * <LI> Only use property files for messages in languages which can
ohair@286 109 * be limited to the ISO Latin/1 (8859-1) characters supported by the
ohair@286 110 * property file format. (This is mostly Western European languages.)
ohair@286 111 * Otherwise, subclass ResourceBundle to provide your messages; it is
ohair@286 112 * simplest to subclass <code>java.util.ListResourceBundle</code>.
ohair@286 113 * <p/>
ohair@286 114 * <LI> Never use another package's message catalog or resource bundles.
ohair@286 115 * It should not be possible for a change internal to one package (such
ohair@286 116 * as eliminating or improving messages) to break another package.
ohair@286 117 * <p/>
ohair@286 118 * </OL>
ohair@286 119 * <p/>
ohair@286 120 * <P> The "resources" sub-package can be treated separately from the
ohair@286 121 * package with which it is associated. That main package may be sealed
ohair@286 122 * and possibly signed, preventing other software from adding classes to
ohair@286 123 * the package which would be able to access methods and data which are
ohair@286 124 * not designed to be publicly accessible. On the other hand, resources
ohair@286 125 * such as localized messages are often provided after initial product
ohair@286 126 * shipment, without a full release cycle for the product. Such files
ohair@286 127 * (text and class files) need to be added to some package. Since they
ohair@286 128 * should not be added to the main package, the "resources" subpackage is
ohair@286 129 * used without risking the security or integrity of that main package
ohair@286 130 * as distributed in its JAR file.
ohair@286 131 *
ohair@286 132 * @author David Brownell
ohair@286 133 * @version 1.1, 00/08/05
ohair@286 134 * @see java.util.Locale
ohair@286 135 * @see java.util.ListResourceBundle
ohair@286 136 * @see java.text.MessageFormat
ohair@286 137 */
ohair@286 138 // leave this as "abstract" -- each package needs its own subclass,
ohair@286 139 // else it's not always going to be using the right class loader.
ohair@286 140 abstract public class MessageCatalog {
ohair@286 141 private String bundleName;
ohair@286 142
ohair@286 143 /**
ohair@286 144 * Create a message catalog for use by classes in the same package
ohair@286 145 * as the specified class. This uses <em>Messages</em> resource
ohair@286 146 * bundles in the <em>resources</em> sub-package of class passed as
ohair@286 147 * a parameter.
ohair@286 148 *
ohair@286 149 * @param packageMember Class whose package has localized messages
ohair@286 150 */
ohair@286 151 protected MessageCatalog(Class packageMember) {
ohair@286 152 this(packageMember, "Messages");
ohair@286 153 }
ohair@286 154
ohair@286 155 /**
ohair@286 156 * Create a message catalog for use by classes in the same package
ohair@286 157 * as the specified class. This uses the specified resource
ohair@286 158 * bundle name in the <em>resources</em> sub-package of class passed
ohair@286 159 * as a parameter; for example, <em>resources.Messages</em>.
ohair@286 160 *
ohair@286 161 * @param packageMember Class whose package has localized messages
ohair@286 162 * @param bundle Name of a group of resource bundles
ohair@286 163 */
ohair@286 164 private MessageCatalog(Class packageMember, String bundle) {
ohair@286 165 int index;
ohair@286 166
ohair@286 167 bundleName = packageMember.getName();
ohair@286 168 index = bundleName.lastIndexOf('.');
ohair@286 169 if (index == -1) // "ClassName"
ohair@286 170 bundleName = "";
ohair@286 171 else // "some.package.ClassName"
ohair@286 172 bundleName = bundleName.substring(0, index) + ".";
ohair@286 173 bundleName = bundleName + "resources." + bundle;
ohair@286 174 }
ohair@286 175
ohair@286 176
ohair@286 177 /**
ohair@286 178 * Get a message localized to the specified locale, using the message ID
ohair@286 179 * and package name if no message is available. The locale is normally
ohair@286 180 * that of the client of a service, chosen with knowledge that both the
ohair@286 181 * client and this server support that locale. There are two error
ohair@286 182 * cases: first, when the specified locale is unsupported or null, the
ohair@286 183 * default locale is used if possible; second, when no bundle supports
ohair@286 184 * that locale, the message ID and package name are used.
ohair@286 185 *
ohair@286 186 * @param locale The locale of the message to use. If this is null,
ohair@286 187 * the default locale will be used.
ohair@286 188 * @param messageId The ID of the message to use.
ohair@286 189 * @return The message, localized as described above.
ohair@286 190 */
ohair@286 191 public String getMessage(Locale locale,
ohair@286 192 String messageId) {
ohair@286 193 ResourceBundle bundle;
ohair@286 194
ohair@286 195 // cope with unsupported locale...
ohair@286 196 if (locale == null)
ohair@286 197 locale = Locale.getDefault();
ohair@286 198
ohair@286 199 try {
ohair@286 200 bundle = ResourceBundle.getBundle(bundleName, locale);
ohair@286 201 } catch (MissingResourceException e) {
ohair@286 202 bundle = ResourceBundle.getBundle(bundleName, Locale.ENGLISH);
ohair@286 203 }
ohair@286 204 return bundle.getString(messageId);
ohair@286 205 }
ohair@286 206
ohair@286 207
ohair@286 208 /**
ohair@286 209 * Format a message localized to the specified locale, using the message
ohair@286 210 * ID with its package name if none is available. The locale is normally
ohair@286 211 * the client of a service, chosen with knowledge that both the client
ohair@286 212 * server support that locale. There are two error cases: first, if the
ohair@286 213 * specified locale is unsupported or null, the default locale is used if
ohair@286 214 * possible; second, when no bundle supports that locale, the message ID
ohair@286 215 * and package name are used.
ohair@286 216 *
ohair@286 217 * @param locale The locale of the message to use. If this is null,
ohair@286 218 * the default locale will be used.
ohair@286 219 * @param messageId The ID of the message format to use.
ohair@286 220 * @param parameters Used when formatting the message. Objects in
ohair@286 221 * this list are turned to strings if they are not Strings, Numbers,
ohair@286 222 * or Dates (that is, if MessageFormat would treat them as errors).
ohair@286 223 * @return The message, localized as described above.
ohair@286 224 * @see java.text.MessageFormat
ohair@286 225 */
ohair@286 226 public String getMessage(Locale locale,
ohair@286 227 String messageId,
ohair@286 228 Object parameters []) {
ohair@286 229 if (parameters == null)
ohair@286 230 return getMessage(locale, messageId);
ohair@286 231
ohair@286 232 // since most messages won't be tested (sigh), be friendly to
ohair@286 233 // the inevitable developer errors of passing random data types
ohair@286 234 // to the message formatting code.
ohair@286 235 for (int i = 0; i < parameters.length; i++) {
ohair@286 236 if (!(parameters[i] instanceof String)
ohair@286 237 && !(parameters[i] instanceof Number)
ohair@286 238 && !(parameters[i] instanceof java.util.Date)) {
ohair@286 239 if (parameters[i] == null)
ohair@286 240 parameters[i] = "(null)";
ohair@286 241 else
ohair@286 242 parameters[i] = parameters[i].toString();
ohair@286 243 }
ohair@286 244 }
ohair@286 245
ohair@286 246 // similarly, cope with unsupported locale...
ohair@286 247 if (locale == null)
ohair@286 248 locale = Locale.getDefault();
ohair@286 249
ohair@286 250 // get the appropriately localized MessageFormat object
ohair@286 251 ResourceBundle bundle;
ohair@286 252 MessageFormat format;
ohair@286 253
ohair@286 254 try {
ohair@286 255 bundle = ResourceBundle.getBundle(bundleName, locale);
ohair@286 256 } catch (MissingResourceException e) {
ohair@286 257 bundle = ResourceBundle.getBundle(bundleName, Locale.ENGLISH);
ohair@286 258 /*String retval;
ohair@286 259
ohair@286 260 retval = packagePrefix (messageId);
ohair@286 261 for (int i = 0; i < parameters.length; i++) {
ohair@286 262 retval += ' ';
ohair@286 263 retval += parameters [i];
ohair@286 264 }
ohair@286 265 return retval;*/
ohair@286 266 }
ohair@286 267 format = new MessageFormat(bundle.getString(messageId));
ohair@286 268 format.setLocale(locale);
ohair@286 269
ohair@286 270 // return the formatted message
ohair@286 271 StringBuffer result = new StringBuffer();
ohair@286 272
ohair@286 273 result = format.format(parameters, result, new FieldPosition(0));
ohair@286 274 return result.toString();
ohair@286 275 }
ohair@286 276
ohair@286 277
ohair@286 278 /**
ohair@286 279 * Chooses a client locale to use, using the first language specified in
ohair@286 280 * the list that is supported by this catalog. If none of the specified
ohair@286 281 * languages is supported, a null value is returned. Such a list of
ohair@286 282 * languages might be provided in an HTTP/1.1 "Accept-Language" header
ohair@286 283 * field, or through some other content negotiation mechanism.
ohair@286 284 * <p/>
ohair@286 285 * <P> The language specifiers recognized are RFC 1766 style ("fr" for
ohair@286 286 * all French, "fr-ca" for Canadian French), although only the strict
ohair@286 287 * ISO subset (two letter language and country specifiers) is currently
ohair@286 288 * supported. Java-style locale strings ("fr_CA") are also supported.
ohair@286 289 *
ohair@286 290 * @param languages Array of language specifiers, ordered with the most
ohair@286 291 * preferable one at the front. For example, "en-ca" then "fr-ca",
ohair@286 292 * followed by "zh_CN".
ohair@286 293 * @return The most preferable supported locale, or null.
ohair@286 294 * @see java.util.Locale
ohair@286 295 */
ohair@286 296 public Locale chooseLocale(String languages []) {
ohair@286 297 if ((languages = canonicalize(languages)) != null) {
ohair@286 298 for (int i = 0; i < languages.length; i++)
ohair@286 299 if (isLocaleSupported(languages[i]))
ohair@286 300 return getLocale(languages[i]);
ohair@286 301 }
ohair@286 302 return null;
ohair@286 303 }
ohair@286 304
ohair@286 305
ohair@286 306 //
ohair@286 307 // Canonicalizes the RFC 1766 style language strings ("en-in") to
ohair@286 308 // match standard Java usage ("en_IN"), removing strings that don't
ohair@286 309 // use two character ISO language and country codes. Avoids all
ohair@286 310 // memory allocations possible, so that if the strings passed in are
ohair@286 311 // just lowercase ISO codes (a common case) the input is returned.
ohair@286 312 //
ohair@286 313 private String[] canonicalize(String languages []) {
ohair@286 314 boolean didClone = false;
ohair@286 315 int trimCount = 0;
ohair@286 316
ohair@286 317 if (languages == null)
ohair@286 318 return languages;
ohair@286 319
ohair@286 320 for (int i = 0; i < languages.length; i++) {
ohair@286 321 String lang = languages[i];
ohair@286 322 int len = lang.length();
ohair@286 323
ohair@286 324 // no RFC1766 extensions allowed; "zh" and "zh-tw" (etc) are OK
ohair@286 325 // as are regular locale names with no variant ("de_CH").
ohair@286 326 if (!(len == 2 || len == 5)) {
ohair@286 327 if (!didClone) {
ohair@286 328 languages = (String[]) languages.clone();
ohair@286 329 didClone = true;
ohair@286 330 }
ohair@286 331 languages[i] = null;
ohair@286 332 trimCount++;
ohair@286 333 continue;
ohair@286 334 }
ohair@286 335
ohair@286 336 // language code ... if already lowercase, we change nothing
ohair@286 337 if (len == 2) {
ohair@286 338 lang = lang.toLowerCase();
ohair@286 339 if (lang != languages[i]) {
ohair@286 340 if (!didClone) {
ohair@286 341 languages = (String[]) languages.clone();
ohair@286 342 didClone = true;
ohair@286 343 }
ohair@286 344 languages[i] = lang;
ohair@286 345 }
ohair@286 346 continue;
ohair@286 347 }
ohair@286 348
ohair@286 349 // language_country ... fixup case, force "_"
ohair@286 350 char buf [] = new char[5];
ohair@286 351
ohair@286 352 buf[0] = Character.toLowerCase(lang.charAt(0));
ohair@286 353 buf[1] = Character.toLowerCase(lang.charAt(1));
ohair@286 354 buf[2] = '_';
ohair@286 355 buf[3] = Character.toUpperCase(lang.charAt(3));
ohair@286 356 buf[4] = Character.toUpperCase(lang.charAt(4));
ohair@286 357 if (!didClone) {
ohair@286 358 languages = (String[]) languages.clone();
ohair@286 359 didClone = true;
ohair@286 360 }
ohair@286 361 languages[i] = new String(buf);
ohair@286 362 }
ohair@286 363
ohair@286 364 // purge any shadows of deleted RFC1766 extended language codes
ohair@286 365 if (trimCount != 0) {
ohair@286 366 String temp [] = new String[languages.length - trimCount];
ohair@286 367 int i;
ohair@286 368
ohair@286 369 for (i = 0, trimCount = 0; i < temp.length; i++) {
ohair@286 370 while (languages[i + trimCount] == null)
ohair@286 371 trimCount++;
ohair@286 372 temp[i] = languages[i + trimCount];
ohair@286 373 }
ohair@286 374 languages = temp;
ohair@286 375 }
ohair@286 376 return languages;
ohair@286 377 }
ohair@286 378
ohair@286 379
ohair@286 380 //
ohair@286 381 // Returns a locale object supporting the specified locale, using
ohair@286 382 // a small cache to speed up some common languages and reduce the
ohair@286 383 // needless allocation of memory.
ohair@286 384 //
ohair@286 385 private Locale getLocale(String localeName) {
ohair@286 386 String language, country;
ohair@286 387 int index;
ohair@286 388
ohair@286 389 index = localeName.indexOf('_');
ohair@286 390 if (index == -1) {
ohair@286 391 //
ohair@286 392 // Special case the builtin JDK languages
ohair@286 393 //
ohair@286 394 if (localeName.equals("de"))
ohair@286 395 return Locale.GERMAN;
ohair@286 396 if (localeName.equals("en"))
ohair@286 397 return Locale.ENGLISH;
ohair@286 398 if (localeName.equals("fr"))
ohair@286 399 return Locale.FRENCH;
ohair@286 400 if (localeName.equals("it"))
ohair@286 401 return Locale.ITALIAN;
ohair@286 402 if (localeName.equals("ja"))
ohair@286 403 return Locale.JAPANESE;
ohair@286 404 if (localeName.equals("ko"))
ohair@286 405 return Locale.KOREAN;
ohair@286 406 if (localeName.equals("zh"))
ohair@286 407 return Locale.CHINESE;
ohair@286 408
ohair@286 409 language = localeName;
ohair@286 410 country = "";
ohair@286 411 } else {
ohair@286 412 if (localeName.equals("zh_CN"))
ohair@286 413 return Locale.SIMPLIFIED_CHINESE;
ohair@286 414 if (localeName.equals("zh_TW"))
ohair@286 415 return Locale.TRADITIONAL_CHINESE;
ohair@286 416
ohair@286 417 //
ohair@286 418 // JDK also has constants for countries: en_GB, en_US, en_CA,
ohair@286 419 // fr_FR, fr_CA, de_DE, ja_JP, ko_KR. We don't use those.
ohair@286 420 //
ohair@286 421 language = localeName.substring(0, index);
ohair@286 422 country = localeName.substring(index + 1);
ohair@286 423 }
ohair@286 424
ohair@286 425 return new Locale(language, country);
ohair@286 426 }
ohair@286 427
ohair@286 428
ohair@286 429 //
ohair@286 430 // cache for isLanguageSupported(), below ... key is a language
ohair@286 431 // or locale name, value is a Boolean
ohair@286 432 //
ohair@286 433 private Hashtable cache = new Hashtable(5);
ohair@286 434
ohair@286 435
ohair@286 436 /**
ohair@286 437 * Returns true iff the specified locale has explicit language support.
ohair@286 438 * For example, the traditional Chinese locale "zh_TW" has such support
ohair@286 439 * if there are message bundles suffixed with either "zh_TW" or "zh".
ohair@286 440 * <p/>
ohair@286 441 * <P> This method is used to bypass part of the search path mechanism
ohair@286 442 * of the <code>ResourceBundle</code> class, specifically the parts which
ohair@286 443 * force use of default locales and bundles. Such bypassing is required
ohair@286 444 * in order to enable use of a client's preferred languages. Following
ohair@286 445 * the above example, if a client prefers "zh_TW" but can also accept
ohair@286 446 * "ja", this method would be used to detect that there are no "zh_TW"
ohair@286 447 * resource bundles and hence that "ja" messages should be used. This
ohair@286 448 * bypasses the ResourceBundle mechanism which will return messages in
ohair@286 449 * some other locale (picking some hard-to-anticipate default) instead
ohair@286 450 * of reporting an error and letting the client choose another locale.
ohair@286 451 *
ohair@286 452 * @param localeName A standard Java locale name, using two character
ohair@286 453 * language codes optionally suffixed by country codes.
ohair@286 454 * @return True iff the language of that locale is supported.
ohair@286 455 * @see java.util.Locale
ohair@286 456 */
ohair@286 457 public boolean isLocaleSupported(String localeName) {
ohair@286 458 //
ohair@286 459 // Use previous results if possible. We expect that the codebase
ohair@286 460 // is immutable, so we never worry about changing the cache.
ohair@286 461 //
ohair@286 462 Boolean value = (Boolean) cache.get(localeName);
ohair@286 463
ohair@286 464 if (value != null)
ohair@286 465 return value.booleanValue();
ohair@286 466
ohair@286 467 //
ohair@286 468 // Try "language_country_variant", then "language_country",
ohair@286 469 // then finally "language" ... assuming the longest locale name
ohair@286 470 // is passed. If not, we'll try fewer options.
ohair@286 471 //
ohair@286 472 ClassLoader loader = null;
ohair@286 473
ohair@286 474 for (; ;) {
ohair@286 475 String name = bundleName + "_" + localeName;
ohair@286 476
ohair@286 477 // look up classes ...
ohair@286 478 try {
ohair@286 479 Class.forName(name);
ohair@286 480 cache.put(localeName, Boolean.TRUE);
ohair@286 481 return true;
ohair@286 482 } catch (Exception e) {
ohair@286 483 }
ohair@286 484
ohair@286 485 // ... then property files (only for ISO Latin/1 messages)
ohair@286 486 InputStream in;
ohair@286 487
ohair@286 488 if (loader == null)
ohair@286 489 loader = getClass().getClassLoader();
ohair@286 490
ohair@286 491 name = name.replace('.', '/');
ohair@286 492 name = name + ".properties";
ohair@286 493 if (loader == null)
ohair@286 494 in = ClassLoader.getSystemResourceAsStream(name);
ohair@286 495 else
ohair@286 496 in = loader.getResourceAsStream(name);
ohair@286 497 if (in != null) {
ohair@286 498 cache.put(localeName, Boolean.TRUE);
ohair@286 499 return true;
ohair@286 500 }
ohair@286 501
ohair@286 502 int index = localeName.indexOf('_');
ohair@286 503
ohair@286 504 if (index > 0)
ohair@286 505 localeName = localeName.substring(0, index);
ohair@286 506 else
ohair@286 507 break;
ohair@286 508 }
ohair@286 509
ohair@286 510 //
ohair@286 511 // If we got this far, we failed. Remember for later.
ohair@286 512 //
ohair@286 513 cache.put(localeName, Boolean.FALSE);
ohair@286 514 return false;
ohair@286 515 }
ohair@286 516 }

mercurial