001    /**
002     * Copyright (c) 2000-2012 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.language;
016    
017    import com.liferay.portal.kernel.language.LanguageUtil;
018    import com.liferay.portal.kernel.log.Log;
019    import com.liferay.portal.kernel.log.LogFactoryUtil;
020    import com.liferay.portal.kernel.util.CharPool;
021    import com.liferay.portal.kernel.util.LocaleUtil;
022    import com.liferay.portal.kernel.util.PropertiesUtil;
023    import com.liferay.portal.kernel.util.StringBundler;
024    import com.liferay.portal.kernel.util.StringPool;
025    import com.liferay.portal.kernel.util.StringUtil;
026    import com.liferay.portal.tools.LangBuilder;
027    
028    import java.io.InputStream;
029    
030    import java.net.URL;
031    
032    import java.util.Collections;
033    import java.util.HashMap;
034    import java.util.Locale;
035    import java.util.Map;
036    import java.util.Properties;
037    import java.util.concurrent.ConcurrentHashMap;
038    
039    /**
040     * @author Shuyang Zhou
041     */
042    public class LanguageResources {
043    
044            public static String fixValue(String value) {
045                    if (value.endsWith(LangBuilder.AUTOMATIC_COPY)) {
046                            value = value.substring(
047                                    0, value.length() - LangBuilder.AUTOMATIC_COPY.length());
048                    }
049    
050                    if (value.endsWith(LangBuilder.AUTOMATIC_TRANSLATION)) {
051                            value = value.substring(
052                                    0, value.length() - LangBuilder.AUTOMATIC_TRANSLATION.length());
053                    }
054    
055                    return value;
056            }
057    
058            public static void fixValues(
059                    Map<String, String> languageMap, Properties properties) {
060    
061                    for (Map.Entry<Object, Object> entry : properties.entrySet()) {
062                            String key = (String)entry.getKey();
063                            String value = (String)entry.getValue();
064    
065                            value = fixValue(value);
066    
067                            languageMap.put(key, value);
068                    }
069            }
070    
071            public static String getMessage(Locale locale, String key) {
072                    if (locale == null) {
073                            return null;
074                    }
075    
076                    Map<String, String> languageMap = _languageMaps.get(locale);
077    
078                    if (languageMap == null) {
079                            languageMap = _loadLocale(locale);
080                    }
081    
082                    String value = languageMap.get(key);
083    
084                    if (value == null) {
085                            return getMessage(getSuperLocale(locale), key);
086                    }
087                    else {
088                            return value;
089                    }
090            }
091    
092            public static Locale getSuperLocale(Locale locale) {
093                    String variant = locale.getVariant();
094    
095                    if (variant.length() > 0) {
096                            return new Locale(locale.getLanguage(), locale.getCountry());
097                    }
098    
099                    String country = locale.getCountry();
100    
101                    if (country.length() > 0) {
102                            Locale priorityLocale = LanguageUtil.getLocale(
103                                    locale.getLanguage());
104    
105                            if ((priorityLocale != null) && (!locale.equals(priorityLocale))) {
106                                    return new Locale(
107                                            priorityLocale.getLanguage(), priorityLocale.getCountry());
108                            }
109    
110                            return LocaleUtil.fromLanguageId(locale.getLanguage());
111                    }
112    
113                    String language = locale.getLanguage();
114    
115                    if (language.length() > 0) {
116                            return _blankLocale;
117                    }
118    
119                    return null;
120            }
121    
122            public static Map<String, String> putLanguageMap(
123                    Locale locale, Map<String, String> languageMap) {
124    
125                    Map<String, String> oldLanguageMap = _languageMaps.get(locale);
126    
127                    if (oldLanguageMap == null) {
128                            _loadLocale(locale);
129                            oldLanguageMap = _languageMaps.get(locale);
130                    }
131    
132                    Map<String, String> newLanguageMap = new HashMap<String, String>();
133    
134                    if (oldLanguageMap != null) {
135                            newLanguageMap.putAll(oldLanguageMap);
136                    }
137    
138                    newLanguageMap.putAll(languageMap);
139    
140                    _languageMaps.put(locale, newLanguageMap);
141    
142                    return oldLanguageMap;
143            }
144    
145            public void setConfig(String config) {
146                    _configNames = StringUtil.split(
147                            config.replace(CharPool.PERIOD, CharPool.SLASH));
148            }
149    
150            private static Map<String, String> _loadLocale(Locale locale) {
151                    Map<String, String> languageMap = null;
152    
153                    if (_configNames.length > 0) {
154                            String localeName = locale.toString();
155    
156                            languageMap = new HashMap<String, String>();
157    
158                            for (String name : _configNames) {
159                                    StringBundler sb = new StringBundler(4);
160    
161                                    sb.append(name);
162    
163                                    if (localeName.length() > 0) {
164                                            sb.append(StringPool.UNDERLINE);
165                                            sb.append(localeName);
166                                    }
167    
168                                    sb.append(".properties");
169    
170                                    Properties properties = _loadProperties(sb.toString());
171    
172                                    fixValues(languageMap, properties);
173                            }
174                    }
175                    else {
176                            languageMap = Collections.emptyMap();
177                    }
178    
179                    _languageMaps.put(locale, languageMap);
180    
181                    return languageMap;
182            }
183    
184            private static Properties _loadProperties(String name) {
185                    Properties properties = new Properties();
186    
187                    try {
188                            ClassLoader classLoader = LanguageResources.class.getClassLoader();
189    
190                            URL url = classLoader.getResource(name);
191    
192                            if (_log.isInfoEnabled()) {
193                                    _log.info("Attempting to load " + name);
194                            }
195    
196                            if (url != null) {
197                                    InputStream inputStream = url.openStream();
198    
199                                    properties = PropertiesUtil.load(inputStream, StringPool.UTF8);
200    
201                                    inputStream.close();
202    
203                                    if (_log.isInfoEnabled()) {
204                                            _log.info(
205                                                    "Loading " + url + " with " + properties.size() +
206                                                            " values");
207                                    }
208                            }
209                    }
210                    catch (Exception e) {
211                            if (_log.isWarnEnabled()) {
212                                    _log.warn(e, e);
213                            }
214                    }
215    
216                    return properties;
217            }
218    
219            private static Log _log = LogFactoryUtil.getLog(LanguageResources.class);
220    
221            private static Locale _blankLocale = new Locale(StringPool.BLANK);
222            private static String[] _configNames;
223            private static Map<Locale, Map<String, String>> _languageMaps =
224                    new ConcurrentHashMap<Locale, Map<String, String>>(64);
225    
226    }