< prev index next >

src/jdk.xml.bind/share/classes/com/sun/xml/internal/dtdparser/MessageCatalog.java

Print this page


   1 /*
   2  * Copyright (c) 2009, 2013, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


  26 package com.sun.xml.internal.dtdparser;
  27 
  28 import java.io.InputStream;
  29 import java.text.FieldPosition;
  30 import java.text.MessageFormat;
  31 import java.util.Hashtable;
  32 import java.util.Locale;
  33 import java.util.MissingResourceException;
  34 import java.util.ResourceBundle;
  35 
  36 
  37 /**
  38  * This class provides support for multi-language string lookup, as needed
  39  * to localize messages from applications supporting multiple languages
  40  * at the same time.  One class of such applications is network services,
  41  * such as HTTP servers, which talk to clients who may not be from the
  42  * same locale as the server.  This class supports a form of negotiation
  43  * for the language used in presenting a message from some package, where
  44  * both user (client) preferences and application (server) support are
  45  * accounted for when choosing locales and formatting messages.
  46  * <p/>
  47  * <P> Each package should have a singleton package-private message catalog
  48  * class.  This ensures that the correct class loader will always be used to
  49  * access message resources, and minimizes use of memory: <PRE>
  50  * package <em>some.package</em>;
  51  * <p/>
  52  * // "foo" might be public
  53  * class foo {
  54  * ...
  55  * // package private
  56  * static final Catalog messages = new Catalog ();
  57  * static final class Catalog extends MessageCatalog {
  58  * Catalog () { super (Catalog.class); }
  59  * }
  60  * ...
  61  * }
  62  * </PRE>
  63  * <p/>
  64  * <P> Messages for a known client could be generated using code
  65  * something like this:  <PRE>
  66  * String clientLanguages [];
  67  * Locale clientLocale;
  68  * String clientMessage;
  69  * <p/>
  70  * // client languages will probably be provided by client,
  71  * // e.g. by an HTTP/1.1 "Accept-Language" header.
  72  * clientLanguages = new String [] { "en-ca", "fr-ca", "ja", "zh" };
  73  * clientLocale = foo.messages.chooseLocale (clientLanguages);
  74  * clientMessage = foo.messages.getMessage (clientLocale,
  75  * "fileCount",
  76  * new Object [] { new Integer (numberOfFiles) }
  77  * );
  78  * </PRE>
  79  * <p/>
  80  * <P> At this time, this class does not include functionality permitting
  81  * messages to be passed around and localized after-the-fact.  The consequence
  82  * of this is that the locale for messages must be passed down through layers
  83  * which have no normal reason to support such passdown, or else the system
  84  * default locale must be used instead of the one the client needs.
  85  * <p/>
  86  * <P> <hr> The following guidelines should be used when constructiong
  87  * multi-language applications:  <OL>
  88  * <p/>
  89  * <LI> Always use <a href=#chooseLocale>chooseLocale</a> to select the
  90  * locale you pass to your <code>getMessage</code> call.  This lets your
  91  * applications use IETF standard locale names, and avoids needless
  92  * use of system defaults.
  93  * <p/>
  94  * <LI> The localized messages for a given package should always go in
  95  * a separate <em>resources</em> sub-package.  There are security
  96  * implications; see below.
  97  * <p/>
  98  * <LI> Make sure that a language name is included in each bundle name,
  99  * so that the developer's locale will not be inadvertently used. That
 100  * is, don't create defaults like <em>resources/Messages.properties</em>
 101  * or <em>resources/Messages.class</em>, since ResourceBundle will choose
 102  * such defaults rather than giving software a chance to choose a more
 103  * appropriate language for its messages.  Your message bundles should
 104  * have names like <em>Messages_en.properties</em> (for the "en", or
 105  * English, language) or <em>Messages_ja.class</em> ("ja" indicates the
 106  * Japanese language).
 107  * <p/>
 108  * <LI> Only use property files for messages in languages which can
 109  * be limited to the ISO Latin/1 (8859-1) characters supported by the
 110  * property file format.  (This is mostly Western European languages.)
 111  * Otherwise, subclass ResourceBundle to provide your messages; it is
 112  * simplest to subclass <code>java.util.ListResourceBundle</code>.
 113  * <p/>
 114  * <LI> Never use another package's message catalog or resource bundles.
 115  * It should not be possible for a change internal to one package (such
 116  * as eliminating or improving messages) to break another package.
 117  * <p/>
 118  * </OL>
 119  * <p/>
 120  * <P> The "resources" sub-package can be treated separately from the
 121  * package with which it is associated.  That main package may be sealed
 122  * and possibly signed, preventing other software from adding classes to
 123  * the package which would be able to access methods and data which are
 124  * not designed to be publicly accessible.  On the other hand, resources
 125  * such as localized messages are often provided after initial product
 126  * shipment, without a full release cycle for the product.  Such files
 127  * (text and class files) need to be added to some package.  Since they
 128  * should not be added to the main package, the "resources" subpackage is
 129  * used without risking the security or integrity of that main package
 130  * as distributed in its JAR file.
 131  *
 132  * @author David Brownell
 133  * @version 1.1, 00/08/05
 134  * @see java.util.Locale
 135  * @see java.util.ListResourceBundle
 136  * @see java.text.MessageFormat
 137  */
 138 // leave this as "abstract" -- each package needs its own subclass,
 139 // else it's not always going to be using the right class loader.
 140 abstract public class MessageCatalog {
 141     private String bundleName;
 142 
 143     /**
 144      * Create a message catalog for use by classes in the same package
 145      * as the specified class.  This uses <em>Messages</em> resource
 146      * bundles in the <em>resources</em> sub-package of class passed as
 147      * a parameter.
 148      *
 149      * @param packageMember Class whose package has localized messages
 150      */


 264             }
 265             return retval;*/
 266         }
 267         format = new MessageFormat(bundle.getString(messageId));
 268         format.setLocale(locale);
 269 
 270         // return the formatted message
 271         StringBuffer result = new StringBuffer();
 272 
 273         result = format.format(parameters, result, new FieldPosition(0));
 274         return result.toString();
 275     }
 276 
 277 
 278     /**
 279      * Chooses a client locale to use, using the first language specified in
 280      * the list that is supported by this catalog.  If none of the specified
 281      * languages is supported, a null value is returned.  Such a list of
 282      * languages might be provided in an HTTP/1.1 "Accept-Language" header
 283      * field, or through some other content negotiation mechanism.
 284      * <p/>
 285      * <P> The language specifiers recognized are RFC 1766 style ("fr" for
 286      * all French, "fr-ca" for Canadian French), although only the strict
 287      * ISO subset (two letter language and country specifiers) is currently
 288      * supported.  Java-style locale strings ("fr_CA") are also supported.
 289      *
 290      * @param languages Array of language specifiers, ordered with the most
 291      *                  preferable one at the front.  For example, "en-ca" then "fr-ca",
 292      *                  followed by "zh_CN".
 293      * @return The most preferable supported locale, or null.
 294      * @see java.util.Locale
 295      */
 296     public Locale chooseLocale(String languages []) {
 297         if ((languages = canonicalize(languages)) != null) {
 298             for (int i = 0; i < languages.length; i++)
 299                 if (isLocaleSupported(languages[i]))
 300                     return getLocale(languages[i]);
 301         }
 302         return null;
 303     }
 304 
 305 
 306     //
 307     // Canonicalizes the RFC 1766 style language strings ("en-in") to
 308     // match standard Java usage ("en_IN"), removing strings that don't


 318             return languages;
 319 
 320         for (int i = 0; i < languages.length; i++) {
 321             String lang = languages[i];
 322             int len = lang.length();
 323 
 324             // no RFC1766 extensions allowed; "zh" and "zh-tw" (etc) are OK
 325             // as are regular locale names with no variant ("de_CH").
 326             if (!(len == 2 || len == 5)) {
 327                 if (!didClone) {
 328                     languages = (String[]) languages.clone();
 329                     didClone = true;
 330                 }
 331                 languages[i] = null;
 332                 trimCount++;
 333                 continue;
 334             }
 335 
 336             // language code ... if already lowercase, we change nothing
 337             if (len == 2) {
 338                 lang = lang.toLowerCase();
 339                 if (lang != languages[i]) {
 340                     if (!didClone) {
 341                         languages = (String[]) languages.clone();
 342                         didClone = true;
 343                     }
 344                     languages[i] = lang;
 345                 }
 346                 continue;
 347             }
 348 
 349             // language_country ... fixup case, force "_"
 350             char buf [] = new char[5];
 351 
 352             buf[0] = Character.toLowerCase(lang.charAt(0));
 353             buf[1] = Character.toLowerCase(lang.charAt(1));
 354             buf[2] = '_';
 355             buf[3] = Character.toUpperCase(lang.charAt(3));
 356             buf[4] = Character.toUpperCase(lang.charAt(4));
 357             if (!didClone) {
 358                 languages = (String[]) languages.clone();


 420             //
 421             language = localeName.substring(0, index);
 422             country = localeName.substring(index + 1);
 423         }
 424 
 425         return new Locale(language, country);
 426     }
 427 
 428 
 429     //
 430     // cache for isLanguageSupported(), below ... key is a language
 431     // or locale name, value is a Boolean
 432     //
 433     private Hashtable cache = new Hashtable(5);
 434 
 435 
 436     /**
 437      * Returns true iff the specified locale has explicit language support.
 438      * For example, the traditional Chinese locale "zh_TW" has such support
 439      * if there are message bundles suffixed with either "zh_TW" or "zh".
 440      * <p/>
 441      * <P> This method is used to bypass part of the search path mechanism
 442      * of the <code>ResourceBundle</code> class, specifically the parts which
 443      * force use of default locales and bundles.  Such bypassing is required
 444      * in order to enable use of a client's preferred languages.  Following
 445      * the above example, if a client prefers "zh_TW" but can also accept
 446      * "ja", this method would be used to detect that there are no "zh_TW"
 447      * resource bundles and hence that "ja" messages should be used.  This
 448      * bypasses the ResourceBundle mechanism which will return messages in
 449      * some other locale (picking some hard-to-anticipate default) instead
 450      * of reporting an error and letting the client choose another locale.
 451      *
 452      * @param localeName A standard Java locale name, using two character
 453      *                   language codes optionally suffixed by country codes.
 454      * @return True iff the language of that locale is supported.
 455      * @see java.util.Locale
 456      */
 457     public boolean isLocaleSupported(String localeName) {
 458         //
 459         // Use previous results if possible.  We expect that the codebase
 460         // is immutable, so we never worry about changing the cache.


   1 /*
   2  * Copyright (c) 1998, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


  26 package com.sun.xml.internal.dtdparser;
  27 
  28 import java.io.InputStream;
  29 import java.text.FieldPosition;
  30 import java.text.MessageFormat;
  31 import java.util.Hashtable;
  32 import java.util.Locale;
  33 import java.util.MissingResourceException;
  34 import java.util.ResourceBundle;
  35 
  36 
  37 /**
  38  * This class provides support for multi-language string lookup, as needed
  39  * to localize messages from applications supporting multiple languages
  40  * at the same time.  One class of such applications is network services,
  41  * such as HTTP servers, which talk to clients who may not be from the
  42  * same locale as the server.  This class supports a form of negotiation
  43  * for the language used in presenting a message from some package, where
  44  * both user (client) preferences and application (server) support are
  45  * accounted for when choosing locales and formatting messages.
  46  *
  47  * <p>Each package should have a singleton package-private message catalog
  48  * class.  This ensures that the correct class loader will always be used to
  49  * access message resources, and minimizes use of memory:</p><pre>
  50  * package <em>some.package</em>;
  51  *
  52  * // "foo" might be public
  53  * class foo {
  54  * ...
  55  * // package private
  56  * static final Catalog messages = new Catalog ();
  57  * static final class Catalog extends MessageCatalog {
  58  * Catalog () { super (Catalog.class); }
  59  * }
  60  * ...
  61  * }
  62  * </pre>
  63  *
  64  * <p> Messages for a known client could be generated using code
  65  * something like this:</p><pre>
  66  * String clientLanguages [];
  67  * Locale clientLocale;
  68  * String clientMessage;
  69  *
  70  * // client languages will probably be provided by client,
  71  * // e.g. by an HTTP/1.1 "Accept-Language" header.
  72  * clientLanguages = new String [] { "en-ca", "fr-ca", "ja", "zh" };
  73  * clientLocale = foo.messages.chooseLocale (clientLanguages);
  74  * clientMessage = foo.messages.getMessage (clientLocale,
  75  * "fileCount",
  76  * new Object [] { new Integer (numberOfFiles) }
  77  * );
  78  * </pre>
  79  *
  80  * <p> At this time, this class does not include functionality permitting
  81  * messages to be passed around and localized after-the-fact.  The consequence
  82  * of this is that the locale for messages must be passed down through layers
  83  * which have no normal reason to support such passdown, or else the system
  84  * default locale must be used instead of the one the client needs.</p>
  85  *
  86  * <p> The following guidelines should be used when constructiong
  87  * multi-language applications:</p>
  88  * <ol>
  89  * <li> Always use <a href=#chooseLocale>chooseLocale</a> to select the
  90  * locale you pass to your <code>getMessage</code> call.  This lets your
  91  * applications use IETF standard locale names, and avoids needless
  92  * use of system defaults.</li>
  93  *
  94  * <li> The localized messages for a given package should always go in
  95  * a separate <em>resources</em> sub-package.  There are security
  96  * implications; see below.</li>
  97  *
  98  * <li> Make sure that a language name is included in each bundle name,
  99  * so that the developer's locale will not be inadvertently used. That
 100  * is, don't create defaults like <em>resources/Messages.properties</em>
 101  * or <em>resources/Messages.class</em>, since ResourceBundle will choose
 102  * such defaults rather than giving software a chance to choose a more
 103  * appropriate language for its messages.  Your message bundles should
 104  * have names like <em>Messages_en.properties</em> (for the "en", or
 105  * English, language) or <em>Messages_ja.class</em> ("ja" indicates the
 106  * Japanese language).</li>
 107  *
 108  * <li> Only use property files for messages in languages which can
 109  * be limited to the ISO Latin/1 (8859-1) characters supported by the
 110  * property file format.  (This is mostly Western European languages.)
 111  * Otherwise, subclass ResourceBundle to provide your messages; it is
 112  * simplest to subclass <code>java.util.ListResourceBundle</code>.</li>
 113  *
 114  * <li> Never use another package's message catalog or resource bundles.
 115  * It should not be possible for a change internal to one package (such
 116  * as eliminating or improving messages) to break another package.</li>
 117  *</ol>
 118  *
 119  * <p>The "resources" sub-package can be treated separately from the

 120  * package with which it is associated.  That main package may be sealed
 121  * and possibly signed, preventing other software from adding classes to
 122  * the package which would be able to access methods and data which are
 123  * not designed to be publicly accessible.  On the other hand, resources
 124  * such as localized messages are often provided after initial product
 125  * shipment, without a full release cycle for the product.  Such files
 126  * (text and class files) need to be added to some package.  Since they
 127  * should not be added to the main package, the "resources" subpackage is
 128  * used without risking the security or integrity of that main package
 129  * as distributed in its JAR file.</p>
 130  *
 131  * @author David Brownell
 132  * @version 1.1, 00/08/05
 133  * @see java.util.Locale
 134  * @see java.util.ListResourceBundle
 135  * @see java.text.MessageFormat
 136  */
 137 // leave this as "abstract" -- each package needs its own subclass,
 138 // else it's not always going to be using the right class loader.
 139 abstract public class MessageCatalog {
 140     private String bundleName;
 141 
 142     /**
 143      * Create a message catalog for use by classes in the same package
 144      * as the specified class.  This uses <em>Messages</em> resource
 145      * bundles in the <em>resources</em> sub-package of class passed as
 146      * a parameter.
 147      *
 148      * @param packageMember Class whose package has localized messages
 149      */


 263             }
 264             return retval;*/
 265         }
 266         format = new MessageFormat(bundle.getString(messageId));
 267         format.setLocale(locale);
 268 
 269         // return the formatted message
 270         StringBuffer result = new StringBuffer();
 271 
 272         result = format.format(parameters, result, new FieldPosition(0));
 273         return result.toString();
 274     }
 275 
 276 
 277     /**
 278      * Chooses a client locale to use, using the first language specified in
 279      * the list that is supported by this catalog.  If none of the specified
 280      * languages is supported, a null value is returned.  Such a list of
 281      * languages might be provided in an HTTP/1.1 "Accept-Language" header
 282      * field, or through some other content negotiation mechanism.
 283      *
 284      * <p> The language specifiers recognized are RFC 1766 style ("fr" for
 285      * all French, "fr-ca" for Canadian French), although only the strict
 286      * ISO subset (two letter language and country specifiers) is currently
 287      * supported.  Java-style locale strings ("fr_CA") are also supported.</p>
 288      *
 289      * @param languages Array of language specifiers, ordered with the most
 290      *                  preferable one at the front.  For example, "en-ca" then "fr-ca",
 291      *                  followed by "zh_CN".
 292      * @return The most preferable supported locale, or null.
 293      * @see java.util.Locale
 294      */
 295     public Locale chooseLocale(String languages []) {
 296         if ((languages = canonicalize(languages)) != null) {
 297             for (int i = 0; i < languages.length; i++)
 298                 if (isLocaleSupported(languages[i]))
 299                     return getLocale(languages[i]);
 300         }
 301         return null;
 302     }
 303 
 304 
 305     //
 306     // Canonicalizes the RFC 1766 style language strings ("en-in") to
 307     // match standard Java usage ("en_IN"), removing strings that don't


 317             return languages;
 318 
 319         for (int i = 0; i < languages.length; i++) {
 320             String lang = languages[i];
 321             int len = lang.length();
 322 
 323             // no RFC1766 extensions allowed; "zh" and "zh-tw" (etc) are OK
 324             // as are regular locale names with no variant ("de_CH").
 325             if (!(len == 2 || len == 5)) {
 326                 if (!didClone) {
 327                     languages = (String[]) languages.clone();
 328                     didClone = true;
 329                 }
 330                 languages[i] = null;
 331                 trimCount++;
 332                 continue;
 333             }
 334 
 335             // language code ... if already lowercase, we change nothing
 336             if (len == 2) {
 337                 lang = lang.toLowerCase(Locale.ENGLISH);
 338                 if (lang != languages[i]) {
 339                     if (!didClone) {
 340                         languages = (String[]) languages.clone();
 341                         didClone = true;
 342                     }
 343                     languages[i] = lang;
 344                 }
 345                 continue;
 346             }
 347 
 348             // language_country ... fixup case, force "_"
 349             char buf [] = new char[5];
 350 
 351             buf[0] = Character.toLowerCase(lang.charAt(0));
 352             buf[1] = Character.toLowerCase(lang.charAt(1));
 353             buf[2] = '_';
 354             buf[3] = Character.toUpperCase(lang.charAt(3));
 355             buf[4] = Character.toUpperCase(lang.charAt(4));
 356             if (!didClone) {
 357                 languages = (String[]) languages.clone();


 419             //
 420             language = localeName.substring(0, index);
 421             country = localeName.substring(index + 1);
 422         }
 423 
 424         return new Locale(language, country);
 425     }
 426 
 427 
 428     //
 429     // cache for isLanguageSupported(), below ... key is a language
 430     // or locale name, value is a Boolean
 431     //
 432     private Hashtable cache = new Hashtable(5);
 433 
 434 
 435     /**
 436      * Returns true iff the specified locale has explicit language support.
 437      * For example, the traditional Chinese locale "zh_TW" has such support
 438      * if there are message bundles suffixed with either "zh_TW" or "zh".
 439      *
 440      * <P> This method is used to bypass part of the search path mechanism
 441      * of the <code>ResourceBundle</code> class, specifically the parts which
 442      * force use of default locales and bundles.  Such bypassing is required
 443      * in order to enable use of a client's preferred languages.  Following
 444      * the above example, if a client prefers "zh_TW" but can also accept
 445      * "ja", this method would be used to detect that there are no "zh_TW"
 446      * resource bundles and hence that "ja" messages should be used.  This
 447      * bypasses the ResourceBundle mechanism which will return messages in
 448      * some other locale (picking some hard-to-anticipate default) instead
 449      * of reporting an error and letting the client choose another locale.
 450      *
 451      * @param localeName A standard Java locale name, using two character
 452      *                   language codes optionally suffixed by country codes.
 453      * @return True iff the language of that locale is supported.
 454      * @see java.util.Locale
 455      */
 456     public boolean isLocaleSupported(String localeName) {
 457         //
 458         // Use previous results if possible.  We expect that the codebase
 459         // is immutable, so we never worry about changing the cache.


< prev index next >