1   /**
2    * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.language;
24  
25  import com.liferay.portal.kernel.language.Language;
26  import com.liferay.portal.kernel.language.LanguageWrapper;
27  import com.liferay.portal.kernel.util.GetterUtil;
28  import com.liferay.portal.kernel.util.JavaConstants;
29  import com.liferay.portal.kernel.util.LocaleUtil;
30  import com.liferay.portal.kernel.util.ParamUtil;
31  import com.liferay.portal.kernel.util.StringPool;
32  import com.liferay.portal.kernel.util.StringUtil;
33  import com.liferay.portal.kernel.util.Time;
34  import com.liferay.portal.kernel.util.Validator;
35  import com.liferay.portal.security.auth.CompanyThreadLocal;
36  import com.liferay.portal.theme.ThemeDisplay;
37  import com.liferay.portal.util.CookieKeys;
38  import com.liferay.portal.util.PortalUtil;
39  import com.liferay.portal.util.PropsValues;
40  import com.liferay.portal.util.WebAppPool;
41  import com.liferay.portal.util.WebKeys;
42  
43  import java.text.MessageFormat;
44  
45  import java.util.HashMap;
46  import java.util.Locale;
47  import java.util.Map;
48  import java.util.MissingResourceException;
49  import java.util.ResourceBundle;
50  import java.util.concurrent.ConcurrentHashMap;
51  
52  import javax.portlet.PortletConfig;
53  import javax.portlet.PortletRequest;
54  
55  import javax.servlet.http.Cookie;
56  import javax.servlet.http.HttpServletRequest;
57  import javax.servlet.http.HttpServletResponse;
58  import javax.servlet.jsp.PageContext;
59  
60  import org.apache.commons.logging.Log;
61  import org.apache.commons.logging.LogFactory;
62  import org.apache.struts.Globals;
63  import org.apache.struts.taglib.TagUtils;
64  import org.apache.struts.util.MessageResources;
65  
66  /**
67   * <a href="LanguageImpl.java.html"><b><i>View Source</i></b></a>
68   *
69   * @author Brian Wing Shun Chan
70   * @author Andrius Vitkauskas
71   *
72   */
73  public class LanguageImpl implements Language {
74  
75      public String format(Locale locale, String pattern, Object argument) {
76          long companyId = CompanyThreadLocal.getCompanyId();
77  
78          return format(companyId, locale, pattern, new Object[] {argument});
79      }
80  
81      public String format(Locale locale, String pattern, Object[] arguments) {
82          long companyId = CompanyThreadLocal.getCompanyId();
83  
84          return format(companyId, locale, pattern, arguments);
85      }
86  
87      public String format(
88          long companyId, Locale locale, String pattern, Object argument) {
89  
90          return format(companyId, locale, pattern, new Object[] {argument});
91      }
92  
93      public String format(
94          long companyId, Locale locale, String pattern, Object[] arguments) {
95  
96          String value = null;
97  
98          try {
99              pattern = get(companyId, locale, pattern);
100 
101             if (arguments != null) {
102                 pattern = _escapePattern(pattern);
103 
104                 Object[] formattedArguments = new Object[arguments.length];
105 
106                 for (int i = 0; i < arguments.length; i++) {
107                     formattedArguments[i] = get(
108                         companyId, locale, arguments[i].toString());
109                 }
110 
111                 value = MessageFormat.format(pattern, formattedArguments);
112             }
113             else {
114                 value = pattern;
115             }
116         }
117         catch (Exception e) {
118             if (_log.isWarnEnabled()) {
119                 _log.warn(e.getMessage());
120             }
121         }
122 
123         return value;
124     }
125 
126     public String format(
127         PageContext pageContext, String pattern, Object argument) {
128 
129         return format(pageContext, pattern, new Object[] {argument}, true);
130     }
131 
132     public String format(
133         PageContext pageContext, String pattern, Object argument,
134         boolean translateArguments) {
135 
136         return format(
137             pageContext, pattern, new Object[] {argument}, translateArguments);
138     }
139 
140     public String format(
141         PageContext pageContext, String pattern, Object[] arguments) {
142 
143         return format(pageContext, pattern, arguments, true);
144     }
145 
146     public String format(
147         PageContext pageContext, String pattern, Object[] arguments,
148         boolean translateArguments) {
149 
150         String value = null;
151 
152         try {
153             pattern = get(pageContext, pattern);
154 
155             if (arguments != null) {
156                 pattern = _escapePattern(pattern);
157 
158                 Object[] formattedArguments = new Object[arguments.length];
159 
160                 for (int i = 0; i < arguments.length; i++) {
161                     if (translateArguments) {
162                         formattedArguments[i] =
163                             get(pageContext, arguments[i].toString());
164                     }
165                     else {
166                         formattedArguments[i] = arguments[i];
167                     }
168                 }
169 
170                 value = MessageFormat.format(pattern, formattedArguments);
171             }
172             else {
173                 value = pattern;
174             }
175         }
176         catch (Exception e) {
177             if (_log.isWarnEnabled()) {
178                 _log.warn(e.getMessage());
179             }
180         }
181 
182         return value;
183     }
184 
185     public String format(
186         PageContext pageContext, String pattern, LanguageWrapper argument) {
187 
188         return format(
189             pageContext, pattern, new LanguageWrapper[] {argument}, true);
190     }
191 
192     public String format(
193         PageContext pageContext, String pattern, LanguageWrapper argument,
194         boolean translateArguments) {
195 
196         return format(
197             pageContext, pattern, new LanguageWrapper[] {argument},
198             translateArguments);
199     }
200 
201     public String format(
202         PageContext pageContext, String pattern, LanguageWrapper[] arguments) {
203 
204         return format(pageContext, pattern, arguments, true);
205     }
206 
207     public String format(
208         PageContext pageContext, String pattern, LanguageWrapper[] arguments,
209         boolean translateArguments) {
210 
211         String value = null;
212 
213         try {
214             pattern = get(pageContext, pattern);
215 
216             if (arguments != null) {
217                 pattern = _escapePattern(pattern);
218 
219                 Object[] formattedArguments = new Object[arguments.length];
220 
221                 for (int i = 0; i < arguments.length; i++) {
222                     if (translateArguments) {
223                         formattedArguments[i] =
224                             arguments[i].getBefore() +
225                             get(pageContext, arguments[i].getText()) +
226                             arguments[i].getAfter();
227                     }
228                     else {
229                         formattedArguments[i] =
230                             arguments[i].getBefore() +
231                             arguments[i].getText() +
232                             arguments[i].getAfter();
233                     }
234                 }
235 
236                 value = MessageFormat.format(pattern, formattedArguments);
237             }
238             else {
239                 value = pattern;
240             }
241         }
242         catch (Exception e) {
243             if (_log.isWarnEnabled()) {
244                 _log.warn(e.getMessage());
245             }
246         }
247 
248         return value;
249     }
250 
251     public void init() {
252         _instances.clear();
253     }
254 
255     public String get(Locale locale, String key) {
256         long companyId = CompanyThreadLocal.getCompanyId();
257 
258         return get(companyId, locale, key, key);
259     }
260 
261     public String get(long companyId, Locale locale, String key) {
262         return get(companyId, locale, key, key);
263     }
264 
265     public String get(
266         long companyId, Locale locale, String key, String defaultValue) {
267 
268         if (key == null) {
269             return null;
270         }
271 
272         String value = null;
273 
274         try {
275             MessageResources resources = (MessageResources)WebAppPool.get(
276                 String.valueOf(companyId), Globals.MESSAGES_KEY);
277 
278             if (resources == null) {
279 
280                 // LEP-4505
281 
282                 ResourceBundle bundle = ResourceBundle.getBundle(
283                     "content/Language", locale);
284 
285                 value = bundle.getString(key);
286             }
287             else {
288                 value = resources.getMessage(locale, key);
289             }
290         }
291         catch (Exception e) {
292             if (_log.isWarnEnabled()) {
293                 _log.warn(e.getMessage());
294             }
295         }
296 
297         if (value == null) {
298             value = defaultValue;
299         }
300 
301         return value;
302     }
303 
304     public String get(PageContext pageContext, String key) {
305         return get(pageContext, key, key);
306     }
307 
308     public String get(
309         PageContext pageContext, String key, String defaultValue) {
310 
311         HttpServletRequest request =
312             (HttpServletRequest)pageContext.getRequest();
313 
314         ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
315             WebKeys.THEME_DISPLAY);
316 
317         if (themeDisplay != null) {
318             return get(
319                 themeDisplay.getCompanyId(), themeDisplay.getLocale(), key,
320                 defaultValue);
321         }
322 
323         if (key == null) {
324             return null;
325         }
326 
327         String value = null;
328 
329         try {
330             value = TagUtils.getInstance().message(
331                 pageContext, null, null, key);
332         }
333         catch (Exception e) {
334             _log.error(e);
335         }
336 
337         if (value == null) {
338 
339             // LEP-2849
340 
341             PortletConfig portletConfig = (PortletConfig)request.getAttribute(
342                 JavaConstants.JAVAX_PORTLET_CONFIG);
343 
344             if (portletConfig != null) {
345                 Locale locale = request.getLocale();
346 
347                 ResourceBundle bundle = portletConfig.getResourceBundle(locale);
348 
349                 try {
350                     value = bundle.getString(key);
351                 }
352                 catch (MissingResourceException mre) {
353                 }
354             }
355         }
356 
357         if (value == null) {
358             value = defaultValue;
359         }
360 
361         return value;
362     }
363 
364     public Locale[] getAvailableLocales() {
365         return _getInstance()._locales;
366     }
367 
368     public String getCharset(Locale locale) {
369         return _getInstance()._getCharset(locale);
370     }
371 
372     public String getLanguageId(PortletRequest portletRequest) {
373         HttpServletRequest request = PortalUtil.getHttpServletRequest(
374             portletRequest);
375 
376         return getLanguageId(request);
377     }
378 
379     public String getLanguageId(HttpServletRequest request) {
380         String languageId = ParamUtil.getString(request, "languageId");
381 
382         if (Validator.isNotNull(languageId)) {
383             return languageId;
384         }
385 
386         Locale locale = PortalUtil.getLocale(request);
387 
388         return getLanguageId(locale);
389     }
390 
391     public String getLanguageId(Locale locale) {
392         return LocaleUtil.toLanguageId(locale);
393     }
394 
395     public Locale getLocale(String languageCode) {
396         return _getInstance()._getLocale(languageCode);
397     }
398 
399     public String getTimeDescription(
400         PageContext pageContext, Long milliseconds) {
401 
402         return getTimeDescription(pageContext, milliseconds.longValue());
403     }
404 
405     public String getTimeDescription(
406         PageContext pageContext, long milliseconds) {
407 
408         String desc = Time.getDescription(milliseconds);
409 
410         String value = null;
411 
412         try {
413             int pos = desc.indexOf(StringPool.SPACE);
414 
415             int x = GetterUtil.getInteger(desc.substring(0, pos));
416 
417             value =
418                 x + " " +
419                 get(
420                     pageContext,
421                     desc.substring(pos + 1, desc.length()).toLowerCase());
422         }
423         catch (Exception e) {
424             if (_log.isWarnEnabled()) {
425                 _log.warn(e.getMessage());
426             }
427         }
428 
429         return value;
430     }
431 
432     public void updateCookie(HttpServletResponse response, Locale locale) {
433         String languageId = LocaleUtil.toLanguageId(locale);
434 
435         Cookie languageIdCookie = new Cookie(
436             CookieKeys.GUEST_LANGUAGE_ID, languageId);
437 
438         languageIdCookie.setPath(StringPool.SLASH);
439         languageIdCookie.setMaxAge(CookieKeys.MAX_AGE);
440 
441         CookieKeys.addCookie(response, languageIdCookie);
442     }
443 
444     private static LanguageImpl _getInstance() {
445         long companyId = CompanyThreadLocal.getCompanyId();
446 
447         LanguageImpl instance = _instances.get(companyId);
448 
449         if (instance == null) {
450             instance = new LanguageImpl();
451 
452             _instances.put(companyId, instance);
453         }
454 
455         return instance;
456     }
457 
458     private LanguageImpl() {
459         String[] localesArray = PropsValues.LOCALES;
460 
461         _locales = new Locale[localesArray.length];
462         _localesByLanguageCode = new HashMap<String, Locale>();
463         _charEncodings = new HashMap<String, String>();
464 
465         for (int i = 0; i < localesArray.length; i++) {
466             String languageId = localesArray[i];
467 
468             int pos = languageId.indexOf(StringPool.UNDERLINE);
469 
470             String language = languageId.substring(0, pos);
471             //String country = languageId.substring(pos + 1);
472 
473             Locale locale = LocaleUtil.fromLanguageId(languageId);
474 
475             _locales[i] = locale;
476             _localesByLanguageCode.put(language, locale);
477             _charEncodings.put(locale.toString(), StringPool.UTF8);
478         }
479     }
480 
481     private String _escapePattern(String pattern) {
482         return StringUtil.replace(
483             pattern, StringPool.APOSTROPHE, StringPool.DOUBLE_APOSTROPHE);
484     }
485 
486     private String _getCharset(Locale locale) {
487         return StringPool.UTF8;
488     }
489 
490     private Locale _getLocale(String languageCode) {
491         return _localesByLanguageCode.get(languageCode);
492     }
493 
494     private static Log _log = LogFactory.getLog(LanguageImpl.class);
495 
496     private static Map<Long, LanguageImpl> _instances =
497         new ConcurrentHashMap<Long, LanguageImpl>();
498 
499     private Locale[] _locales;
500     private Map<String, Locale> _localesByLanguageCode;
501     private Map<String, String> _charEncodings;
502 
503 }