DateFormatProvider implementation for application specific locale variant not loaded
<p>I have an implementation of DateFormatProvider packed in a jar with an appropriate java.text.spi.DateFormatProvider file, however that DateFormatProvider will not be used (in fact <code>LocaleServiceProviderPool.getPool(DateFormatProvider.class).hasEntries()</code> is false in the test program below.</p>

<h2>Implementation of DateFormatProvider:</h2>

<pre><code>package dateformatproviders;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.text.spi.DateFormatProvider;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Locale;

public class DateFormatProviderImpl extends DateFormatProvider
{
  private static final CompareLocales COMPARE_LOCALES = new CompareLocales();
  private Locale[] availableLocales;
  private static final String VARIANT = "variant_xxx";
  private final String formatString;
  private final Object availableLocalesLock = new Object();

  /**
   * for each available locale create a variant using the given variantString.
   * Return the list of all these locales
   *
   * @param variantString must not be null
   * @return never null nor empty
   */
  public static Locale[] installVariant(String variantString)
  {
    Locale[] availableLocales = Locale.getAvailableLocales();
    Locale[] result = new Locale[availableLocales.length];
    int pos = 0;
    for (Locale locale : availableLocales)
    {
      Locale newLocale = createLocale(locale, variantString);
      result[pos] = newLocale;
      ++pos;
    }
    return result;
  }

  public static Locale createLocale(Locale originalDefaultLocale, String variant)
  {
    Locale modifiedDefaultLocale = new Locale(originalDefaultLocale.getLanguage(), originalDefaultLocale.getCountry(), variant);
    return modifiedDefaultLocale;
  }

  public DateFormatProviderImpl()
  {
    formatString = "HH:mm:ss 't' MM/dd/yy";
  }

  private DateFormat createDateFormat()
  {
    return new SimpleDateFormat(formatString);
  }

  @Override
  public final DateFormat getTimeInstance(int style, Locale locale)
  {
    checkArguments(locale, style);
    return createDateFormat();
  }

  @Override
  public final DateFormat getDateInstance(int style, Locale locale)
  {
    checkArguments(locale, style);
    return createDateFormat();
  }

  @Override
  public final DateFormat getDateTimeInstance(int dateStyle, int timeStyle, Locale locale)
  {
    checkArguments(locale, dateStyle, timeStyle);
    return createDateFormat();
  }

  @Override
  public final Locale[] getAvailableLocales()
  {
    synchronized (availableLocalesLock)
    {
      if (null == availableLocales)
      {
        Locale[] sourceLocales = installVariant(VARIANT);
        availableLocales = Arrays.copyOf(sourceLocales, sourceLocales.length);
        Arrays.sort(availableLocales, COMPARE_LOCALES);
      }
    }
    return availableLocales;
  }

  public final String getVariant()
  {
    return VARIANT;
  }

  private void checkArguments(Locale locale, int... styles)
  {
    for (int style : styles)
    {
      switch (style)
      {
        case DateFormat.SHORT:
        case DateFormat.MEDIUM:

        case DateFormat.LONG:
        case DateFormat.FULL:
          break;
        default:
          throw new IllegalArgumentException("style:" + style + " must be one of{" + DateFormat.SHORT + ',' + DateFormat.MEDIUM + ','
                  + DateFormat.LONG + ',' + DateFormat.FULL + '}');
      }
    }
    checkLocale(locale);
  }

  private void checkLocale(Locale locale)
  {
    if (null == locale)
    {
      throw new IllegalArgumentException("locale must not be null");
    }
    if (Arrays.binarySearch(availableLocales, locale, COMPARE_LOCALES) &lt; 0)
    {
      throw new IllegalArgumentException("locale not supported:" + locale);
    }
  }

  private static class CompareLocales implements Comparator&lt;Locale&gt;
  {
    @Override
    public int compare(Locale lhs, Locale rhs)
    {
      if (null == lhs)
      {
        if (null == rhs)
        {
          return 0;
        }
        return -1;
      }
      if (null == rhs)
      {
        return 1;
      }
      String lhsLang = lhs.getLanguage();
      String rhsLang = rhs.getLanguage();
      int langCompare = lhsLang.compareTo(rhsLang);
      if (0 == langCompare)
      {
        String lhsCountry = lhs.getCountry();
        String rhsCountry = rhs.getCountry();
        int countryCompare = lhsCountry.compareTo(rhsCountry);
        if (0 == countryCompare)
        {
          String lhsVariant = lhs.getVariant();
          String rhsVariant = rhs.getVariant();
          return lhsVariant.compareTo(rhsVariant);
        }
        return countryCompare;
      }
      return langCompare;
    }
  }
}
</code></pre>

<h2>META-INF/services/java.text.spi.DateFormatProvider:</h2>

<pre><code>dateformatproviders.DateFormatProviderImpl
</code></pre>

<h2>Test program:</h2>

<pre><code>package datetest;

import dateformatproviders.DateFormatProviderImpl;
import java.text.DateFormat;
import java.text.spi.DateFormatProvider;
import java.util.Date;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import sun.util.LocaleServiceProviderPool;

public class Main
{
  /**
   * install the given dateFormatProvider for the default locale, using the default variant. &lt;br/&gt;
   * Changes the default locale
   *
   * @param dateFormatProvider
   */
  public static void install(DateFormatProviderImpl dateFormatProvider)
  {
    Locale originalDefaultLocale = Locale.getDefault();
    Locale modifiedDefaultLocale = DateFormatProviderImpl.createLocale(originalDefaultLocale, dateFormatProvider.getVariant());
    Locale.setDefault(modifiedDefaultLocale);
  }

  public static void main(String[] args) throws InterruptedException
  {
    install(new DateFormatProviderImpl());
    LocaleServiceProviderPool pool = LocaleServiceProviderPool.getPool(DateFormatProvider.class);
    boolean hasEntries = pool.hasProviders(); // is false
    while (true)
    {
      System.out.printf("%s\n", DateFormat.getDateTimeInstance().format(new Date()));
      TimeUnit.SECONDS.sleep(2);
    }

  }
}
</code></pre>

<p>in the directory that contains DateTest.jar and a folder lib containing DateFormatProvider.jar execution of:</p>

<pre><code>java -cp DateTest.jar:lib/DateFormatProvider.jar dateTest.Main
</code></pre>

<p>produces default formatted dates</p>

<p>When the jar file containing the DateFormatProvider and its java.text.spi.DateFormatProvider file is copied to jre/lib/ext the test program works however.</p>
