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

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