1
22
23 package com.liferay.util;
24
25 import com.liferay.portal.kernel.language.LanguageUtil;
26 import com.liferay.portal.kernel.log.Log;
27 import com.liferay.portal.kernel.log.LogFactoryUtil;
28 import com.liferay.portal.kernel.util.LocaleUtil;
29 import com.liferay.portal.kernel.util.ParamUtil;
30 import com.liferay.portal.kernel.util.StringPool;
31 import com.liferay.portal.kernel.util.StringUtil;
32 import com.liferay.portal.kernel.util.Tuple;
33 import com.liferay.portal.kernel.util.Validator;
34
35 import java.io.StringReader;
36 import java.io.StringWriter;
37
38 import java.util.HashMap;
39 import java.util.Locale;
40 import java.util.Map;
41
42 import javax.portlet.ActionRequest;
43 import javax.portlet.PortletPreferences;
44 import javax.portlet.PortletRequest;
45
46 import javax.xml.stream.XMLInputFactory;
47 import javax.xml.stream.XMLOutputFactory;
48 import javax.xml.stream.XMLStreamConstants;
49 import javax.xml.stream.XMLStreamException;
50 import javax.xml.stream.XMLStreamReader;
51 import javax.xml.stream.XMLStreamWriter;
52
53 import org.apache.commons.collections.map.ReferenceMap;
54
55
77 public class LocalizationUtil {
78
79 public static String[] getAvailableLocales(String xml) {
80 String attributeValue = _getRootAttribute(
81 xml, _AVAILABLE_LOCALES, StringPool.BLANK);
82
83 return StringUtil.split(attributeValue);
84 }
85
86 public static String getDefaultLocale(String xml) {
87 String defaultLanguageId = LocaleUtil.toLanguageId(
88 LocaleUtil.getDefault());
89
90 return _getRootAttribute(xml, _DEFAULT_LOCALE, defaultLanguageId);
91 }
92
93 public static String getLocalization(
94 String xml, String requestedLanguageId) {
95
96 return getLocalization(xml, requestedLanguageId, true);
97 }
98
99 public static String getLocalization(
100 String xml, String requestedLanguageId, boolean useDefault) {
101
102 String value = _getCachedValue(xml, requestedLanguageId, useDefault);
103
104 if (value != null) {
105 return value;
106 }
107 else {
108 value = StringPool.BLANK;
109 }
110
111 String defaultLanguageId = LocaleUtil.toLanguageId(
112 LocaleUtil.getDefault());
113
114 String defaultValue = StringPool.BLANK;
115
116 XMLStreamReader reader = null;
117
118 try {
119 XMLInputFactory factory = XMLInputFactory.newInstance();
120
121 reader = factory.createXMLStreamReader(new StringReader(xml));
122
123
125 if (reader.hasNext()) {
126 reader.nextTag();
127 }
128
129
131 while (reader.hasNext()) {
132 int event = reader.next();
133
134 if (event == XMLStreamConstants.START_ELEMENT) {
135 String languageId = reader.getAttributeValue(
136 null, _LANGUAGE_ID);
137
138 if (Validator.isNull(languageId)) {
139 languageId = defaultLanguageId;
140 }
141
142 if (languageId.equals(defaultLanguageId) ||
143 languageId.equals(requestedLanguageId)) {
144
145 while (reader.hasNext()) {
146 event = reader.next();
147
148 if (event == XMLStreamConstants.CHARACTERS ||
149 event == XMLStreamConstants.CDATA) {
150
151 String text = reader.getText();
152
153 if (languageId.equals(defaultLanguageId)) {
154 defaultValue = text;
155 }
156
157 if (languageId.equals(requestedLanguageId)) {
158 value = text;
159 }
160
161 break;
162 }
163 else if (event == XMLStreamConstants.END_ELEMENT) {
164 break;
165 }
166 }
167
168 if (Validator.isNotNull(value)) {
169 break;
170 }
171 }
172 }
173 else if (event == XMLStreamConstants.END_DOCUMENT) {
174 break;
175 }
176 }
177
178 if (useDefault && Validator.isNull(value)) {
179 value = defaultValue;
180 }
181 }
182 catch (Exception e) {
183 if (_log.isWarnEnabled()) {
184 _log.warn(e, e);
185 }
186 }
187 finally {
188 if (reader != null) {
189 try {
190 reader.close();
191 }
192 catch (Exception e) {
193 }
194 }
195 }
196
197 _setCachedValue(xml, requestedLanguageId, useDefault, value);
198
199 return value;
200 }
201
202 public static Map<Locale, String> getLocalizedParameter(
203 PortletRequest portletRequest, String parameter) {
204
205 Locale[] locales = LanguageUtil.getAvailableLocales();
206
207 Map<Locale, String> map = new HashMap<Locale, String>();
208
209 for (Locale locale : locales) {
210 String languageId = LocaleUtil.toLanguageId(locale);
211
212 String localeParameter =
213 parameter + StringPool.UNDERLINE + languageId;
214
215 map.put(
216 locale, ParamUtil.getString(portletRequest, localeParameter));
217 }
218
219 return map;
220 }
221
222 public static String getPreferencesValue(
223 PortletPreferences preferences, String key, String languageId) {
224
225 return getPreferencesValue(preferences, key, languageId, true);
226 }
227
228 public static String getPreferencesValue(
229 PortletPreferences preferences, String key, String languageId,
230 boolean useDefault) {
231
232 String localizedKey = _getPreferencesKey(key, languageId);
233
234 String value = preferences.getValue(localizedKey, StringPool.BLANK);
235
236 if (useDefault && Validator.isNull(value)) {
237 value = preferences.getValue(key, StringPool.BLANK);
238 }
239
240 return value;
241 }
242
243 public static String[] getPreferencesValues(
244 PortletPreferences preferences, String key, String languageId) {
245
246 return getPreferencesValues(preferences, key, languageId, true);
247 }
248
249 public static String[] getPreferencesValues(
250 PortletPreferences preferences, String key, String languageId,
251 boolean useDefault) {
252
253 String localizedKey = _getPreferencesKey(key, languageId);
254
255 String[] values = preferences.getValues(localizedKey, new String[0]);
256
257 if (useDefault && Validator.isNull(values)) {
258 values = preferences.getValues(key, new String[0]);
259 }
260
261 return values;
262 }
263
264 public static String removeLocalization(
265 String xml, String key, String requestedLanguageId) {
266
267 return removeLocalization(xml, key, requestedLanguageId, false);
268 }
269
270 public static String removeLocalization(
271 String xml, String key, String requestedLanguageId, boolean cdata) {
272
273 xml = _sanitizeXML(xml);
274
275 String systemDefaultLanguageId = LocaleUtil.toLanguageId(
276 LocaleUtil.getDefault());
277
278 XMLStreamReader reader = null;
279 XMLStreamWriter writer = null;
280
281 try {
282 XMLInputFactory inputFactory = XMLInputFactory.newInstance();
283
284 reader = inputFactory.createXMLStreamReader(new StringReader(xml));
285
286 String availableLocales = StringPool.BLANK;
287 String defaultLanguageId = StringPool.BLANK;
288
289
291 if (reader.hasNext()) {
292 reader.nextTag();
293
294 availableLocales = reader.getAttributeValue(
295 null, _AVAILABLE_LOCALES);
296 defaultLanguageId = reader.getAttributeValue(
297 null, _DEFAULT_LOCALE);
298
299 if (Validator.isNull(defaultLanguageId)) {
300 defaultLanguageId = systemDefaultLanguageId;
301 }
302 }
303
304 if ((availableLocales != null) &&
305 (availableLocales.indexOf(requestedLanguageId) != -1)) {
306
307 availableLocales = StringUtil.remove(
308 availableLocales, requestedLanguageId, StringPool.COMMA);
309
310 StringWriter sw = new StringWriter(xml.length());
311
312 XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
313
314 writer = outputFactory.createXMLStreamWriter(sw);
315
316 writer.writeStartDocument();
317 writer.writeStartElement(_ROOT);
318 writer.writeAttribute(_AVAILABLE_LOCALES, availableLocales);
319 writer.writeAttribute(_DEFAULT_LOCALE, defaultLanguageId);
320
321 _copyNonExempt(
322 reader, writer, requestedLanguageId, defaultLanguageId,
323 cdata);
324
325 writer.writeEndElement();
326 writer.writeEndDocument();
327
328 writer.close();
329 writer = null;
330
331 xml = sw.toString();
332 }
333 }
334 catch (Exception e) {
335 if (_log.isWarnEnabled()) {
336 _log.warn(e, e);
337 }
338 }
339 finally {
340 if (reader != null) {
341 try {
342 reader.close();
343 }
344 catch (Exception e) {
345 }
346 }
347
348 if (writer != null) {
349 try {
350 writer.close();
351 }
352 catch (Exception e) {
353 }
354 }
355 }
356
357 return xml;
358 }
359
360 public static void setLocalizedPreferencesValues (
361 ActionRequest actionRequest, PortletPreferences preferences,
362 String parameter)
363 throws Exception {
364
365 Map<Locale, String> map = getLocalizedParameter(
366 actionRequest, parameter);
367
368 for (Locale locale : map.keySet()) {
369 String languageId = LocaleUtil.toLanguageId(locale);
370
371 String key = parameter + StringPool.UNDERLINE + languageId;
372 String value = map.get(locale);
373
374 preferences.setValue(key, value);
375 }
376 }
377
378 public static void setPreferencesValue(
379 PortletPreferences preferences, String key, String languageId,
380 String value)
381 throws Exception {
382
383 preferences.setValue(_getPreferencesKey(key, languageId), value);
384 }
385
386 public static void setPreferencesValues(
387 PortletPreferences preferences, String key, String languageId,
388 String[] values)
389 throws Exception {
390
391 preferences.setValues(_getPreferencesKey(key, languageId), values);
392 }
393
394 public static String updateLocalization(
395 String xml, String key, String value) {
396
397 String defaultLanguageId = LocaleUtil.toLanguageId(
398 LocaleUtil.getDefault());
399
400 return updateLocalization(
401 xml, key, value, defaultLanguageId, defaultLanguageId);
402 }
403
404 public static String updateLocalization(
405 String xml, String key, String value, String requestedLanguageId) {
406
407 String defaultLanguageId = LocaleUtil.toLanguageId(
408 LocaleUtil.getDefault());
409
410 return updateLocalization(
411 xml, key, value, requestedLanguageId, defaultLanguageId);
412 }
413
414 public static String updateLocalization(
415 String xml, String key, String value, String requestedLanguageId,
416 String defaultLanguageId) {
417
418 return updateLocalization(
419 xml, key, value, requestedLanguageId, defaultLanguageId, false);
420 }
421
422 public static String updateLocalization(
423 String xml, String key, String value, String requestedLanguageId,
424 String defaultLanguageId, boolean cdata) {
425
426 xml = _sanitizeXML(xml);
427
428 XMLStreamReader reader = null;
429 XMLStreamWriter writer = null;
430
431 try {
432 XMLInputFactory inputFactory = XMLInputFactory.newInstance();
433
434 reader = inputFactory.createXMLStreamReader(new StringReader(xml));
435
436 String availableLocales = StringPool.BLANK;
437
438
440 if (reader.hasNext()) {
441 reader.nextTag();
442
443 availableLocales = reader.getAttributeValue(
444 null, _AVAILABLE_LOCALES);
445
446 if (Validator.isNull(availableLocales)) {
447 availableLocales = defaultLanguageId;
448 }
449
450 if (availableLocales.indexOf(requestedLanguageId) == -1) {
451 availableLocales = StringUtil.add(
452 availableLocales, requestedLanguageId,
453 StringPool.COMMA);
454 }
455 }
456
457 StringWriter sw = new StringWriter(xml.length());
458
459 XMLOutputFactory outputFactory = XMLOutputFactory.newInstance();
460
461 writer = outputFactory.createXMLStreamWriter(sw);
462
463 writer.writeStartDocument();
464 writer.writeStartElement(_ROOT);
465 writer.writeAttribute(_AVAILABLE_LOCALES, availableLocales);
466 writer.writeAttribute(_DEFAULT_LOCALE, defaultLanguageId);
467
468 _copyNonExempt(
469 reader, writer, requestedLanguageId, defaultLanguageId,
470 cdata);
471
472 if (cdata) {
473 writer.writeStartElement(key);
474 writer.writeAttribute(_LANGUAGE_ID, requestedLanguageId);
475 writer.writeCData(value);
476 writer.writeEndElement();
477 }
478 else {
479 writer.writeStartElement(key);
480 writer.writeAttribute(_LANGUAGE_ID, requestedLanguageId);
481 writer.writeCharacters(value);
482 writer.writeEndElement();
483 }
484
485 writer.writeEndElement();
486 writer.writeEndDocument();
487
488 writer.close();
489 writer = null;
490
491 xml = sw.toString();
492 }
493 catch (Exception e) {
494 if (_log.isWarnEnabled()) {
495 _log.warn(e, e);
496 }
497 }
498 finally {
499 if (reader != null) {
500 try {
501 reader.close();
502 }
503 catch (Exception e) {
504 }
505 }
506
507 if (writer != null) {
508 try {
509 writer.close();
510 }
511 catch (Exception e) {
512 }
513 }
514 }
515
516 return xml;
517 }
518
519 private static void _copyNonExempt(
520 XMLStreamReader reader, XMLStreamWriter writer,
521 String exemptLanguageId, String defaultLanguageId, boolean cdata)
522 throws XMLStreamException {
523
524 while (reader.hasNext()) {
525 int event = reader.next();
526
527 if (event == XMLStreamConstants.START_ELEMENT) {
528 String languageId = reader.getAttributeValue(
529 null, _LANGUAGE_ID);
530
531 if (Validator.isNull(languageId)) {
532 languageId = defaultLanguageId;
533 }
534
535 if (!languageId.equals(exemptLanguageId)) {
536 writer.writeStartElement(reader.getLocalName());
537 writer.writeAttribute(_LANGUAGE_ID, languageId);
538
539 while (reader.hasNext()) {
540 event = reader.next();
541
542 if (event == XMLStreamConstants.CHARACTERS ||
543 event == XMLStreamConstants.CDATA) {
544
545 String text = reader.getText();
546
547 if (cdata) {
548 writer.writeCData(text);
549 }
550 else {
551 writer.writeCharacters(reader.getText());
552 }
553
554 break;
555 }
556 else if (event == XMLStreamConstants.END_ELEMENT) {
557 break;
558 }
559 }
560
561 writer.writeEndElement();
562 }
563 }
564 else if (event == XMLStreamConstants.END_DOCUMENT) {
565 break;
566 }
567 }
568 }
569
570 private static String _getCachedValue(
571 String xml, String requestedLanguageId, boolean useDefault) {
572
573 String value = null;
574
575 Map<Tuple, String> valueMap = _cache.get(xml);
576
577 if (valueMap != null) {
578 Tuple subkey = new Tuple(useDefault, requestedLanguageId);
579
580 value = valueMap.get(subkey);
581 }
582
583 return value;
584 }
585
586 private static String _getPreferencesKey(String key, String languageId) {
587 String defaultLanguageId = LocaleUtil.toLanguageId(
588 LocaleUtil.getDefault());
589
590 if (!languageId.equals(defaultLanguageId)) {
591 key += StringPool.UNDERLINE + languageId;
592 }
593
594 return key;
595 }
596
597 private static String _getRootAttribute(
598 String xml, String name, String defaultValue) {
599
600 String value = null;
601
602 XMLStreamReader reader = null;
603
604 try {
605 XMLInputFactory factory = XMLInputFactory.newInstance();
606
607 reader = factory.createXMLStreamReader(new StringReader(xml));
608
609 if (reader.hasNext()) {
610 reader.nextTag();
611
612 value = reader.getAttributeValue(null, name);
613 }
614 }
615 catch (Exception e) {
616 if (_log.isWarnEnabled()) {
617 _log.warn(e, e);
618 }
619 }
620 finally {
621 if (reader != null) {
622 try {
623 reader.close();
624 }
625 catch (Exception e) {
626 }
627 }
628 }
629
630 if (Validator.isNull(value)) {
631 value = defaultValue;
632 }
633
634 return value;
635 }
636
637 private static String _sanitizeXML(String xml) {
638 if (Validator.isNull(xml) || (xml.indexOf("<root") == -1)) {
639 xml = _EMPTY_ROOT_NODE;
640 }
641
642 return xml;
643 }
644
645 private static void _setCachedValue(
646 String xml, String requestedLanguageId, boolean useDefault,
647 String value) {
648
649 if (Validator.isNotNull(xml) && !xml.equals(_EMPTY_ROOT_NODE)) {
650 synchronized (_cache) {
651 Map<Tuple, String> map = _cache.get(xml);
652
653 if (map == null) {
654 map = new HashMap<Tuple, String>();
655 }
656
657 Tuple subkey = new Tuple(useDefault, requestedLanguageId);
658
659 map.put(subkey, value);
660
661 _cache.put(xml, map);
662 }
663 }
664 }
665
666 private static final String _AVAILABLE_LOCALES = "available-locales";
667
668 private static final String _DEFAULT_LOCALE = "default-locale";
669
670 private static final String _EMPTY_ROOT_NODE = "<root />";
671
672 private static final String _LANGUAGE_ID = "language-id";
673
674 private static final String _ROOT = "root";
675
676 private static Log _log = LogFactoryUtil.getLog(LocalizationUtil.class);
677
678 private static Map<String, Map<Tuple, String>> _cache = new ReferenceMap(
679 ReferenceMap.SOFT, ReferenceMap.HARD);
680
681 }