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.Validator;
33  import com.liferay.portal.security.auth.CompanyThreadLocal;
34  import com.liferay.portal.util.CookieKeys;
35  import com.liferay.portal.util.PortalUtil;
36  import com.liferay.portal.util.PropsValues;
37  import com.liferay.portal.util.WebAppPool;
38  import com.liferay.util.CollectionFactory;
39  import com.liferay.util.Time;
40  
41  import java.text.MessageFormat;
42  
43  import java.util.Locale;
44  import java.util.Map;
45  import java.util.MissingResourceException;
46  import java.util.ResourceBundle;
47  
48  import javax.portlet.ActionRequest;
49  import javax.portlet.PortletConfig;
50  import javax.portlet.RenderRequest;
51  
52  import javax.servlet.http.Cookie;
53  import javax.servlet.http.HttpServletRequest;
54  import javax.servlet.http.HttpServletResponse;
55  import javax.servlet.jsp.PageContext;
56  
57  import org.apache.commons.logging.Log;
58  import org.apache.commons.logging.LogFactory;
59  import org.apache.struts.Globals;
60  import org.apache.struts.taglib.TagUtils;
61  import org.apache.struts.util.MessageResources;
62  
63  /**
64   * <a href="LanguageImpl.java.html"><b><i>View Source</i></b></a>
65   *
66   * @author Brian Wing Shun Chan
67   * @author Andrius Vitkauskas
68   *
69   */
70  public class LanguageImpl implements Language {
71  
72      public static final String DEFAULT_ENCODING = "UTF-8";
73  
74      public String format(Locale locale, String pattern, Object argument) {
75          long companyId = CompanyThreadLocal.getCompanyId();
76  
77          return format(companyId, locale, pattern, new Object[] {argument});
78      }
79  
80      public String format(Locale locale, String pattern, Object[] arguments) {
81          long companyId = CompanyThreadLocal.getCompanyId();
82  
83          return format(companyId, locale, pattern, arguments);
84      }
85  
86      public String format(
87          long companyId, Locale locale, String pattern, Object argument) {
88  
89          return format(companyId, locale, pattern, new Object[] {argument});
90      }
91  
92      public String format(
93          long companyId, Locale locale, String pattern, Object[] arguments) {
94  
95          String value = null;
96  
97          try {
98              pattern = get(companyId, locale, pattern);
99  
100             if (arguments != null) {
101                 Object[] formattedArguments = new Object[arguments.length];
102 
103                 for (int i = 0; i < arguments.length; i++) {
104                     formattedArguments[i] = get(
105                         companyId, locale, arguments[i].toString());
106                 }
107 
108                 value = MessageFormat.format(pattern, formattedArguments);
109             }
110             else {
111                 value = pattern;
112             }
113         }
114         catch (Exception e) {
115             if (_log.isWarnEnabled()) {
116                 _log.warn(e.getMessage());
117             }
118         }
119 
120         return value;
121     }
122 
123     public String format(
124         PageContext pageContext, String pattern, Object argument) {
125 
126         return format(pageContext, pattern, new Object[] {argument}, true);
127     }
128 
129     public String format(
130         PageContext pageContext, String pattern, Object argument,
131         boolean translateArguments) {
132 
133         return format(
134             pageContext, pattern, new Object[] {argument}, translateArguments);
135     }
136 
137     public String format(
138         PageContext pageContext, String pattern, Object[] arguments) {
139 
140         return format(pageContext, pattern, arguments, true);
141     }
142 
143     public String format(
144         PageContext pageContext, String pattern, Object[] arguments,
145         boolean translateArguments) {
146 
147         String value = null;
148 
149         try {
150             pattern = get(pageContext, pattern);
151 
152             if (arguments != null) {
153                 Object[] formattedArguments = new Object[arguments.length];
154 
155                 for (int i = 0; i < arguments.length; i++) {
156                     if (translateArguments) {
157                         formattedArguments[i] =
158                             get(pageContext, arguments[i].toString());
159                     }
160                     else {
161                         formattedArguments[i] = arguments[i];
162                     }
163                 }
164 
165                 value = MessageFormat.format(pattern, formattedArguments);
166             }
167             else {
168                 value = pattern;
169             }
170         }
171         catch (Exception e) {
172             if (_log.isWarnEnabled()) {
173                 _log.warn(e.getMessage());
174             }
175         }
176 
177         return value;
178     }
179 
180     public String format(
181         PageContext pageContext, String pattern, LanguageWrapper argument) {
182 
183         return format(
184             pageContext, pattern, new LanguageWrapper[] {argument}, true);
185     }
186 
187     public String format(
188         PageContext pageContext, String pattern, LanguageWrapper argument,
189         boolean translateArguments) {
190 
191         return format(
192             pageContext, pattern, new LanguageWrapper[] {argument},
193             translateArguments);
194     }
195 
196     public String format(
197         PageContext pageContext, String pattern, LanguageWrapper[] arguments) {
198 
199         return format(pageContext, pattern, arguments, true);
200     }
201 
202     public String format(
203         PageContext pageContext, String pattern, LanguageWrapper[] arguments,
204         boolean translateArguments) {
205 
206         String value = null;
207 
208         try {
209             pattern = get(pageContext, pattern);
210 
211             if (arguments != null) {
212                 Object[] formattedArguments = new Object[arguments.length];
213 
214                 for (int i = 0; i < arguments.length; i++) {
215                     if (translateArguments) {
216                         formattedArguments[i] =
217                             arguments[i].getBefore() +
218                             get(pageContext, arguments[i].getText()) +
219                             arguments[i].getAfter();
220                     }
221                     else {
222                         formattedArguments[i] =
223                             arguments[i].getBefore() +
224                             arguments[i].getText() +
225                             arguments[i].getAfter();
226                     }
227                 }
228 
229                 value = MessageFormat.format(pattern, formattedArguments);
230             }
231             else {
232                 value = pattern;
233             }
234         }
235         catch (Exception e) {
236             if (_log.isWarnEnabled()) {
237                 _log.warn(e.getMessage());
238             }
239         }
240 
241         return value;
242     }
243 
244     public String get(Locale locale, String key) {
245         long companyId = CompanyThreadLocal.getCompanyId();
246 
247         return get(companyId, locale, key, key);
248     }
249 
250     public String get(long companyId, Locale locale, String key) {
251         return get(companyId, locale, key, key);
252     }
253 
254     public String get(
255         long companyId, Locale locale, String key, String defaultValue) {
256 
257         if (key == null) {
258             return null;
259         }
260 
261         String value = null;
262 
263         try {
264             MessageResources resources = (MessageResources)WebAppPool.get(
265                 String.valueOf(companyId), Globals.MESSAGES_KEY);
266 
267             if (resources == null) {
268 
269                 // LEP-4505
270 
271                 ResourceBundle bundle = ResourceBundle.getBundle(
272                     "content/Language", locale);
273 
274                 value = bundle.getString(key);
275             }
276             else {
277                 value = resources.getMessage(locale, key);
278             }
279         }
280         catch (Exception e) {
281             if (_log.isWarnEnabled()) {
282                 _log.warn(e.getMessage());
283             }
284         }
285 
286         if (value == null) {
287             value = defaultValue;
288         }
289 
290         return value;
291     }
292 
293     public String get(PageContext pageContext, String key) {
294         return get(pageContext, key, key);
295     }
296 
297     public String get(
298         PageContext pageContext, String key, String defaultValue) {
299 
300         if (key == null) {
301             return null;
302         }
303 
304         String value = null;
305 
306         try {
307             value = TagUtils.getInstance().message(
308                 pageContext, null, null, key);
309         }
310         catch (Exception e) {
311             _log.error(e);
312         }
313 
314         if (value == null) {
315 
316             // LEP-2849
317 
318             HttpServletRequest req =
319                 (HttpServletRequest)pageContext.getRequest();
320 
321             PortletConfig portletConfig = (PortletConfig)req.getAttribute(
322                 JavaConstants.JAVAX_PORTLET_CONFIG);
323 
324             if (portletConfig != null) {
325                 Locale locale = req.getLocale();
326 
327                 ResourceBundle bundle = portletConfig.getResourceBundle(locale);
328 
329                 try {
330                     value = bundle.getString(key);
331                 }
332                 catch (MissingResourceException mre) {
333                 }
334             }
335         }
336 
337         if (value == null) {
338             value = defaultValue;
339         }
340 
341         return value;
342     }
343 
344     public Locale[] getAvailableLocales() {
345         return _getInstance()._locales;
346     }
347 
348     public String getCharset(Locale locale) {
349         return _getInstance()._getCharset(locale);
350     }
351 
352     public String getLanguageId(ActionRequest req) {
353         HttpServletRequest httpReq = PortalUtil.getHttpServletRequest(req);
354 
355         return getLanguageId(httpReq);
356     }
357 
358     public String getLanguageId(RenderRequest req) {
359         HttpServletRequest httpReq = PortalUtil.getHttpServletRequest(req);
360 
361         return getLanguageId(httpReq);
362     }
363 
364     public String getLanguageId(HttpServletRequest req) {
365         String languageId = ParamUtil.getString(req, "languageId");
366 
367         if (Validator.isNotNull(languageId)) {
368             return languageId;
369         }
370 
371         Locale locale =
372             (Locale)req.getSession().getAttribute(Globals.LOCALE_KEY);
373 
374         if (locale == null) {
375             languageId = CookieKeys.getCookie(
376                 req, CookieKeys.GUEST_LANGUAGE_ID);
377 
378             if (Validator.isNotNull(languageId)) {
379                 locale = LocaleUtil.fromLanguageId(languageId);
380             }
381         }
382 
383         return getLanguageId(locale);
384     }
385 
386     public String getLanguageId(Locale locale) {
387         return LocaleUtil.toLanguageId(locale);
388     }
389 
390     public Locale getLocale(String languageCode) {
391         return _getInstance()._getLocale(languageCode);
392     }
393 
394     public String getTimeDescription(
395         PageContext pageContext, Long milliseconds) {
396 
397         return getTimeDescription(pageContext, milliseconds.longValue());
398     }
399 
400     public String getTimeDescription(
401         PageContext pageContext, long milliseconds) {
402 
403         String desc = Time.getDescription(milliseconds);
404 
405         String value = null;
406 
407         try {
408             int pos = desc.indexOf(StringPool.SPACE);
409 
410             int x = GetterUtil.getInteger(desc.substring(0, pos));
411 
412             value =
413                 x + " " +
414                 get(
415                     pageContext,
416                     desc.substring(pos + 1, desc.length()).toLowerCase());
417         }
418         catch (Exception e) {
419             if (_log.isWarnEnabled()) {
420                 _log.warn(e.getMessage());
421             }
422         }
423 
424         return value;
425     }
426 
427     public void updateCookie(HttpServletResponse res, Locale locale) {
428         String languageId = LocaleUtil.toLanguageId(locale);
429 
430         Cookie languageIdCookie = new Cookie(
431             CookieKeys.GUEST_LANGUAGE_ID, languageId);
432 
433         languageIdCookie.setPath(StringPool.SLASH);
434         languageIdCookie.setMaxAge(CookieKeys.MAX_AGE);
435 
436         CookieKeys.addCookie(res, languageIdCookie);
437     }
438 
439     private static LanguageImpl _getInstance() {
440         Long companyIdObj = new Long(CompanyThreadLocal.getCompanyId());
441 
442         LanguageImpl instance = (LanguageImpl)_instances.get(companyIdObj);
443 
444         if (instance == null) {
445             instance = new LanguageImpl();
446 
447             _instances.put(companyIdObj, instance);
448         }
449 
450         return instance;
451     }
452 
453     private LanguageImpl() {
454         String[] localesArray = PropsValues.LOCALES;
455 
456         _locales = new Locale[localesArray.length];
457         _localesByLanguageCode = CollectionFactory.getHashMap();
458         _charEncodings = CollectionFactory.getHashMap();
459 
460         for (int i = 0; i < localesArray.length; i++) {
461             String languageId = localesArray[i];
462 
463             int x = languageId.indexOf(StringPool.UNDERLINE);
464 
465             String language = languageId.substring(0, x);
466             //String country = languageId.substring(x + 1, languageId.length());
467 
468             Locale locale = LocaleUtil.fromLanguageId(languageId);
469 
470             _locales[i] = locale;
471             _localesByLanguageCode.put(language, locale);
472             _charEncodings.put(locale.toString(), DEFAULT_ENCODING);
473         }
474     }
475 
476     private String _getCharset(Locale locale) {
477         return DEFAULT_ENCODING;
478     }
479 
480     private Locale _getLocale(String languageCode) {
481         return (Locale)_localesByLanguageCode.get(languageCode);
482     }
483 
484     private static Log _log = LogFactory.getLog(LanguageImpl.class);
485 
486     private static Map _instances = CollectionFactory.getSyncHashMap();
487 
488     private Locale[] _locales;
489     private Map _localesByLanguageCode;
490     private Map _charEncodings;
491 
492 }