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.resources.LocaleData;
  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     @Override
 145     public LocaleResources getLocaleResources(Locale locale) {
 146         return null;
 147     }
 148 
 149     @Override
 150     public LocaleData getLocaleData() {
 151         return null;
 152     }
 153 
 154     private static Locale[] availableLocales = null;
 155 
 156     @Override
 157     public Locale[] getAvailableLocales() {
 158         if (availableLocales == null) {
 159             Set<Locale> avail = new HashSet<>();
 160             for (Class<? extends LocaleServiceProvider> c :
 161                     LocaleServiceProviderPool.spiClasses) {
 162                 LocaleServiceProvider lsp = getLocaleServiceProvider(c);
 163                 if (lsp != null) {
 164                     avail.addAll(Arrays.asList(lsp.getAvailableLocales()));
 165                 }
 166             }
 167             availableLocales = avail.toArray(new Locale[0]);
 168         }
 169 
 170         // assuming caller won't mutate the array.
 171         return availableLocales;
 172     }
 173 
 174     /**
 175      * A dummy locale service provider that indicates there is no
 176      * provider available
 177      */
 178     private static NullProvider NULL_PROVIDER = new NullProvider();
 179     private static class NullProvider extends LocaleServiceProvider {
 180         @Override
 181         public Locale[] getAvailableLocales() {
 182             return new Locale[0];
 183         }
 184     }
 185 }