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