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