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(
85              companyId, locale, pattern, new Object[] {argument}, true);
86      }
87  
88      public String format(Locale locale, String pattern, Object argument,
89          boolean translateArguments) {
90  
91          long companyId = CompanyThreadLocal.getCompanyId();
92  
93          return format(
94              companyId, locale, pattern, new Object[] {argument},
95              translateArguments);
96      }
97  
98      public String format(Locale locale, String pattern, Object[] arguments) {
99          long companyId = CompanyThreadLocal.getCompanyId();
100 
101         return format(companyId, locale, pattern, arguments, true);
102     }
103 
104     public String format(
105         long companyId, Locale locale, String pattern, Object argument) {
106 
107         return format(
108             companyId, locale, pattern, new Object[] {argument}, true);
109     }
110 
111     public String format(
112         long companyId, Locale locale, String pattern, Object argument,
113         boolean translateArguments) {
114 
115         return format(
116             companyId, locale, pattern, new Object[] {argument},
117             translateArguments);
118     }
119 
120     public String format(
121         long companyId, Locale locale, String pattern, Object[] arguments) {
122 
123         return format(companyId, locale, pattern, arguments, true);
124     }
125 
126     public String format(
127         long companyId, Locale locale, String pattern, Object[] arguments,
128         boolean translateArguments) {
129 
130         String value = null;
131 
132         try {
133             pattern = get(companyId, locale, pattern);
134 
135             if (arguments != null) {
136                 pattern = _escapePattern(pattern);
137 
138                 Object[] formattedArguments = new Object[arguments.length];
139 
140                 for (int i = 0; i < arguments.length; i++) {
141                     if (translateArguments) {
142                         formattedArguments[i] = get(
143                             companyId, locale, arguments[i].toString());
144                     }
145                     else {
146                         formattedArguments[i] = arguments[i];
147                     }
148                 }
149 
150                 value = MessageFormat.format(pattern, formattedArguments);
151             }
152             else {
153                 value = pattern;
154             }
155         }
156         catch (Exception e) {
157             if (_log.isWarnEnabled()) {
158                 _log.warn(e, e);
159             }
160         }
161 
162         return value;
163     }
164 
165     public String format(
166         PageContext pageContext, String pattern, Object argument) {
167 
168         return format(pageContext, pattern, new Object[] {argument}, true);
169     }
170 
171     public String format(
172         PageContext pageContext, String pattern, Object argument,
173         boolean translateArguments) {
174 
175         return format(
176             pageContext, pattern, new Object[] {argument}, translateArguments);
177     }
178 
179     public String format(
180         PageContext pageContext, String pattern, Object[] arguments) {
181 
182         return format(pageContext, pattern, arguments, true);
183     }
184 
185     public String format(
186         PageContext pageContext, String pattern, Object[] arguments,
187         boolean translateArguments) {
188 
189         String value = null;
190 
191         try {
192             pattern = get(pageContext, pattern);
193 
194             if (arguments != null) {
195                 pattern = _escapePattern(pattern);
196 
197                 Object[] formattedArguments = new Object[arguments.length];
198 
199                 for (int i = 0; i < arguments.length; i++) {
200                     if (translateArguments) {
201                         formattedArguments[i] =
202                             get(pageContext, arguments[i].toString());
203                     }
204                     else {
205                         formattedArguments[i] = arguments[i];
206                     }
207                 }
208 
209                 value = MessageFormat.format(pattern, formattedArguments);
210             }
211             else {
212                 value = pattern;
213             }
214         }
215         catch (Exception e) {
216             if (_log.isWarnEnabled()) {
217                 _log.warn(e, e);
218             }
219         }
220 
221         return value;
222     }
223 
224     public String format(
225         PageContext pageContext, String pattern, LanguageWrapper argument) {
226 
227         return format(
228             pageContext, pattern, new LanguageWrapper[] {argument}, true);
229     }
230 
231     public String format(
232         PageContext pageContext, String pattern, LanguageWrapper argument,
233         boolean translateArguments) {
234 
235         return format(
236             pageContext, pattern, new LanguageWrapper[] {argument},
237             translateArguments);
238     }
239 
240     public String format(
241         PageContext pageContext, String pattern, LanguageWrapper[] arguments) {
242 
243         return format(pageContext, pattern, arguments, true);
244     }
245 
246     public String format(
247         PageContext pageContext, String pattern, LanguageWrapper[] arguments,
248         boolean translateArguments) {
249 
250         String value = null;
251 
252         try {
253             pattern = get(pageContext, pattern);
254 
255             if (arguments != null) {
256                 pattern = _escapePattern(pattern);
257 
258                 Object[] formattedArguments = new Object[arguments.length];
259 
260                 for (int i = 0; i < arguments.length; i++) {
261                     if (translateArguments) {
262                         formattedArguments[i] =
263                             arguments[i].getBefore() +
264                             get(pageContext, arguments[i].getText()) +
265                             arguments[i].getAfter();
266                     }
267                     else {
268                         formattedArguments[i] =
269                             arguments[i].getBefore() +
270                             arguments[i].getText() +
271                             arguments[i].getAfter();
272                     }
273                 }
274 
275                 value = MessageFormat.format(pattern, formattedArguments);
276             }
277             else {
278                 value = pattern;
279             }
280         }
281         catch (Exception e) {
282             if (_log.isWarnEnabled()) {
283                 _log.warn(e, e);
284             }
285         }
286 
287         return value;
288     }
289 
290     public void init() {
291         _instances.clear();
292     }
293 
294     public String get(Locale locale, String key) {
295         long companyId = CompanyThreadLocal.getCompanyId();
296 
297         return get(companyId, locale, key, key);
298     }
299 
300     public String get(long companyId, Locale locale, String key) {
301         return get(companyId, locale, key, key);
302     }
303 
304     public String get(
305         long companyId, Locale locale, String key, String defaultValue) {
306 
307         if (key == null) {
308             return null;
309         }
310 
311         String value = null;
312 
313         try {
314             MessageResources resources = (MessageResources)WebAppPool.get(
315                 String.valueOf(companyId), Globals.MESSAGES_KEY);
316 
317             if (resources == null) {
318 
319                 // LEP-4505
320 
321                 ResourceBundle bundle = ResourceBundle.getBundle(
322                     "content/Language", locale);
323 
324                 value = bundle.getString(key);
325             }
326             else {
327                 value = resources.getMessage(locale, key);
328             }
329         }
330         catch (Exception e) {
331             if (_log.isWarnEnabled()) {
332                 _log.warn(e, e);
333             }
334         }
335 
336         if (value == null) {
337             value = defaultValue;
338         }
339 
340         return value;
341     }
342 
343     public String get(PageContext pageContext, String key) {
344         return get(pageContext, key, key);
345     }
346 
347     public String get(
348         PageContext pageContext, String key, String defaultValue) {
349 
350         HttpServletRequest request =
351             (HttpServletRequest)pageContext.getRequest();
352 
353         ThemeDisplay themeDisplay = (ThemeDisplay)request.getAttribute(
354             WebKeys.THEME_DISPLAY);
355 
356         PortletConfig portletConfig = (PortletConfig)request.getAttribute(
357             JavaConstants.JAVAX_PORTLET_CONFIG);
358 
359         String value = null;
360 
361         if (themeDisplay != null) {
362             if ((portletConfig != null) && (key != null) &&
363                 (!key.endsWith(StringPool.CLOSE_BRACKET))) {
364 
365                 StringBuilder sb = new StringBuilder();
366 
367                 sb.append(key);
368                 sb.append(StringPool.OPEN_BRACKET);
369                 sb.append(portletConfig.getPortletName());
370                 sb.append(StringPool.CLOSE_BRACKET);
371 
372                 key = sb.toString();
373             }
374 
375             value = get(
376                 themeDisplay.getCompanyId(), themeDisplay.getLocale(), key,
377                 defaultValue);
378 
379             if (((value == null) || (value.equals(defaultValue))) &&
380                 ((key != null) && (key.endsWith(StringPool.CLOSE_BRACKET)))) {
381 
382                 int pos = key.lastIndexOf(StringPool.OPEN_BRACKET);
383 
384                 if (pos != -1) {
385                     key = key.substring(0, pos);
386 
387                     value = get(
388                         themeDisplay.getCompanyId(), themeDisplay.getLocale(),
389                         key, defaultValue);
390                 }
391             }
392 
393             // LEP-7292
394 
395             if ((value != null) && !value.equals(defaultValue)) {
396                 return value;
397             }
398         }
399 
400         if (key == null) {
401             return null;
402         }
403 
404         try {
405             value = TagUtils.getInstance().message(
406                 pageContext, null, null, key);
407         }
408         catch (Exception e) {
409             _log.error(e);
410         }
411 
412         if (value == null) {
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 = LogFactory.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 }