1 /*
   2  * Copyright (c) 2012, 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
  23  * questions.
  24  */
  25 
  26 package sun.util.locale.provider;
  27 
  28 import java.text.spi.BreakIteratorProvider;
  29 import java.text.spi.CollatorProvider;
  30 import java.text.spi.DateFormatProvider;
  31 import java.text.spi.DateFormatSymbolsProvider;
  32 import java.text.spi.DecimalFormatSymbolsProvider;
  33 import java.text.spi.NumberFormatProvider;
  34 import java.util.Arrays;
  35 import java.util.HashSet;
  36 import java.util.Locale;
  37 import java.util.Set;
  38 import java.util.concurrent.ConcurrentHashMap;
  39 import java.util.concurrent.ConcurrentMap;
  40 import java.util.spi.CalendarDataProvider;
  41 import java.util.spi.CalendarNameProvider;
  42 import java.util.spi.CurrencyNameProvider;
  43 import java.util.spi.LocaleNameProvider;
  44 import java.util.spi.LocaleServiceProvider;
  45 import java.util.spi.TimeZoneNameProvider;
  46 import sun.util.spi.CalendarProvider;
  47 
  48 /**
  49  * An abstract parent class for the
  50  * HostLocaleProviderAdapter/SPILocaleProviderAdapter.
  51  *
  52  * @author Naoto Sato
  53  * @author Masayoshi Okutsu
  54  */
  55 public abstract class AuxLocaleProviderAdapter extends LocaleProviderAdapter {
  56     /**
  57      * SPI implementations map
  58      */
  59     private ConcurrentMap<Class<? extends LocaleServiceProvider>, LocaleServiceProvider> providersMap =
  60             new ConcurrentHashMap<>();
  61 
  62     /**
  63      * Getter method for Locale Service Providers
  64      */
  65     @Override
  66     public <P extends LocaleServiceProvider> P getLocaleServiceProvider(Class<P> c) {
  67         @SuppressWarnings("unchecked")
  68         P lsp = (P) providersMap.get(c);
  69         if (lsp == null) {
  70             lsp = findInstalledProvider(c);
  71             providersMap.putIfAbsent(c, lsp == null ? NULL_PROVIDER : lsp);
  72         }
  73 
  74         return lsp;
  75     }
  76 
  77     /**
  78      * Real body to find an implementation for each SPI.
  79      *
  80      * @param <P>
  81      * @param c
  82      * @return
  83      */
  84     protected abstract <P extends LocaleServiceProvider> P findInstalledProvider(final Class<P> c);
  85 
  86     @Override
  87     public BreakIteratorProvider getBreakIteratorProvider() {
  88         return getLocaleServiceProvider(BreakIteratorProvider.class);
  89     }
  90 
  91     @Override
  92     public CollatorProvider getCollatorProvider() {
  93         return getLocaleServiceProvider(CollatorProvider.class);
  94     }
  95 
  96     @Override
  97     public DateFormatProvider getDateFormatProvider() {
  98         return getLocaleServiceProvider(DateFormatProvider.class);
  99     }
 100 
 101     @Override
 102     public DateFormatSymbolsProvider getDateFormatSymbolsProvider() {
 103         return getLocaleServiceProvider(DateFormatSymbolsProvider.class);
 104     }
 105 
 106     @Override
 107     public DecimalFormatSymbolsProvider getDecimalFormatSymbolsProvider() {
 108         return getLocaleServiceProvider(DecimalFormatSymbolsProvider.class);
 109     }
 110 
 111     @Override
 112     public NumberFormatProvider getNumberFormatProvider() {
 113         return getLocaleServiceProvider(NumberFormatProvider.class);
 114     }
 115 
 116     /**
 117      * Getter methods for java.util.spi.* providers
 118      */
 119     @Override
 120     public CurrencyNameProvider getCurrencyNameProvider() {
 121         return getLocaleServiceProvider(CurrencyNameProvider.class);
 122     }
 123 
 124     @Override
 125     public LocaleNameProvider getLocaleNameProvider() {
 126         return getLocaleServiceProvider(LocaleNameProvider.class);
 127     }
 128 
 129     @Override
 130     public TimeZoneNameProvider getTimeZoneNameProvider() {
 131         return getLocaleServiceProvider(TimeZoneNameProvider.class);
 132     }
 133 
 134     @Override
 135     public CalendarDataProvider getCalendarDataProvider() {
 136         return getLocaleServiceProvider(CalendarDataProvider.class);
 137     }
 138 
 139     @Override
 140     public CalendarNameProvider getCalendarNameProvider() {
 141         return getLocaleServiceProvider(CalendarNameProvider.class);
 142     }
 143 
 144     /**
 145      * Getter methods for sun.util.spi.* providers
 146      */
 147     @Override
 148     public CalendarProvider getCalendarProvider() {
 149         return getLocaleServiceProvider(CalendarProvider.class);
 150     }
 151 
 152     @Override
 153     public LocaleResources getLocaleResources(Locale locale) {
 154         return null;
 155     }
 156 
 157     private static Locale[] availableLocales = null;
 158 
 159     @Override
 160     public Locale[] getAvailableLocales() {
 161         if (availableLocales == null) {
 162             Set<Locale> avail = new HashSet<>();
 163             for (Class<? extends LocaleServiceProvider> c :
 164                     LocaleServiceProviderPool.spiClasses) {
 165                 LocaleServiceProvider lsp = getLocaleServiceProvider(c);
 166                 if (lsp != null) {
 167                     avail.addAll(Arrays.asList(lsp.getAvailableLocales()));
 168                 }
 169             }
 170             availableLocales = avail.toArray(new Locale[0]);
 171         }
 172 
 173         // assuming caller won't mutate the array.
 174         return availableLocales;
 175     }
 176 
 177     /**
 178      * A dummy locale service provider that indicates there is no
 179      * provider available
 180      */
 181     private static NullProvider NULL_PROVIDER = new NullProvider();
 182     private static class NullProvider extends LocaleServiceProvider {
 183         @Override
 184         public Locale[] getAvailableLocales() {
 185             return new Locale[0];
 186         }
 187     }
 188 }