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