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