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