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                            protected Object handleGetObject(String key) {
045                                    return key;
046                            }
047    
048                            @Override
049                            public Enumeration<String> getKeys() {
050                                    return Collections.emptyEnumeration();
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            public static String getString(
117                    ResourceBundle resourceBundle, Locale locale, String key,
118                    Object[] arguments) {
119    
120                    String value = getString(resourceBundle, key);
121    
122                    if (value == null) {
123                            return null;
124                    }
125    
126                    // Get the value associated with the specified key, and substitute any
127                    // arguments like {0}, {1}, {2}, etc. with the specified argument
128                    // values.
129    
130                    if (ArrayUtil.isNotEmpty(arguments)) {
131                            MessageFormat messageFormat = new MessageFormat(value, locale);
132    
133                            value = messageFormat.format(arguments);
134                    }
135    
136                    return value;
137            }
138    
139            public static String getString(ResourceBundle resourceBundle, String key) {
140                    if (!resourceBundle.containsKey(key)) {
141                            return null;
142                    }
143    
144                    try {
145                            return resourceBundle.getString(key);
146                    }
147                    catch (MissingResourceException mre) {
148                            return null;
149                    }
150            }
151    
152            public static void loadResourceBundles(
153                    Map<String, ResourceBundle> resourceBundles, Locale locale,
154                    ResourceBundleLoader resourceBundleLoader) {
155    
156                    String languageId = LocaleUtil.toLanguageId(locale);
157    
158                    loadResourceBundles(resourceBundles, languageId, resourceBundleLoader);
159            }
160    
161            public static void loadResourceBundles(
162                    Map<String, ResourceBundle> resourceBundles, String languageId,
163                    ResourceBundleLoader resourceBundleLoader) {
164    
165                    Deque<ResourceBundle> currentResourceBundles = new LinkedList<>();
166    
167                    for (String currentLanguageId : _getLanguageIds(languageId)) {
168                            ResourceBundle resourceBundle =
169                                    resourceBundleLoader.loadResourceBundle(currentLanguageId);
170    
171                            if (resourceBundle != null) {
172                                    currentResourceBundles.addFirst(resourceBundle);
173                            }
174                            else if (currentResourceBundles.isEmpty()) {
175                                    continue;
176                            }
177    
178                            if (currentResourceBundles.size() == 1) {
179                                    resourceBundles.put(
180                                            currentLanguageId, currentResourceBundles.peek());
181                            }
182                            else {
183                                    int size = currentResourceBundles.size();
184    
185                                    resourceBundles.put(
186                                            currentLanguageId,
187                                            new AggregateResourceBundle(
188                                                    currentResourceBundles.toArray(
189                                                            new ResourceBundle[size])));
190                            }
191                    }
192            }
193    
194            private static List<String> _getLanguageIds(String languageId) {
195                    List<String> languageIds = new ArrayList<>();
196    
197                    languageIds.add(StringPool.BLANK);
198    
199                    int index = 0;
200    
201                    while ((index = languageId.indexOf(CharPool.UNDERLINE, index + 1)) !=
202                                            -1) {
203    
204                            languageIds.add(languageId.substring(0, index));
205                    }
206    
207                    languageIds.add(languageId);
208    
209                    return languageIds;
210            }
211    
212    }