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