001
014
015 package com.liferay.portal.util;
016
017 import com.liferay.portal.kernel.io.unsync.UnsyncStringReader;
018 import com.liferay.portal.kernel.io.unsync.UnsyncStringWriter;
019 import com.liferay.portal.kernel.json.JSONObject;
020 import com.liferay.portal.kernel.language.LanguageUtil;
021 import com.liferay.portal.kernel.log.Log;
022 import com.liferay.portal.kernel.log.LogFactoryUtil;
023 import com.liferay.portal.kernel.security.pacl.DoPrivileged;
024 import com.liferay.portal.kernel.settings.Settings;
025 import com.liferay.portal.kernel.util.ArrayUtil;
026 import com.liferay.portal.kernel.util.LocaleUtil;
027 import com.liferay.portal.kernel.util.Localization;
028 import com.liferay.portal.kernel.util.ParamUtil;
029 import com.liferay.portal.kernel.util.PrefsParamUtil;
030 import com.liferay.portal.kernel.util.StringBundler;
031 import com.liferay.portal.kernel.util.StringPool;
032 import com.liferay.portal.kernel.util.StringUtil;
033 import com.liferay.portal.kernel.util.Tuple;
034 import com.liferay.portal.kernel.util.Validator;
035 import com.liferay.portal.kernel.xml.Document;
036 import com.liferay.portal.kernel.xml.Element;
037 import com.liferay.portal.language.LanguageResources;
038 import com.liferay.util.ContentUtil;
039
040 import java.util.HashMap;
041 import java.util.Locale;
042 import java.util.Map;
043 import java.util.ResourceBundle;
044
045 import javax.portlet.PortletPreferences;
046 import javax.portlet.PortletRequest;
047
048 import javax.servlet.http.HttpServletRequest;
049
050 import javax.xml.stream.XMLInputFactory;
051 import javax.xml.stream.XMLOutputFactory;
052 import javax.xml.stream.XMLStreamConstants;
053 import javax.xml.stream.XMLStreamException;
054 import javax.xml.stream.XMLStreamReader;
055 import javax.xml.stream.XMLStreamWriter;
056
057 import org.apache.commons.collections.map.ReferenceMap;
058
059
067 @DoPrivileged
068 public class LocalizationImpl implements Localization {
069
070 @Override
071 public Object deserialize(JSONObject jsonObject) {
072 Locale[] locales = LanguageUtil.getAvailableLocales();
073
074 Map<Locale, String> map = new HashMap<Locale, String>();
075
076 for (Locale locale : locales) {
077 String languageId = LocaleUtil.toLanguageId(locale);
078
079 String value = jsonObject.getString(languageId);
080
081 if (Validator.isNotNull(value)) {
082 map.put(locale, value);
083 }
084 }
085
086 return map;
087 }
088
089 @Override
090 public String[] getAvailableLanguageIds(Document document) {
091 String attributeValue = _getRootAttributeValue(
092 document, _AVAILABLE_LOCALES, StringPool.BLANK);
093
094 return StringUtil.split(attributeValue);
095 }
096
097 @Override
098 public String[] getAvailableLanguageIds(String xml) {
099 String attributeValue = _getRootAttributeValue(
100 xml, _AVAILABLE_LOCALES, StringPool.BLANK);
101
102 return StringUtil.split(attributeValue);
103 }
104
105 @Override
106 public Locale getDefaultImportLocale(
107 String className, long classPK, Locale contentDefaultLocale,
108 Locale[] contentAvailableLocales) {
109
110 Locale[] availableLocales = LanguageUtil.getAvailableLocales();
111
112 if (ArrayUtil.contains(availableLocales, contentDefaultLocale)) {
113 return contentDefaultLocale;
114 }
115
116 Locale defaultLocale = LocaleUtil.getDefault();
117
118 if (ArrayUtil.contains(contentAvailableLocales, defaultLocale)) {
119 return defaultLocale;
120 }
121
122 for (Locale contentAvailableLocale : contentAvailableLocales) {
123 if (ArrayUtil.contains(availableLocales, contentAvailableLocale)) {
124 return contentAvailableLocale;
125 }
126 }
127
128 if (_log.isWarnEnabled()) {
129 StringBundler sb = new StringBundler(9);
130
131 sb.append("Language ");
132 sb.append(LocaleUtil.toLanguageId(contentDefaultLocale));
133 sb.append(" is missing for ");
134 sb.append(className);
135 sb.append(" with primary key ");
136 sb.append(classPK);
137 sb.append(". Setting default language to ");
138 sb.append(LocaleUtil.toLanguageId(defaultLocale));
139 sb.append(".");
140
141 _log.warn(sb.toString());
142 }
143
144 return defaultLocale;
145 }
146
147 @Override
148 public String getDefaultLanguageId(Document document) {
149 return getDefaultLanguageId(document, LocaleUtil.getDefault());
150 }
151
152 @Override
153 public String getDefaultLanguageId(
154 Document document, Locale defaultLocale) {
155
156 String defaultLanguageId = LocaleUtil.toLanguageId(defaultLocale);
157
158 return _getRootAttributeValue(
159 document, _DEFAULT_LOCALE, defaultLanguageId);
160 }
161
162 @Override
163 public String getDefaultLanguageId(String xml) {
164 return getDefaultLanguageId(xml, LocaleUtil.getDefault());
165 }
166
167 @Override
168 public String getDefaultLanguageId(String xml, Locale defaultLocale) {
169 String defaultLanguageId = LocaleUtil.toLanguageId(defaultLocale);
170
171 return _getRootAttributeValue(xml, _DEFAULT_LOCALE, defaultLanguageId);
172 }
173
174 @Override
175 public String getLocalization(String xml, String requestedLanguageId) {
176 return getLocalization(xml, requestedLanguageId, true);
177 }
178
179 @Override
180 public String getLocalization(
181 String xml, String requestedLanguageId, boolean useDefault) {
182
183 return getLocalization(
184 xml, requestedLanguageId, useDefault, StringPool.BLANK);
185 }
186
187 @Override
188 public String getLocalization(
189 String xml, String requestedLanguageId, boolean useDefault,
190 String defaultValue) {
191
192 String systemDefaultLanguageId = LocaleUtil.toLanguageId(
193 LocaleUtil.getDefault());
194
195 if (!Validator.isXml(xml)) {
196 if (useDefault ||
197 requestedLanguageId.equals(systemDefaultLanguageId)) {
198
199 return xml;
200 }
201 else {
202 return defaultValue;
203 }
204 }
205
206 String value = _getCachedValue(xml, requestedLanguageId, useDefault);
207
208 if (value != null) {
209 return value;
210 }
211
212 String priorityLanguageId = null;
213
214 Locale requestedLocale = LocaleUtil.fromLanguageId(requestedLanguageId);
215
216 if (useDefault &&
217 LanguageUtil.isDuplicateLanguageCode(
218 requestedLocale.getLanguage())) {
219
220 Locale priorityLocale = LanguageUtil.getLocale(
221 requestedLocale.getLanguage());
222
223 if (!requestedLanguageId.equals(priorityLanguageId)) {
224 priorityLanguageId = LocaleUtil.toLanguageId(priorityLocale);
225 }
226 }
227
228 XMLStreamReader xmlStreamReader = null;
229
230 ClassLoader portalClassLoader = ClassLoaderUtil.getPortalClassLoader();
231
232 ClassLoader contextClassLoader =
233 ClassLoaderUtil.getContextClassLoader();
234
235 try {
236 if (contextClassLoader != portalClassLoader) {
237 ClassLoaderUtil.setContextClassLoader(portalClassLoader);
238 }
239
240 XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
241
242 xmlStreamReader = xmlInputFactory.createXMLStreamReader(
243 new UnsyncStringReader(xml));
244
245 String defaultLanguageId = StringPool.BLANK;
246
247
248
249 if (xmlStreamReader.hasNext()) {
250 xmlStreamReader.nextTag();
251
252 defaultLanguageId = xmlStreamReader.getAttributeValue(
253 null, _DEFAULT_LOCALE);
254
255 if (Validator.isNull(defaultLanguageId)) {
256 defaultLanguageId = systemDefaultLanguageId;
257 }
258 }
259
260
261
262 String priorityValue = null;
263 String defaultLocalizationValue = null;
264
265 while (xmlStreamReader.hasNext()) {
266 int event = xmlStreamReader.next();
267
268 if (event == XMLStreamConstants.START_ELEMENT) {
269 String languageId = xmlStreamReader.getAttributeValue(
270 null, _LANGUAGE_ID);
271
272 if (Validator.isNull(languageId)) {
273 languageId = defaultLanguageId;
274 }
275
276 if (languageId.equals(defaultLanguageId) ||
277 languageId.equals(priorityLanguageId) ||
278 languageId.equals(requestedLanguageId)) {
279
280 String text = xmlStreamReader.getElementText();
281
282 if (languageId.equals(defaultLanguageId)) {
283 defaultLocalizationValue = text;
284 }
285
286 if (languageId.equals(priorityLanguageId)) {
287 priorityValue = text;
288 }
289
290 if (languageId.equals(requestedLanguageId)) {
291 value = text;
292 }
293
294 if (Validator.isNotNull(value)) {
295 break;
296 }
297 }
298 }
299 else if (event == XMLStreamConstants.END_DOCUMENT) {
300 break;
301 }
302 }
303
304 if (useDefault && Validator.isNotNull(priorityLanguageId) &&
305 Validator.isNull(value) && Validator.isNotNull(priorityValue)) {
306
307 value = priorityValue;
308 }
309
310 if (useDefault && Validator.isNull(value)) {
311 value = defaultLocalizationValue;
312 }
313
314 if (Validator.isNull(value)) {
315 value = defaultValue;
316 }
317 }
318 catch (Exception e) {
319 if (_log.isWarnEnabled()) {
320 _log.warn(e, e);
321 }
322 }
323 finally {
324 if (contextClassLoader != portalClassLoader) {
325 ClassLoaderUtil.setContextClassLoader(contextClassLoader);
326 }
327
328 if (xmlStreamReader != null) {
329 try {
330 xmlStreamReader.close();
331 }
332 catch (Exception e) {
333 }
334 }
335 }
336
337 _setCachedValue(xml, requestedLanguageId, useDefault, value);
338
339 return value;
340 }
341
342 @Override
343 public Map<Locale, String> getLocalizationMap(
344 HttpServletRequest request, String parameter) {
345
346 Locale[] locales = LanguageUtil.getAvailableLocales();
347
348 Map<Locale, String> map = new HashMap<Locale, String>();
349
350 for (Locale locale : locales) {
351 String localizedParameter = getLocalizedName(
352 parameter, LocaleUtil.toLanguageId(locale));
353
354 map.put(locale, ParamUtil.getString(request, localizedParameter));
355 }
356
357 return map;
358 }
359
360 @Override
361 public Map<Locale, String> getLocalizationMap(
362 PortletPreferences preferences, String preferenceName) {
363
364 return getLocalizationMap(preferences, preferenceName, null);
365 }
366
367 @Override
368 public Map<Locale, String> getLocalizationMap(
369 PortletPreferences preferences, String preferenceName,
370 String propertyName) {
371
372 Locale[] locales = LanguageUtil.getAvailableLocales();
373
374 Map<Locale, String> map = new HashMap<Locale, String>();
375
376 for (Locale locale : locales) {
377 String localizedPreference = getLocalizedName(
378 preferenceName, LocaleUtil.toLanguageId(locale));
379
380 map.put(
381 locale,
382 preferences.getValue(localizedPreference, StringPool.BLANK));
383 }
384
385 if (Validator.isNull(propertyName)) {
386 return map;
387 }
388
389 Locale defaultLocale = LocaleUtil.getSiteDefault();
390
391 String defaultValue = map.get(defaultLocale);
392
393 if (Validator.isNotNull(defaultValue)) {
394 return map;
395 }
396
397 map.put(defaultLocale, ContentUtil.get(PropsUtil.get(propertyName)));
398
399 return map;
400 }
401
402 @Override
403 public Map<Locale, String> getLocalizationMap(
404 PortletRequest portletRequest, String parameter) {
405
406 Locale[] locales = LanguageUtil.getAvailableLocales();
407
408 Map<Locale, String> map = new HashMap<Locale, String>();
409
410 for (Locale locale : locales) {
411 String localizedParameter = getLocalizedName(
412 parameter, LocaleUtil.toLanguageId(locale));
413
414 map.put(
415 locale,
416 ParamUtil.getString(portletRequest, localizedParameter));
417 }
418
419 return map;
420 }
421
422 @Override
423 public Map<Locale, String> getLocalizationMap(String xml) {
424 return getLocalizationMap(xml, false);
425 }
426
427 @Override
428 public Map<Locale, String> getLocalizationMap(
429 String xml, boolean useDefault) {
430
431 Locale[] locales = LanguageUtil.getAvailableLocales();
432
433 Map<Locale, String> map = new HashMap<Locale, String>();
434
435 for (Locale locale : locales) {
436 String languageId = LocaleUtil.toLanguageId(locale);
437
438 String value = getLocalization(xml, languageId, useDefault);
439
440 if (Validator.isNotNull(value)) {
441 map.put(locale, value);
442 }
443 }
444
445 return map;
446 }
447
448 @Override
449 public Map<Locale, String> getLocalizationMap(
450 String bundleName, ClassLoader classLoader, String key,
451 boolean includeBetaLocales) {
452
453 if (key == null) {
454 return null;
455 }
456
457 Map<Locale, String> map = new HashMap<Locale, String>();
458
459 Locale defaultLocale = LocaleUtil.getDefault();
460
461 String defaultValue = _getLocalization(
462 bundleName, defaultLocale, classLoader, key, key);
463
464 map.put(defaultLocale, defaultValue);
465
466 Locale[] locales = null;
467
468 if (includeBetaLocales) {
469 locales = LanguageUtil.getAvailableLocales();
470 }
471 else {
472 locales = LanguageUtil.getSupportedLocales();
473 }
474
475 for (Locale locale : locales) {
476 if (locale.equals(defaultLocale)) {
477 continue;
478 }
479
480 String value = _getLocalization(
481 bundleName, locale, classLoader, key, null);
482
483 if (Validator.isNotNull(value) && !value.equals(defaultValue)) {
484 map.put(locale, value);
485 }
486 }
487
488 return map;
489 }
490
491 @Override
492 public Map<Locale, String> getLocalizationMap(
493 String[] languageIds, String[] values) {
494
495 Map<Locale, String> map = new HashMap<Locale, String>();
496
497 for (int i = 0; i < values.length; i++) {
498 Locale locale = LocaleUtil.fromLanguageId(languageIds[i]);
499
500 map.put(locale, values[i]);
501 }
502
503 return map;
504 }
505
506 @Override
507 public String getLocalizationXmlFromPreferences(
508 PortletPreferences preferences, PortletRequest portletRequest,
509 String parameter) {
510
511 return getLocalizationXmlFromPreferences(
512 preferences, portletRequest, parameter, null, null);
513 }
514
515 @Override
516 public String getLocalizationXmlFromPreferences(
517 PortletPreferences preferences, PortletRequest portletRequest,
518 String parameter, String defaultValue) {
519
520 return getLocalizationXmlFromPreferences(
521 preferences, portletRequest, parameter, defaultValue, null);
522 }
523
524 @Override
525 public String getLocalizationXmlFromPreferences(
526 PortletPreferences preferences, PortletRequest portletRequest,
527 String parameter, String prefix, String defaultValue) {
528
529 String xml = null;
530
531 Locale[] locales = LanguageUtil.getAvailableLocales();
532 Locale defaultLocale = LocaleUtil.getDefault();
533 String defaultLanguageId = LocaleUtil.toLanguageId(defaultLocale);
534
535 for (Locale locale : locales) {
536 String languageId = LocaleUtil.toLanguageId(locale);
537
538 String localizedParameter = getLocalizedName(parameter, languageId);
539
540 String prefixedLocalizedParameter = localizedParameter;
541
542 if (Validator.isNotNull(prefix)) {
543 prefixedLocalizedParameter =
544 prefix + "--" + localizedParameter + "--";
545 }
546
547 String value = ParamUtil.getString(
548 portletRequest, prefixedLocalizedParameter,
549 preferences.getValue(localizedParameter, null));
550
551 if (value != null) {
552 xml = updateLocalization(xml, parameter, value, languageId);
553 }
554 }
555
556 if (getLocalization(xml, defaultLanguageId, true, null) == null) {
557 String oldValue = PrefsParamUtil.getString(
558 preferences, portletRequest, parameter, defaultValue);
559
560 if (Validator.isNotNull(oldValue)) {
561 xml = updateLocalization(xml, parameter, oldValue);
562 }
563 }
564
565 return xml;
566 }
567
568 @Override
569 public String getLocalizedName(String name, String languageId) {
570 return name.concat(StringPool.UNDERLINE).concat(languageId);
571 }
572
573 @Override
574 public Map<Locale, String> getLocalizedParameter(
575 PortletRequest portletRequest, String parameter) {
576
577 return getLocalizationMap(portletRequest, parameter);
578 }
579
580 @Override
581 public String getPreferencesKey(String key, String languageId) {
582 String defaultLanguageId = LocaleUtil.toLanguageId(
583 LocaleUtil.getDefault());
584
585 if (!languageId.equals(defaultLanguageId)) {
586 key = getLocalizedName(key, languageId);
587 }
588
589 return key;
590 }
591
592 @Override
593 public String getPreferencesValue(
594 PortletPreferences preferences, String key, String languageId) {
595
596 return getPreferencesValue(preferences, key, languageId, true);
597 }
598
599 @Override
600 public String getPreferencesValue(
601 PortletPreferences preferences, String key, String languageId,
602 boolean useDefault) {
603
604 String localizedKey = getPreferencesKey(key, languageId);
605
606 String value = preferences.getValue(localizedKey, StringPool.BLANK);
607
608 if (useDefault && Validator.isNull(value)) {
609 value = preferences.getValue(key, StringPool.BLANK);
610 }
611
612 return value;
613 }
614
615 @Override
616 public String[] getPreferencesValues(
617 PortletPreferences preferences, String key, String languageId) {
618
619 return getPreferencesValues(preferences, key, languageId, true);
620 }
621
622 @Override
623 public String[] getPreferencesValues(
624 PortletPreferences preferences, String key, String languageId,
625 boolean useDefault) {
626
627 String localizedKey = getPreferencesKey(key, languageId);
628
629 String[] values = preferences.getValues(localizedKey, new String[0]);
630
631 if (useDefault && ArrayUtil.isEmpty(values)) {
632 values = preferences.getValues(key, new String[0]);
633 }
634
635 return values;
636 }
637
638 @Override
639 public String getSettingsValue(
640 Settings settings, String key, String languageId) {
641
642 return getSettingsValue(settings, key, languageId, true);
643 }
644
645 @Override
646 public String getSettingsValue(
647 Settings settings, String key, String languageId, boolean useDefault) {
648
649 String localizedKey = getPreferencesKey(key, languageId);
650
651 String value = settings.getValue(localizedKey, StringPool.BLANK);
652
653 if (useDefault && Validator.isNull(value)) {
654 value = settings.getValue(key, StringPool.BLANK);
655 }
656
657 return value;
658 }
659
660 @Override
661 public String[] getSettingsValues(
662 Settings settings, String key, String languageId) {
663
664 return getSettingsValues(settings, key, languageId, true);
665 }
666
667 @Override
668 public String[] getSettingsValues(
669 Settings settings, String key, String languageId, boolean useDefault) {
670
671 String localizedKey = getPreferencesKey(key, languageId);
672
673 String[] values = settings.getValues(localizedKey, new String[0]);
674
675 if (useDefault && ArrayUtil.isEmpty(values)) {
676 values = settings.getValues(key, new String[0]);
677 }
678
679 return values;
680 }
681
682 @Override
683 public String removeLocalization(
684 String xml, String key, String requestedLanguageId) {
685
686 return removeLocalization(xml, key, requestedLanguageId, false);
687 }
688
689 @Override
690 public String removeLocalization(
691 String xml, String key, String requestedLanguageId, boolean cdata) {
692
693 return removeLocalization(xml, key, requestedLanguageId, cdata, true);
694 }
695
696 @Override
697 public String removeLocalization(
698 String xml, String key, String requestedLanguageId, boolean cdata,
699 boolean localized) {
700
701 if (Validator.isNull(xml)) {
702 return StringPool.BLANK;
703 }
704
705 if (!Validator.isXml(xml)) {
706 return xml;
707 }
708
709 xml = _sanitizeXML(xml);
710
711 String systemDefaultLanguageId = LocaleUtil.toLanguageId(
712 LocaleUtil.getDefault());
713
714 XMLStreamReader xmlStreamReader = null;
715 XMLStreamWriter xmlStreamWriter = null;
716
717 ClassLoader portalClassLoader = ClassLoaderUtil.getPortalClassLoader();
718
719 ClassLoader contextClassLoader =
720 ClassLoaderUtil.getContextClassLoader();
721
722 try {
723 if (contextClassLoader != portalClassLoader) {
724 ClassLoaderUtil.setContextClassLoader(portalClassLoader);
725 }
726
727 XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
728
729 xmlStreamReader = xmlInputFactory.createXMLStreamReader(
730 new UnsyncStringReader(xml));
731
732 String availableLocales = StringPool.BLANK;
733 String defaultLanguageId = StringPool.BLANK;
734
735
736
737 if (xmlStreamReader.hasNext()) {
738 xmlStreamReader.nextTag();
739
740 availableLocales = xmlStreamReader.getAttributeValue(
741 null, _AVAILABLE_LOCALES);
742 defaultLanguageId = xmlStreamReader.getAttributeValue(
743 null, _DEFAULT_LOCALE);
744
745 if (Validator.isNull(defaultLanguageId)) {
746 defaultLanguageId = systemDefaultLanguageId;
747 }
748 }
749
750 if ((availableLocales != null) &&
751 availableLocales.contains(requestedLanguageId)) {
752
753 availableLocales = StringUtil.removeFromList(
754 availableLocales, requestedLanguageId);
755
756 UnsyncStringWriter unsyncStringWriter =
757 new UnsyncStringWriter();
758
759 XMLOutputFactory xmlOutputFactory =
760 XMLOutputFactory.newInstance();
761
762 xmlStreamWriter = xmlOutputFactory.createXMLStreamWriter(
763 unsyncStringWriter);
764
765 xmlStreamWriter.writeStartDocument();
766 xmlStreamWriter.writeStartElement(_ROOT);
767
768 if (localized) {
769 xmlStreamWriter.writeAttribute(
770 _AVAILABLE_LOCALES, availableLocales);
771 xmlStreamWriter.writeAttribute(
772 _DEFAULT_LOCALE, defaultLanguageId);
773 }
774
775 _copyNonExempt(
776 xmlStreamReader, xmlStreamWriter, requestedLanguageId,
777 defaultLanguageId, cdata);
778
779 xmlStreamWriter.writeEndElement();
780 xmlStreamWriter.writeEndDocument();
781
782 xmlStreamWriter.close();
783 xmlStreamWriter = null;
784
785 xml = unsyncStringWriter.toString();
786 }
787 }
788 catch (Exception e) {
789 if (_log.isWarnEnabled()) {
790 _log.warn(e, e);
791 }
792 }
793 finally {
794 if (contextClassLoader != portalClassLoader) {
795 ClassLoaderUtil.setContextClassLoader(contextClassLoader);
796 }
797
798 if (xmlStreamReader != null) {
799 try {
800 xmlStreamReader.close();
801 }
802 catch (Exception e) {
803 }
804 }
805
806 if (xmlStreamWriter != null) {
807 try {
808 xmlStreamWriter.close();
809 }
810 catch (Exception e) {
811 }
812 }
813 }
814
815 return xml;
816 }
817
818 @Override
819 public void setLocalizedPreferencesValues(
820 PortletRequest portletRequest, PortletPreferences preferences,
821 String parameter)
822 throws Exception {
823
824 Map<Locale, String> map = getLocalizationMap(portletRequest, parameter);
825
826 for (Map.Entry<Locale, String> entry : map.entrySet()) {
827 String languageId = LocaleUtil.toLanguageId(entry.getKey());
828 String value = entry.getValue();
829
830 setPreferencesValue(preferences, parameter, languageId, value);
831 }
832 }
833
834 @Override
835 public void setPreferencesValue(
836 PortletPreferences preferences, String key, String languageId,
837 String value)
838 throws Exception {
839
840 preferences.setValue(getPreferencesKey(key, languageId), value);
841 }
842
843 @Override
844 public void setPreferencesValues(
845 PortletPreferences preferences, String key, String languageId,
846 String[] values)
847 throws Exception {
848
849 preferences.setValues(getPreferencesKey(key, languageId), values);
850 }
851
852 @Override
853 public String updateLocalization(
854 Map<Locale, String> localizationMap, String xml, String key,
855 String defaultLanguageId) {
856
857 Locale[] locales = LanguageUtil.getAvailableLocales();
858
859 for (Locale locale : locales) {
860 String value = localizationMap.get(locale);
861
862 String languageId = LocaleUtil.toLanguageId(locale);
863
864 if (Validator.isNotNull(value)) {
865 xml = updateLocalization(
866 xml, key, value, languageId, defaultLanguageId);
867 }
868 else {
869 xml = removeLocalization(xml, key, languageId);
870 }
871 }
872
873 return xml;
874 }
875
876 @Override
877 public String updateLocalization(String xml, String key, String value) {
878 String defaultLanguageId = LocaleUtil.toLanguageId(
879 LocaleUtil.getDefault());
880
881 return updateLocalization(
882 xml, key, value, defaultLanguageId, defaultLanguageId);
883 }
884
885 @Override
886 public String updateLocalization(
887 String xml, String key, String value, String requestedLanguageId) {
888
889 String defaultLanguageId = LocaleUtil.toLanguageId(
890 LocaleUtil.getDefault());
891
892 return updateLocalization(
893 xml, key, value, requestedLanguageId, defaultLanguageId);
894 }
895
896 @Override
897 public String updateLocalization(
898 String xml, String key, String value, String requestedLanguageId,
899 String defaultLanguageId) {
900
901 return updateLocalization(
902 xml, key, value, requestedLanguageId, defaultLanguageId, false);
903 }
904
905 @Override
906 public String updateLocalization(
907 String xml, String key, String value, String requestedLanguageId,
908 String defaultLanguageId, boolean cdata) {
909
910 return updateLocalization(
911 xml, key, value, requestedLanguageId, defaultLanguageId, cdata,
912 true);
913 }
914
915 @Override
916 public String updateLocalization(
917 String xml, String key, String value, String requestedLanguageId,
918 String defaultLanguageId, boolean cdata, boolean localized) {
919
920 xml = _sanitizeXML(xml);
921
922 XMLStreamReader xmlStreamReader = null;
923 XMLStreamWriter xmlStreamWriter = null;
924
925 ClassLoader portalClassLoader = ClassLoaderUtil.getPortalClassLoader();
926
927 ClassLoader contextClassLoader =
928 ClassLoaderUtil.getContextClassLoader();
929
930 try {
931 if (contextClassLoader != portalClassLoader) {
932 ClassLoaderUtil.setContextClassLoader(portalClassLoader);
933 }
934
935 XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
936
937 xmlStreamReader = xmlInputFactory.createXMLStreamReader(
938 new UnsyncStringReader(xml));
939
940 String availableLocales = StringPool.BLANK;
941
942
943
944 if (xmlStreamReader.hasNext()) {
945 xmlStreamReader.nextTag();
946
947 availableLocales = xmlStreamReader.getAttributeValue(
948 null, _AVAILABLE_LOCALES);
949
950 if (Validator.isNull(availableLocales)) {
951 availableLocales = defaultLanguageId;
952 }
953
954 if (!availableLocales.contains(requestedLanguageId)) {
955 availableLocales = StringUtil.add(
956 availableLocales, requestedLanguageId,
957 StringPool.COMMA);
958 }
959 }
960
961 UnsyncStringWriter unsyncStringWriter = new UnsyncStringWriter();
962
963 XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance();
964
965 xmlStreamWriter = xmlOutputFactory.createXMLStreamWriter(
966 unsyncStringWriter);
967
968 xmlStreamWriter.writeStartDocument();
969 xmlStreamWriter.writeStartElement(_ROOT);
970
971 if (localized) {
972 xmlStreamWriter.writeAttribute(
973 _AVAILABLE_LOCALES, availableLocales);
974 xmlStreamWriter.writeAttribute(
975 _DEFAULT_LOCALE, defaultLanguageId);
976 }
977
978 _copyNonExempt(
979 xmlStreamReader, xmlStreamWriter, requestedLanguageId,
980 defaultLanguageId, cdata);
981
982 xmlStreamWriter.writeStartElement(key);
983
984 if (localized) {
985 xmlStreamWriter.writeAttribute(
986 _LANGUAGE_ID, requestedLanguageId);
987 }
988
989 if (cdata) {
990 xmlStreamWriter.writeCData(value);
991 }
992 else {
993 xmlStreamWriter.writeCharacters(value);
994 }
995
996 xmlStreamWriter.writeEndElement();
997 xmlStreamWriter.writeEndElement();
998 xmlStreamWriter.writeEndDocument();
999
1000 xmlStreamWriter.close();
1001 xmlStreamWriter = null;
1002
1003 xml = unsyncStringWriter.toString();
1004 }
1005 catch (Exception e) {
1006 if (_log.isWarnEnabled()) {
1007 _log.warn(e, e);
1008 }
1009 }
1010 finally {
1011 if (contextClassLoader != portalClassLoader) {
1012 ClassLoaderUtil.setContextClassLoader(contextClassLoader);
1013 }
1014
1015 if (xmlStreamReader != null) {
1016 try {
1017 xmlStreamReader.close();
1018 }
1019 catch (Exception e) {
1020 }
1021 }
1022
1023 if (xmlStreamWriter != null) {
1024 try {
1025 xmlStreamWriter.close();
1026 }
1027 catch (Exception e) {
1028 }
1029 }
1030 }
1031
1032 return xml;
1033 }
1034
1035 private void _copyNonExempt(
1036 XMLStreamReader xmlStreamReader, XMLStreamWriter xmlStreamWriter,
1037 String exemptLanguageId, String defaultLanguageId, boolean cdata)
1038 throws XMLStreamException {
1039
1040 while (xmlStreamReader.hasNext()) {
1041 int event = xmlStreamReader.next();
1042
1043 if (event == XMLStreamConstants.START_ELEMENT) {
1044 String languageId = xmlStreamReader.getAttributeValue(
1045 null, _LANGUAGE_ID);
1046
1047 if (Validator.isNull(languageId)) {
1048 languageId = defaultLanguageId;
1049 }
1050
1051 if (!languageId.equals(exemptLanguageId)) {
1052 xmlStreamWriter.writeStartElement(
1053 xmlStreamReader.getLocalName());
1054 xmlStreamWriter.writeAttribute(_LANGUAGE_ID, languageId);
1055
1056 while (xmlStreamReader.hasNext()) {
1057 event = xmlStreamReader.next();
1058
1059 if ((event == XMLStreamConstants.CHARACTERS) ||
1060 (event == XMLStreamConstants.CDATA)) {
1061
1062 String text = xmlStreamReader.getText();
1063
1064 if (cdata) {
1065 xmlStreamWriter.writeCData(text);
1066 }
1067 else {
1068 xmlStreamWriter.writeCharacters(
1069 xmlStreamReader.getText());
1070 }
1071
1072 break;
1073 }
1074 else if (event == XMLStreamConstants.END_ELEMENT) {
1075 break;
1076 }
1077 }
1078
1079 xmlStreamWriter.writeEndElement();
1080 }
1081 }
1082 else if (event == XMLStreamConstants.END_DOCUMENT) {
1083 break;
1084 }
1085 }
1086 }
1087
1088 private String _getCachedValue(
1089 String xml, String requestedLanguageId, boolean useDefault) {
1090
1091 String value = null;
1092
1093 Map<Tuple, String> valueMap = _cache.get(xml);
1094
1095 if (valueMap != null) {
1096 Tuple subkey = new Tuple(useDefault, requestedLanguageId);
1097
1098 value = valueMap.get(subkey);
1099 }
1100
1101 return value;
1102 }
1103
1104 private String _getLocalization(
1105 String bundleName, Locale locale, ClassLoader classLoader, String key,
1106 String defaultValue) {
1107
1108 ResourceBundle resourceBundle = ResourceBundle.getBundle(
1109 bundleName, locale, classLoader);
1110
1111 String value = null;
1112
1113 if (resourceBundle.containsKey(key)) {
1114 try {
1115 value = resourceBundle.getString(key);
1116
1117 value = new String(
1118 value.getBytes(StringPool.ISO_8859_1), StringPool.UTF8);
1119 }
1120
1121 catch (Exception e) {
1122 }
1123 }
1124
1125 if (Validator.isNotNull(value)) {
1126 value = LanguageResources.fixValue(value);
1127 }
1128 else {
1129 value = LanguageUtil.get(locale, key, defaultValue);
1130 }
1131
1132 return value;
1133 }
1134
1135 private String _getRootAttributeValue(
1136 Document document, String name, String defaultValue) {
1137
1138 Element rootElement = document.getRootElement();
1139
1140 return rootElement.attributeValue(name, defaultValue);
1141 }
1142
1143 private String _getRootAttributeValue(
1144 String xml, String name, String defaultValue) {
1145
1146 String value = null;
1147
1148 XMLStreamReader xmlStreamReader = null;
1149
1150 ClassLoader portalClassLoader = ClassLoaderUtil.getPortalClassLoader();
1151
1152 ClassLoader contextClassLoader =
1153 ClassLoaderUtil.getContextClassLoader();
1154
1155 try {
1156 if (contextClassLoader != portalClassLoader) {
1157 ClassLoaderUtil.setContextClassLoader(portalClassLoader);
1158 }
1159
1160 XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
1161
1162 xmlStreamReader = xmlInputFactory.createXMLStreamReader(
1163 new UnsyncStringReader(xml));
1164
1165 if (xmlStreamReader.hasNext()) {
1166 xmlStreamReader.nextTag();
1167
1168 value = xmlStreamReader.getAttributeValue(null, name);
1169 }
1170 }
1171 catch (Exception e) {
1172 if (_log.isWarnEnabled()) {
1173 _log.warn(e, e);
1174 }
1175 }
1176 finally {
1177 if (contextClassLoader != portalClassLoader) {
1178 ClassLoaderUtil.setContextClassLoader(contextClassLoader);
1179 }
1180
1181 if (xmlStreamReader != null) {
1182 try {
1183 xmlStreamReader.close();
1184 }
1185 catch (Exception e) {
1186 }
1187 }
1188 }
1189
1190 if (Validator.isNull(value)) {
1191 value = defaultValue;
1192 }
1193
1194 return value;
1195 }
1196
1197 private String _sanitizeXML(String xml) {
1198 if (Validator.isNull(xml) || !xml.contains("<root")) {
1199 xml = _EMPTY_ROOT_NODE;
1200 }
1201
1202 return xml;
1203 }
1204
1205 private void _setCachedValue(
1206 String xml, String requestedLanguageId, boolean useDefault,
1207 String value) {
1208
1209 if (Validator.isNotNull(xml) && !xml.equals(_EMPTY_ROOT_NODE)) {
1210 synchronized (_cache) {
1211 Map<Tuple, String> map = _cache.get(xml);
1212
1213 if (map == null) {
1214 map = new HashMap<Tuple, String>();
1215 }
1216
1217 Tuple subkey = new Tuple(useDefault, requestedLanguageId);
1218
1219 map.put(subkey, value);
1220
1221 _cache.put(xml, map);
1222 }
1223 }
1224 }
1225
1226 private static final String _AVAILABLE_LOCALES = "available-locales";
1227
1228 private static final String _DEFAULT_LOCALE = "default-locale";
1229
1230 private static final String _EMPTY_ROOT_NODE = "<root />";
1231
1232 private static final String _LANGUAGE_ID = "language-id";
1233
1234 private static final String _ROOT = "root";
1235
1236 private static Log _log = LogFactoryUtil.getLog(LocalizationImpl.class);
1237
1238 private Map<String, Map<Tuple, String>> _cache = new ReferenceMap(
1239 ReferenceMap.SOFT, ReferenceMap.HARD);
1240
1241 }