1f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/*
2f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  Licensed to the Apache Software Foundation (ASF) under one or more
3f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  contributor license agreements.  See the NOTICE file distributed with
4f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  this work for additional information regarding copyright ownership.
5f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  The ASF licenses this file to You under the Apache License, Version 2.0
6f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  (the "License"); you may not use this file except in compliance with
7f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  the License.  You may obtain a copy of the License at
8f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
9f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *     http://www.apache.org/licenses/LICENSE-2.0
10f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *
11f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  Unless required by applicable law or agreed to in writing, software
12f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  distributed under the License is distributed on an "AS IS" BASIS,
13f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  See the License for the specific language governing permissions and
15f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project *  limitations under the License.
16f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
17f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
18f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpackage java.util;
19f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
20f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.IOException;
21f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.io.InputStream;
22f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.AccessController;
23f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport java.security.PrivilegedAction;
24f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
25f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// BEGIN android-changed
26f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// import org.apache.harmony.kernel.vm.VM;
27f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectimport dalvik.system.VMStack;
28f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project// END android-changed
293819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilsonimport org.apache.harmony.luni.util.Msg;
30f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
31f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project/**
32f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * {@code ResourceBundle} is an abstract class which is the superclass of classes which
33f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * provide {@code Locale}-specific resources. A bundle contains a number of named
34f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * resources, where the names are {@code Strings}. A bundle may have a parent bundle,
35f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * and when a resource is not found in a bundle, the parent bundle is searched for
36f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the resource. If the fallback mechanism reaches the base bundle and still
37f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * can't find the resource it throws a {@code MissingResourceException}.
383819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson *
39f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <ul>
40f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>All bundles for the same group of resources share a common base bundle.
41f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * This base bundle acts as the root and is the last fallback in case none of
42f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * its children was able to respond to a request.</li>
43f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>The first level contains changes between different languages. Only the
44f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * differences between a language and the language of the base bundle need to be
45f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * handled by a language-specific {@code ResourceBundle}.</li>
46f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>The second level contains changes between different countries that use
47f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the same language. Only the differences between a country and the country of
48f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the language bundle need to be handled by a country-specific {@code ResourceBundle}.
49f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * </li>
50f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>The third level contains changes that don't have a geographic reason
51f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * (e.g. changes that where made at some point in time like {@code PREEURO} where the
52f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * currency of come countries changed. The country bundle would return the
53f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * current currency (Euro) and the {@code PREEURO} variant bundle would return the old
54f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * currency (e.g. DM for Germany).</li>
55f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * </ul>
563819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson *
57f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <strong>Examples</strong>
58f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <ul>
59f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>BaseName (base bundle)
60f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>BaseName_de (german language bundle)
61f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>BaseName_fr (french language bundle)
62f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>BaseName_de_DE (bundle with Germany specific resources in german)
63f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>BaseName_de_CH (bundle with Switzerland specific resources in german)
64f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>BaseName_fr_CH (bundle with Switzerland specific resources in french)
65f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>BaseName_de_DE_PREEURO (bundle with Germany specific resources in german of
66f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the time before the Euro)
67f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * <li>BaseName_fr_FR_PREEURO (bundle with France specific resources in french of
68f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * the time before the Euro)
69f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * </ul>
703819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson *
71f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * It's also possible to create variants for languages or countries. This can be
72f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * done by just skipping the country or language abbreviation:
73f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * BaseName_us__POSIX or BaseName__DE_PREEURO. But it's not allowed to
74f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * circumvent both language and country: BaseName___VARIANT is illegal.
753819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson *
76f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @see Properties
77f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @see PropertyResourceBundle
78f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project * @see ListResourceBundle
793819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson * @since 1.1
80f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project */
81f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Projectpublic abstract class ResourceBundle {
82f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
83f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
84f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The parent of this {@code ResourceBundle} that is used if this bundle doesn't
85f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * include the requested resource.
86f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
87f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected ResourceBundle parent;
88f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
89f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private Locale locale;
90f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
91f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    static class MissingBundle extends ResourceBundle {
92f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        @Override
93f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public Enumeration<String> getKeys() {
94f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return null;
95f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
96f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
97f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        @Override
98f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        public Object handleGetObject(String name) {
99f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return null;
100f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
101f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
102f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
103f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final ResourceBundle MISSING = new MissingBundle();
104f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
105f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final ResourceBundle MISSINGBASE = new MissingBundle();
106f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
107f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static final WeakHashMap<Object, Hashtable<String, ResourceBundle>> cache = new WeakHashMap<Object, Hashtable<String, ResourceBundle>>();
108f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
109f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // BEGIN android-added
110f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static Locale defaultLocale = Locale.getDefault();
111f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    // END android-added
112f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
113f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
114f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Constructs a new instance of this class.
115f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
116f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public ResourceBundle() {
117f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        /* empty */
118f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
119f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
120f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
121f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Finds the named resource bundle for the default {@code Locale} and the caller's
122f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@code ClassLoader}.
1233819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
124f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param bundleName
125f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the name of the {@code ResourceBundle}.
126f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the requested {@code ResourceBundle}.
1273819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     * @throws MissingResourceException
128f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *                if the {@code ResourceBundle} cannot be found.
129f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
130f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static final ResourceBundle getBundle(String bundleName)
131f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throws MissingResourceException {
132f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // BEGIN android-changed
133f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return getBundleImpl(bundleName, Locale.getDefault(), VMStack
134f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                .getCallingClassLoader());
135f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // END android-changed
136f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
137f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
138f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
139f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Finds the named {@code ResourceBundle} for the specified {@code Locale} and the caller
140f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * {@code ClassLoader}.
1413819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
142f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param bundleName
143f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the name of the {@code ResourceBundle}.
144f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param locale
145f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the {@code Locale}.
146f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the requested resource bundle.
1473819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     * @throws MissingResourceException
148f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *                if the resource bundle cannot be found.
149f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
150f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static final ResourceBundle getBundle(String bundleName,
151f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Locale locale) {
152f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // BEGIN android-changed
153f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return getBundleImpl(bundleName, locale,
154f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                VMStack.getCallingClassLoader());
155f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // END android-changed
156f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
157f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
158f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
159f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Finds the named resource bundle for the specified {@code Locale} and {@code ClassLoader}.
1603819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
161f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The passed base name and {@code Locale} are used to create resource bundle names.
162f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * The first name is created by concatenating the base name with the result
163f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * of {@link Locale#toString()}. From this name all parent bundle names are
164f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * derived. Then the same thing is done for the default {@code Locale}. This results
165f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * in a list of possible bundle names.
1663819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
167f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <strong>Example</strong> For the basename "BaseName", the {@code Locale} of the
168f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * German part of Switzerland (de_CH) and the default {@code Locale} en_US the list
169f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * would look something like this:
1703819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
171f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <ol>
172f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <li>BaseName_de_CH</li>
173f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <li>BaseName_de</li>
174f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <li>Basename_en_US</li>
175f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <li>Basename_en</li>
176f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * <li>BaseName</li>
177f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * </ol>
1783819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
179f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * This list also shows the order in which the bundles will be searched for a requested
180f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * resource in the German part of Switzerland (de_CH).
1813819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
1823819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     * As a first step, this method tries to instantiate
183f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * a {@code ResourceBundle} with the names provided.
184f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * If such a class can be instantiated and initialized, it is returned and
185f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * all the parent bundles are instantiated too. If no such class can be
186f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * found this method tries to load a {@code .properties} file with the names by
187f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * replacing dots in the base name with a slash and by appending
188f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * "{@code .properties}" at the end of the string. If such a resource can be found
189f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * by calling {@link ClassLoader#getResource(String)} it is used to
190f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * initialize a {@link PropertyResourceBundle}. If this succeeds, it will
191f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * also load the parents of this {@code ResourceBundle}.
1923819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
193f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * For compatibility with older code, the bundle name isn't required to be
194f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * a fully qualified class name. It's also possible to directly pass
195f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * the path to a properties file (without a file extension).
1963819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
197f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param bundleName
198f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the name of the {@code ResourceBundle}.
199f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param locale
200f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the {@code Locale}.
201f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param loader
202f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the {@code ClassLoader} to use.
203f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the requested {@code ResourceBundle}.
2043819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     * @throws MissingResourceException
205f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *                if the {@code ResourceBundle} cannot be found.
206f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
207f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public static ResourceBundle getBundle(String bundleName, Locale locale,
208f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ClassLoader loader) throws MissingResourceException {
209f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (loader == null) {
210f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            throw new NullPointerException();
211f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
212f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // BEGIN android-changed
213f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return getBundleImpl(bundleName, locale, loader);
214f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        // END android-changed
215f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
216f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
217f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static ResourceBundle getBundleImpl(String bundleName,
218f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Locale locale, ClassLoader loader) throws MissingResourceException {
219f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (bundleName != null) {
220f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            ResourceBundle bundle;
221f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // BEGIN android-added
222f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!defaultLocale.equals(Locale.getDefault())) {
223f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                cache.clear();
224f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                defaultLocale = Locale.getDefault();
225f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
226f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            // END android-added
227f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (!locale.equals(Locale.getDefault())) {
228f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                String localeName = locale.toString();
229f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (localeName.length() > 0) {
230f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    localeName = "_" + localeName; //$NON-NLS-1$
231f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
232f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if ((bundle = handleGetBundle(bundleName, localeName, false,
233f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        loader)) != null) {
234f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    return bundle;
235f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
236f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
237f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            String localeName = Locale.getDefault().toString();
238f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (localeName.length() > 0) {
239f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                localeName = "_" + localeName; //$NON-NLS-1$
240f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
241f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if ((bundle = handleGetBundle(bundleName, localeName, true, loader)) != null) {
242f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return bundle;
243f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
2443819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson            throw new MissingResourceException(Msg.getString("KA029", bundleName, locale), bundleName + '_' + locale, //$NON-NLS-1$
245f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    ""); //$NON-NLS-1$
246f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
247f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        throw new NullPointerException();
248f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
249f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
250f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
251f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the names of the resources contained in this {@code ResourceBundle}.
2523819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
253f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return an {@code Enumeration} of the resource names.
254f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
255f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public abstract Enumeration<String> getKeys();
256f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
257f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
258f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Gets the {@code Locale} of this {@code ResourceBundle}. In case a bundle was not
259f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * found for the requested {@code Locale}, this will return the actual {@code Locale} of
260f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * this resource bundle that was found after doing a fallback.
2613819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
262f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the {@code Locale} of this {@code ResourceBundle}.
263f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
264f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public Locale getLocale() {
265f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return locale;
266f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
267f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
268f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
269f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the named resource from this {@code ResourceBundle}. If the resource
270f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * cannot be found in this bundle, it falls back to the parent bundle (if
271f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * it's not null) by calling the {@link #handleGetObject} method. If the resource still
272f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * can't be found it throws a {@code MissingResourceException}.
2733819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
274f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param key
275f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the name of the resource.
276f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the resource object.
2773819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     * @throws MissingResourceException
278f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *                if the resource is not found.
279f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
280f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final Object getObject(String key) {
281f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ResourceBundle last, theParent = this;
282f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        do {
283f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            Object result = theParent.handleGetObject(key);
284f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (result != null) {
285f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return result;
286f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
287f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            last = theParent;
288f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            theParent = theParent.parent;
289f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } while (theParent != null);
2903819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson        throw new MissingResourceException(Msg.getString("KA029", last.getClass().getName(), key), last.getClass().getName(), key); //$NON-NLS-1$
291f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
292f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
293f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
294f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the named string resource from this {@code ResourceBundle}.
2953819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
296f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param key
297f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the name of the resource.
298f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the resource string.
2993819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     * @throws MissingResourceException
300f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *                if the resource is not found.
3013819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     * @throws ClassCastException
302f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *                if the resource found is not a string.
303f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see #getObject(String)
304f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
305f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final String getString(String key) {
306f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (String) getObject(key);
307f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
308f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
309f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
310f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the named resource from this {@code ResourceBundle}.
3113819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
312f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param key
313f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the name of the resource.
314f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the resource string array.
3153819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     * @throws MissingResourceException
316f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *                if the resource is not found.
3173819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     * @throws ClassCastException
318f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *                if the resource found is not an array of strings.
319f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @see #getObject(String)
320f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
321f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    public final String[] getStringArray(String key) {
322f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return (String[]) getObject(key);
323f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
324f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
325f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static ResourceBundle handleGetBundle(String base, String locale,
326f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            boolean loadBase, final ClassLoader loader) {
327f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ResourceBundle bundle = null;
328f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String bundleName = base + locale;
329f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Object cacheKey = loader != null ? (Object) loader : (Object) "null"; //$NON-NLS-1$
330f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        Hashtable<String, ResourceBundle> loaderCache;
331f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        synchronized (cache) {
332f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            loaderCache = cache.get(cacheKey);
333f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (loaderCache == null) {
3343819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson                loaderCache = new Hashtable<String, ResourceBundle>();
335f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                cache.put(cacheKey, loaderCache);
336f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
337f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
338f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        ResourceBundle result = loaderCache.get(bundleName);
339f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (result != null) {
340f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (result == MISSINGBASE) {
341f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return null;
342f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
343f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (result == MISSING) {
344f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (!loadBase) {
345f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    return null;
346f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
347f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                String extension = strip(locale);
348f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (extension == null) {
349f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    return null;
350f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
351f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return handleGetBundle(base, extension, loadBase, loader);
352f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
353f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return result;
354f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
355f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
356f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        try {
357c3334e4914f02d97a9ab406428673597b1ca84a3Elliott Hughes            Class<?> bundleClass = Class.forName(bundleName, true, loader);
358c3334e4914f02d97a9ab406428673597b1ca84a3Elliott Hughes
359c3334e4914f02d97a9ab406428673597b1ca84a3Elliott Hughes            if (ResourceBundle.class.isAssignableFrom(bundleClass)) {
360c3334e4914f02d97a9ab406428673597b1ca84a3Elliott Hughes                bundle = (ResourceBundle) bundleClass.newInstance();
361f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
362f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (LinkageError e) {
363f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        } catch (Exception e) {
364f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
365f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
366f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (bundle != null) {
367f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            bundle.setLocale(locale);
3683819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson        } else {
369f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            final String fileName = bundleName.replace('.', '/');
370f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            InputStream stream = AccessController
371f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    .doPrivileged(new PrivilegedAction<InputStream>() {
372f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        public InputStream run() {
373f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                            return loader == null ? ClassLoader
374f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                    .getSystemResourceAsStream(fileName
375f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                            + ".properties") : loader //$NON-NLS-1$
376f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                    .getResourceAsStream(fileName
377f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                                            + ".properties"); //$NON-NLS-1$
378f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        }
379f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    });
380f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (stream != null) {
381f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                try {
382f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    try {
383f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        bundle = new PropertyResourceBundle(stream);
384f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    } finally {
385f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        stream.close();
386f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    }
387f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    bundle.setLocale(locale);
388f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                } catch (IOException e) {
389f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
390f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
391f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
392f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
393f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String extension = strip(locale);
394f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (bundle != null) {
395f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (extension != null) {
396f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                ResourceBundle parent = handleGetBundle(base, extension, true,
397f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                        loader);
398f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (parent != null) {
399f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    bundle.setParent(parent);
400f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
401f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
402f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            loaderCache.put(bundleName, bundle);
403f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return bundle;
404f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
405f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
406f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (extension != null && (loadBase || extension.length() > 0)) {
407f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            bundle = handleGetBundle(base, extension, loadBase, loader);
408f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (bundle != null) {
409f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                loaderCache.put(bundleName, bundle);
410f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                return bundle;
411f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
412f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
413f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        loaderCache.put(bundleName, loadBase ? MISSINGBASE : MISSING);
414f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return null;
415f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
416f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
417f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
418f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Returns the named resource from this {@code ResourceBundle}, or null if the
419f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * resource is not found.
4203819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
421f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param key
422f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the name of the resource.
423f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @return the resource object.
424f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
425f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected abstract Object handleGetObject(String key);
426f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
427f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    /**
428f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * Sets the parent resource bundle of this {@code ResourceBundle}. The parent is
429f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * searched for resources which are not found in this {@code ResourceBundle}.
4303819a76e7c1f49253f0e077bd497f149340c02b8Jesse Wilson     *
431f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     * @param bundle
432f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     *            the parent {@code ResourceBundle}.
433f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project     */
434f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    protected void setParent(ResourceBundle bundle) {
435f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        parent = bundle;
436f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
437f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
438f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private static String strip(String name) {
439f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        int index = name.lastIndexOf('_');
440f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (index != -1) {
441f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            return name.substring(0, index);
442f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
443f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        return null;
444f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
445f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project
446f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    private void setLocale(String name) {
447f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        String language = "", country = "", variant = ""; //$NON-NLS-1$//$NON-NLS-2$ //$NON-NLS-3$
448f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        if (name.length() > 1) {
449f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            int nextIndex = name.indexOf('_', 1);
450f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (nextIndex == -1) {
451f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                nextIndex = name.length();
452f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
453f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            language = name.substring(1, nextIndex);
454f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            if (nextIndex + 1 < name.length()) {
455f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                int index = nextIndex;
456f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                nextIndex = name.indexOf('_', nextIndex + 1);
457f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (nextIndex == -1) {
458f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    nextIndex = name.length();
459f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
460f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                country = name.substring(index + 1, nextIndex);
461f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                if (nextIndex + 1 < name.length()) {
462f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                    variant = name.substring(nextIndex + 1, name.length());
463f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project                }
464f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project            }
465f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        }
466f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project        locale = new Locale(language, country, variant);
467f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project    }
468f6c387128427e121477c1b32ad35cdcaa5101ba3The Android Open Source Project}
469