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