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.model.Portlet;
36  import com.liferay.portal.security.auth.CompanyThreadLocal;
37  import com.liferay.portal.service.PortletLocalServiceUtil;
38  import com.liferay.portal.theme.ThemeDisplay;
39  import com.liferay.portal.util.CookieKeys;
40  import com.liferay.portal.util.PortalUtil;
41  import com.liferay.portal.util.PortletKeys;
42  import com.liferay.portal.util.PropsValues;
43  import com.liferay.portal.util.WebAppPool;
44  import com.liferay.portal.util.WebKeys;
45  import com.liferay.portlet.PortletConfigFactory;
46  
47  import java.text.MessageFormat;
48  
49  import java.util.HashMap;
50  import java.util.HashSet;
51  import java.util.Locale;
52  import java.util.Map;
53  import java.util.MissingResourceException;
54  import java.util.ResourceBundle;
55  import java.util.Set;
56  import java.util.concurrent.ConcurrentHashMap;
57  
58  import javax.portlet.PortletConfig;
59  import javax.portlet.PortletRequest;
60  
61  import javax.servlet.http.Cookie;
62  import javax.servlet.http.HttpServletRequest;
63  import javax.servlet.http.HttpServletResponse;
64  import javax.servlet.jsp.PageContext;
65  
66  import org.apache.commons.logging.Log;
67  import org.apache.commons.logging.LogFactory;
68  import org.apache.struts.Globals;
69  import org.apache.struts.taglib.TagUtils;
70  import org.apache.struts.util.MessageResources;
71  
72  /**
73   * <a href="LanguageImpl.java.html"><b><i>View Source</i></b></a>
74   *
75   * @author Brian Wing Shun Chan
76   * @author Andrius Vitkauskas
77   *
78   */
79  public class LanguageImpl implements Language {
80  
81      public String format(Locale locale, String pattern, Object argument) {
82          long companyId = CompanyThreadLocal.getCompanyId();
83  
84          return format(companyId, locale, pattern, new Object[] {argument});
85      }
86  
87      public String format(Locale locale, String pattern, Object[] arguments) {
88          long companyId = CompanyThreadLocal.getCompanyId();
89  
90          return format(companyId, locale, pattern, arguments);
91      }
92  
93      public String format(
94          long companyId, Locale locale, String pattern, Object argument) {
95  
96          return format(companyId, locale, pattern, new Object[] {argument});
97      }
98  
99      public String format(
100         long companyId, Locale locale, String pattern, Object[] arguments) {
101 
102         String value = null;
103 
104         try {
105             pattern = get(companyId, locale, pattern);
106 
107             if (arguments != null) {
108                 pattern = _escapePattern(pattern);
109 
110                 Object[] formattedArguments = new Object[arguments.length];
111 
112                 for (int i = 0; i < arguments.length; i++) {
113                     formattedArguments[i] = get(
114                         companyId, locale, arguments[i].toString());
115                 }
116 
117                 value = MessageFormat.format(pattern, formattedArguments);
118             }
119             else {
120                 value = pattern;
121             }
122         }
123         catch (Exception e) {
124             if (_log.isWarnEnabled()) {
125                 _log.warn(e, e);
126             }
127         }
128 
129         return value;
130     }
131 
132     public String format(
133         PageContext pageContext, String pattern, Object argument) {
134 
135         return format(pageContext, pattern, new Object[] {argument}, true);
136     }
137 
138     public String format(
139         PageContext pageContext, String pattern, Object argument,
140         boolean translateArguments) {
141 
142         return format(
143             pageContext, pattern, new Object[] {argument}, translateArguments);
144     }
145 
146     public String format(
147         PageContext pageContext, String pattern, Object[] arguments) {
148 
149         return format(pageContext, pattern, arguments, true);
150     }
151 
152     public String format(
153         PageContext pageContext, String pattern, Object[] arguments,
154         boolean translateArguments) {
155 
156         String value = null;
157 
158         try {
159             pattern = get(pageContext, pattern);
160 
161             if (arguments != null) {
162                 pattern = _escapePattern(pattern);
163 
164                 Object[] formattedArguments = new Object[arguments.length];
165 
166                 for (int i = 0; i < arguments.length; i++) {
167                     if (translateArguments) {
168                         formattedArguments[i] =
169                             get(pageContext, arguments[i].toString());
170                     }
171                     else {
172                         formattedArguments[i] = arguments[i];
173                     }
174                 }
175 
176                 value = MessageFormat.format(pattern, formattedArguments);
177             }
178             else {
179                 value = pattern;
180             }
181         }
182         catch (Exception e) {
183             if (_log.isWarnEnabled()) {
184                 _log.warn(e, e);
185             }
186         }
187 
188         return value;
189     }
190 
191     public String format(
192         PageContext pageContext, String pattern, LanguageWrapper argument) {
193 
194         return format(
195             pageContext, pattern, new LanguageWrapper[] {argument}, true);
196     }
197 
198     public String format(
199         PageContext pageContext, String pattern, LanguageWrapper argument,
200         boolean translateArguments) {
201 
202         return format(
203             pageContext, pattern, new LanguageWrapper[] {argument},
204             translateArguments);
205     }
206 
207     public String format(
208         PageContext pageContext, String pattern, LanguageWrapper[] arguments) {
209 
210         return format(pageContext, pattern, arguments, true);
211     }
212 
213     public String format(
214         PageContext pageContext, String pattern, LanguageWrapper[] arguments,
215         boolean translateArguments) {
216 
217         String value = null;
218 
219         try {
220             pattern = get(pageContext, pattern);
221 
222             if (arguments != null) {
223                 pattern = _escapePattern(pattern);
224 
225                 Object[] formattedArguments = new Object[arguments.length];
226 
227                 for (int i = 0; i < arguments.length; i++) {
228                     if (translateArguments) {
229                         formattedArguments[i] =
230                             arguments[i].getBefore() +
231                             get(pageContext, arguments[i].getText()) +
232                             arguments[i].getAfter();
233                     }
234                     else {
235                         formattedArguments[i] =
236                             arguments[i].getBefore() +
237                             arguments[i].getText() +
238                             arguments[i].getAfter();
239                     }
240                 }
241 
242                 value = MessageFormat.format(pattern, formattedArguments);
243             }
244             else {
245                 value = pattern;
246             }
247         }
248         catch (Exception e) {
249             if (_log.isWarnEnabled()) {
250                 _log.warn(e, e);
251             }
252         }
253 
254         return value;
255     }
256 
257     public void init() {
258         _instances.clear();
259     }
260 
261     public String get(Locale locale, String key) {
262         long companyId = CompanyThreadLocal.getCompanyId();
263 
264         return get(companyId, locale, key, key);
265     }
266 
267     public String get(long companyId, Locale locale, String key) {
268         return get(companyId, locale, key, key);
269     }
270 
271     public String get(
272         long companyId, Locale locale, String key, String defaultValue) {
273 
274         if (key == null) {
275             return null;
276         }
277 
278         String value = null;
279 
280         try {
281             MessageResources resources = (MessageResources)WebAppPool.get(
282                 String.valueOf(companyId), Globals.MESSAGES_KEY);
283 
284             if (resources == null) {
285 
286                 // LEP-4505
287 
288                 ResourceBundle bundle = ResourceBundle.getBundle(
289                     "content/Language", locale);
290 
291                 value = bundle.getString(key);
292             }
293             else {
294                 value = resources.getMessage(locale, key);
295             }
296         }
297         catch (Exception e) {
298             if (_log.isWarnEnabled()) {
299                 _log.warn(e, e);
300             }
301         }
302 
303         if (value == null) {
304             value = defaultValue;
305         }
306 
307         return value;
308     }
309 
310     public String get(PageContext pageContext, String key) {
311         return get(pageContext, key, key);
312     }
313 
314     public String get(
315         PageContext pageContext, String key, String defaultValue) {
316 
317         HttpServletRequest request =
318             (HttpServletRequest)pageContext.getRequest();
319 
320         ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
321             WebKeys.THEME_DISPLAY);
322 
323         String value = null;
324 
325         if (themeDisplay != null) {
326             value = get(
327                 themeDisplay.getCompanyId(), themeDisplay.getLocale(), key,
328                 defaultValue);
329 
330             // LEP-7292
331 
332             if ((value != null) && !value.equals(defaultValue)) {
333                 return value;
334             }
335         }
336 
337         if (key == null) {
338             return null;
339         }
340 
341         try {
342             value = TagUtils.getInstance().message(
343                 pageContext, null, null, key);
344         }
345         catch (Exception e) {
346             _log.error(e);
347         }
348 
349         if (value == null) {
350 
351             // LEP-2849
352 
353             PortletConfig portletConfig = (PortletConfig)request.getAttribute(
354                 JavaConstants.JAVAX_PORTLET_CONFIG);
355 
356             if (portletConfig != null) {
357                 Locale locale = request.getLocale();
358 
359                 ResourceBundle bundle = portletConfig.getResourceBundle(locale);
360 
361                 try {
362                     value = bundle.getString(key);
363                 }
364                 catch (MissingResourceException mre) {
365                 }
366 
367                 // LEP-7393
368 
369                 if (((value == null) || (value.equals(defaultValue))) &&
370                     (portletConfig.getPortletName().equals(
371                         PortletKeys.PORTLET_CONFIGURATION))) {
372 
373                     value = _getPortletConfigurationValue(pageContext, key);
374                 }
375             }
376         }
377 
378         if (value == null) {
379             value = defaultValue;
380         }
381 
382         return value;
383     }
384 
385     public Locale[] getAvailableLocales() {
386         return _getInstance()._locales;
387     }
388 
389     public String getCharset(Locale locale) {
390         return _getInstance()._getCharset(locale);
391     }
392 
393     public String getLanguageId(PortletRequest portletRequest) {
394         HttpServletRequest request = PortalUtil.getHttpServletRequest(
395             portletRequest);
396 
397         return getLanguageId(request);
398     }
399 
400     public String getLanguageId(HttpServletRequest request) {
401         String languageId = ParamUtil.getString(request, "languageId");
402 
403         if (Validator.isNotNull(languageId)) {
404             return languageId;
405         }
406 
407         Locale locale = PortalUtil.getLocale(request);
408 
409         return getLanguageId(locale);
410     }
411 
412     public String getLanguageId(Locale locale) {
413         return LocaleUtil.toLanguageId(locale);
414     }
415 
416     public Locale getLocale(String languageCode) {
417         return _getInstance()._getLocale(languageCode);
418     }
419 
420     public String getTimeDescription(
421         PageContext pageContext, Long milliseconds) {
422 
423         return getTimeDescription(pageContext, milliseconds.longValue());
424     }
425 
426     public String getTimeDescription(
427         PageContext pageContext, long milliseconds) {
428 
429         String desc = Time.getDescription(milliseconds);
430 
431         String value = null;
432 
433         try {
434             int pos = desc.indexOf(StringPool.SPACE);
435 
436             int x = GetterUtil.getInteger(desc.substring(0, pos));
437 
438             value =
439                 x + " " +
440                 get(
441                     pageContext,
442                     desc.substring(pos + 1, desc.length()).toLowerCase());
443         }
444         catch (Exception e) {
445             if (_log.isWarnEnabled()) {
446                 _log.warn(e, e);
447             }
448         }
449 
450         return value;
451     }
452 
453     public boolean isAvailableLocale(Locale locale) {
454         return _localesSet.contains(locale);
455     }
456 
457     public void updateCookie(HttpServletResponse response, Locale locale) {
458         String languageId = LocaleUtil.toLanguageId(locale);
459 
460         Cookie languageIdCookie = new Cookie(
461             CookieKeys.GUEST_LANGUAGE_ID, languageId);
462 
463         languageIdCookie.setPath(StringPool.SLASH);
464         languageIdCookie.setMaxAge(CookieKeys.MAX_AGE);
465 
466         CookieKeys.addCookie(response, languageIdCookie);
467     }
468 
469     private static LanguageImpl _getInstance() {
470         long companyId = CompanyThreadLocal.getCompanyId();
471 
472         LanguageImpl instance = _instances.get(companyId);
473 
474         if (instance == null) {
475             instance = new LanguageImpl();
476 
477             _instances.put(companyId, instance);
478         }
479 
480         return instance;
481     }
482 
483     private LanguageImpl() {
484         String[] localesArray = PropsValues.LOCALES;
485 
486         _locales = new Locale[localesArray.length];
487         _localesSet = new HashSet<Locale>(localesArray.length);
488         _localesMap = new HashMap<String, Locale>(localesArray.length);
489         _charEncodings = new HashMap<String, String>();
490 
491         for (int i = 0; i < localesArray.length; i++) {
492             String languageId = localesArray[i];
493 
494             int pos = languageId.indexOf(StringPool.UNDERLINE);
495 
496             String language = languageId.substring(0, pos);
497             //String country = languageId.substring(pos + 1);
498 
499             Locale locale = LocaleUtil.fromLanguageId(languageId);
500 
501             _locales[i] = locale;
502             _localesSet.add(locale);
503             _localesMap.put(language, locale);
504             _charEncodings.put(locale.toString(), StringPool.UTF8);
505         }
506     }
507 
508     private String _escapePattern(String pattern) {
509         return StringUtil.replace(
510             pattern, StringPool.APOSTROPHE, StringPool.DOUBLE_APOSTROPHE);
511     }
512 
513     private String _getCharset(Locale locale) {
514         return StringPool.UTF8;
515     }
516 
517     private Locale _getLocale(String languageCode) {
518         return _localesMap.get(languageCode);
519     }
520 
521     private String _getPortletConfigurationValue(
522         PageContext pageContext, String key) {
523 
524         String value = null;
525 
526         try {
527             HttpServletRequest request =
528                 (HttpServletRequest)pageContext.getRequest();
529 
530             String portletResource = ParamUtil.getString(
531                 request, "portletResource");
532 
533             long companyId = PortalUtil.getCompanyId(request);
534 
535             Portlet portlet = PortletLocalServiceUtil.getPortletById(
536                 companyId, portletResource);
537 
538             PortletConfig portletConfig = PortletConfigFactory.create(
539                 portlet, pageContext.getServletContext());
540 
541             Locale locale = request.getLocale();
542 
543             ResourceBundle bundle = portletConfig.getResourceBundle(locale);
544 
545             value = bundle.getString(key);
546         }
547         catch (Exception e) {
548             if (_log.isWarnEnabled()) {
549                 _log.warn(e, e);
550             }
551         }
552 
553         return value;
554     }
555 
556     private static Log _log = LogFactory.getLog(LanguageImpl.class);
557 
558     private static Map<Long, LanguageImpl> _instances =
559         new ConcurrentHashMap<Long, LanguageImpl>();
560 
561     private Locale[] _locales;
562     private Set<Locale> _localesSet;
563     private Map<String, Locale> _localesMap;
564     private Map<String, String> _charEncodings;
565 
566 }