001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.kernel.util;
016    
017    import com.liferay.portal.kernel.language.LanguageUtil;
018    import com.liferay.portal.kernel.language.UTF8Control;
019    
020    import java.text.MessageFormat;
021    
022    import java.util.ArrayList;
023    import java.util.Collections;
024    import java.util.Deque;
025    import java.util.Enumeration;
026    import java.util.HashMap;
027    import java.util.LinkedList;
028    import java.util.List;
029    import java.util.Locale;
030    import java.util.Map;
031    import java.util.MissingResourceException;
032    import java.util.ResourceBundle;
033    
034    /**
035     * @author Shuyang Zhou
036     * @author Neil Griffin
037     */
038    public class ResourceBundleUtil {
039    
040            public static final ResourceBundle EMPTY_RESOURCE_BUNDLE =
041                    new ResourceBundle() {
042    
043                            @Override
044                            public Enumeration<String> getKeys() {
045                                    return Collections.emptyEnumeration();
046                            }
047    
048                            @Override
049                            protected Object handleGetObject(String key) {
050                                    return key;
051                            }
052    
053                    };
054    
055            public static ResourceBundle getBundle(String baseName, Class<?> clazz) {
056                    return getBundle(baseName, clazz.getClassLoader());
057            }
058    
059            public static ResourceBundle getBundle(
060                    String baseName, ClassLoader classLoader) {
061    
062                    return ResourceBundle.getBundle(
063                            baseName, Locale.getDefault(), classLoader, UTF8Control.INSTANCE);
064            }
065    
066            public static ResourceBundle getBundle(
067                    String baseName, Locale locale, Class<?> clazz) {
068    
069                    return getBundle(baseName, locale, clazz.getClassLoader());
070            }
071    
072            public static ResourceBundle getBundle(
073                    String baseName, Locale locale, ClassLoader classLoader) {
074    
075                    return ResourceBundle.getBundle(
076                            baseName, locale, classLoader, UTF8Control.INSTANCE);
077            }
078    
079            public static Map<Locale, String> getLocalizationMap(
080                    ResourceBundleLoader resourceBundleLoader, String key) {
081    
082                    Map<Locale, String> map = new HashMap<>();
083    
084                    for (Locale locale : LanguageUtil.getAvailableLocales()) {
085                            ResourceBundle resourceBundle =
086                                    resourceBundleLoader.loadResourceBundle(
087                                            LocaleUtil.toLanguageId(locale));
088    
089                            map.put(locale, getString(resourceBundle, key));
090                    }
091    
092                    return map;
093            }
094    
095            @Deprecated
096            public static Map<Locale, String> getLocalizationMap(
097                    String baseName, Class<?> clazz, String key) {
098    
099                    Map<Locale, String> map = new HashMap<>();
100    
101                    for (Locale locale : LanguageUtil.getAvailableLocales()) {
102                            ResourceBundle resourceBundle = getBundle(baseName, locale, clazz);
103    
104                            map.put(locale, getString(resourceBundle, key));
105                    }
106    
107                    return map;
108            }
109    
110            public static ResourceBundleLoader getResourceBundleLoader(
111                    final String baseName, final ClassLoader classLoader) {
112    
113                    return new ClassResourceBundleLoader(baseName, classLoader);
114            }
115    
116            /**
117             * @deprecated As of 7.0.1, replaced by {@link #getString(ResourceBundle,
118             *             String, Object...)}
119             */
120            @Deprecated
121            public static String getString(
122                    ResourceBundle resourceBundle, Locale locale, String key,
123                    Object[] arguments) {
124    
125                    return getString(resourceBundle, key, arguments);
126            }
127    
128            public static String getString(ResourceBundle resourceBundle, String key) {
129                    if (!resourceBundle.containsKey(key)) {
130                            return null;
131                    }
132    
133                    try {
134                            return resourceBundle.getString(key);
135                    }
136                    catch (MissingResourceException mre) {
137                            return null;
138                    }
139            }
140    
141            public static String getString(
142                    ResourceBundle resourceBundle, String key, Object... arguments) {
143    
144                    String value = getString(resourceBundle, key);
145    
146                    if (value == null) {
147                            return null;
148                    }
149    
150                    // Get the value associated with the specified key, and substitute any
151                    // arguments like {0}, {1}, {2}, etc. with the specified argument
152                    // values.
153    
154                    if (ArrayUtil.isNotEmpty(arguments)) {
155                            MessageFormat messageFormat = new MessageFormat(
156                                    value, resourceBundle.getLocale());
157    
158                            value = messageFormat.format(arguments);
159                    }
160    
161                    return value;
162            }
163    
164            public static void loadResourceBundles(
165                    Map<String, ResourceBundle> resourceBundles, Locale locale,
166                    ResourceBundleLoader resourceBundleLoader) {
167    
168                    String languageId = LocaleUtil.toLanguageId(locale);
169    
170                    loadResourceBundles(resourceBundles, languageId, resourceBundleLoader);
171            }
172    
173            public static void loadResourceBundles(
174                    Map<String, ResourceBundle> resourceBundles, String languageId,
175                    ResourceBundleLoader resourceBundleLoader) {
176    
177                    Deque<ResourceBundle> currentResourceBundles = new LinkedList<>();
178    
179                    for (String currentLanguageId : _getLanguageIds(languageId)) {
180                            ResourceBundle resourceBundle =
181                                    resourceBundleLoader.loadResourceBundle(currentLanguageId);
182    
183                            if (resourceBundle != null) {
184                                    currentResourceBundles.addFirst(resourceBundle);
185                            }
186                            else if (currentResourceBundles.isEmpty()) {
187                                    continue;
188                            }
189    
190                            if (currentResourceBundles.size() == 1) {
191                                    resourceBundles.put(
192                                            currentLanguageId, currentResourceBundles.peek());
193                            }
194                            else {
195                                    int size = currentResourceBundles.size();
196    
197                                    resourceBundles.put(
198                                            currentLanguageId,
199                                            new AggregateResourceBundle(
200                                                    currentResourceBundles.toArray(
201                                                            new ResourceBundle[size])));
202                            }
203                    }
204            }
205    
206            private static List<String> _getLanguageIds(String languageId) {
207                    List<String> languageIds = new ArrayList<>();
208    
209                    languageIds.add(StringPool.BLANK);
210    
211                    int index = 0;
212    
213                    while ((index = languageId.indexOf(CharPool.UNDERLINE, index + 1)) !=
214                                            -1) {
215    
216                            languageIds.add(languageId.substring(0, index));
217                    }
218    
219                    languageIds.add(languageId);
220    
221                    return languageIds;
222            }
223    
224    }