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