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