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.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             if (_log.isWarnEnabled()) {
410                 _log.warn(e);
411             }
412         }
413 
414         if ((value == null) || value.equals(defaultValue)) {
415 
416             // LEP-2849
417 
418             if (portletConfig != null) {
419                 Locale locale = request.getLocale();
420 
421                 ResourceBundle bundle = portletConfig.getResourceBundle(locale);
422 
423                 try {
424                     value = bundle.getString(key);
425                 }
426                 catch (MissingResourceException mre) {
427                 }
428 
429                 // LEP-7393
430 
431                 if (((value == null) || (value.equals(defaultValue))) &&
432                     (portletConfig.getPortletName().equals(
433                         PortletKeys.PORTLET_CONFIGURATION))) {
434 
435                     value = _getPortletConfigurationValue(pageContext, key);
436                 }
437             }
438         }
439 
440         if (value == null) {
441             value = defaultValue;
442         }
443 
444         return value;
445     }
446 
447     public Locale[] getAvailableLocales() {
448         return _getInstance()._locales;
449     }
450 
451     public String getCharset(Locale locale) {
452         return _getInstance()._getCharset(locale);
453     }
454 
455     public String getLanguageId(PortletRequest portletRequest) {
456         HttpServletRequest request = PortalUtil.getHttpServletRequest(
457             portletRequest);
458 
459         return getLanguageId(request);
460     }
461 
462     public String getLanguageId(HttpServletRequest request) {
463         String languageId = ParamUtil.getString(request, "languageId");
464 
465         if (Validator.isNotNull(languageId)) {
466             return languageId;
467         }
468 
469         Locale locale = PortalUtil.getLocale(request);
470 
471         return getLanguageId(locale);
472     }
473 
474     public String getLanguageId(Locale locale) {
475         return LocaleUtil.toLanguageId(locale);
476     }
477 
478     public Locale getLocale(String languageCode) {
479         return _getInstance()._getLocale(languageCode);
480     }
481 
482     public String getTimeDescription(
483         PageContext pageContext, Long milliseconds) {
484 
485         return getTimeDescription(pageContext, milliseconds.longValue());
486     }
487 
488     public String getTimeDescription(
489         PageContext pageContext, long milliseconds) {
490 
491         String desc = Time.getDescription(milliseconds);
492 
493         String value = null;
494 
495         try {
496             int pos = desc.indexOf(StringPool.SPACE);
497 
498             int x = GetterUtil.getInteger(desc.substring(0, pos));
499 
500             value =
501                 x + " " +
502                 get(
503                     pageContext,
504                     desc.substring(pos + 1, desc.length()).toLowerCase());
505         }
506         catch (Exception e) {
507             if (_log.isWarnEnabled()) {
508                 _log.warn(e, e);
509             }
510         }
511 
512         return value;
513     }
514 
515     public boolean isAvailableLocale(Locale locale) {
516         return _localesSet.contains(locale);
517     }
518 
519     public void updateCookie(
520         HttpServletRequest request, HttpServletResponse response,
521         Locale locale) {
522 
523         String languageId = LocaleUtil.toLanguageId(locale);
524 
525         Cookie languageIdCookie = new Cookie(
526             CookieKeys.GUEST_LANGUAGE_ID, languageId);
527 
528         languageIdCookie.setPath(StringPool.SLASH);
529         languageIdCookie.setMaxAge(CookieKeys.MAX_AGE);
530 
531         CookieKeys.addCookie(request, response, languageIdCookie);
532     }
533 
534     private static LanguageImpl _getInstance() {
535         long companyId = CompanyThreadLocal.getCompanyId();
536 
537         LanguageImpl instance = _instances.get(companyId);
538 
539         if (instance == null) {
540             instance = new LanguageImpl();
541 
542             _instances.put(companyId, instance);
543         }
544 
545         return instance;
546     }
547 
548     private LanguageImpl() {
549         String[] localesArray = PropsValues.LOCALES;
550 
551         _locales = new Locale[localesArray.length];
552         _localesSet = new HashSet<Locale>(localesArray.length);
553         _localesMap = new HashMap<String, Locale>(localesArray.length);
554         _charEncodings = new HashMap<String, String>();
555 
556         for (int i = 0; i < localesArray.length; i++) {
557             String languageId = localesArray[i];
558 
559             int pos = languageId.indexOf(StringPool.UNDERLINE);
560 
561             String language = languageId.substring(0, pos);
562             //String country = languageId.substring(pos + 1);
563 
564             Locale locale = LocaleUtil.fromLanguageId(languageId);
565 
566             _locales[i] = locale;
567             _localesSet.add(locale);
568             _localesMap.put(language, locale);
569             _charEncodings.put(locale.toString(), StringPool.UTF8);
570         }
571     }
572 
573     private String _escapePattern(String pattern) {
574         return StringUtil.replace(
575             pattern, StringPool.APOSTROPHE, StringPool.DOUBLE_APOSTROPHE);
576     }
577 
578     private String _getCharset(Locale locale) {
579         return StringPool.UTF8;
580     }
581 
582     private Locale _getLocale(String languageCode) {
583         return _localesMap.get(languageCode);
584     }
585 
586     private String _getPortletConfigurationValue(
587         PageContext pageContext, String key) {
588 
589         String value = null;
590 
591         try {
592             HttpServletRequest request =
593                 (HttpServletRequest)pageContext.getRequest();
594 
595             String portletResource = ParamUtil.getString(
596                 request, "portletResource");
597 
598             long companyId = PortalUtil.getCompanyId(request);
599 
600             Portlet portlet = PortletLocalServiceUtil.getPortletById(
601                 companyId, portletResource);
602 
603             PortletConfig portletConfig = PortletConfigFactory.create(
604                 portlet, pageContext.getServletContext());
605 
606             Locale locale = request.getLocale();
607 
608             ResourceBundle bundle = portletConfig.getResourceBundle(locale);
609 
610             value = bundle.getString(key);
611         }
612         catch (Exception e) {
613             if (_log.isWarnEnabled()) {
614                 _log.warn(e, e);
615             }
616         }
617 
618         return value;
619     }
620 
621     private static Log _log = LogFactoryUtil.getLog(LanguageImpl.class);
622 
623     private static Map<Long, LanguageImpl> _instances =
624         new ConcurrentHashMap<Long, LanguageImpl>();
625 
626     private Locale[] _locales;
627     private Set<Locale> _localesSet;
628     private Map<String, Locale> _localesMap;
629     private Map<String, String> _charEncodings;
630 
631 }