You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

NLS.java 3.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. /*
  2. * Copyright (C) 2010, Sasa Zivkov <sasa.zivkov@sap.com> and others
  3. *
  4. * This program and the accompanying materials are made available under the
  5. * terms of the Eclipse Distribution License v. 1.0 which is available at
  6. * https://www.eclipse.org/org/documents/edl-v10.php.
  7. *
  8. * SPDX-License-Identifier: BSD-3-Clause
  9. */
  10. package org.eclipse.jgit.nls;
  11. import java.util.Locale;
  12. import java.util.concurrent.ConcurrentHashMap;
  13. import org.eclipse.jgit.errors.TranslationBundleLoadingException;
  14. import org.eclipse.jgit.errors.TranslationStringMissingException;
  15. /**
  16. * The purpose of this class is to provide NLS (National Language Support)
  17. * configurable per thread.
  18. *
  19. * <p>
  20. * The {@link #setLocale(Locale)} method is used to configure locale for the
  21. * calling thread. The locale setting is thread inheritable. This means that a
  22. * child thread will have the same locale setting as its creator thread until it
  23. * changes it explicitly.
  24. *
  25. * <p>
  26. * Example of usage:
  27. *
  28. * <pre>
  29. * NLS.setLocale(Locale.GERMAN);
  30. * TransportText t = NLS.getBundleFor(TransportText.class);
  31. * </pre>
  32. */
  33. public class NLS {
  34. /**
  35. * The root locale constant. It is defined here because the Locale.ROOT is
  36. * not defined in Java 5
  37. */
  38. public static final Locale ROOT_LOCALE = new Locale("", "", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
  39. private static final InheritableThreadLocal<NLS> local = new InheritableThreadLocal<>();
  40. /**
  41. * Sets the locale for the calling thread.
  42. * <p>
  43. * The {@link #getBundleFor(Class)} method will honor this setting if it
  44. * is supported by the provided resource bundle property files. Otherwise,
  45. * it will use a fall back locale as described in the
  46. * {@link TranslationBundle}
  47. *
  48. * @param locale
  49. * the preferred locale
  50. */
  51. public static void setLocale(Locale locale) {
  52. local.set(new NLS(locale));
  53. }
  54. /**
  55. * Sets the JVM default locale as the locale for the calling thread.
  56. * <p>
  57. * Semantically this is equivalent to
  58. * <code>NLS.setLocale(Locale.getDefault())</code>.
  59. */
  60. public static void useJVMDefaultLocale() {
  61. useJVMDefaultInternal();
  62. }
  63. // TODO(ms): change signature of public useJVMDefaultLocale() in 5.0 to get
  64. // rid of this internal method
  65. private static NLS useJVMDefaultInternal() {
  66. NLS b = new NLS(Locale.getDefault());
  67. local.set(b);
  68. return b;
  69. }
  70. /**
  71. * Returns an instance of the translation bundle of the required type. All
  72. * public String fields of the bundle instance will get their values
  73. * injected as described in the
  74. * {@link org.eclipse.jgit.nls.TranslationBundle}.
  75. *
  76. * @param type
  77. * required bundle type
  78. * @return an instance of the required bundle type
  79. * @exception TranslationBundleLoadingException
  80. * see
  81. * {@link org.eclipse.jgit.errors.TranslationBundleLoadingException}
  82. * @exception TranslationStringMissingException
  83. * see
  84. * {@link org.eclipse.jgit.errors.TranslationStringMissingException}
  85. */
  86. public static <T extends TranslationBundle> T getBundleFor(Class<T> type) {
  87. NLS b = local.get();
  88. if (b == null) {
  89. b = useJVMDefaultInternal();
  90. }
  91. return b.get(type);
  92. }
  93. /**
  94. * Release resources held by NLS
  95. * @since 5.8
  96. */
  97. public static void clear() {
  98. local.remove();
  99. GlobalBundleCache.clear();
  100. }
  101. private final Locale locale;
  102. private final ConcurrentHashMap<Class, TranslationBundle> map = new ConcurrentHashMap<>();
  103. private NLS(Locale locale) {
  104. this.locale = locale;
  105. }
  106. @SuppressWarnings("unchecked")
  107. private <T extends TranslationBundle> T get(Class<T> type) {
  108. TranslationBundle bundle = map.get(type);
  109. if (bundle == null) {
  110. bundle = GlobalBundleCache.lookupBundle(locale, type);
  111. // There is a small opportunity for a race, which we may
  112. // lose. Accept defeat and return the winner's instance.
  113. TranslationBundle old = map.putIfAbsent(type, bundle);
  114. if (old != null)
  115. bundle = old;
  116. }
  117. return (T) bundle;
  118. }
  119. }